From 674f1495ab082c8f5a604cbb5a4dadc95b8c7ebb Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Wed, 10 Mar 2010 18:12:02 +0200 Subject: libtf: fix stack frame creation and valgrind issues debugging looks now better. there was also some valgrind issues that needed attention. --- include/libtf/fiber.h | 3 +-- src/fiber.c | 62 +++++++++++++++++++++++++-------------------------- src/uctx.h | 20 ++++++++--------- test/httpget.c | 2 +- test/read.c | 4 ++-- test/simple1.c | 2 +- test/sleep.c | 2 +- 7 files changed, 46 insertions(+), 49 deletions(-) diff --git a/include/libtf/fiber.h b/include/libtf/fiber.h index a140607..d5c6153 100644 --- a/include/libtf/fiber.h +++ b/include/libtf/fiber.h @@ -30,8 +30,7 @@ struct tf_scheduler; typedef void (*tf_fiber_proc)(void *fiber); void *__tf_fiber_create(tf_fiber_proc fiber_main, int private_size); -void *tf_fiber_create(struct tf_scheduler *sched, - tf_fiber_proc fiber_main, int private_size); +void *tf_fiber_create(tf_fiber_proc fiber_main, int private_size); void *tf_fiber_get(void *data); void tf_fiber_put(void *data); void __tf_fiber_wakeup(void *data, int wakeup_type); diff --git a/src/fiber.c b/src/fiber.c index 3f58b6d..e507815 100644 --- a/src/fiber.c +++ b/src/fiber.c @@ -39,6 +39,15 @@ struct tf_fiber *tf_fiber_get_current(void) return container_of(data, struct tf_fiber, data); } +static void tf_fiber_main(void *user_data, void *arg) +{ + tf_fiber_proc proc = (tf_fiber_proc) arg; + struct tf_fiber *f = user_data; + + proc(f->data); + tf_fiber_exit(); +} + void *__tf_fiber_create(tf_fiber_proc fiber_main, int private_size) { struct tf_fiber *fiber; @@ -47,8 +56,7 @@ void *__tf_fiber_create(tf_fiber_proc fiber_main, int private_size) TF_STACK_SIZE, sizeof(struct tf_fiber) + private_size, offsetof(struct tf_fiber, context), - fiber_main, offsetof(struct tf_fiber, data), - tf_fiber_exit); + tf_fiber_main, fiber_main); if (fiber == NULL) return NULL; @@ -61,15 +69,12 @@ void *__tf_fiber_create(tf_fiber_proc fiber_main, int private_size) return fiber->data; } -void *tf_fiber_create( - struct tf_scheduler *sched, - tf_fiber_proc fiber_main, int private_size) +void *tf_fiber_create(tf_fiber_proc fiber_main, int private_size) { struct tf_fiber *fiber; + struct tf_scheduler *sched; - if (sched == NULL) - sched = tf_scheduler_get_current(); - + sched = tf_scheduler_get_current(); if (tf_heap_prealloc(&sched->heap, sched->num_fibers + 1) < 0) return NULL; @@ -94,15 +99,19 @@ void *tf_fiber_get(void *data) static void __tf_fiber_destroy(struct tf_fiber *fiber) { struct tf_scheduler *sched = fiber->scheduler; - int main_fiber; + int main_fiber, num_fibers; + + /* decrease first the number of fibers as we might be + * killing the scheduler it self */ + num_fibers = --sched->num_fibers; main_fiber = (fiber->context.alloc == NULL); tf_heap_delete(&fiber->heap_node, &sched->heap); tf_uctx_destroy(&fiber->context); if (main_fiber) free(fiber); - sched->num_fibers--; - if (sched->num_fibers == 1) { + + if (num_fibers == 1) { /* FIXME: Use proper fiber event*/ __tf_fiber_wakeup(sched->main_fiber, TF_WAKEUP_IMMEDIATE); } @@ -132,28 +141,10 @@ void __tf_fiber_wakeup_heapnode(struct tf_heap_node *node) TF_WAKEUP_TIMEOUT); } -static void __tf_fiber_schedule_next(void) -{ - struct tf_scheduler *sched = tf_scheduler_get_current(); - struct tf_fiber *f = tf_fiber_get_current(); - struct tf_fiber *nf; - - /* Figure out the next fibre to run */ - if (unlikely(tf_list_empty(&sched->scheduled_q))) { - tf_list_splice_tail(&sched->running_q, - &sched->scheduled_q); - TF_BUG_ON(tf_list_empty(&sched->scheduled_q)); - } - nf = tf_list_entry(tf_list_pop(&sched->scheduled_q), - struct tf_fiber, queue_node); - sched->active_fiber = nf->data; - tf_uctx_transfer(&f->context, &nf->context); -} - int __tf_fiber_schedule(void) { struct tf_scheduler *sched = tf_scheduler_get_current(); - struct tf_fiber *f = tf_fiber_get_current(); + struct tf_fiber *f = tf_fiber_get_current(), *nf; int wakeup; if (unlikely(f->timeout_change)) { @@ -168,7 +159,16 @@ int __tf_fiber_schedule(void) f->timeout_change = 0; } - __tf_fiber_schedule_next(); + /* Figure out the next fibre to run */ + if (unlikely(tf_list_empty(&sched->scheduled_q))) { + tf_list_splice_tail(&sched->running_q, + &sched->scheduled_q); + TF_BUG_ON(tf_list_empty(&sched->scheduled_q)); + } + nf = tf_list_entry(tf_list_pop(&sched->scheduled_q), + struct tf_fiber, queue_node); + sched->active_fiber = nf->data; + tf_uctx_transfer(&f->context, &nf->context); wakeup = f->wakeup_type; f->wakeup_type = TF_WAKEUP_NONE; diff --git a/src/uctx.h b/src/uctx.h index e27a53c..5eca6be 100644 --- a/src/uctx.h +++ b/src/uctx.h @@ -37,15 +37,15 @@ struct tf_uctx { do { \ unsigned eax, ebx, ecx, edx, esi, edi; \ __asm__ __volatile__ ( \ - "push %%ebp \n" \ "call 1f \n" \ "1: \n" \ "addl $2f-1b, (%%esp) \n" \ + "push %%ebp \n" \ "movl %%esp, %[prev_sp] \n" \ "movl %[next_sp], %%esp \n" \ + "pop %%ebp \n" \ "ret \n" \ "2: \n" \ - "pop %%ebp \n" \ : [prev_sp] "=m"(prev->current_sp), \ "=a"(eax), "=b"(ebx), "=c"(ecx), \ "=d"(edx), "=S"(esi), "=D"(edi) \ @@ -101,8 +101,8 @@ tf_uctx_create_embedded( size_t stack_size, size_t private_size, off_t uctx_offset, - void (*stack_frame_main)(void*), off_t main_argument_offset, - void (*stack_frame_return)(void)) + void (*stack_frame_main)(void*, void*), + void *main_argument) { size_t size = TF_STACK_SIZE; void *user_data; @@ -117,20 +117,18 @@ tf_uctx_create_embedded( /* Create initial stack frame (cdecl convention) */ stack = stack_pointer(stack_base, size); user_data = stack_push(&stack, TF_ALIGN(private_size, 64)); + stack_push_ptr(&stack, main_argument); + stack_push_ptr(&stack, user_data); stack_push_ptr(&stack, NULL); - stack_push_ptr(&stack, NULL); - stack_push_ptr(&stack, NULL); - stack_push_ptr(&stack, NULL); - stack_push_ptr(&stack, user_data + main_argument_offset); - stack_push_ptr(&stack, stack_frame_return); - stack_push_ptr(&stack, stack_frame_main); + stack_push_ptr(&stack, stack_frame_main); /* eip */ + stack_push_ptr(&stack, NULL); /* ebp */ uctx = user_data + uctx_offset; *uctx = (struct tf_uctx) { .stack_guard = stack_guard(stack_base, size), .alloc = stack_base, .current_sp = stack, - .stack_id = VALGRIND_STACK_REGISTER(stack_base, size), + .stack_id = VALGRIND_STACK_REGISTER(stack_base, stack_base+size), }; *uctx->stack_guard = STACK_GUARD; diff --git a/test/httpget.c b/test/httpget.c index 9aec886..29f7f14 100644 --- a/test/httpget.c +++ b/test/httpget.c @@ -51,7 +51,7 @@ int main(int argc, char **argv) tf_scheduler_enable(NULL); for (i = 1; i < argc; i++) { - c = tf_fiber_create(NULL, ping_fiber, sizeof(struct ctx)); + c = tf_fiber_create(ping_fiber, sizeof(struct ctx)); c->hostname = argv[i]; tf_fiber_put(c); } diff --git a/test/read.c b/test/read.c index 3d318a3..0dc72cc 100644 --- a/test/read.c +++ b/test/read.c @@ -35,7 +35,7 @@ static void io_fiber(void *ptr) int main(int argc, char **argv) { tf_scheduler_enable(NULL); - tf_fiber_put(tf_fiber_create(NULL, time_fiber, 0)); - tf_fiber_put(tf_fiber_create(NULL, io_fiber, 0)); + tf_fiber_put(tf_fiber_create(time_fiber, 0)); + tf_fiber_put(tf_fiber_create(io_fiber, 0)); tf_scheduler_disable(); } diff --git a/test/simple1.c b/test/simple1.c index 6a05b7a..6f40f8d 100644 --- a/test/simple1.c +++ b/test/simple1.c @@ -21,7 +21,7 @@ int main(int argc, char **argv) tf_scheduler_enable(NULL); for (i = 0; i < 6; i++) { - c = tf_fiber_create(NULL, work_fiber, sizeof(struct ctx)); + c = tf_fiber_create(work_fiber, sizeof(struct ctx)); c->id = i; tf_fiber_put(c); } diff --git a/test/sleep.c b/test/sleep.c index 82399e1..ec21a76 100644 --- a/test/sleep.c +++ b/test/sleep.c @@ -23,7 +23,7 @@ int main(int argc, char **argv) tf_scheduler_enable(NULL); for (i = 0; i < 100; i++) { - c = tf_fiber_create(NULL, work_fiber, sizeof(struct ctx)); + c = tf_fiber_create(work_fiber, sizeof(struct ctx)); tf_fiber_put(c); } tf_scheduler_disable(); -- cgit v1.2.3