The unified diff between revisions [cc8258a6..] and [3dc5e7ac..] 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 [3dc5e7ac4bcb952cc267892653dd78ed095d8778]
#
# 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;
+}