summaryrefslogtreecommitdiffstats
path: root/include/libtf/fiber.h
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2009-11-26 09:35:49 +0200
committerTimo Teras <timo.teras@iki.fi>2009-11-26 09:37:24 +0200
commitaa530f352b0410150bfe94c821ae32c1378b9d02 (patch)
treefb27f277db0c7feaaf12ce43169d3b0b44e95c0f /include/libtf/fiber.h
parent4db830052d941d9c6de281bc9a2f6ac212c59ad8 (diff)
downloadlibtf-aa530f352b0410150bfe94c821ae32c1378b9d02.tar.bz2
libtf-aa530f352b0410150bfe94c821ae32c1378b9d02.tar.xz
libtf: stackable timeouts
instead of having per-function argument, use a push/pop mechanism: - multiple timers inside fiber use only one heap entry - easy to chain multiple possibly blocking operations inside one timeout block
Diffstat (limited to 'include/libtf/fiber.h')
-rw-r--r--include/libtf/fiber.h55
1 files changed, 37 insertions, 18 deletions
diff --git a/include/libtf/fiber.h b/include/libtf/fiber.h
index c3d87c6..ce3745b 100644
--- a/include/libtf/fiber.h
+++ b/include/libtf/fiber.h
@@ -19,27 +19,22 @@
#include <libtf/list.h>
#include <libtf/heap.h>
-#define TF_UCTX_H "uctx-setjmp.h"
-
/* Fiber wakeup reasons */
#define TF_WAKEUP_NONE 0
#define TF_WAKEUP_IMMEDIATE -EAGAIN
#define TF_WAKEUP_KILL -EINTR
-#define TF_WAKEUP_TIMEOUT -ETIMEDOUT
+#define TF_WAKEUP_TIMEOUT -ETIME
+#define TF_WAKEUP_THIS_TIMEOUT -ETIMEDOUT
#define TF_WAKEUP_FD -EIO
-/* Special timeouts for tf_schedule() */
-#define TF_NO_TIMEOUT -1
-#define TF_NO_TIMEOUT_CHANGE -2
+struct tf_poll_data {
+ int epoll_fd;
+ int num_waiters;
+};
/* Scheduler */
struct tf_fiber;
-struct tf_poll_data {
- int epoll_fd;
- int num_waiters;
-};
-
struct tf_scheduler {
struct tf_list_head run_q;
struct tf_heap_head heap;
@@ -47,7 +42,6 @@ struct tf_scheduler {
int num_fibers;
tf_mtime_t scheduler_time;
struct tf_poll_data poll_data;
-
};
struct tf_main_ctx {
@@ -55,6 +49,11 @@ struct tf_main_ctx {
char ** argv;
};
+struct tf_timeout {
+ tf_mtime_t saved_timeout;
+ unsigned int timeout_change;
+};
+
static inline
struct tf_scheduler *tf_get_scheduler(void)
{
@@ -86,18 +85,38 @@ void *tf_fiber_create(tf_fiber_proc fiber_main, int private_size);
void *tf_fiber_get(void *data);
void tf_fiber_put(void *data);
-/* Scheduling and fiber management */
-void tf_exit(void) attribute_noreturn;
-void tf_kill(void *fiber);
+#define tf_timed(func, timeout) \
+ ({ \
+ struct tf_timeout __timeout; \
+ tf_timeout_push(&__timeout, timeout); \
+ 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);
+
+static inline int tf_timeout_pop(struct tf_timeout *timeout, int err)
+{
+ if (unlikely(timeout->timeout_change))
+ return __tf_timeout_pop(timeout, err);
+ return err;
+}
-int tf_schedule(int milliseconds);
+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(int milliseconds)
+int tf_msleep(tf_mtime_diff_t milliseconds)
{
- return tf_schedule(milliseconds);
+ int r;
+ r = tf_timed(tf_schedule(), milliseconds);
+ if (r == TF_WAKEUP_THIS_TIMEOUT)
+ r = 0;
+ return r;
}
#endif