summaryrefslogtreecommitdiffstats
path: root/include/libtf/fiber.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/libtf/fiber.h')
-rw-r--r--include/libtf/fiber.h141
1 files changed, 102 insertions, 39 deletions
diff --git a/include/libtf/fiber.h b/include/libtf/fiber.h
index d5c6153..f97e963 100644
--- a/include/libtf/fiber.h
+++ b/include/libtf/fiber.h
@@ -16,64 +16,127 @@
#include <errno.h>
#include <libtf/defines.h>
#include <libtf/heap.h>
+#include <libtf/list.h>
-/* Fiber wakeup reasons */
-#define TF_WAKEUP_NONE 0
-#define TF_WAKEUP_IMMEDIATE -EAGAIN
-#define TF_WAKEUP_KILL -EINTR
-#define TF_WAKEUP_TIMEOUT -ETIME
-#define TF_WAKEUP_THIS_TIMEOUT -ETIMEDOUT
-#define TF_WAKEUP_FD -EIO
+/* Inter-fibre calls */
+struct tf_fiber;
+struct tf_ifc;
+typedef void (*tf_ifc_handler_t)(void *fiber, struct tf_ifc *msg);
-/* Fiber management */
-struct tf_scheduler;
-typedef void (*tf_fiber_proc)(void *fiber);
+struct tf_ifc {
+ union {
+ struct tf_ifc *next;
+ struct tf_list_node list;
+ };
+ tf_ifc_handler_t handler;
+ struct tf_fiber * sender;
+};
-void *__tf_fiber_create(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);
-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);
+void tf_ifc_queue(void *fiber, struct tf_ifc *msg, tf_ifc_handler_t handler);
+void tf_ifc_complete(void *fiber, struct tf_ifc *msg, tf_ifc_handler_t handler);
+void tf_ifc_process(void);
+void tf_ifc_process_unordered(void);
-void tf_fiber_exit(void) attribute_noreturn;
-void tf_fiber_kill(void *fiber);
-int tf_fiber_yield(void);
+/* Timeouts */
+struct tf_timeout_manager {
+ struct tf_heap_head heap;
+ unsigned int num_fibers;
+};
+
+struct tf_timeout_client {
+ struct tf_timeout_manager * manager;
+ tf_mtime_t value;
+ tf_mtime_t latched;
+ struct tf_heap_node heap_node;
+ struct tf_ifc ifc;
+};
-/* Scheduling and fiber management */
struct tf_timeout {
- tf_mtime_t saved_timeout;
- unsigned int timeout_change;
+ tf_mtime_t saved_timeout;
+ tf_mtime_t my_timeout;
};
-#define tf_timed(func, timeout) \
+static inline int tf_timeout_expired(struct tf_timeout *to)
+{
+ return tf_mtime_diff(to->my_timeout, tf_mtime_now()) <= 0;
+}
+
+struct tf_timeout_fiber *tf_timeout_fiber_create(void);
+void tf_timeout_adjust(struct tf_timeout_client *tc);
+void tf_timeout_delete(struct tf_timeout_client *tc);
+
+#define tf_timed(__to, func, timeout) \
({ \
- struct tf_timeout __timeout; \
- tf_timeout_push(&__timeout, timeout); \
- tf_timeout_pop(&__timeout, (func)); \
+ tf_timeout_push(__to, timeout); \
+ tf_timeout_pop(__to, (func)); \
})
-void tf_timeout_push(struct tf_timeout *timeout, tf_mtime_diff_t milliseconds);
-int __tf_timeout_pop(struct tf_timeout *timeout, int err);
+/* Fibres and their management */
+typedef void *tf_uctx_t;
+
+struct tf_fiber {
+ unsigned int ref_count;
+ unsigned int flags;
+ tf_uctx_t context;
+ tf_uctx_t return_context;
+ struct tf_list_node queue_node;
+ struct tf_list_head wakeup_q;
+ struct tf_timeout_client timeout;
+ struct tf_ifc * pending_ifc;
+ char data[TF_EMPTY_ARRAY];
+};
+
+typedef void (*tf_fiber_proc)(void *fiber);
+
+void *__tf_fiber_create(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 *fiber);
+void tf_fiber_put(void *fiber);
+int tf_fiber_run(void *fiber);
+void tf_fiber_kill(void *fiber);
+
+void tf_fiber_wakeup(struct tf_fiber *fiber);
+int tf_fiber_schedule(void);
-static inline int tf_timeout_pop(struct tf_timeout *timeout, int err)
+void tf_fiber_exit(void) attribute_noreturn;
+
+static inline struct tf_fiber *tf_vmach_get_current_fiber(void)
{
- if (unlikely(timeout->timeout_change))
- return __tf_timeout_pop(timeout, err);
+ extern __thread struct tf_fiber *tf_current_fiber;
+ return tf_current_fiber;
+}
+
+static inline void tf_timeout_push(struct tf_timeout *to, tf_mtime_diff_t ms)
+{
+ struct tf_fiber *f = tf_vmach_get_current_fiber();
+
+ to->saved_timeout = f->timeout.value;
+ to->my_timeout = tf_mtime_now() + ms;
+ if (f->timeout.value == 0 ||
+ tf_mtime_diff(to->my_timeout, f->timeout.value) < 0)
+ f->timeout.value = to->my_timeout;
+}
+
+static inline int tf_timeout_pop(struct tf_timeout *to, int err)
+{
+ struct tf_fiber *f = tf_vmach_get_current_fiber();
+
+ f->timeout.value = to->saved_timeout;
return err;
}
static inline
-int tf_msleep(tf_mtime_diff_t milliseconds)
+int tf_msleep(tf_mtime_diff_t ms)
{
+ struct tf_timeout to;
int r;
- r = tf_timed(__tf_fiber_schedule(), milliseconds);
- if (r == TF_WAKEUP_THIS_TIMEOUT)
- r = 0;
- return r;
+
+ tf_timeout_push(&to, ms);
+ do {
+ r = tf_fiber_schedule();
+ } while (r != -ETIME);
+
+ return tf_timeout_pop(&to, r);
}
#endif