The unified diff between revisions [cc8258a6..] and [dc88787e..] is displayed below. It can also be downloaded as a raw diff.
This diff has been restricted to the following files: 'event.c'
# # old_revision [cc8258a6c3643514892e84cf24fed008bc6f9660] # new_revision [dc88787ecd1d574feba045763baed2a7651ff33d] # # add_file "event.c" # content [0931d041137bc29648c8785b0198b3712fda631e] # ============================================================ --- /dev/null +++ event.c 0931d041137bc29648c8785b0198b3712fda631e @@ -0,0 +1,86 @@ +#include "event.h" +#include "interrupt.h" +#include "types.h" +#include "log.h" + +event_handler *event_handler_table[EVENT_MAX+1]; + +#define EVENT_WORDS ((EVENT_MAX+1+31)/32) + +unsigned int event_pending[EVENT_WORDS]; + +#define EVENT_WORDLEN 32 +#define EVENT_WORD(x) (x/EVENT_WORDLEN) +#define EVENT_BIT(x) (x%EVENT_WORDLEN) +#define EVENT_MASK(x) (1<<EVENT_BIT(x)) + +/* + * This function must be called with interrupts disabled. + * This will normally be the case as it is typically called from within + * an interrupt handler anyway. + */ + +void event_set(unsigned int event) +{ + if (event > EVENT_MAX) + return; + + event_pending[EVENT_WORD(event)] |= EVENT_MASK(event); +} + +static int bitset(unsigned int x) +{ + x = 0xffffffff - (x-1); + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x = x + (x << 8); + x = x + (x << 16); + return 32 - (x >> 24); +} + +bool event_get(unsigned int *event) +{ + int i; + unsigned int p; + + for (i = 0; i < EVENT_WORDS; i++) { + if ((p = event_pending[i]) != 0) { + p = p & (-p); + *event = bitset(p) + EVENT_WORDLEN*i; + return TRUE; + } + } + return FALSE; +} + +void event_clear(unsigned int event) +{ + interrupt_block(); + event_pending[EVENT_WORD(event)] &= ~EVENT_MASK(event); + interrupt_unblock(); +} + +bool event_dispatch(void) +{ + unsigned int event; + + if (event_get(&event)) { + event_clear(event); + if (event_handler_table[event] != NULL) { + log_mark_busy(); + (event_handler_table[event])(); + log_mark_idle(); + } + return TRUE; + } + + return FALSE; +} + +void event_register(unsigned int event, event_handler *handler) +{ + if (event > EVENT_MAX) + return; + event_handler_table[event] = handler; +}