feat: publish Android 1.0.1 candidate source and acceptance evidence

This commit is contained in:
UCVL Software Automation
2026-09-03 11:07:02 +08:00
commit 0a8bdc9fff
971 changed files with 184984 additions and 0 deletions
@@ -0,0 +1,94 @@
/*
============================================================================
Name : hev-task-aide.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2022 - 2024 everyone.
Description : Aide
============================================================================
*/
#include <poll.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include "kern/task/hev-task-private.h"
#include "kern/io/hev-task-io-reactor.h"
#include "lib/io/basic/hev-task-io.h"
#include "hev-task-aide.h"
static pthread_t thread;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static HevTaskIOReactor *reactor;
static void *
hev_task_aide_entry (void *data)
{
for (;;) {
HevTaskIOReactorWaitEvent events[256];
int i, count;
count = hev_task_io_reactor_wait (reactor, events, 256, -1);
for (i = 0; i < count; i++) {
HevTaskAideWork *work;
unsigned int revents;
work = hev_task_io_reactor_wait_event_get_data (&events[i]);
revents = hev_task_io_reactor_wait_event_get_events (&events[i]);
work->handler (revents, work->data);
}
}
return NULL;
}
int
hev_task_aide_init (void)
{
int res = 0;
if (reactor)
return 0;
pthread_mutex_lock (&mutex);
if (!reactor) {
reactor = hev_task_io_reactor_new ();
if (!reactor) {
res = -1;
} else {
res = pthread_create (&thread, NULL, hev_task_aide_entry, NULL);
if (res != 0)
res = -1;
}
}
pthread_mutex_unlock (&mutex);
return res;
}
int
hev_task_aide_add (HevTaskAideWork *work)
{
HevTaskIOReactorSetupEvent revents[HEV_TASK_IO_REACTOR_EVENT_GEN_MAX];
int count;
count = hev_task_io_reactor_setup_event_fd_gen (
revents, work->fd, HEV_TASK_IO_REACTOR_OP_ADD, work->events, work);
return hev_task_io_reactor_setup (reactor, revents, count);
}
int
hev_task_aide_del (HevTaskAideWork *work)
{
HevTaskIOReactorSetupEvent revents[HEV_TASK_IO_REACTOR_EVENT_GEN_MAX];
int count;
count = hev_task_io_reactor_setup_event_fd_gen (
revents, work->fd, HEV_TASK_IO_REACTOR_OP_DEL, 0, NULL);
return hev_task_io_reactor_setup (reactor, revents, count);
}
@@ -0,0 +1,29 @@
/*
============================================================================
Name : hev-task-aide.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2022 everyone.
Description : Aide
============================================================================
*/
#ifndef __HEV_TASK_AIDE_H__
#define __HEV_TASK_AIDE_H__
typedef struct _HevTaskAideWork HevTaskAideWork;
typedef void (*HevTaskAideWorkHandler) (unsigned int revents, void *data);
struct _HevTaskAideWork
{
int fd;
unsigned int events;
HevTaskAideWorkHandler handler;
void *data;
};
int hev_task_aide_init (void);
int hev_task_aide_add (HevTaskAideWork *work);
int hev_task_aide_del (HevTaskAideWork *work);
#endif /* __HEV_TASK_AIDE_H__ */
@@ -0,0 +1,69 @@
/*
============================================================================
Name : hev-task-system-private.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2017 - 2025 everyone.
Description :
============================================================================
*/
#ifndef __HEV_TASK_SYSTEM_PRIVATE_H__
#define __HEV_TASK_SYSTEM_PRIVATE_H__
#include <time.h>
#include <setjmp.h>
#include "hev-task-system.h"
#include "kern/task/hev-task.h"
#include "kern/task/hev-task-private.h"
#include "kern/time/hev-task-timer.h"
#include "kern/io/hev-task-io-reactor.h"
#include "lib/list/hev-list.h"
#include "lib/dns/hev-task-dns-proxy.h"
#include "lib/rbtree/hev-rbtree-cached.h"
#include "lib/misc/hev-task-stack-detector.h"
#define CLOCK_NONE (-1)
#define HEV_TASK_RUN_SCHEDULER HEV_TASK_YIELD_COUNT
#define PRIORITY_COUNT (HEV_TASK_PRIORITY_MAX - HEV_TASK_PRIORITY_MIN + 1)
typedef struct _HevTaskSystemContext HevTaskSystemContext;
enum
{
HEV_TASK_SCHED_SWITCH = HEV_TASK_YIELD,
HEV_TASK_SCHED_WAITIO = HEV_TASK_WAITIO,
HEV_TASK_SCHED_REMOVE = HEV_TASK_YIELD_COUNT,
};
struct _HevTaskSystemContext
{
unsigned int total_task_count;
unsigned int running_task_count;
HevTaskTimer *timer;
HevTaskIOReactor *reactor;
HevTaskDNSProxy *dns_proxy;
HevTaskStackDetector *stack_detector;
HevTask *current_task;
HevRBTreeCached running_tasks;
struct timespec sched_time;
jmp_buf kernel_context;
HevList all_tasks;
};
void hev_task_system_schedule (HevTaskYieldType type);
void hev_task_system_wakeup_task (HevTask *task);
void hev_task_system_run_new_task (HevTask *task);
void hev_task_system_kill_current_task (void);
void hev_task_system_wakeup_task_with_context (HevTaskSystemContext *ctx,
HevTask *task);
HevTaskSystemContext *hev_task_system_get_context (void);
#endif /* __HEV_TASK_SYSTEM_PRIVATE_H__ */
@@ -0,0 +1,281 @@
/*
============================================================================
Name : hev-task-system-schedule.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2017 - 2025 everyone.
Description :
============================================================================
*/
/* Disable signal stack check in longjmp */
#ifdef _FORTIFY_SOURCE
#undef _FORTIFY_SOURCE
#endif
#include <stdlib.h>
#include "hev-task-system.h"
#include "hev-task-system-private.h"
#include "kern/task/hev-task-private.h"
#include "kern/task/hev-task-executer.h"
#include "kern/io/hev-task-io-reactor.h"
#include "lib/misc/hev-compiler.h"
static inline void
hev_task_system_get_clock_time (struct timespec *ts)
{
#if CONFIG_SCHED_CLOCK != CLOCK_NONE
if (-1 == clock_gettime (CONFIG_SCHED_CLOCK, ts))
abort ();
#endif
}
static inline void
hev_task_system_update_sched_key (HevTaskSystemContext *ctx)
{
HevTask *curr_task = ctx->current_task;
uint64_t runtime = 1;
#if CONFIG_SCHED_CLOCK != CLOCK_NONE
struct timespec curr_time;
time_t sec;
long nsec;
hev_task_system_get_clock_time (&curr_time);
sec = curr_time.tv_sec - ctx->sched_time.tv_sec;
nsec = curr_time.tv_nsec - ctx->sched_time.tv_nsec;
if (nsec < 0) {
sec--;
nsec += 1000000000L;
}
runtime += (uint64_t)sec * 1000000000UL + nsec;
#endif
curr_task->sched_key += runtime * curr_task->priority;
}
static inline void
hev_task_system_update_sched_time (HevTaskSystemContext *ctx)
{
hev_task_system_get_clock_time (&ctx->sched_time);
}
static inline uint64_t
hev_task_system_get_min_sched_key (HevTaskSystemContext *ctx)
{
HevRBTreeNode *sched_node;
sched_node = hev_rbtree_cached_first (&ctx->running_tasks);
if (sched_node) {
HevTask *task = container_of (sched_node, HevTask, sched_node);
return task->sched_key;
}
return 0;
}
static inline void
_hev_task_system_insert_task (HevRBTreeCached *tree, HevTask *task)
{
HevRBTreeNode **new = &tree->base.root, *parent = NULL;
int leftmost = 1;
while (*new) {
HevTask *this = container_of (*new, HevTask, sched_node);
parent = *new;
if (task->sched_key < this->sched_key) {
new = &((*new)->left);
} else {
new = &((*new)->right);
leftmost = 0;
}
}
hev_rbtree_node_link (&task->sched_node, parent, new);
hev_rbtree_cached_insert_color (tree, &task->sched_node, leftmost);
}
static inline void
hev_task_system_insert_task (HevTaskSystemContext *ctx, HevTask *task)
{
task->state = HEV_TASK_RUNNING;
task->priority = task->next_priority;
_hev_task_system_insert_task (&ctx->running_tasks, task);
ctx->running_task_count++;
}
static inline void
hev_task_system_reinsert_current_task (HevTaskSystemContext *ctx)
{
HevTask *task = ctx->current_task;
task->priority = task->next_priority;
hev_rbtree_cached_erase (&ctx->running_tasks, &task->sched_node);
_hev_task_system_insert_task (&ctx->running_tasks, task);
}
static inline void
hev_task_system_remove_current_task (HevTaskSystemContext *ctx,
HevTaskState state)
{
HevTask *task = ctx->current_task;
task->state = state;
hev_rbtree_cached_erase (&ctx->running_tasks, &task->sched_node);
ctx->running_task_count--;
if (HEV_TASK_STOPPED == state) {
ctx->total_task_count--;
hev_task_unref (task);
} else {
task->sched_key = task->next_priority;
}
}
void
hev_task_system_wakeup_task_with_context (HevTaskSystemContext *ctx,
HevTask *task)
{
/* skip to wake up this task that is already in running */
if (task->state == HEV_TASK_RUNNING)
return;
if (task->state == HEV_TASK_STOPPED)
abort ();
task->sched_key += hev_task_system_get_min_sched_key (ctx);
hev_task_system_insert_task (ctx, task);
}
static inline void
hev_task_system_io_poll (HevTaskSystemContext *ctx, int timeout)
{
int i, count;
HevTaskIOReactorWaitEvent events[1024];
if (timeout < 0)
timeout = hev_task_timer_get_timeout (ctx->timer);
count = hev_task_io_reactor_wait (ctx->reactor, events, 1024, timeout);
for (i = 0; i < count; i++) {
HevTaskSchedEntity *sched_entity;
sched_entity = hev_task_io_reactor_wait_event_get_data (&events[i]);
hev_task_system_wakeup_task_with_context (ctx, sched_entity->task);
}
hev_task_timer_wake (ctx->timer);
}
static inline void
hev_task_system_pick_current_task (HevTaskSystemContext *ctx)
{
HevRBTreeNode *sched_node;
if (ctx->running_task_count < ctx->total_task_count) {
if (ctx->running_task_count) {
hev_task_system_io_poll (ctx, 0);
} else {
do {
hev_task_system_io_poll (ctx, -1);
} while (!ctx->running_task_count);
}
}
sched_node = hev_rbtree_cached_first (&ctx->running_tasks);
ctx->current_task = container_of (sched_node, HevTask, sched_node);
}
void
hev_task_system_schedule (HevTaskYieldType type)
{
HevTaskSystemContext *ctx = hev_task_system_get_context ();
if (ctx->current_task) {
/*
* NOTE: in task context
* save current task context
*/
if (_setjmp (ctx->current_task->context))
return; /* resume to task context */
/* resume to kernel context */
_longjmp (ctx->kernel_context, type);
}
/* NOTE: in kernel context */
if (type == HEV_TASK_RUN_SCHEDULER) {
switch (_setjmp (ctx->kernel_context)) {
case HEV_TASK_SCHED_SWITCH:
hev_task_system_update_sched_key (ctx);
hev_task_system_reinsert_current_task (ctx);
break;
case HEV_TASK_SCHED_WAITIO:
hev_task_system_update_sched_key (ctx);
hev_task_system_remove_current_task (ctx, HEV_TASK_WAITING);
break;
case HEV_TASK_SCHED_REMOVE:
hev_task_system_remove_current_task (ctx, HEV_TASK_STOPPED);
break;
}
}
/* All tasks exited, Bye! */
if (ctx->total_task_count == 0) {
ctx->current_task = NULL;
return;
}
/* pick a task */
hev_task_system_pick_current_task (ctx);
/* update schedule time */
hev_task_system_update_sched_time (ctx);
/* switch to task */
_longjmp (ctx->current_task->context, 1);
}
void
hev_task_system_wakeup_task (HevTask *task)
{
HevTaskSystemContext *ctx;
ctx = hev_task_system_get_context ();
hev_task_system_wakeup_task_with_context (ctx, task);
}
void
hev_task_system_run_new_task (HevTask *task)
{
HevTaskSystemContext *ctx = hev_task_system_get_context ();
hev_task_execute (task, hev_task_executer);
if (ctx->current_task)
task->sched_key += hev_task_system_get_min_sched_key (ctx);
hev_task_system_insert_task (ctx, task);
ctx->total_task_count++;
}
void
hev_task_system_kill_current_task (void)
{
HevTaskSystemContext *ctx = hev_task_system_get_context ();
/*
* NOTE: remove current task in kernel context, because current
* task stack may be freed.
*/
_longjmp (ctx->kernel_context, HEV_TASK_SCHED_REMOVE);
}
@@ -0,0 +1,117 @@
/*
============================================================================
Name : hev-task-system.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2017 - 2025 everyone.
Description :
============================================================================
*/
#include <stdlib.h>
#include <pthread.h>
#include "lib/misc/hev-compiler.h"
#include "lib/misc/hev-task-stack-detector.h"
#include "mem/api/hev-memory-allocator-api.h"
#include "mem/slice/hev-memory-allocator-slice.h"
#include "hev-task-system-private.h"
#include "hev-task-system.h"
static pthread_key_t key;
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
static void
pthread_key_creator (void)
{
pthread_key_create (&key, NULL);
}
HevTaskSystemContext *
hev_task_system_get_context (void)
{
return pthread_getspecific (key);
}
static inline int
hev_task_system_set_context (HevTaskSystemContext *context)
{
return pthread_setspecific (key, context);
}
EXPORT_SYMBOL int
hev_task_system_init (void)
{
HevMemoryAllocator *allocator = NULL;
HevTaskSystemContext *context;
#ifdef ENABLE_MEMALLOC_SLICE
allocator = hev_memory_allocator_slice_new ();
#endif
allocator = hev_memory_allocator_set_default (allocator);
if (allocator)
hev_memory_allocator_unref (allocator);
pthread_once (&key_once, pthread_key_creator);
if (hev_task_system_get_context ())
goto exit;
context = hev_malloc0 (sizeof (HevTaskSystemContext));
if (!context)
goto exit;
if (hev_task_system_set_context (context) < 0)
goto free_context;
context->reactor = hev_task_io_reactor_new ();
if (!context->reactor)
goto rest_context;
context->timer = hev_task_timer_new (context);
if (!context->timer)
goto free_reactor;
context->stack_detector = hev_task_stack_detector_new ();
if (!context->stack_detector)
goto free_timer;
return 0;
free_timer:
hev_task_timer_destroy (context->timer);
free_reactor:
hev_task_io_reactor_destroy (context->reactor);
rest_context:
hev_task_system_set_context (NULL);
free_context:
hev_free (context);
exit:
return -1;
}
EXPORT_SYMBOL void
hev_task_system_fini (void)
{
HevMemoryAllocator *allocator;
HevTaskSystemContext *context = hev_task_system_get_context ();
if (context->dns_proxy)
hev_task_dns_proxy_destroy (context->dns_proxy);
hev_task_stack_detector_destroy (context->stack_detector);
hev_task_timer_destroy (context->timer);
hev_task_io_reactor_destroy (context->reactor);
hev_free (context);
hev_task_system_set_context (NULL);
allocator = hev_memory_allocator_set_default (NULL);
if (allocator)
hev_memory_allocator_unref (allocator);
}
EXPORT_SYMBOL void
hev_task_system_run (void)
{
hev_task_system_schedule (HEV_TASK_RUN_SCHEDULER);
}
@@ -0,0 +1,54 @@
/*
============================================================================
Name : hev-task-system.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2021 - 2024 everyone.
Description :
============================================================================
*/
#ifndef __HEV_TASK_SYSTEM_H__
#define __HEV_TASK_SYSTEM_H__
#ifdef __cplusplus
extern "C" {
#endif
#define HEV_TASK_SYSTEM_MAJOR_VERSION (5)
#define HEV_TASK_SYSTEM_MINOR_VERSION (10)
#define HEV_TASK_SYSTEM_MICRO_VERSION (1)
/**
* hev_task_system_init:
*
* Initialize the task system.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 1.0
*/
int hev_task_system_init (void);
/**
* hev_task_system_fini:
*
* Finalize the task system.
*
* Since: 1.0
*/
void hev_task_system_fini (void);
/**
* hev_task_system_run:
*
* Run the task system.
*
* Since: 1.0
*/
void hev_task_system_run (void);
#ifdef __cplusplus
}
#endif
#endif /* __HEV_TASK_SYSTEM_H__ */
@@ -0,0 +1,71 @@
/*
============================================================================
Name : hev-task-io-reactor-epoll.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2018 - 2025 everyone.
Description : I/O Reactor EPoll
============================================================================
*/
#if defined(__linux__)
#include <fcntl.h>
#include <unistd.h>
#include "mem/api/hev-memory-allocator-api.h"
#include "kern/io/hev-task-io-reactor.h"
HevTaskIOReactor *
hev_task_io_reactor_new (void)
{
HevTaskIOReactor *self;
int flags;
self = hev_malloc0 (sizeof (HevTaskIOReactor));
if (!self)
return NULL;
self->fd = epoll_create (128);
if (self->fd < 0) {
hev_free (self);
return NULL;
}
flags = fcntl (self->fd, F_GETFD);
if (flags < 0) {
hev_free (self);
return NULL;
}
flags |= FD_CLOEXEC;
if (fcntl (self->fd, F_SETFD, flags) < 0) {
hev_free (self);
return NULL;
}
return self;
}
void
hev_task_io_reactor_destroy (HevTaskIOReactor *self)
{
close (self->fd);
hev_free (self);
}
int
hev_task_io_reactor_setup (HevTaskIOReactor *self,
HevTaskIOReactorSetupEvent *events, int count)
{
int i, res = 0;
for (i = 0; i < count; i++) {
HevTaskIOReactorSetupEvent *ev = &events[i];
res |= epoll_ctl (self->fd, ev->op, ev->fd, &ev->event);
}
return res;
}
#endif /* defined(__linux__) */
@@ -0,0 +1,102 @@
/*
============================================================================
Name : hev-task-io-reactor-epoll.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2018 - 2022 everyone.
Description : I/O Reactor EPoll
============================================================================
*/
#ifndef __HEV_TASK_IO_REACTOR_EPOLL_H__
#define __HEV_TASK_IO_REACTOR_EPOLL_H__
#include <poll.h>
#include <sys/epoll.h>
#define HEV_TASK_IO_REACTOR_EVENT_GEN_MAX (1)
typedef struct _HevTaskIOReactorSetupEvent HevTaskIOReactorSetupEvent;
typedef struct epoll_event HevTaskIOReactorWaitEvent;
enum _HevTaskIOReactorEvents
{
HEV_TASK_IO_REACTOR_EV_RO = EPOLLIN,
HEV_TASK_IO_REACTOR_EV_WO = EPOLLOUT,
HEV_TASK_IO_REACTOR_EV_ER = EPOLLERR,
};
enum _HevTaskIOReactorOperation
{
HEV_TASK_IO_REACTOR_OP_ADD = EPOLL_CTL_ADD,
HEV_TASK_IO_REACTOR_OP_MOD = EPOLL_CTL_MOD,
HEV_TASK_IO_REACTOR_OP_DEL = EPOLL_CTL_DEL,
};
struct _HevTaskIOReactorSetupEvent
{
HevTaskIOReactorOperation op;
int fd;
struct epoll_event event;
};
static inline int
hev_task_io_reactor_wait (HevTaskIOReactor *self,
HevTaskIOReactorWaitEvent *events, int count,
int timeout)
{
return epoll_wait (self->fd, events, count, timeout);
}
static inline void
hev_task_io_reactor_setup_event_set (HevTaskIOReactorSetupEvent *event, int fd,
HevTaskIOReactorOperation op,
unsigned int events, void *data)
{
event->op = op;
event->fd = fd;
event->event.events = events | EPOLLET;
event->event.data.ptr = data;
}
static inline int
hev_task_io_reactor_setup_event_fd_gen (HevTaskIOReactorSetupEvent *events,
int fd, HevTaskIOReactorOperation op,
unsigned int poll_events, void *data)
{
HevTaskIOReactorEvents reactor_events = 0;
if (poll_events & POLLIN)
reactor_events |= HEV_TASK_IO_REACTOR_EV_RO;
if (poll_events & POLLOUT)
reactor_events |= HEV_TASK_IO_REACTOR_EV_WO;
if (poll_events & POLLERR)
reactor_events |= HEV_TASK_IO_REACTOR_EV_ER;
hev_task_io_reactor_setup_event_set (events, fd, op, reactor_events, data);
return 1;
}
static inline int
hev_task_io_reactor_setup_event_whandle_gen (HevTaskIOReactorSetupEvent *events,
void *handle,
HevTaskIOReactorOperation op,
void *data)
{
return -1;
}
static inline unsigned int
hev_task_io_reactor_wait_event_get_events (HevTaskIOReactorWaitEvent *event)
{
return event->events;
}
static inline void *
hev_task_io_reactor_wait_event_get_data (HevTaskIOReactorWaitEvent *event)
{
return event->data.ptr;
}
#endif /* __HEV_TASK_IO_REACTOR_EPOLL_H__ */
@@ -0,0 +1,344 @@
/*
============================================================================
Name : hev-task-io-reactor-iocp.c
Author : hev <r@hev.cc>
Copyright : Copyright (c) 2025 hev
Description : I/O Reactor IOCP
============================================================================
*/
#if defined(__MSYS__)
#include <assert.h>
#include <stdlib.h>
#include <stdatomic.h>
#include "lib/misc/hev-compiler.h"
#include "mem/api/hev-memory-allocator-api.h"
#include "kern/io/hev-task-io-reactor.h"
typedef struct _HevTaskIOReactorIOCPNode HevTaskIOReactorIOCPNode;
struct _HevTaskIOReactorIOCPNode
{
HevRBTreeNode base;
int ref_count;
int events;
long handle;
void *data;
void *ihandle;
void *ehandle;
void *whandle;
};
static HevTaskIOReactorIOCPNode *
hev_task_io_reactor_iocp_node_new (void)
{
HevTaskIOReactorIOCPNode *node;
atomic_int *rcp;
node = calloc (1, sizeof (HevTaskIOReactorIOCPNode));
if (!node)
return NULL;
rcp = (atomic_int *)&node->ref_count;
atomic_store_explicit (rcp, 1, memory_order_relaxed);
return node;
}
static void
hev_task_io_reactor_iocp_node_ref (HevTaskIOReactorIOCPNode *node)
{
atomic_int *rcp = (atomic_int *)&node->ref_count;
atomic_fetch_add_explicit (rcp, 1, memory_order_relaxed);
}
static void
hev_task_io_reactor_iocp_node_unref (HevTaskIOReactorIOCPNode *node)
{
atomic_int *rcp = (atomic_int *)&node->ref_count;
int rc;
rc = atomic_fetch_sub_explicit (rcp, 1, memory_order_relaxed);
if (rc > 1)
return;
assert (rc >= 1);
free (node);
}
static int
hev_task_io_reactor_iocp_insert (HevTaskIOReactorIOCP *self,
HevTaskIOReactorIOCPNode *node)
{
HevRBTreeNode **new = &self->tree.root, *parent = NULL;
while (*new) {
HevTaskIOReactorIOCPNode *this;
this = container_of (*new, HevTaskIOReactorIOCPNode, base);
parent = *new;
if (this->handle < node->handle)
new = &((*new)->left);
else if (this->handle > node->handle)
new = &((*new)->right);
else
return -1;
}
hev_rbtree_node_link (&node->base, parent, new);
hev_rbtree_insert_color (&self->tree, &node->base);
return 0;
}
static HevTaskIOReactorIOCPNode *
hev_task_io_reactor_iocp_lookup (HevTaskIOReactorIOCP *self, long handle)
{
HevRBTreeNode *node = self->tree.root;
while (node) {
HevTaskIOReactorIOCPNode *this;
this = container_of (node, HevTaskIOReactorIOCPNode, base);
if (this->handle < handle)
node = node->left;
else if (this->handle > handle)
node = node->right;
else
return this;
}
return NULL;
}
static VOID CALLBACK
hev_task_io_reactor_iocp_handler (void *data, BOOLEAN fired)
{
HevTaskIOReactorIOCPNode *node = data;
int res;
if (fired)
return;
if (node->handle != (long)node->ehandle) {
WSANETWORKEVENTS events;
res = WSAEnumNetworkEvents (node->handle, node->ehandle, &events);
if (res || !events.lNetworkEvents)
return;
node->events = events.lNetworkEvents;
}
hev_task_io_reactor_iocp_node_ref (node);
res = PostQueuedCompletionStatus (node->ihandle, 1, 0, (LPOVERLAPPED)node);
if (!res)
hev_task_io_reactor_iocp_node_unref (node);
}
static int
hev_task_io_reactor_iocp_add (HevTaskIOReactorIOCP *self,
HevTaskIOReactorSetupEvent *event)
{
HevTaskIOReactorIOCPNode *node;
int res;
node = hev_task_io_reactor_iocp_lookup (self, event->handle);
if (node)
goto exit;
node = hev_task_io_reactor_iocp_node_new ();
if (!node)
goto exit;
if (event->events) {
long events;
node->ehandle = CreateEventA (NULL, FALSE, FALSE, NULL);
if (!node->ehandle)
goto free_node;
events = event->events | HEV_TASK_IO_REACTOR_EV_ER;
res = WSAEventSelect (event->handle, node->ehandle, events);
if (res)
goto free_event;
} else {
node->ehandle = (void *)event->handle;
}
node->data = event->data;
node->handle = event->handle;
node->ihandle = self->base.handle;
res = RegisterWaitForSingleObject (&node->whandle, node->ehandle,
hev_task_io_reactor_iocp_handler, node,
INFINITE, WT_EXECUTEINPERSISTENTTHREAD);
if (!res)
goto free_event;
hev_task_io_reactor_iocp_insert (self, node);
return 0;
free_event:
if (event->handle != (long)node->ehandle)
WSACloseEvent (node->ehandle);
free_node:
hev_task_io_reactor_iocp_node_unref (node);
exit:
return -1;
}
static int
hev_task_io_reactor_iocp_mod (HevTaskIOReactorIOCP *self,
HevTaskIOReactorSetupEvent *event)
{
HevTaskIOReactorIOCPNode *node;
node = hev_task_io_reactor_iocp_lookup (self, event->handle);
if (!node)
return -1;
if (node->handle != (long)node->ehandle && event->events) {
long events = event->events | HEV_TASK_IO_REACTOR_EV_ER;
int res = WSAEventSelect (node->handle, node->ehandle, events);
if (res)
return -1;
}
return 0;
}
static int
hev_task_io_reactor_iocp_del (HevTaskIOReactorIOCP *self,
HevTaskIOReactorSetupEvent *event)
{
HevTaskIOReactorIOCPNode *node;
int res;
node = hev_task_io_reactor_iocp_lookup (self, event->handle);
if (!node)
return -1;
res = UnregisterWaitEx (node->whandle, INVALID_HANDLE_VALUE);
if (node->handle != (long)node->ehandle)
res &= WSACloseEvent (node->ehandle);
if (!res)
return -1;
node->ehandle = NULL;
node->whandle = NULL;
hev_rbtree_erase (&self->tree, &node->base);
hev_task_io_reactor_iocp_node_unref (node);
return 0;
}
HevTaskIOReactor *
hev_task_io_reactor_new (void)
{
HevTaskIOReactorIOCP *self;
HANDLE handle;
self = hev_malloc0 (sizeof (HevTaskIOReactorIOCP));
if (!self)
return NULL;
handle = CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL, 0, 0);
if (!handle) {
hev_free (self);
return NULL;
}
pthread_mutex_init (&self->mutex, NULL);
self->base.handle = handle;
return &self->base;
}
void
hev_task_io_reactor_destroy (HevTaskIOReactor *_self)
{
HevTaskIOReactorIOCP *self = (HevTaskIOReactorIOCP *)_self;
CloseHandle (_self->handle);
pthread_mutex_destroy (&self->mutex);
hev_free (self);
}
int
hev_task_io_reactor_setup (HevTaskIOReactor *_self,
HevTaskIOReactorSetupEvent *events, int count)
{
HevTaskIOReactorIOCP *self = (HevTaskIOReactorIOCP *)_self;
int res = -1;
assert (count <= HEV_TASK_IO_REACTOR_EVENT_GEN_MAX);
if (!events || count <= 0)
return res;
pthread_mutex_lock (&self->mutex);
switch (events->op) {
case HEV_TASK_IO_REACTOR_OP_ADD:
res = hev_task_io_reactor_iocp_add (self, events);
break;
case HEV_TASK_IO_REACTOR_OP_MOD:
res = hev_task_io_reactor_iocp_mod (self, events);
break;
case HEV_TASK_IO_REACTOR_OP_DEL:
res = hev_task_io_reactor_iocp_del (self, events);
default:
break;
}
pthread_mutex_unlock (&self->mutex);
return res;
}
int
hev_task_io_reactor_wait (HevTaskIOReactor *self,
HevTaskIOReactorWaitEvent *events, int count,
int timeout)
{
HevTaskIOReactorIOCPNode *node;
OVERLAPPED *overlap = NULL;
ULONG_PTR key = 0;
DWORD bytes = 0;
int res;
if (count <= 0)
return -1;
retry:
res = GetQueuedCompletionStatus (self->handle, &bytes, &key, &overlap,
timeout);
if (!res) {
if (GetLastError () == WAIT_TIMEOUT)
return 0;
return -1;
}
node = (HevTaskIOReactorIOCPNode *)overlap;
events->events = node->events;
events->data = node->data;
res = node->ehandle && node->whandle;
hev_task_io_reactor_iocp_node_unref (node);
if (!res)
goto retry;
return 1;
}
#endif /* defined(__MSYS__) */
@@ -0,0 +1,130 @@
/*
============================================================================
Name : hev-task-io-reactor-iocp.h
Author : hev <r@hev.cc>
Copyright : Copyright (c) 2025 hev
Description : I/O Reactor IOCP
============================================================================
*/
#ifndef __HEV_TASK_IO_REACTOR_IOCP_H__
#define __HEV_TASK_IO_REACTOR_IOCP_H__
#include <io.h>
#include <poll.h>
#include <pthread.h>
#include "lib/rbtree/hev-rbtree.h"
#include "lib/misc/hev-windows-api.h"
#define HEV_TASK_IO_REACTOR_EVENT_GEN_MAX (1)
typedef struct _HevTaskIOReactorIOCP HevTaskIOReactorIOCP;
typedef struct _HevTaskIOReactorSetupEvent HevTaskIOReactorSetupEvent;
typedef struct _HevTaskIOReactorWaitEvent HevTaskIOReactorWaitEvent;
struct _HevTaskIOReactorIOCP
{
HevTaskIOReactor base;
HevRBTree tree;
pthread_mutex_t mutex;
};
enum _HevTaskIOReactorEvents
{
HEV_TASK_IO_REACTOR_EV_RO = FD_READ | FD_ACCEPT,
HEV_TASK_IO_REACTOR_EV_WO = FD_WRITE | FD_CONNECT,
HEV_TASK_IO_REACTOR_EV_ER = FD_CLOSE,
};
enum _HevTaskIOReactorOperation
{
HEV_TASK_IO_REACTOR_OP_ADD,
HEV_TASK_IO_REACTOR_OP_MOD,
HEV_TASK_IO_REACTOR_OP_DEL,
};
struct _HevTaskIOReactorSetupEvent
{
HevTaskIOReactorOperation op;
long handle;
int events;
void *data;
};
struct _HevTaskIOReactorWaitEvent
{
int events;
void *data;
};
int hev_task_io_reactor_wait (HevTaskIOReactor *self,
HevTaskIOReactorWaitEvent *events, int count,
int timeout);
static inline void
hev_task_io_reactor_setup_event_set (HevTaskIOReactorSetupEvent *event,
long handle, HevTaskIOReactorOperation op,
unsigned int events, void *data)
{
event->op = op;
event->handle = handle;
event->events = events;
event->data = data;
}
static inline int
hev_task_io_reactor_setup_event_fd_gen (HevTaskIOReactorSetupEvent *events,
long fd, HevTaskIOReactorOperation op,
unsigned int poll_events, void *data)
{
HevTaskIOReactorEvents reactor_events = 0;
if (poll_events & POLLIN)
reactor_events |= HEV_TASK_IO_REACTOR_EV_RO;
if (poll_events & POLLOUT)
reactor_events |= HEV_TASK_IO_REACTOR_EV_WO;
if (poll_events & POLLERR)
reactor_events |= HEV_TASK_IO_REACTOR_EV_ER;
hev_task_io_reactor_setup_event_set (events, get_osfhandle (fd), op,
reactor_events, data);
return 1;
}
static inline int
hev_task_io_reactor_setup_event_whandle_gen (HevTaskIOReactorSetupEvent *events,
void *handle,
HevTaskIOReactorOperation op,
void *data)
{
hev_task_io_reactor_setup_event_set (events, (long)handle, op, 0, data);
return 1;
}
static inline unsigned int
hev_task_io_reactor_wait_event_get_events (HevTaskIOReactorWaitEvent *event)
{
unsigned int events = 0;
if (event->events & HEV_TASK_IO_REACTOR_EV_RO)
events |= POLLIN;
if (event->events & HEV_TASK_IO_REACTOR_EV_WO)
events |= POLLOUT;
if (event->events & HEV_TASK_IO_REACTOR_EV_ER)
events |= POLLERR;
return events;
}
static inline void *
hev_task_io_reactor_wait_event_get_data (HevTaskIOReactorWaitEvent *event)
{
return event->data;
}
#endif /* __HEV_TASK_IO_REACTOR_IOCP_H__ */
@@ -0,0 +1,74 @@
/*
============================================================================
Name : hev-task-io-reactor-kqueue.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2018 - 2025 everyone.
Description : I/O Reactor KQueue
============================================================================
*/
#if !defined(__linux__) && !defined(__MSYS__)
#include <fcntl.h>
#include <unistd.h>
#include "mem/api/hev-memory-allocator-api.h"
#include "kern/io/hev-task-io-reactor.h"
HevTaskIOReactor *
hev_task_io_reactor_new (void)
{
HevTaskIOReactor *self;
int flags;
self = hev_malloc0 (sizeof (HevTaskIOReactor));
if (!self)
return NULL;
self->fd = kqueue ();
if (self->fd < 0) {
hev_free (self);
return NULL;
}
flags = fcntl (self->fd, F_GETFD);
if (flags < 0) {
hev_free (self);
return NULL;
}
flags |= FD_CLOEXEC;
if (fcntl (self->fd, F_SETFD, flags) < 0) {
hev_free (self);
return NULL;
}
return self;
}
void
hev_task_io_reactor_destroy (HevTaskIOReactor *self)
{
close (self->fd);
hev_free (self);
}
int
hev_task_io_reactor_setup (HevTaskIOReactor *self,
HevTaskIOReactorSetupEvent *events, int count)
{
int i, res = -1;
for (i = 0; i < count; i++) {
if (!(events[i].flags & EV_DELETE)) {
res = kevent (self->fd, &events[i], count - i, NULL, 0, NULL);
break;
}
res &= kevent (self->fd, &events[i], 1, NULL, 0, NULL);
}
return res;
}
#endif /* !defined(__linux__) && !defined(__MSYS__) */
@@ -0,0 +1,145 @@
/*
============================================================================
Name : hev-task-io-reactor-kqueue.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2018 - 2025 everyone.
Description : I/O Reactor KQueue
============================================================================
*/
#ifndef __HEV_TASK_IO_REACTOR_KQUEUE_H__
#define __HEV_TASK_IO_REACTOR_KQUEUE_H__
#include <poll.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#ifndef EVFILT_EXCEPT
#define EVFILT_EXCEPT (0)
#endif
#define HEV_TASK_IO_REACTOR_EVENT_GEN_MAX (6)
typedef struct kevent HevTaskIOReactorSetupEvent;
typedef struct kevent HevTaskIOReactorWaitEvent;
enum _HevTaskIOReactorEvents
{
HEV_TASK_IO_REACTOR_EV_RO = EVFILT_READ,
HEV_TASK_IO_REACTOR_EV_WO = EVFILT_WRITE,
HEV_TASK_IO_REACTOR_EV_ER = EVFILT_EXCEPT,
};
enum _HevTaskIOReactorOperation
{
HEV_TASK_IO_REACTOR_OP_ADD,
HEV_TASK_IO_REACTOR_OP_MOD,
HEV_TASK_IO_REACTOR_OP_DEL,
};
static inline int
hev_task_io_reactor_wait (HevTaskIOReactor *self,
HevTaskIOReactorWaitEvent *events, int count,
int timeout)
{
struct timespec *tsp = NULL;
struct timespec ts;
if (timeout >= 0) {
ts.tv_sec = timeout / 1000;
ts.tv_nsec = (timeout % 1000) * 1000000;
tsp = &ts;
}
return kevent (self->fd, NULL, 0, events, count, tsp);
}
static inline void
hev_task_io_reactor_setup_event_set (HevTaskIOReactorSetupEvent *event, int fd,
HevTaskIOReactorOperation op,
unsigned int events, void *data)
{
int action;
switch (op) {
case HEV_TASK_IO_REACTOR_OP_ADD:
case HEV_TASK_IO_REACTOR_OP_MOD:
action = EV_ADD;
break;
case HEV_TASK_IO_REACTOR_OP_DEL:
action = EV_DELETE;
}
EV_SET (event, fd, events, action | EV_CLEAR, 0, 0, data);
}
static inline int
hev_task_io_reactor_setup_event_fd_gen (HevTaskIOReactorSetupEvent *events,
int fd, HevTaskIOReactorOperation op,
unsigned int poll_events, void *data)
{
int count = 0;
if (op > HEV_TASK_IO_REACTOR_OP_ADD) {
if (!(poll_events & POLLIN))
hev_task_io_reactor_setup_event_set (&events[count++], fd,
HEV_TASK_IO_REACTOR_OP_DEL,
HEV_TASK_IO_REACTOR_EV_RO,
data);
if (!(poll_events & POLLOUT))
hev_task_io_reactor_setup_event_set (&events[count++], fd,
HEV_TASK_IO_REACTOR_OP_DEL,
HEV_TASK_IO_REACTOR_EV_WO,
data);
if (!(poll_events & POLLERR))
hev_task_io_reactor_setup_event_set (&events[count++], fd,
HEV_TASK_IO_REACTOR_OP_DEL,
HEV_TASK_IO_REACTOR_EV_ER,
data);
if (op == HEV_TASK_IO_REACTOR_OP_DEL)
return count;
}
if (poll_events & POLLIN)
hev_task_io_reactor_setup_event_set (&events[count++], fd, op,
HEV_TASK_IO_REACTOR_EV_RO, data);
if (poll_events & POLLOUT)
hev_task_io_reactor_setup_event_set (&events[count++], fd, op,
HEV_TASK_IO_REACTOR_EV_WO, data);
if (poll_events & POLLERR)
hev_task_io_reactor_setup_event_set (&events[count++], fd, op,
HEV_TASK_IO_REACTOR_EV_ER, data);
return count;
}
static inline int
hev_task_io_reactor_setup_event_whandle_gen (HevTaskIOReactorSetupEvent *events,
void *handle,
HevTaskIOReactorOperation op,
void *data)
{
return -1;
}
static inline unsigned int
hev_task_io_reactor_wait_event_get_events (HevTaskIOReactorWaitEvent *event)
{
switch (event->filter) {
case HEV_TASK_IO_REACTOR_EV_RO:
return POLLIN;
case HEV_TASK_IO_REACTOR_EV_WO:
return POLLOUT;
default:
return POLLERR;
}
}
static inline void *
hev_task_io_reactor_wait_event_get_data (HevTaskIOReactorWaitEvent *event)
{
return event->udata;
}
#endif /* __HEV_TASK_IO_REACTOR_KQUEUE_H__ */
@@ -0,0 +1,40 @@
/*
============================================================================
Name : hev-task-io-reactor.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2018 - 2025 everyone.
Description : I/O Reactor
============================================================================
*/
#ifndef __HEV_TASK_IO_REACTOR_H__
#define __HEV_TASK_IO_REACTOR_H__
typedef struct _HevTaskIOReactor HevTaskIOReactor;
typedef enum _HevTaskIOReactorEvents HevTaskIOReactorEvents;
typedef enum _HevTaskIOReactorOperation HevTaskIOReactorOperation;
struct _HevTaskIOReactor
{
union
{
int fd;
void *handle;
};
};
#if defined(__MSYS__)
#include "kern/io/hev-task-io-reactor-iocp.h"
#elif defined(__linux__)
#include "kern/io/hev-task-io-reactor-epoll.h"
#else
#include "kern/io/hev-task-io-reactor-kqueue.h"
#endif
HevTaskIOReactor *hev_task_io_reactor_new (void);
void hev_task_io_reactor_destroy (HevTaskIOReactor *self);
int hev_task_io_reactor_setup (HevTaskIOReactor *self,
HevTaskIOReactorSetupEvent *events, int count);
#endif /* __HEV_TASK_IO_REACTOR_H__ */
@@ -0,0 +1,96 @@
/*
============================================================================
Name : hev-task-channel-private.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2019 everyone.
Description : Channel
============================================================================
*/
#ifndef __HEV_TASK_CHANNEL_PRIVATE_H__
#define __HEV_TASK_CHANNEL_PRIVATE_H__
#include "lib/list/hev-list.h"
#include "kern/task/hev-task.h"
#include "hev-task-channel-select.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef union _HevTaskChannelData HevTaskChannelData;
typedef struct _HevTaskChannelBuffer HevTaskChannelBuffer;
union _HevTaskChannelData
{
char b[0];
short h[0];
int w[0];
long long d[0];
};
struct _HevTaskChannelBuffer
{
size_t size;
HevTaskChannelData *data;
};
struct _HevTaskChannel
{
HevTaskChannel *peer;
struct
{
HevListNode node;
int used;
} read;
struct
{
HevListNode node;
int used;
} write;
HevListNode chan_node;
HevTask *task;
HevTaskChannelSelect *select;
unsigned int rd_idx;
unsigned int wr_idx;
unsigned int max_size;
unsigned int use_count;
unsigned int max_count;
unsigned int ref_count;
HevTaskChannelBuffer buffers[0];
};
static inline int
hev_task_channel_is_active (HevTaskChannel *self)
{
return READ_ONCE (self->peer) != NULL;
}
static inline int
hev_task_channel_is_readable (HevTaskChannel *self)
{
return READ_ONCE (self->use_count) != 0;
}
static inline int
hev_task_channel_is_writable (HevTaskChannel *peer)
{
return READ_ONCE (peer->use_count) < READ_ONCE (peer->max_count);
}
static inline int
hev_task_channel_is_select_writable (HevTaskChannel *peer)
{
return READ_ONCE (peer->use_count) < (READ_ONCE (peer->max_count) - 1);
}
#ifdef __cplusplus
}
#endif
#endif /* __HEV_TASK_CHANNEL_PRIVATE_H__ */
@@ -0,0 +1,81 @@
/*
============================================================================
Name : hev-task-channel-select-private.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2019 everyone.
Description : Channel Selector
============================================================================
*/
#ifndef __HEV_TASK_CHANNEL_SELECT_PRIVATE_H__
#define __HEV_TASK_CHANNEL_SELECT_PRIVATE_H__
#include "lib/list/hev-list.h"
#include "kern/task/hev-task.h"
#include "hev-task-channel.h"
#include "hev-task-channel-private.h"
#include "hev-task-channel-select.h"
#ifdef __cplusplus
extern "C" {
#endif
struct _HevTaskChannelSelect
{
HevTask *task;
HevList chan_list;
HevList read_list;
HevList write_list;
};
static inline void
hev_task_channel_select_add_read (HevTaskChannelSelect *self,
HevTaskChannel *chan)
{
if (chan->read.used)
return;
chan->read.used = 1;
hev_list_add_tail (&self->read_list, &chan->read.node);
}
static inline void
hev_task_channel_select_del_read (HevTaskChannelSelect *self,
HevTaskChannel *chan)
{
if (!chan->read.used)
return;
chan->read.used = 0;
hev_list_del (&self->read_list, &chan->read.node);
}
static inline void
hev_task_channel_select_add_write (HevTaskChannelSelect *self,
HevTaskChannel *chan)
{
if (chan->write.used)
return;
chan->write.used = 1;
hev_list_add_tail (&self->write_list, &chan->write.node);
}
static inline void
hev_task_channel_select_del_write (HevTaskChannelSelect *self,
HevTaskChannel *chan)
{
if (!chan->write.used)
return;
chan->write.used = 0;
hev_list_del (&self->write_list, &chan->write.node);
}
#ifdef __cplusplus
}
#endif
#endif /* __HEV_TASK_CHANNEL_SELECT_PRIVATE_H__ */
@@ -0,0 +1,99 @@
/*
============================================================================
Name : hev-task-channel-select.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2019 everyone.
Description : Channel Selector
============================================================================
*/
#include "lib/misc/hev-compiler.h"
#include "mem/api/hev-memory-allocator-api.h"
#include "hev-task-channel-select.h"
#include "hev-task-channel-select-private.h"
EXPORT_SYMBOL HevTaskChannelSelect *
hev_task_channel_select_new (void)
{
HevTaskChannelSelect *self;
self = hev_malloc0 (sizeof (HevTaskChannelSelect));
return self;
}
EXPORT_SYMBOL void
hev_task_channel_select_destroy (HevTaskChannelSelect *self)
{
hev_free (self);
}
EXPORT_SYMBOL void
hev_task_channel_select_add (HevTaskChannelSelect *self, HevTaskChannel *chan)
{
chan->select = self;
chan->task = hev_task_self ();
hev_list_add_tail (&self->chan_list, &chan->chan_node);
if (hev_task_channel_is_readable (chan))
hev_task_channel_select_add_read (self, chan);
if (chan->peer && hev_task_channel_is_select_writable (chan->peer))
hev_task_channel_select_add_write (self, chan);
}
EXPORT_SYMBOL void
hev_task_channel_select_del (HevTaskChannelSelect *self, HevTaskChannel *chan)
{
hev_task_channel_select_del_read (self, chan);
hev_task_channel_select_del_write (self, chan);
hev_list_del (&self->chan_list, &chan->chan_node);
chan->task = NULL;
chan->select = NULL;
}
static HevListNode *
hev_task_channel_select (HevTaskChannelSelect *self, HevList *list, int timeout)
{
HevListNode *node;
unsigned int milliseconds = timeout;
if (!hev_list_first (&self->chan_list))
return NULL;
while (!(node = hev_list_first (list)) && milliseconds) {
barrier ();
if (timeout < 0)
hev_task_yield (HEV_TASK_WAITIO);
else
milliseconds = hev_task_sleep (milliseconds);
barrier ();
}
return node;
}
EXPORT_SYMBOL HevTaskChannel *
hev_task_channel_select_read (HevTaskChannelSelect *self, int timeout)
{
HevListNode *node;
node = hev_task_channel_select (self, &self->read_list, timeout);
if (!node)
return NULL;
return container_of (node, HevTaskChannel, read.node);
}
EXPORT_SYMBOL HevTaskChannel *
hev_task_channel_select_write (HevTaskChannelSelect *self, int timeout)
{
HevListNode *node;
node = hev_task_channel_select (self, &self->write_list, timeout);
if (!node)
return NULL;
return container_of (node, HevTaskChannel, write.node);
}
@@ -0,0 +1,102 @@
/*
============================================================================
Name : hev-task-channel-select.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2019 everyone.
Description : Channel Selector
============================================================================
*/
#ifndef __HEV_TASK_CHANNEL_SELECT_H__
#define __HEV_TASK_CHANNEL_SELECT_H__
#include <sys/types.h>
#include "hev-task-channel.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _HevTaskChannelSelect HevTaskChannelSelect;
/**
* hev_task_channel_select_new:
*
* Creates A task channel selector.
*
* Returns: A #HevTaskChannelSelect
*
* Since: 4.6.9
*/
HevTaskChannelSelect *hev_task_channel_select_new (void);
/**
* hev_task_channel_select_destroy:
* @self: A #HevTaskChannelSelect
*
* Destroy the task channel selector.
*
* Since: 4.6.9
*/
void hev_task_channel_select_destroy (HevTaskChannelSelect *self);
/**
* hev_task_channel_select_add:
* @self: A #HevTaskChannelSelect
* @chan: A #HevTaskChannel
*
* Add the task channel @chan to selector @self.
*
* Since: 4.6.9
*/
void hev_task_channel_select_add (HevTaskChannelSelect *self,
HevTaskChannel *chan);
/**
* hev_task_channel_select_del:
* @self: A #HevTaskChannelSelect
* @chan: A #HevTaskChannel
*
* Remove the task channel @chan to selector @self.
*
* Since: 4.6.9
*/
void hev_task_channel_select_del (HevTaskChannelSelect *self,
HevTaskChannel *chan);
/**
* hev_task_channel_select_read:
* @self: A #HevTaskChannelSelect
* @timeout: (milliseconds): wait timeout
*
* The select read function shall attempt to select a readable channel.
* The function will wait until at least one channel is ready or timeout.
*
* Returns: A #HevTaskChannel
*
* Since: 4.6.9
*/
HevTaskChannel *hev_task_channel_select_read (HevTaskChannelSelect *self,
int timeout);
/**
* hev_task_channel_select_write:
* @self: A #HevTaskChannelSelect
* @timeout: (milliseconds): wait timeout
*
* The select write function shall attempt to select a writable channel.
* The function will wait until at least one channel is ready or timeout.
*
* Returns: A #HevTaskChannel
*
* Since: 5.1.0
*/
HevTaskChannel *hev_task_channel_select_write (HevTaskChannelSelect *self,
int timeout);
#ifdef __cplusplus
}
#endif
#endif /* __HEV_TASK_CHANNEL_SELECT_H__ */
@@ -0,0 +1,248 @@
/*
============================================================================
Name : hev-task-channel.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2019 everyone.
Description : Channel
============================================================================
*/
#include "kern/task/hev-task.h"
#include "lib/misc/hev-compiler.h"
#include "mem/api/hev-memory-allocator-api.h"
#include "hev-task-channel-select-private.h"
#include "hev-task-channel.h"
#include "hev-task-channel-private.h"
EXPORT_SYMBOL int
hev_task_channel_new (HevTaskChannel **chan1, HevTaskChannel **chan2)
{
return hev_task_channel_new_with_buffers (chan1, chan2, 0, 0);
}
EXPORT_SYMBOL int
hev_task_channel_new_with_buffers (HevTaskChannel **chan1,
HevTaskChannel **chan2, unsigned int size,
unsigned int buffers)
{
HevTaskChannel *c1, *c2;
unsigned int buffers_size;
unsigned int data_size = 0;
buffers += 1;
if (buffers > 1)
data_size = size * buffers;
buffers_size = sizeof (HevTaskChannelBuffer) * buffers;
c1 = hev_malloc (sizeof (HevTaskChannel) + buffers_size + data_size);
if (!c1)
goto err0;
c2 = hev_malloc (sizeof (HevTaskChannel) + buffers_size + data_size);
if (!c2)
goto err1;
__builtin_bzero (c1, sizeof (HevTaskChannel));
c1->peer = c2;
c1->max_size = size;
c1->max_count = buffers;
c1->ref_count = 1;
__builtin_bzero (c2, sizeof (HevTaskChannel));
c2->peer = c1;
c2->max_size = size;
c2->max_count = buffers;
c2->ref_count = 1;
if (buffers > 1) {
unsigned int i;
for (i = 0; i < buffers; i++) {
c1->buffers[i].data = (void *)c1->buffers + buffers_size + size * i;
c2->buffers[i].data = (void *)c2->buffers + buffers_size + size * i;
}
}
*chan1 = c1;
*chan2 = c2;
return 0;
hev_free (c2);
err1:
hev_free (c1);
err0:
return -1;
}
static void
hev_task_channel_ref (HevTaskChannel *self)
{
self->ref_count++;
}
static void
hev_task_channel_unref (HevTaskChannel *self)
{
self->ref_count--;
if (self->ref_count)
return;
hev_free (self);
}
EXPORT_SYMBOL void
hev_task_channel_destroy (HevTaskChannel *self)
{
if (self->peer) {
self->peer->peer = NULL;
if (self->peer->task)
hev_task_wakeup (self->peer->task);
}
if (self->task)
hev_task_wakeup (self->task);
hev_task_channel_unref (self);
}
static ssize_t
hev_task_channel_data_copy (void *dst, const void *src, size_t size)
{
HevTaskChannelData *d = dst;
const HevTaskChannelData *s = src;
switch (size) {
case 0:
break;
case sizeof (char):
d->b[0] = s->b[0];
break;
case sizeof (short):
d->h[0] = s->h[0];
break;
case sizeof (int):
d->w[0] = s->w[0];
break;
case sizeof (long long):
d->d[0] = s->d[0];
break;
default:
__builtin_memcpy (dst, src, size);
}
return size;
}
EXPORT_SYMBOL ssize_t
hev_task_channel_read (HevTaskChannel *self, void *buffer, size_t count)
{
HevTaskChannelBuffer *cbuf;
ssize_t size = -1;
/* wait on empty */
while (!hev_task_channel_is_readable (self)) {
/* check is peer alive because cond wait may yield */
if (!hev_task_channel_is_active (self))
goto out;
WRITE_ONCE (self->task, hev_task_self ());
hev_task_yield (HEV_TASK_WAITIO);
}
barrier ();
cbuf = &self->buffers[self->rd_idx];
self->rd_idx = (self->rd_idx + 1) % self->max_count;
size = count;
if (cbuf->size < count)
size = cbuf->size;
size = hev_task_channel_data_copy (buffer, cbuf->data, size);
if (self->use_count == self->max_count) {
HevTaskChannel *peer = self->peer;
if (peer) {
if (peer->select)
hev_task_channel_select_add_write (peer->select, peer);
if (peer->task)
hev_task_wakeup (peer->task);
}
}
self->use_count--;
if (self->select && !hev_task_channel_is_readable (self))
hev_task_channel_select_del_read (self->select, self);
out:
return size;
}
EXPORT_SYMBOL ssize_t
hev_task_channel_write (HevTaskChannel *self, const void *buffer, size_t count)
{
HevTaskChannel *peer = self->peer;
HevTaskChannelBuffer *cbuf;
ssize_t size = -1;
if (!peer)
goto out0;
hev_task_channel_ref (peer);
/* wait on full */
while (!hev_task_channel_is_writable (peer)) {
/* check is peer alive because cond wait may yield */
if (!hev_task_channel_is_active (self))
goto out1;
WRITE_ONCE (self->task, hev_task_self ());
hev_task_yield (HEV_TASK_WAITIO);
}
barrier ();
cbuf = &peer->buffers[peer->wr_idx];
peer->wr_idx = (peer->wr_idx + 1) % peer->max_count;
size = count;
if (peer->max_count == 1) {
cbuf->data = (HevTaskChannelData *)buffer;
} else {
if (size > self->max_size)
size = self->max_size;
size = hev_task_channel_data_copy (cbuf->data, buffer, size);
}
cbuf->size = size;
if (peer->use_count == 0) {
if (peer->select)
hev_task_channel_select_add_read (peer->select, peer);
if (peer->task)
hev_task_wakeup (peer->task);
}
peer->use_count++;
if (self->select && !hev_task_channel_is_select_writable (peer))
hev_task_channel_select_del_write (self->select, self);
/* sync */
while (!hev_task_channel_is_writable (peer)) {
/* check is peer alive because cond wait may yield */
if (!hev_task_channel_is_active (self)) {
size = -1;
break;
}
WRITE_ONCE (self->task, hev_task_self ());
hev_task_yield (HEV_TASK_WAITIO);
}
barrier ();
out1:
hev_task_channel_unref (peer);
out0:
return size;
}
@@ -0,0 +1,101 @@
/*
============================================================================
Name : hev-task-channel.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2019 everyone.
Description : Channel
============================================================================
*/
#ifndef __HEV_TASK_CHANNEL_H__
#define __HEV_TASK_CHANNEL_H__
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _HevTaskChannel HevTaskChannel;
/**
* hev_task_channel_new:
* @chan1: (out): a #HevTaskChannel
* @chan2: (out): a #HevTaskChannel
*
* Creates a pair of connected task channel.
* The channels are synchronous, both sides of the channel will wait until the
* other side is ready.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 4.5
*/
int hev_task_channel_new (HevTaskChannel **chan1, HevTaskChannel **chan2);
/**
* hev_task_channel_new_with_buffers:
* @chan1: (out): a #HevTaskChannel
* @chan2: (out): a #HevTaskChannel
* @size: buffer size
* @buffers: buffers capacity
*
* Creates a pair of connected task channel with a capacity of @buffers.
* The channels are asynchronous, sending or receiving a data will not wait
* unless the channel is already full.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 5.1.0
*/
int hev_task_channel_new_with_buffers (HevTaskChannel **chan1,
HevTaskChannel **chan2,
unsigned int size, unsigned int buffers);
/**
* hev_task_channel_destroy:
* @self: a #HevTaskChannel
*
* Destroy the task channel.
*
* Since: 4.5
*/
void hev_task_channel_destroy (HevTaskChannel *self);
/**
* hev_task_channel_read:
* @self: a #HevTaskChannel
* @buffer: (array length=count): a buffer to read data into
* @count: the number of bytes that will be read
*
* The read function shall attempt to read @count bytes from the channel into
* @buffer. Just as datagram which the data transfer on task channel.
*
* Returns: the number of bytes actually read
*
* Since: 4.5
*/
ssize_t hev_task_channel_read (HevTaskChannel *self, void *buffer,
size_t count);
/**
* hev_task_channel_write:
* @self: a #HevTaskChannel
* @buffer: (array length=count): a buffer to write data from
* @count: the number of bytes that will be write
*
* The write function shall attempt to write @count bytes to the channel from
* @buffer. Just as datagram which the data transfer on task channel.
*
* Returns: the number of bytes actually write
*
* Since: 4.5
*/
ssize_t hev_task_channel_write (HevTaskChannel *self, const void *buffer,
size_t count);
#ifdef __cplusplus
}
#endif
#endif /* __HEV_TASK_CHANNEL_H__ */
@@ -0,0 +1,113 @@
/*
============================================================================
Name : hev-task-cond.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2019 everyone.
Description : Condition
============================================================================
*/
#include <stddef.h>
#include "kern/task/hev-task.h"
#include "lib/misc/hev-compiler.h"
#include "hev-task-cond.h"
struct _HevTaskCondNode
{
HevTaskCondNode *prev;
HevTaskCondNode *next;
HevTask *task;
};
EXPORT_SYMBOL int
hev_task_cond_init (HevTaskCond *self)
{
self->waiters = NULL;
return 0;
}
EXPORT_SYMBOL int
hev_task_cond_wait (HevTaskCond *self, HevTaskMutex *mutex)
{
HevTaskCondNode node;
node.prev = NULL;
node.next = self->waiters;
node.task = hev_task_self ();
if (self->waiters)
self->waiters->prev = &node;
self->waiters = &node;
hev_task_mutex_unlock (mutex);
do {
hev_task_yield (HEV_TASK_WAITIO);
} while (READ_ONCE (node.task));
hev_task_mutex_lock (mutex);
return 0;
}
EXPORT_SYMBOL int
hev_task_cond_timedwait (HevTaskCond *self, HevTaskMutex *mutex,
unsigned int milliseconds)
{
HevTaskCondNode node;
node.prev = NULL;
node.next = self->waiters;
node.task = hev_task_self ();
if (self->waiters)
self->waiters->prev = &node;
self->waiters = &node;
hev_task_mutex_unlock (mutex);
while (milliseconds && READ_ONCE (node.task))
milliseconds = hev_task_sleep (milliseconds);
hev_task_mutex_lock (mutex);
if (READ_ONCE (node.task)) {
if (node.prev)
node.prev->next = node.next;
if (node.next)
node.next->prev = node.prev;
if (self->waiters == &node)
self->waiters = NULL;
return -1;
}
return 0;
}
EXPORT_SYMBOL int
hev_task_cond_signal (HevTaskCond *self)
{
if (self->waiters) {
hev_task_wakeup (self->waiters->task);
self->waiters->task = NULL;
self->waiters = self->waiters->next;
if (self->waiters)
self->waiters->prev = NULL;
}
return 0;
}
EXPORT_SYMBOL int
hev_task_cond_broadcast (HevTaskCond *self)
{
while (self->waiters) {
hev_task_wakeup (self->waiters->task);
self->waiters->task = NULL;
self->waiters = self->waiters->next;
}
return 0;
}
@@ -0,0 +1,96 @@
/*
============================================================================
Name : hev-task-cond.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2019 everyone.
Description : Condition
============================================================================
*/
#ifndef __HEV_TASK_COND_H__
#define __HEV_TASK_COND_H__
#include "hev-task-mutex.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _HevTaskCond HevTaskCond;
typedef struct _HevTaskCondNode HevTaskCondNode;
struct _HevTaskCond
{
HevTaskCondNode *waiters;
};
/**
* hev_task_cond_init:
* @self: a #HevTaskCond
*
* Initialize the task condition.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 4.4
*/
int hev_task_cond_init (HevTaskCond *self);
/**
* hev_task_cond_wait:
* @self: a #HevTaskCond
* @mutex: a #HevTaskMutex
*
* Wait on the task condition.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 4.4
*/
int hev_task_cond_wait (HevTaskCond *self, HevTaskMutex *mutex);
/**
* hev_task_cond_wait:
* @self: a #HevTaskCond
* @mutex: a #HevTaskMutex
* @milliseconds: wait time
*
* The timedwait function shall be equivalent to condition wait, except that an
* error is returned if the time specified by @milliseconds passes.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 4.4
*/
int hev_task_cond_timedwait (HevTaskCond *self, HevTaskMutex *mutex,
unsigned int milliseconds);
/**
* hev_task_cond_signal:
* @self: a #HevTaskCond
*
* Wake one task that wait on condition.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 4.4
*/
int hev_task_cond_signal (HevTaskCond *self);
/**
* hev_task_cond_broadcast:
* @self: a #HevTaskCond
*
* Wake all task that wait on condition.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 4.4
*/
int hev_task_cond_broadcast (HevTaskCond *self);
#ifdef __cplusplus
}
#endif
#endif /* __HEV_TASK_MUTEX_H__ */
@@ -0,0 +1,82 @@
/*
============================================================================
Name : hev-task-mutex.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2019 everyone.
Description : Mutex
============================================================================
*/
#include <stddef.h>
#include "kern/task/hev-task.h"
#include "lib/misc/hev-compiler.h"
#include "hev-task-mutex.h"
struct _HevTaskMutexNode
{
HevTaskMutexNode *next;
HevTask *task;
};
EXPORT_SYMBOL int
hev_task_mutex_init (HevTaskMutex *self)
{
self->locker = 0;
self->waiters = NULL;
return 0;
}
EXPORT_SYMBOL int
hev_task_mutex_lock (HevTaskMutex *self)
{
if (self->locker) {
HevTaskMutexNode node;
node.next = self->waiters;
node.task = hev_task_self ();
self->waiters = &node;
do {
hev_task_yield (HEV_TASK_WAITIO);
} while (READ_ONCE (self->locker) ||
READ_ONCE (self->waiters) != &node);
self->waiters = node.next;
}
barrier ();
self->locker = 1;
barrier ();
return 0;
}
EXPORT_SYMBOL int
hev_task_mutex_trylock (HevTaskMutex *self)
{
if (self->locker)
return -1;
barrier ();
self->locker = 1;
barrier ();
return 0;
}
EXPORT_SYMBOL int
hev_task_mutex_unlock (HevTaskMutex *self)
{
barrier ();
self->locker = 0;
barrier ();
if (self->waiters)
hev_task_wakeup (self->waiters->task);
return 0;
}
@@ -0,0 +1,79 @@
/*
============================================================================
Name : hev-task-mutex.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2019 everyone.
Description : Mutex
============================================================================
*/
#ifndef __HEV_TASK_MUTEX_H__
#define __HEV_TASK_MUTEX_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _HevTaskMutex HevTaskMutex;
typedef struct _HevTaskMutexNode HevTaskMutexNode;
struct _HevTaskMutex
{
unsigned int locker;
HevTaskMutexNode *waiters;
};
/**
* hev_task_mutex_init:
* @self: a #HevTaskMutex
*
* Initialize the task mutex.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 4.3
*/
int hev_task_mutex_init (HevTaskMutex *self);
/**
* hev_task_mutex_lock:
* @self: a #HevTaskMutex
*
* Lock the task mutex.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 4.3
*/
int hev_task_mutex_lock (HevTaskMutex *self);
/**
* hev_task_mutex_trylock:
* @self: a #HevTaskMutex
*
* Try lock the task mutex.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 4.3
*/
int hev_task_mutex_trylock (HevTaskMutex *self);
/**
* hev_task_mutex_unlock:
* @self: a #HevTaskMutex
*
* Unlock the task mutex.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 4.3
*/
int hev_task_mutex_unlock (HevTaskMutex *self);
#ifdef __cplusplus
}
#endif
#endif /* __HEV_TASK_MUTEX_H__ */
@@ -0,0 +1,45 @@
/*
============================================================================
Name : hev-task-call.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2020 everyone.
Description : Task call
============================================================================
*/
#include <stdint.h>
#include "lib/misc/hev-compiler.h"
#include "mem/api/hev-memory-allocator-api.h"
#include "hev-task-call.h"
extern void hev_task_execute (HevTaskCall *self, HevTaskCallEntry entry);
EXPORT_SYMBOL HevTaskCall *
hev_task_call_new (int base_size, int stack_size)
{
HevTaskCall *self;
self = hev_malloc (base_size + stack_size);
if (self) {
uintptr_t stack_addr;
stack_addr = (uintptr_t)((void *)self + base_size + stack_size);
self->stack_top = (void *)ALIGN_DOWN (stack_addr, 16);
}
return self;
}
EXPORT_SYMBOL void
hev_task_call_destroy (HevTaskCall *self)
{
hev_free (self);
}
EXPORT_SYMBOL void *
hev_task_call_jump (HevTaskCall *self, HevTaskCallEntry entry)
{
hev_task_execute (self, entry);
return self->retval;
}
@@ -0,0 +1,81 @@
/*
============================================================================
Name : hev-task-call.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2020 everyone.
Description : Task call
============================================================================
*/
#ifndef __HEV_TASK_CALL_H__
#define __HEV_TASK_CALL_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _HevTaskCall HevTaskCall;
typedef void (*HevTaskCallEntry) (HevTaskCall *call);
struct _HevTaskCall
{
void *stack_top;
void *retval;
};
/**
* hev_task_call_new:
* @base_size: base size
* @stack_size: stack size
*
* Creates a new task call.
*
* Returns: a new #HevTaskCall.
*
* Since: 4.8.0
*/
HevTaskCall *hev_task_call_new (int base_size, int stack_size);
/**
* hev_task_call_destroy:
* @self: a #HevTaskCall
*
* Destroy the task call.
*
* Since: 4.8.0
*/
void hev_task_call_destroy (HevTaskCall *self);
/**
* hev_task_call_jump:
* @self: a #HevTaskCall
* @entry: task call entry
*
* Call @entry on new stack.
*
* Returns: value from @entry (see set_retval).
*
* Since: 4.8.0
*/
void *hev_task_call_jump (HevTaskCall *self, HevTaskCallEntry entry);
/**
* hev_task_call_set_retval:
* @self: a #HevTaskCall
* @value: return value
*
* Set return value of task call.
*
* Since: 4.8.0
*/
static inline void
hev_task_call_set_retval (HevTaskCall *self, void *value)
{
self->retval = value;
}
#ifdef __cplusplus
}
#endif
#endif /* __HEV_TASK_CALL_H__ */
@@ -0,0 +1,96 @@
/*
============================================================================
Name : hev-task-execute.S
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2017 everyone.
Description :
============================================================================
*/
#if defined(__i386__)
# include "arch/x86/hev-task-execute-x86.s"
#elif defined(__x86_64__)
# include "arch/x86/hev-task-execute-x86_64.s"
#elif defined(__mips__)
# if (_MIPS_SIM == _ABI64)
# include "arch/mips/hev-task-execute-mips64.s"
# else
# include "arch/mips/hev-task-execute-mips32.s"
# endif
#elif defined(__arm__)
# include "arch/arm/hev-task-execute-arm.s"
#elif defined(__aarch64__)
# include "arch/arm/hev-task-execute-aarch64.s"
#elif defined(__sw_64__)
# include "arch/sw64/hev-task-execute-sw64.s"
#elif defined(__riscv)
# if defined(_LP64)
# include "arch/riscv/hev-task-execute-riscv64.s"
# else
# include "arch/riscv/hev-task-execute-riscv32.s"
# endif
#elif defined(__loongarch__)
# if defined(_LP64)
# include "arch/loong/hev-task-execute-la64.s"
# else
# include "arch/loong/hev-task-execute-la32.s"
# endif
#elif defined(__powerpc64__)
# include "arch/ppc/hev-task-execute-ppc64.s"
#elif defined(__powerpc__)
# include "arch/ppc/hev-task-execute-ppc32.s"
#elif defined(__arc__)
# include "arch/arc/hev-task-execute-arc32.s"
#elif defined(__m68k__)
# include "arch/m68k/hev-task-execute-m68k.s"
#elif defined(__microblaze__)
# include "arch/microblaze/hev-task-execute-microblaze.s"
#elif defined(__s390x__)
# include "arch/s390/hev-task-execute-s390x.s"
#elif defined(__sh__)
# include "arch/sh/hev-task-execute-sh.s"
#elif defined(__or1k__)
# include "arch/openrisc/hev-task-execute-or1k.s"
#else
# error "Unsupported platform!"
#endif
#if defined(__ELF__) && defined(__linux__)
/* An executable stack is *not* required for these functions. */
.section .note.GNU-stack,"",%progbits
.previous
#endif
@@ -0,0 +1,25 @@
/*
============================================================================
Name : hev-task-executer.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2017 everyone.
Description :
============================================================================
*/
#include "hev-task-executer.h"
#include "kern/core/hev-task-system-private.h"
void
hev_task_executer (HevTask *task)
{
if (_setjmp (task->context) == 0)
return;
task->entry (task->data);
if (task->joiner)
hev_task_wakeup (task->joiner);
hev_task_system_kill_current_task ();
}
@@ -0,0 +1,17 @@
/*
============================================================================
Name : hev-task-executer.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2017 everyone.
Description :
============================================================================
*/
#ifndef __HEV_TASK_EXECUTER_H__
#define __HEV_TASK_EXECUTER_H__
#include "hev-task-private.h"
extern void hev_task_executer (HevTask *task);
#endif /* __HEV_TASK_EXECUTER_H__ */
@@ -0,0 +1,53 @@
/*
============================================================================
Name : hev-task-private.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2017 - 2020 everyone.
Description :
============================================================================
*/
#ifndef __HEV_TASK_PRIVATE_H__
#define __HEV_TASK_PRIVATE_H__
#include <stdint.h>
#include <setjmp.h>
#include "hev-task.h"
#include "hev-task-stack.h"
#include "lib/list/hev-list.h"
#include "lib/rbtree/hev-rbtree.h"
typedef struct _HevTaskSchedEntity HevTaskSchedEntity;
struct _HevTaskSchedEntity
{
HevTask *task;
};
struct _HevTask
{
void *stack_bottom;
HevTaskEntry entry;
void *data;
uint64_t sched_key;
HevRBTreeNode sched_node;
HevTaskSchedEntity sched_entity;
HevTaskStack *stack;
HevTask *joiner;
int ref_count;
int priority;
int next_priority;
HevTaskState state;
jmp_buf context;
HevListNode list_node;
};
extern void hev_task_execute (HevTask *self, void *executer);
#endif /* __HEV_TASK_PRIVATE_H__ */
@@ -0,0 +1,99 @@
/*
============================================================================
Name : hev-task-stack-heap.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2020 everyone.
Description :
============================================================================
*/
#include <assert.h>
#include <stdint.h>
#include "lib/misc/hev-compiler.h"
#include "mem/api/hev-memory-allocator-api.h"
#include "hev-task-stack.h"
#if CONFIG_STACK_BACKEND == STACK_HEAP
#ifdef ENABLE_STACK_OVERFLOW_DETECTION
#if CONFIG_STACK_OVERFLOW_DETECTION == 1
#define STACK_OVERFLOW_DETECTION_SIZE (4)
#elif CONFIG_STACK_OVERFLOW_DETECTION == 2
#define STACK_OVERFLOW_DETECTION_SIZE (4096)
#else
#define STACK_OVERFLOW_DETECTION_SIZE (8192)
#endif
#define STACK_OVERFLOW_DETECTION_TAG (0xdeadbeefu)
#else
#define STACK_OVERFLOW_DETECTION_SIZE (0)
#endif
struct _HevTaskStack
{
int size;
};
static inline void
hev_task_stack_detection_mark (HevTaskStack *self)
{
#ifdef ENABLE_STACK_OVERFLOW_DETECTION
const unsigned int tag = STACK_OVERFLOW_DETECTION_TAG;
const unsigned int tags = STACK_OVERFLOW_DETECTION_SIZE / sizeof (tag);
unsigned int *tagp = (unsigned int *)(self + 1);
int i;
for (i = 0; i < tags; i++)
tagp[i] = tag;
#endif
}
static inline void
hev_task_stack_detection_check (HevTaskStack *self)
{
#ifdef ENABLE_STACK_OVERFLOW_DETECTION
const unsigned int tag = STACK_OVERFLOW_DETECTION_TAG;
const unsigned int tags = STACK_OVERFLOW_DETECTION_SIZE / sizeof (tag);
unsigned int *tagp = (unsigned int *)(self + 1);
int i;
for (i = 0; i < tags; i++)
assert (tagp[i] == tag);
#endif
}
HevTaskStack *
hev_task_stack_new (int size)
{
HevTaskStack *self;
size += STACK_OVERFLOW_DETECTION_SIZE;
self = hev_malloc (sizeof (HevTaskStack) + size);
if (self)
self->size = size;
hev_task_stack_detection_mark (self);
return self;
}
void
hev_task_stack_destroy (HevTaskStack *self)
{
hev_task_stack_detection_check (self);
hev_free (self);
}
void *
hev_task_stack_get_base (HevTaskStack *self)
{
return (void *)(self + 1);
}
void *
hev_task_stack_get_bottom (HevTaskStack *self)
{
return (void *)ALIGN_DOWN ((intptr_t)self + self->size, 16);
}
#endif /* CONFIG_STACK_BACKEND == STACK_HEAP */
@@ -0,0 +1,87 @@
/*
============================================================================
Name : hev-task-stack-mmap.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2021 - 2025 everyone.
Description :
============================================================================
*/
#include <unistd.h>
#include <sys/mman.h>
#include "lib/misc/hev-compiler.h"
#include "mem/api/hev-memory-allocator-api.h"
#include "hev-task-stack.h"
#if CONFIG_STACK_BACKEND == STACK_MMAP
#ifndef MAP_STACK
#define MAP_STACK (0)
#endif
struct _HevTaskStack
{
int size;
void *stack;
};
HevTaskStack *
hev_task_stack_new (int size)
{
HevTaskStack *self;
static int page_size;
if (!page_size)
page_size = getpagesize ();
size = ALIGN_UP (size, page_size);
#ifdef ENABLE_STACK_OVERFLOW_DETECTION
size += page_size;
#endif
self = hev_malloc (sizeof (HevTaskStack));
if (!self)
return NULL;
self->stack = mmap (NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
if (self->stack == MAP_FAILED) {
hev_free (self);
return NULL;
}
#ifdef ENABLE_STACK_OVERFLOW_DETECTION
if (mprotect (self->stack, page_size, PROT_NONE) < 0) {
munmap (self->stack, size);
hev_free (self);
return NULL;
}
#endif
self->size = size;
return self;
}
void
hev_task_stack_destroy (HevTaskStack *self)
{
munmap (self->stack, self->size);
hev_free (self);
}
void *
hev_task_stack_get_base (HevTaskStack *self)
{
return self->stack;
}
void *
hev_task_stack_get_bottom (HevTaskStack *self)
{
return self->stack + self->size;
}
#endif /* CONFIG_STACK_BACKEND == STACK_MMAP */
@@ -0,0 +1,24 @@
/*
============================================================================
Name : hev-task-stack.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2020 everyone.
Description :
============================================================================
*/
#ifndef __HEV_TASK_STACK_H__
#define __HEV_TASK_STACK_H__
#define STACK_HEAP (0)
#define STACK_MMAP (1)
typedef struct _HevTaskStack HevTaskStack;
HevTaskStack *hev_task_stack_new (int size);
void hev_task_stack_destroy (HevTaskStack *self);
void *hev_task_stack_get_base (HevTaskStack *self);
void *hev_task_stack_get_bottom (HevTaskStack *self);
#endif /* __HEV_TASK_STACK_H__ */
@@ -0,0 +1,240 @@
/*
============================================================================
Name : hev-task.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2017 - 2025 everyone.
Description :
============================================================================
*/
#include <stdlib.h>
#include <stdint.h>
#include "lib/misc/hev-compiler.h"
#include "kern/core/hev-task-system-private.h"
#include "mem/api/hev-memory-allocator-api.h"
#include "hev-task-private.h"
#include "hev-task.h"
#define HEV_TASK_STACK_SIZE (64 * 1024)
EXPORT_SYMBOL HevTask *
hev_task_new (int stack_size)
{
HevTask *self;
self = hev_malloc0 (sizeof (HevTask));
if (!self)
return NULL;
self->ref_count = 1;
self->next_priority = HEV_TASK_PRIORITY_DEFAULT;
if (stack_size < 0)
stack_size = HEV_TASK_STACK_SIZE;
self->stack = hev_task_stack_new (stack_size);
if (!self->stack) {
hev_free (self);
return NULL;
}
self->stack_bottom = hev_task_stack_get_bottom (self->stack);
self->sched_entity.task = self;
hev_list_add_tail (&hev_task_system_get_context ()->all_tasks,
&self->list_node);
return self;
}
EXPORT_SYMBOL HevTask *
hev_task_ref (HevTask *self)
{
self->ref_count++;
return self;
}
EXPORT_SYMBOL void
hev_task_unref (HevTask *self)
{
self->ref_count--;
if (self->ref_count)
return;
hev_list_del (&hev_task_system_get_context ()->all_tasks, &self->list_node);
hev_task_stack_destroy (self->stack);
hev_free (self);
}
EXPORT_SYMBOL HevTask *
hev_task_self (void)
{
return hev_task_system_get_context ()->current_task;
}
EXPORT_SYMBOL HevTaskState
hev_task_get_state (HevTask *self)
{
return self->state;
}
EXPORT_SYMBOL void
hev_task_set_priority (HevTask *self, int priority)
{
if (priority < HEV_TASK_PRIORITY_MIN)
priority = HEV_TASK_PRIORITY_MIN;
else if (priority > HEV_TASK_PRIORITY_MAX)
priority = HEV_TASK_PRIORITY_MAX;
self->next_priority = priority;
}
EXPORT_SYMBOL int
hev_task_get_priority (HevTask *self)
{
return self->next_priority;
}
EXPORT_SYMBOL int
hev_task_add_fd (HevTask *self, int fd, unsigned int events)
{
HevTaskIOReactor *reactor;
HevTaskIOReactorSetupEvent revents[HEV_TASK_IO_REACTOR_EVENT_GEN_MAX];
int count;
reactor = hev_task_system_get_context ()->reactor;
count = hev_task_io_reactor_setup_event_fd_gen (
revents, fd, HEV_TASK_IO_REACTOR_OP_ADD, events, &self->sched_entity);
return hev_task_io_reactor_setup (reactor, revents, count);
}
EXPORT_SYMBOL int
hev_task_mod_fd (HevTask *self, int fd, unsigned int events)
{
HevTaskIOReactor *reactor;
HevTaskIOReactorSetupEvent revents[HEV_TASK_IO_REACTOR_EVENT_GEN_MAX];
int count;
reactor = hev_task_system_get_context ()->reactor;
count = hev_task_io_reactor_setup_event_fd_gen (
revents, fd, HEV_TASK_IO_REACTOR_OP_MOD, events, &self->sched_entity);
return hev_task_io_reactor_setup (reactor, revents, count);
}
EXPORT_SYMBOL int
hev_task_del_fd (HevTask *self, int fd)
{
HevTaskIOReactor *reactor;
HevTaskIOReactorSetupEvent revents[HEV_TASK_IO_REACTOR_EVENT_GEN_MAX];
int count;
reactor = hev_task_system_get_context ()->reactor;
count = hev_task_io_reactor_setup_event_fd_gen (
revents, fd, HEV_TASK_IO_REACTOR_OP_DEL, 0, NULL);
return hev_task_io_reactor_setup (reactor, revents, count);
}
EXPORT_SYMBOL int
hev_task_add_whandle (HevTask *self, void *handle)
{
HevTaskIOReactor *reactor;
HevTaskIOReactorSetupEvent revents[HEV_TASK_IO_REACTOR_EVENT_GEN_MAX];
int count;
reactor = hev_task_system_get_context ()->reactor;
count = hev_task_io_reactor_setup_event_whandle_gen (
revents, handle, HEV_TASK_IO_REACTOR_OP_ADD, &self->sched_entity);
if (count < 0)
return -1;
return hev_task_io_reactor_setup (reactor, revents, count);
}
EXPORT_SYMBOL int
hev_task_del_whandle (HevTask *self, void *handle)
{
HevTaskIOReactor *reactor;
HevTaskIOReactorSetupEvent revents[HEV_TASK_IO_REACTOR_EVENT_GEN_MAX];
int count;
reactor = hev_task_system_get_context ()->reactor;
count = hev_task_io_reactor_setup_event_whandle_gen (
revents, handle, HEV_TASK_IO_REACTOR_OP_DEL, NULL);
if (count < 0)
return -1;
return hev_task_io_reactor_setup (reactor, revents, count);
}
EXPORT_SYMBOL void
hev_task_wakeup (HevTask *task)
{
hev_task_system_wakeup_task (task);
}
EXPORT_SYMBOL void
hev_task_yield (HevTaskYieldType type)
{
hev_task_system_schedule (type);
}
EXPORT_SYMBOL unsigned int
hev_task_sleep (unsigned int milliseconds)
{
HevTaskSystemContext *ctx;
if (milliseconds == 0)
return 0;
ctx = hev_task_system_get_context ();
return hev_task_timer_wait (ctx->timer, milliseconds, ctx->current_task);
}
EXPORT_SYMBOL void
hev_task_run (HevTask *self, HevTaskEntry entry, void *data)
{
/* Skip to run task that already running */
if (self->state != HEV_TASK_STOPPED)
return;
self->entry = entry;
self->data = data;
self->priority = self->next_priority;
self->sched_key = self->next_priority;
hev_task_system_run_new_task (self);
}
EXPORT_SYMBOL void
hev_task_exit (void)
{
hev_task_system_kill_current_task ();
}
EXPORT_SYMBOL int
hev_task_join (HevTask *task)
{
if (task->joiner)
return -1;
task->joiner = hev_task_self ();
for (;;) {
if (hev_task_get_state (task) == HEV_TASK_STOPPED)
break;
hev_task_wakeup (task);
hev_task_yield (HEV_TASK_WAITIO);
}
return 0;
}
EXPORT_SYMBOL void *
hev_task_get_data (HevTask *self)
{
return self->data;
}
@@ -0,0 +1,314 @@
/*
============================================================================
Name : hev-task.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2017 - 2025 everyone.
Description :
============================================================================
*/
#ifndef __HEV_TASK_H__
#define __HEV_TASK_H__
#include <poll.h>
#ifdef __cplusplus
extern "C" {
#endif
#define HEV_TASK_PRIORITY_MIN (0)
#define HEV_TASK_PRIORITY_MAX (15)
#define HEV_TASK_PRIORITY_HIGH HEV_TASK_PRIORITY_MIN
#define HEV_TASK_PRIORITY_LOW HEV_TASK_PRIORITY_MAX
#define HEV_TASK_PRIORITY_DEFAULT (8)
#define HEV_TASK_PRIORITY_REALTIME (0)
typedef struct _HevTask HevTask;
typedef void (*HevTaskEntry) (void *data);
/**
* HevTaskState:
* @HEV_TASK_STOPPED: The task is not in any task system.
* @HEV_TASK_RUNNING: The task is in a task system's running tree.
* @HEV_TASK_WAITING: The task is in a task system's waiting poll.
*
* Since: 1.0
*/
typedef enum
{
HEV_TASK_STOPPED,
HEV_TASK_RUNNING,
HEV_TASK_WAITING,
} HevTaskState;
/**
* HevTaskYieldType:
* @HEV_TASK_YIELD: Move task to yield waiting state.
* @HEV_TASK_WAITIO: Move task to I/O waiting state.
* @HEV_TASK_YIELD_COUNT: Maximum yield type count.
*
* Since: 1.0
*/
typedef enum
{
HEV_TASK_YIELD = 1,
HEV_TASK_WAITIO,
HEV_TASK_YIELD_COUNT,
} HevTaskYieldType;
/**
* hev_task_new:
* @stack_size: stack size for task
*
* Creates a new task. If @stack_size = -1, the default stack size
* will be used.
*
* Returns: a new #HevTask.
*
* Since: 1.0
*/
HevTask *hev_task_new (int stack_size);
/**
* hev_task_ref:
* @self: a #HevTask
*
* Increases the reference count of the @self by one.
*
* Returns: a #HevTask
*
* Since: 1.0
*/
HevTask *hev_task_ref (HevTask *self);
/**
* hev_task_unref:
* @self: a #HevTask
*
* Decreases the reference count of @self. When its reference count
* drops to 0, the object is finalized (i.e. its memory is freed).
*
* Since: 1.0
*/
void hev_task_unref (HevTask *self);
/**
* hev_task_self:
*
* Get the current task.
*
* Returns: a #HevTask
*
* Since: 1.0
*/
HevTask *hev_task_self (void);
/**
* hev_task_get_state:
* @self: a #HevTask
*
* Get the state of a task.
*
* Returns: a #HevTaskState
*
* Since: 1.0
*/
HevTaskState hev_task_get_state (HevTask *self);
/**
* hev_task_set_priority:
* @self: a #HevTask
* @priority: priority
*
* Set the priority of a task. The value range of priority are [0-1],
* with smaller values representing higher priorities.
*
* Since: 1.0
*/
void hev_task_set_priority (HevTask *self, int priority);
/**
* hev_task_get_priority:
* @self: a #HevTask
*
* Get the priority of a task.
*
* Returns: current priority of task
*
* Since: 1.0
*/
int hev_task_get_priority (HevTask *self);
/**
* hev_task_add_fd:
* @self: a #HevTask
* @fd: a file descriptor
* @events: a poll events. (e.g. POLLIN, POLLOUT)
*
* Add a file descriptor to I/O reactor of task system. The task system will
* wake up the task when I/O events ready.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 1.0
*/
int hev_task_add_fd (HevTask *self, int fd, unsigned int events);
/**
* hev_task_mod_fd:
* @self: a #HevTask
* @fd: a file descriptor
* @events: a poll events.
*
* Modify events of a file descriptor that added into I/O reactor of task
* system.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 1.0
*/
int hev_task_mod_fd (HevTask *self, int fd, unsigned int events);
/**
* hev_task_del_fd:
* @self: a #HevTask
* @fd: a file descriptor
*
* Remove a file descriptor from I/O reactor of task system.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 1.0
*/
int hev_task_del_fd (HevTask *self, int fd);
/**
* hev_task_add_whandle:
* @self: a #HevTask
* @handle: a waitable handle
*
* Add a waitable handle to I/O reactor of task system. The task system will
* wake up the task when signaled.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 5.8
*/
int hev_task_add_whandle (HevTask *self, void *handle);
/**
* hev_task_del_whandle:
* @self: a #HevTask
* @handle: a waitable handle
*
* Remove a waitable handle from I/O reactor of task system.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 5.8
*/
int hev_task_del_whandle (HevTask *self, void *handle);
/**
* hev_task_wakeup:
* @self: a #HevTask
*
* Wake up a task. Don't switch tasks immediately.
*
* Since: 1.0
*/
void hev_task_wakeup (HevTask *task);
/**
* hev_task_yield:
* @type: type of #HevTaskYieldType
*
* Save current task context, pick a new task and switch to.
*
* Since: 1.0
*/
void hev_task_yield (HevTaskYieldType type);
/**
* hev_task_sleep:
* @milliseconds: time to sleep
*
* Like yield. The task will be waked up by two condition:
* 1. Timer. time has elapsed.
* 2. I/O events. The task will be waked up by file descriptors events.
*
* Returns: Zero if the requested time has elapsed, or
* the number of milliseconds left to sleep.
*
* Since: 1.0
*/
unsigned int hev_task_sleep (unsigned int milliseconds);
/**
* hev_task_usleep:
* @microseconds: time to sleep
*
* Like yield. The task will be waked up by two condition:
* 1. Timer. time has elapsed.
* 2. I/O events. The task will be waked up by file descriptors events.
*
* Returns: Zero if the requested time has elapsed, or
* the number of microseconds left to sleep.
*
* Deprecated: 5.4.0
*/
unsigned int hev_task_usleep (unsigned int microseconds);
/**
* hev_task_run:
* @self (transfer full): a #HevTask
* @entry: A #HevTaskEntry
* @data (nullable): a user data to passed to @entry
*
* Set the entry and data to the task, and add to running tree of task system.
* The task will be really run after task system run or current task yield.
*
* Since: 1.0
*/
void hev_task_run (HevTask *self, HevTaskEntry entry, void *data);
/**
* hev_task_exit:
*
* The function terminates the calling process immediately.
*
* Since: 1.4
*/
void hev_task_exit (void);
/**
* hev_task_join:
* @task: a #HevTask
*
* Join with a terminated task.
*
* Returns: When successful, returns zero. When an error occurs, returns -1.
*
* Since: 5.2.6
*/
int hev_task_join (HevTask *task);
/**
* hev_task_get_data:
* @self: a #HevTask
*
* Get the user data of a task that set by run.
*
* Returns: current data of task.
*
* Since: 3.3.4
*/
void *hev_task_get_data (HevTask *self);
#ifdef __cplusplus
}
#endif
#endif /* __HEV_TASK_H__ */
@@ -0,0 +1,216 @@
/*
============================================================================
Name : hev-task-timer.c
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2018 - 2025 everyone.
Description : Timer
============================================================================
*/
#include <stdlib.h>
#include "hev-task-timer.h"
#include "kern/core/hev-task-system-private.h"
#include "mem/api/hev-memory-allocator-api.h"
#include "lib/misc/hev-compiler.h"
typedef struct _HevTaskTimerNode HevTaskTimerNode;
struct _HevTaskTimer
{
HevRBTreeCached sort_tree;
HevTaskSystemContext *ctx;
};
struct _HevTaskTimerNode
{
HevRBTreeNode base;
struct timespec expire;
HevTask *task;
};
static inline int
hev_task_timer_cmp (const struct timespec *a, const struct timespec *b)
{
if (a->tv_sec < b->tv_sec)
return -1;
if (a->tv_sec > b->tv_sec)
return 1;
if (a->tv_nsec < b->tv_nsec)
return -1;
if (a->tv_nsec > b->tv_nsec)
return 1;
return 0;
}
static inline int
hev_task_timer_node_cmp (HevTaskTimerNode *a, HevTaskTimerNode *b)
{
int res;
res = hev_task_timer_cmp (&a->expire, &b->expire);
if (res)
return res;
if (a < b)
return -1;
if (a > b)
return 1;
return 0;
}
static inline void
hev_task_timer_get_curr (struct timespec *curr)
{
if (clock_gettime (CLOCK_MONOTONIC, curr) < 0)
abort ();
}
static inline void
hev_task_timer_get_expire (struct timespec *expire, unsigned int milliseconds)
{
expire->tv_sec += milliseconds / 1000;
expire->tv_nsec += (milliseconds % 1000) * 1000000;
if (expire->tv_nsec > 1000000000L) {
expire->tv_sec++;
expire->tv_nsec -= 1000000000L;
}
}
static inline unsigned int
hev_task_timer_get_time (const struct timespec *curr,
const struct timespec *expire)
{
time_t sec;
long nsec;
sec = expire->tv_sec - curr->tv_sec;
nsec = expire->tv_nsec - curr->tv_nsec;
if (nsec < 0) {
sec--;
nsec += 1000000000L;
}
if (sec < 0)
return 0;
return (sec * 1000) + ((nsec + 999999) / 1000000);
}
HevTaskTimer *
hev_task_timer_new (void *ctx)
{
HevTaskTimer *self;
self = hev_malloc0 (sizeof (HevTaskTimer));
if (!self)
return NULL;
self->ctx = ctx;
return self;
}
void
hev_task_timer_destroy (HevTaskTimer *self)
{
hev_free (self);
}
int
hev_task_timer_get_timeout (HevTaskTimer *self)
{
HevTaskTimerNode *this;
HevRBTreeNode *node;
struct timespec curr;
node = hev_rbtree_cached_first (&self->sort_tree);
if (!node)
return -1;
hev_task_timer_get_curr (&curr);
this = container_of (node, HevTaskTimerNode, base);
return hev_task_timer_get_time (&curr, &this->expire);
}
static void
hev_task_timer_wakeup (HevTaskTimer *self, const struct timespec *curr)
{
HevTaskTimerNode *this;
HevRBTreeNode *node;
node = hev_rbtree_cached_first (&self->sort_tree);
if (!node)
return;
this = container_of (node, HevTaskTimerNode, base);
if (hev_task_timer_cmp (curr, &this->expire) < 0)
return;
hev_task_system_wakeup_task_with_context (self->ctx, this->task);
}
void
hev_task_timer_wake (HevTaskTimer *self)
{
HevRBTreeNode *node;
struct timespec curr;
node = hev_rbtree_cached_first (&self->sort_tree);
if (!node)
return;
hev_task_timer_get_curr (&curr);
hev_task_timer_wakeup (self, &curr);
}
unsigned int
hev_task_timer_wait (HevTaskTimer *self, unsigned int milliseconds,
HevTask *task)
{
HevTaskTimerNode curr_node, *node = &curr_node;
HevRBTreeNode **new = &self->sort_tree.base.root, *parent = NULL;
struct timespec curr;
int leftmost = 1;
/* get expire time */
hev_task_timer_get_curr (&node->expire);
hev_task_timer_get_expire (&node->expire, milliseconds);
node->task = task;
/* insert to sort tree */
while (*new) {
HevTaskTimerNode *this = container_of (*new, HevTaskTimerNode, base);
int result = hev_task_timer_node_cmp (node, this);
parent = *new;
if (result < 0) {
new = &((*new)->left);
} else {
new = &((*new)->right);
leftmost = 0;
}
}
hev_rbtree_node_link (&node->base, parent, new);
hev_rbtree_cached_insert_color (&self->sort_tree, &node->base, leftmost);
hev_task_yield (HEV_TASK_WAITIO);
/* check current is first */
if (&node->base == hev_rbtree_cached_first (&self->sort_tree))
leftmost = 1;
/* remove from sort tree */
hev_rbtree_cached_erase (&self->sort_tree, &node->base);
hev_task_timer_get_curr (&curr);
if (leftmost)
hev_task_timer_wakeup (self, &curr);
/* get remaining milliseconds */
return hev_task_timer_get_time (&curr, &curr_node.expire);
}
@@ -0,0 +1,29 @@
/*
============================================================================
Name : hev-task-timer.h
Author : Heiher <r@hev.cc>
Copyright : Copyright (c) 2018 - 2025 everyone.
Description : Timer
============================================================================
*/
#ifndef __HEV_TASK_TIMER_H__
#define __HEV_TASK_TIMER_H__
#include <time.h>
#include "kern/task/hev-task.h"
#include "lib/rbtree/hev-rbtree-cached.h"
typedef struct _HevTaskTimer HevTaskTimer;
HevTaskTimer *hev_task_timer_new (void *ctx);
void hev_task_timer_destroy (HevTaskTimer *self);
int hev_task_timer_get_timeout (HevTaskTimer *self);
void hev_task_timer_wake (HevTaskTimer *self);
unsigned int hev_task_timer_wait (HevTaskTimer *self, unsigned int milliseconds,
HevTask *task);
#endif /* __HEV_TASK_TIMER_H__ */