diff options
author | Timo Teras <timo.teras@iki.fi> | 2009-11-27 18:42:11 +0200 |
---|---|---|
committer | Timo Teras <timo.teras@iki.fi> | 2009-11-27 18:42:11 +0200 |
commit | 959645020619f02d6ab8bb4026b0e0121b3971da (patch) | |
tree | d87a0ef5bf3b50dae70dc7c5c1688b446f8e559b /src/fiber.c | |
parent | aa530f352b0410150bfe94c821ae32c1378b9d02 (diff) | |
download | libtf-959645020619f02d6ab8bb4026b0e0121b3971da.tar.bz2 libtf-959645020619f02d6ab8bb4026b0e0121b3971da.tar.xz |
libtf: implement x86 assembly fiber switching
it's faster and has smaller context in the beginning of the
fiber. it's also required since setjmp() seems to use mangled
pointers in glibc so we could not schedule fibers in non-creation
threads. additionally the setjmp() setup code has a race condition.
Diffstat (limited to 'src/fiber.c')
-rw-r--r-- | src/fiber.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/src/fiber.c b/src/fiber.c index 3f8bb15..6ddde1b 100644 --- a/src/fiber.c +++ b/src/fiber.c @@ -29,7 +29,7 @@ struct tf_fiber { char data[TF_EMPTY_ARRAY]; }; -#include "uctx-setjmp.h" +#include "uctx.h" /* FIXME: should be in thread local storage */ struct tf_scheduler *__tf_scheduler; @@ -91,12 +91,13 @@ static void run_fiber(struct tf_scheduler *sched, struct tf_fiber *f) struct tf_fiber *schedf = container_of((void*) tf_get_scheduler(), struct tf_fiber, data); sched->active_fiber = f; - switch (tf_uctx_transfer(schedf, f, f->wakeup_type)) { + tf_uctx_transfer(schedf, f); + switch (f->wakeup_type) { case TF_WAKEUP_KILL: tf_fiber_put(f->data); sched->num_fibers--; break; - case TF_WAKEUP_IMMEDIATE: + case TF_WAKEUP_NONE: break; default: TF_BUG_ON("bad scheduler call from fiber"); @@ -222,15 +223,19 @@ int tf_schedule(void) struct tf_fiber *f = sched->active_fiber; if (unlikely(f->timeout_change)) { - if (f->timeout_change & TF_TIMEOUT_CHANGE_NEW_VALUE) + if (f->timeout_change & TF_TIMEOUT_CHANGE_NEW_VALUE) { + if (tf_mtime_diff(f->timeout, tf_mtime()) <= 0) { + f->timeout_change = TF_TIMEOUT_CHANGE; + return TF_WAKEUP_TIMEOUT; + } tf_heap_change(&f->heap_node, &sched->heap, f->timeout); - else + } else tf_heap_delete(&f->heap_node, &sched->heap); f->timeout_change = 0; } f->wakeup_type = TF_WAKEUP_NONE; - - return tf_uctx_transfer(f, schedf, TF_WAKEUP_IMMEDIATE); + tf_uctx_transfer(f, schedf); + return f->wakeup_type; } void tf_wakeup(struct tf_fiber *fiber, int wakeup_type) @@ -250,7 +255,8 @@ void tf_exit(void) struct tf_fiber *schedf = container_of((void*) sched, struct tf_fiber, data); tf_heap_delete(&f->heap_node, &sched->heap); - tf_uctx_transfer(f, schedf, TF_WAKEUP_KILL); + f->wakeup_type = TF_WAKEUP_KILL; + tf_uctx_transfer(f, schedf); TF_BUG_ON(1); } |