trigger.h 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #ifndef __TRIGGER_H_
  2. #define __TRIGGER_H_ 1
  3. #include "util/debug.h"
  4. #include "asm/bug.h"
  5. /*
  6. * Use trigger to model operations which need to be executed when
  7. * an event (a signal, for example) is observed.
  8. *
  9. * States and transits:
  10. *
  11. *
  12. * OFF--(on)--> READY --(hit)--> HIT
  13. * ^ |
  14. * | (ready)
  15. * | |
  16. * \_____________/
  17. *
  18. * is_hit and is_ready are two key functions to query the state of
  19. * a trigger. is_hit means the event already happen; is_ready means the
  20. * trigger is waiting for the event.
  21. */
  22. struct trigger {
  23. volatile enum {
  24. TRIGGER_ERROR = -2,
  25. TRIGGER_OFF = -1,
  26. TRIGGER_READY = 0,
  27. TRIGGER_HIT = 1,
  28. } state;
  29. const char *name;
  30. };
  31. #define TRIGGER_WARN_ONCE(t, exp) \
  32. WARN_ONCE(t->state != exp, "trigger '%s' state transist error: %d in %s()\n", \
  33. t->name, t->state, __func__)
  34. static inline bool trigger_is_available(struct trigger *t)
  35. {
  36. return t->state >= 0;
  37. }
  38. static inline bool trigger_is_error(struct trigger *t)
  39. {
  40. return t->state <= TRIGGER_ERROR;
  41. }
  42. static inline void trigger_on(struct trigger *t)
  43. {
  44. TRIGGER_WARN_ONCE(t, TRIGGER_OFF);
  45. t->state = TRIGGER_READY;
  46. }
  47. static inline void trigger_ready(struct trigger *t)
  48. {
  49. if (!trigger_is_available(t))
  50. return;
  51. t->state = TRIGGER_READY;
  52. }
  53. static inline void trigger_hit(struct trigger *t)
  54. {
  55. if (!trigger_is_available(t))
  56. return;
  57. TRIGGER_WARN_ONCE(t, TRIGGER_READY);
  58. t->state = TRIGGER_HIT;
  59. }
  60. static inline void trigger_off(struct trigger *t)
  61. {
  62. if (!trigger_is_available(t))
  63. return;
  64. t->state = TRIGGER_OFF;
  65. }
  66. static inline void trigger_error(struct trigger *t)
  67. {
  68. t->state = TRIGGER_ERROR;
  69. }
  70. static inline bool trigger_is_ready(struct trigger *t)
  71. {
  72. return t->state == TRIGGER_READY;
  73. }
  74. static inline bool trigger_is_hit(struct trigger *t)
  75. {
  76. return t->state == TRIGGER_HIT;
  77. }
  78. #define DEFINE_TRIGGER(n) \
  79. struct trigger n = {.state = TRIGGER_OFF, .name = #n}
  80. #endif