summaryrefslogtreecommitdiffstats
path: root/include
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
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')
-rw-r--r--include/libtf/fiber.h55
-rw-r--r--include/libtf/heap.h6
-rw-r--r--include/libtf/io.h19
3 files changed, 52 insertions, 28 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
diff --git a/include/libtf/heap.h b/include/libtf/heap.h
index 24f4767..a68e01d 100644
--- a/include/libtf/heap.h
+++ b/include/libtf/heap.h
@@ -61,6 +61,12 @@ int tf_heap_empty(struct tf_heap_head *head)
}
static inline
+int tf_heap_node_active(struct tf_heap_node *node)
+{
+ return node->index != 0;
+}
+
+static inline
int tf_heap_prealloc(struct tf_heap_head *head, uint32_t size)
{
if (unlikely(head->num_items + TF_HEAP_ITEM0 >= head->allocated))
diff --git a/include/libtf/io.h b/include/libtf/io.h
index 38dd541..1f0b793 100644
--- a/include/libtf/io.h
+++ b/include/libtf/io.h
@@ -52,27 +52,26 @@ void tf_poll_close(void);
int tf_open_fd(struct tf_fd *fd, int kfd, int flags);
int tf_open(struct tf_fd *fd, const char *pathname, int flags);
int tf_close(struct tf_fd *fd);
-ssize_t tf_read(struct tf_fd *fd, void *buf, size_t count, tf_mtime_diff_t timeout);
-ssize_t tf_write(struct tf_fd *fd, const void *buf, size_t count, tf_mtime_diff_t timeout);
-int tf_read_fully(struct tf_fd *fd, void *buf, size_t count, tf_mtime_diff_t timeout);
-int tf_write_fully(struct tf_fd *fd, const void *buf, size_t count, tf_mtime_diff_t timeout);
+ssize_t tf_read(struct tf_fd *fd, void *buf, size_t count);
+ssize_t tf_write(struct tf_fd *fd, const void *buf, size_t count);
+int tf_read_fully(struct tf_fd *fd, void *buf, size_t count);
+int tf_write_fully(struct tf_fd *fd, const void *buf, size_t count);
int tf_socket(struct tf_fd *fd, int domain, int type, int protocol);
int tf_bind(struct tf_fd *fd, const struct tf_sockaddr *addr);
int tf_listen(struct tf_fd *fd, int backlog);
int tf_accept(struct tf_fd *listen_fd, struct tf_fd *child_fd,
- struct tf_sockaddr *from, tf_mtime_diff_t timeout);
-int tf_connect(struct tf_fd *fd, const struct tf_sockaddr *addr, tf_mtime_diff_t timeout);
+ struct tf_sockaddr *from);
+int tf_connect(struct tf_fd *fd, const struct tf_sockaddr *addr);
ssize_t tf_recvmsg(struct tf_fd *fd,
struct tf_sockaddr *from, struct tf_sockaddr *to,
- void *buf, size_t count, tf_mtime_diff_t timeout);
+ void *buf, size_t count);
ssize_t tf_sendmsg(struct tf_fd *fd,
struct tf_sockaddr *from, const struct tf_sockaddr *to,
- const void *buf, size_t count, tf_mtime_diff_t timeout);
+ const void *buf, size_t count);
-int tf_query_dns(const char *name, int num_res, struct tf_sockaddr *res,
- tf_mtime_diff_t timeout);
+int tf_query_dns(const char *name, int num_res, struct tf_sockaddr *res);
#endif