trigger.h 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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_ON = 0,
  27. TRIGGER_READY = 1,
  28. TRIGGER_HIT = 2,
  29. } state;
  30. const char *name;
  31. };
  32. #define TRIGGER_WARN_ONCE(t, exp) \
  33. WARN_ONCE(t->state != exp, "trigger '%s' state transist error: %d in %s()\n", \
  34. t->name, t->state, __func__)
  35. static inline bool trigger_is_available(struct trigger *t)
  36. {
  37. return t->state >= 0;
  38. }
  39. static inline bool trigger_is_error(struct trigger *t)
  40. {
  41. return t->state <= TRIGGER_ERROR;
  42. }
  43. static inline void trigger_on(struct trigger *t)
  44. {
  45. TRIGGER_WARN_ONCE(t, TRIGGER_OFF);
  46. t->state = TRIGGER_ON;
  47. }
  48. static inline void trigger_ready(struct trigger *t)
  49. {
  50. if (!trigger_is_available(t))
  51. return;
  52. t->state = TRIGGER_READY;
  53. }
  54. static inline void trigger_hit(struct trigger *t)
  55. {
  56. if (!trigger_is_available(t))
  57. return;
  58. TRIGGER_WARN_ONCE(t, TRIGGER_READY);
  59. t->state = TRIGGER_HIT;
  60. }
  61. static inline void trigger_off(struct trigger *t)
  62. {
  63. if (!trigger_is_available(t))
  64. return;
  65. t->state = TRIGGER_OFF;
  66. }
  67. static inline void trigger_error(struct trigger *t)
  68. {
  69. t->state = TRIGGER_ERROR;
  70. }
  71. static inline bool trigger_is_ready(struct trigger *t)
  72. {
  73. return t->state == TRIGGER_READY;
  74. }
  75. static inline bool trigger_is_hit(struct trigger *t)
  76. {
  77. return t->state == TRIGGER_HIT;
  78. }
  79. #define DEFINE_TRIGGER(n) \
  80. struct trigger n = {.state = TRIGGER_OFF, .name = #n}
  81. #endif