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