From 5ef38570315dc68d7ddf8d9475d9a8830528e8a4 Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Wed, 10 Mar 2010 13:58:39 +0200 Subject: libtf: separate scheduler fibre, change the core api --- include/libtf/defines.h | 1 + include/libtf/fiber.h | 82 ++++++++++++----------------------------------- include/libtf/heap.h | 10 ++++++ include/libtf/io.h | 4 +-- include/libtf/list.h | 33 ++++++++++++++++++- include/libtf/scheduler.h | 64 ++++++++++++++++++++++++++++++++++++ include/libtf/tf.h | 1 + 7 files changed, 129 insertions(+), 66 deletions(-) create mode 100644 include/libtf/scheduler.h (limited to 'include/libtf') diff --git a/include/libtf/defines.h b/include/libtf/defines.h index ae72980..8e39c7e 100644 --- a/include/libtf/defines.h +++ b/include/libtf/defines.h @@ -62,6 +62,7 @@ __FILE__, __LINE__, __func__, #cond); \ abort(); \ } +#define TF_BUILD_BUG_ON(cond) ((void) sizeof(struct { char TF_BUILD_BUG_ON[-!!(cond)]; })) #define TF_ALIGN(size,align) ((((size_t)(size)) + (align)-1) & ~((align)-1)) diff --git a/include/libtf/fiber.h b/include/libtf/fiber.h index ce3745b..a140607 100644 --- a/include/libtf/fiber.h +++ b/include/libtf/fiber.h @@ -1,6 +1,6 @@ -/* fiber.h - libtf fiber scheduler header +/* fiber.h - libtf fiber manager header * - * Copyright (C) 2009 Timo Teräs + * Copyright (C) 2009-2010 Timo Teräs * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -15,8 +15,6 @@ #include #include -#include -#include #include /* Fiber wakeup reasons */ @@ -27,64 +25,31 @@ #define TF_WAKEUP_THIS_TIMEOUT -ETIMEDOUT #define TF_WAKEUP_FD -EIO -struct tf_poll_data { - int epoll_fd; - int num_waiters; -}; - -/* Scheduler */ -struct tf_fiber; +/* Fiber management */ +struct tf_scheduler; +typedef void (*tf_fiber_proc)(void *fiber); -struct tf_scheduler { - struct tf_list_head run_q; - struct tf_heap_head heap; - struct tf_fiber * active_fiber; - int num_fibers; - tf_mtime_t scheduler_time; - struct tf_poll_data poll_data; -}; +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_get(void *data); +void tf_fiber_put(void *data); +void __tf_fiber_wakeup(void *data, int wakeup_type); +void __tf_fiber_wakeup_heapnode(struct tf_heap_node *node); +int __tf_fiber_schedule(void); +int __tf_fiber_bind_scheduler(struct tf_scheduler *sched); +int __tf_fiber_release_scheduler(struct tf_scheduler *sched); -struct tf_main_ctx { - int argc; - char ** argv; -}; +void tf_fiber_exit(void) attribute_noreturn; +void tf_fiber_kill(void *fiber); +int tf_fiber_yield(void); +/* Scheduling and fiber management */ struct tf_timeout { tf_mtime_t saved_timeout; unsigned int timeout_change; }; -static inline -struct tf_scheduler *tf_get_scheduler(void) -{ - extern struct tf_scheduler *__tf_scheduler; - return __tf_scheduler; -} - -static inline -struct tf_fiber *tf_get_fiber(void) -{ - return tf_get_scheduler()->active_fiber; -} - -static inline -tf_mtime_t tf_mtime(void) -{ - return tf_get_scheduler()->scheduler_time; -} - -/* Fiber creation */ -typedef void (*tf_fiber_proc)(void *fiber); -int tf_main_args(tf_fiber_proc fiber_main, int argc, char **argv); -static inline int tf_main(tf_fiber_proc fiber_main) -{ - return tf_main_args(fiber_main, 0, NULL); -} - -void *tf_fiber_create(tf_fiber_proc fiber_main, int private_size); -void *tf_fiber_get(void *data); -void tf_fiber_put(void *data); - #define tf_timed(func, timeout) \ ({ \ struct tf_timeout __timeout; \ @@ -92,7 +57,6 @@ void tf_fiber_put(void *data); tf_timeout_pop(&__timeout, (func)); \ }) -//* Scheduling and fiber management */ void tf_timeout_push(struct tf_timeout *timeout, tf_mtime_diff_t milliseconds); int __tf_timeout_pop(struct tf_timeout *timeout, int err); @@ -103,17 +67,11 @@ static inline int tf_timeout_pop(struct tf_timeout *timeout, int err) return err; } -int tf_schedule(void); -void tf_wakeup(struct tf_fiber *fiber, int wakeup_type); -void tf_exit(void) attribute_noreturn; -void tf_kill(void *fiber); -int tf_yield(void); - static inline int tf_msleep(tf_mtime_diff_t milliseconds) { int r; - r = tf_timed(tf_schedule(), milliseconds); + r = tf_timed(__tf_fiber_schedule(), milliseconds); if (r == TF_WAKEUP_THIS_TIMEOUT) r = 0; return r; diff --git a/include/libtf/heap.h b/include/libtf/heap.h index a68e01d..3a16159 100644 --- a/include/libtf/heap.h +++ b/include/libtf/heap.h @@ -74,4 +74,14 @@ int tf_heap_prealloc(struct tf_heap_head *head, uint32_t size) return 0; } +static inline +void tf_heap_destroy(struct tf_heap_head *head) +{ + if (head->item) + free(head->item); + head->item = NULL; + head->num_items = 0; + head->allocated = 0; +} + #endif diff --git a/include/libtf/io.h b/include/libtf/io.h index 1f0b793..1f37d81 100644 --- a/include/libtf/io.h +++ b/include/libtf/io.h @@ -26,8 +26,6 @@ #define TF_FD_SET_CLOEXEC 4 #define TF_FD_ALREADY_NONBLOCKING 8 -struct tf_fiber; - struct tf_sockaddr { union { struct sockaddr addr; @@ -42,7 +40,7 @@ struct tf_fd { /* Single waiter -- would be relatively trivial to modify to allow * multiple waiters, if someone actually needs it */ unsigned int events; - struct tf_fiber *waiting_fiber; + void *waiting_fiber; }; void tf_poll_init(void); diff --git a/include/libtf/list.h b/include/libtf/list.h index 22b76a8..f75a0be 100644 --- a/include/libtf/list.h +++ b/include/libtf/list.h @@ -142,7 +142,7 @@ static inline void tf_list_add_tail(struct tf_list_node *new, struct tf_list_hea tf_list_add_before(new, &head->node); } -static inline void __tf_list_del(struct tf_list_node * prev, struct tf_list_node *next) +static inline void __tf_list_del(struct tf_list_node *prev, struct tf_list_node *next) { next->prev = prev; prev->next = next; @@ -155,6 +155,14 @@ static inline void tf_list_del(struct tf_list_node *entry) entry->prev = NULL; } +static inline struct tf_list_node *tf_list_pop(struct tf_list_head *head) +{ + struct tf_list_node *n; + n = head->node.next; + tf_list_del(n); + return n; +} + static inline int tf_list_hashed(const struct tf_list_node *n) { return n->next != n && n->next != NULL; @@ -165,6 +173,29 @@ static inline int tf_list_empty(const struct tf_list_head *h) return !tf_list_hashed(&h->node); } +static inline void __tf_list_splice(const struct tf_list_head *list, + struct tf_list_node *prev, + struct tf_list_node *next) +{ + struct tf_list_node *first = list->node.next; + struct tf_list_node *last = list->node.prev; + + first->prev = prev; + prev->next = first; + + last->next = next; + next->prev = last; +} + +static inline void tf_list_splice_tail(struct tf_list_head *src, + struct tf_list_head *dst) +{ + if (!tf_list_empty(src)) { + __tf_list_splice(src, dst->node.prev, &dst->node); + tf_list_init_head(src); + } +} + #define tf_list_next(ptr, type, member) \ (tf_list_hashed(ptr) ? container_of((ptr)->next,type,member) : NULL) diff --git a/include/libtf/scheduler.h b/include/libtf/scheduler.h new file mode 100644 index 0000000..cc8db70 --- /dev/null +++ b/include/libtf/scheduler.h @@ -0,0 +1,64 @@ +/* scheduler.h - libtf fiber scheduler header + * + * Copyright (C) 2009-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. + */ + +#ifndef TF_SCHEDULER_H +#define TF_SCHEDULER_H + +#include +#include +#include +#include + +struct tf_scheduler { + struct tf_list_head scheduled_q; + struct tf_list_head running_q; + struct tf_heap_head heap; + void * active_fiber; + void * main_fiber; + int num_fibers; + tf_mtime_t scheduler_time; + unsigned long poll_data[2]; +}; + +static inline +struct tf_scheduler *tf_scheduler_get_current(void) +{ + extern struct tf_scheduler *__tf_scheduler; + TF_BUG_ON(__tf_scheduler == NULL); + return __tf_scheduler; +} + +static inline +tf_mtime_t tf_scheduler_get_mtime(void) +{ + return tf_scheduler_get_current()->scheduler_time; +} + +struct tf_scheduler *tf_scheduler_create(void); +int tf_scheduler_enable(struct tf_scheduler *); +void tf_scheduler_disable(void); + +static inline struct tf_scheduler * +tf_scheduler_get(struct tf_scheduler *s) +{ + tf_fiber_get(s); + return s; +} + +static inline void +tf_scheduler_put(struct tf_scheduler *s) +{ + tf_fiber_put(s); +} + +#endif + diff --git a/include/libtf/tf.h b/include/libtf/tf.h index 7a089ff..e613f18 100644 --- a/include/libtf/tf.h +++ b/include/libtf/tf.h @@ -14,6 +14,7 @@ #define TF_H #include +#include #include #endif -- cgit v1.2.3