summaryrefslogtreecommitdiffstats
path: root/src/ifc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ifc.c')
-rw-r--r--src/ifc.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/ifc.c b/src/ifc.c
new file mode 100644
index 0000000..2dfafe8
--- /dev/null
+++ b/src/ifc.c
@@ -0,0 +1,57 @@
+/* ifc.c - inter fiber communications
+ *
+ * Copyright (C) 2010 Timo Teräs <timo.teras@iki.fi>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 or later as
+ * published by the Free Software Foundation.
+ *
+ * See http://www.gnu.org/ for details.
+ */
+
+#include <libtf/atomic.h>
+#include <libtf/fiber.h>
+
+void tf_ifc_queue(void *fiber, struct tf_ifc *ifc, tf_ifc_handler_t handler)
+{
+ struct tf_fiber *f = container_of(fiber, struct tf_fiber, data);
+ struct tf_ifc *old;
+
+ TF_BUG_ON(ifc->next != NULL);
+ ifc->handler = handler;
+ do {
+ old = f->pending_ifc;
+ ifc->next = old;
+ } while (!tf_atomic_cmpxchg(&f->pending_ifc, old, ifc));
+
+ tf_fiber_wakeup(f);
+}
+
+void tf_ifc_complete(void *fiber, struct tf_ifc *ifc, tf_ifc_handler_t handler)
+{
+ ifc->sender = tf_vmach_get_current_fiber();
+ tf_ifc_queue(fiber, ifc, handler);
+ while (ifc->sender != NULL)
+ tf_fiber_schedule();
+}
+
+void tf_ifc_process_unordered(void)
+{
+ struct tf_fiber *f = tf_vmach_get_current_fiber(), *s;
+ struct tf_ifc *pending, *ifc;
+
+ while (f->pending_ifc != NULL) {
+ pending = tf_atomic_xchg(&f->pending_ifc, NULL);
+ while (pending) {
+ ifc = pending;
+ pending = ifc->next;
+ ifc->handler(f->data, ifc);
+ s = ifc->sender;
+ ifc->next = NULL;
+ ifc->sender = NULL;
+ if (s != NULL)
+ tf_fiber_wakeup(s);
+ }
+ }
+}