/* ifc.c - inter fiber communications * * Copyright (C) 2010 Timo Teräs * 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 #include 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); } } }