diff options
Diffstat (limited to 'src/ifc.c')
-rw-r--r-- | src/ifc.c | 57 |
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); + } + } +} |