From 0865609ec741865e4440d7751f2a52d53da32fdb Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 10 Jun 2025 22:27:12 +0900 Subject: [PATCH] fixed wrong chaining in hip_sleep() --- Makefile | 19 ++++++- ctx.c | 170 ++++++++++++++++++++----------------------------------- hip.h | 82 +++++++++++++++++++++++++++ 3 files changed, 159 insertions(+), 112 deletions(-) create mode 100644 hip.h diff --git a/Makefile b/Makefile index 417c72a..eef6e72 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,17 @@ -all: - cc -Wall -g -o ctx ctx.c -lrt +SRCS = ctx.c +OBJS = $(SRCS:.c=.o) + +CFLAGS := -Wall -g +LDFLAGS := +LIBS := -lrt + +all: $(OBJS) + $(CC) $(LDFLAGS) -o hip $(OBJS) $(LIBS) + +clean: + rm -f $(OBJS) hip + +.SUFFIXES: .c .o + +.c.o: + $(CC) $(CFLAGS) -c $< diff --git a/ctx.c b/ctx.c index 12ce311..c7c12d8 100644 --- a/ctx.c +++ b/ctx.c @@ -1,4 +1,5 @@ -#include +#include "hip.h" + #include #include #include @@ -21,70 +22,6 @@ #include #endif -typedef unsigned char hip_uint8_t; -typedef unsigned short hip_uint16_t; -typedef unsigned int hip_uint32_t; -typedef unsigned long long hip_uint64_t; - -typedef signed char hip_int8_t; -typedef signed short hip_int16_t; -typedef signed int hip_int32_t; -typedef signed long long hip_int64_t; - - -typedef hip_uint64_t hip_nsecdur_t; - -#if defined(__ILP32__) || defined(_WIN32) -# define MKCTX_NARGS 1 -typedef hip_uint32_t hip_oow_t; -typedef hip_int32_t hip_ooi_t; -#else -# define MKCTX_NARGS 2 -typedef hip_uint64_t hip_oow_t; -typedef hip_int64_t hip_ooi_t; -#endif - -#define HIP_NULL ((void*)0) -#define HIP_INVALID_FD (-1) - -typedef struct hip_t hip_t; -typedef struct hip_uctx_t hip_uctx_t; -typedef struct hip_uctx_link_t hip_uctx_link_t; -typedef void (*hip_ufun_t) (hip_uctx_t* uc, void* ctx); - -enum hip_io_flag_t -{ - HIP_IO_READ = (1 << 0), - HIP_IO_WRITE = (1 << 1) -}; -typedef enum hip_io_flag_t hip_io_flag_t; - -struct hip_uctx_link_t -{ - hip_uctx_link_t* next; - hip_uctx_link_t* prev; -}; - -struct hip_uctx_t -{ - hip_t* hip; - ucontext_t uc; - hip_ufun_t uf; - void* ctx; - hip_oow_t csi; /* number of context switches in */ - hip_oow_t cso; /* number of context switches out */ - - hip_nsecdur_t wakeup_time; - int waiting_fd; - unsigned int stid; - - hip_uctx_link_t uctx; - hip_uctx_link_t io_done; -}; - -#define HIP_OFFSETOF(type, field) ((hip_oow_t)&(((type*)0)->field)) -#define HIP_CONTAINEROF(ptr, type, field) ((type*)((hip_uint8_t*)ptr - HIP_OFFSETOF(type, field))) - #define CHAIN(_link, _prev, _next) do { \ hip_uctx_link_t* _p = _prev; \ hip_uctx_link_t* _n = _next; \ @@ -108,11 +45,23 @@ struct hip_uctx_t #define UCTX_FROM_LINK(_link) HIP_CONTAINEROF(_link, hip_uctx_t, uctx) -enum hip_flag_t +struct hip_uctx_t { - HIP_FLAG_LAZY = (1 << 0) + hip_t* hip; + ucontext_t uc; + int flags; + hip_ufun_t uf; + void* ctx; + hip_oow_t csi; /* number of context switches in */ + hip_oow_t cso; /* number of context switches out */ + + hip_nsecdur_t wakeup_time; + int waiting_fd; + unsigned int stid; + + hip_uctx_link_t uctx; + hip_uctx_link_t io_done; }; -typedef enum hip_flag_t hip_flag_t; struct hip_t { @@ -134,7 +83,6 @@ struct hip_t hip_uctx_t* uctx_mux; ucontext_t uc_main; }; - /* ---------------------------------------------------- */ #if (MKCTX_NARGS <= 1) @@ -171,13 +119,18 @@ printf ("invoke_uf XXXXXXXXXXXXXXXXXXXXX...%p\n", uctx); /* switch to the scheduler */ UNCHAIN(&uctx->uctx); -/* TODO: if auto-destroy is on, delete it */ - //if (uctx->flags & HIP_UCTX_FLAG_AUTO_DESTROY) hip_freertn(hip, uctx); - //else + if (uctx->flags & HIP_RTN_FLAG_AUTO_DESTROY) + { + hip_uctx_close(uctx); +printf (">>>>>>>>>> *********************** CLOSED TERMINATED\n"); + } + else + { ADD_BACK(&uctx->uctx, &hip->terminated); -printf ("ADDED TO TERMINATED\n"); +printf (">>>>>>>>>> ************************ ADDED TO TERMINATED\n"); + } - setcontext(&hip->uctx_sched->uc); + setcontext(&hip->uctx_sched->uc); /* switch to the scheduler */ } //TODO: This part must not be interrupted? @@ -186,7 +139,7 @@ printf ("ADDED TO TERMINATED\n"); // TODO: destroy the object? } -hip_uctx_t* hip_uctx_open(hip_t* hip, hip_oow_t stack_size, hip_ufun_t uf, void* ctx) +hip_uctx_t* hip_uctx_open(hip_t* hip, hip_oow_t stack_size, int flags, hip_ufun_t uf, void* ctx) { hip_uctx_t* uc; void* sp; @@ -197,6 +150,7 @@ hip_uctx_t* hip_uctx_open(hip_t* hip, hip_oow_t stack_size, hip_ufun_t uf, void* memset(uc, 0, sizeof(*uc) + stack_size); uc->hip = hip; + uc->flags = flags; uc->uf = uf; uc->ctx = ctx; uc->waiting_fd = HIP_INVALID_FD; @@ -277,7 +231,7 @@ static void schedule(hip_uctx_t* uctx, void *ctx) if (IS_EMPTY(&hip->runnables)) { /* TODO: check if there are sleeping ... */ - printf (" NO TASK\n"); +// printf (" NO TASK\n"); swapcontext(&hip->uctx_sched->uc, &hip->uctx_mux->uc); if (IS_EMPTY(&hip->runnables)) break; /* no task? */ } @@ -305,12 +259,12 @@ static void multiplex(hip_uctx_t* uctx, void *ctx) hip = uctx->hip; while (1) { -printf ("sleeping empty[%d] io_waiting empty[%d]\n", IS_EMPTY(&hip->sleeping), IS_EMPTY(&hip->io_waiting)); +//printf ("sleeping empty[%d] io_waiting empty[%d]\n", IS_EMPTY(&hip->sleeping), IS_EMPTY(&hip->io_waiting)); if (IS_EMPTY(&hip->sleeping) && IS_EMPTY(&hip->io_waiting)) { // STILL NEED TO HANDLE IO FILE DESCRIPTORS... /* go back to the scheduler */ -printf ("NO SLEEPING. BACK TO SCEDULER\n"); +//printf ("NO SLEEPING. BACK TO SCEDULER\n"); swapcontext(&hip->uctx_mux->uc, &hip->uctx_sched->uc); } else @@ -340,7 +294,7 @@ printf ("NO SLEEPING. BACK TO SCEDULER\n"); epoll_ctl(hip->mux_id, EPOLL_CTL_DEL, u->waiting_fd, HIP_NULL); } -printf ("WAITING %llu\n", (unsigned long long)wait); +//printf ("WAITING %llu\n", (unsigned long long)wait); /* TODO: support different io multiplexers...*/ #if defined(HAVE_EPOLL_PWAIT2) tmout.tv_sec = wait / 1000000000; @@ -356,7 +310,7 @@ printf ("WAITING %llu\n", (unsigned long long)wait); */ n = epoll_pwait(hip->mux_id, ee, 100, (wait + 1000000 - 1) / 1000000, HIP_NULL); #endif -printf ("Epoll returned [%d]\n", (int)n); +//printf ("Epoll returned [%d]\n", (int)n); if (n <= -1) { /* TODO: some error handling action is required */ @@ -385,7 +339,7 @@ printf ("Epoll returned [%d]\n", (int)n); else { -printf ("PWAIT link MULTIPLEX DEL %p fd[%d] io_waiting empty[%d]\n", l, u->waiting_fd, IS_EMPTY(&hip->io_waiting)); +//printf ("PWAIT link MULTIPLEX DEL %p fd[%d] io_waiting empty[%d]\n", l, u->waiting_fd, IS_EMPTY(&hip->io_waiting)); epoll_ctl(hip->mux_id, EPOLL_CTL_DEL, u->waiting_fd, HIP_NULL); u->waiting_fd = HIP_INVALID_FD; @@ -409,7 +363,7 @@ printf ("PWAIT link MULTIPLEX DEL %p fd[%d] io_waiting empty[%d]\n", l, u->waiti /* go back to the scheduler */ if (!IS_EMPTY(&hip->runnables)) { -printf ("BACK TO SCHEDULER \n"); +//printf ("BACK TO SCHEDULER \n"); swapcontext(&hip->uctx_mux->uc, &hip->uctx_sched->uc); } } @@ -516,11 +470,11 @@ void hip_close(hip_t* hip) free(hip); } -hip_uctx_t* hip_newrtn(hip_t* hip, hip_ufun_t uf, void* ctx) +hip_uctx_t* hip_newrtn(hip_t* hip, int flags, hip_ufun_t uf, void* ctx) { hip_uctx_t* uctx; - uctx = hip_uctx_open(hip, 8192, uf, ctx); /* TODO: stack size */ + uctx = hip_uctx_open(hip, 8192, flags, uf, ctx); /* TODO: stack size */ if (!uctx) return HIP_NULL; /* append to the list */ @@ -531,13 +485,13 @@ hip_uctx_t* hip_newrtn(hip_t* hip, hip_ufun_t uf, void* ctx) int hip_schedule(hip_t* hip, int preempt) { - hip->uctx_sched = hip_uctx_open(hip, 40960, schedule, hip); + hip->uctx_sched = hip_uctx_open(hip, 40960, 0, schedule, hip); if (!hip->uctx_sched) return -1; - hip->uctx_mux = hip_uctx_open(hip, 40960, multiplex, hip); + hip->uctx_mux = hip_uctx_open(hip, 40960, 0, multiplex, hip); if (!hip->uctx_mux) { - hip_uctx_close (hip->uctx_sched); + hip_uctx_close(hip->uctx_sched); hip->uctx_sched = HIP_NULL; return -1; } @@ -596,11 +550,7 @@ void hip_sleep(hip_t* hip, hip_nsecdur_t nsecs) rr->wakeup_time = monotime() + nsecs; /* TODO: switch to HEAP. for now simply linear search to keep this list sorted. */ - if (IS_EMPTY(&hip->sleeping)) - { - ADD_BACK(hip->running, &hip->sleeping); - } - else + if (!IS_EMPTY(&hip->sleeping)) { hip_uctx_link_t* l; hip_uctx_t* r; @@ -609,16 +559,17 @@ void hip_sleep(hip_t* hip, hip_nsecdur_t nsecs) r = UCTX_FROM_LINK(l); if (rr->wakeup_time <= r->wakeup_time) { - CHAIN(hip->running, l->prev, l->next); + CHAIN(hip->running, l->prev, l); goto do_sched; } } - ADD_BACK(hip->running, &hip->sleeping); } + /* place the running rountine at the end of the sleeping routines list */ + ADD_BACK(hip->running, &hip->sleeping); do_sched: hip->running = HIP_NULL; - swapcontext(&rr->uc, &hip->uctx_sched->uc); + swapcontext(&rr->uc, &hip->uctx_sched->uc); /* switch to the scheduler */ } void hip_awaitio(hip_t* hip, int fd, int flags) @@ -644,13 +595,13 @@ void hip_awaitio(hip_t* hip, int fd, int flags) * - the waiting context could have changed. */ /* TODO: more optimization based on above */ ev.data.ptr = hip->running; /* store running context link */ -printf ("PWAIT link UPDATE %p fd[%d]\n", ev.data.ptr, fd); +//printf ("PWAIT link UPDATE %p fd[%d]\n", ev.data.ptr, fd); epoll_ctl(hip->mux_id, EPOLL_CTL_MOD, fd, &ev); } else { /* delete and add */ -printf ("PWAIT link DELETE fd[%d]\n", fd); +//printf ("PWAIT link DELETE fd[%d]\n", fd); epoll_ctl(hip->mux_id, EPOLL_CTL_DEL, fd, HIP_NULL); goto add; } @@ -662,7 +613,7 @@ printf ("PWAIT link DELETE fd[%d]\n", fd); if (flags & HIP_IO_READ) ev.events |= EPOLLIN; if (flags & HIP_IO_WRITE) ev.events |= EPOLLOUT; ev.data.ptr = hip->running; /* store running context link */ -printf ("PWAIT link ADD %p fd[%d]\n", ev.data.ptr, fd); +//printf ("PWAIT link ADD %p fd[%d]\n", ev.data.ptr, fd); epoll_ctl(hip->mux_id, EPOLL_CTL_ADD, fd, &ev); /* TODO: error handling - probably panic? */ } @@ -780,12 +731,10 @@ static void uf1(hip_uctx_t* uc, void* ctx) int i; for (i =0; i < 5; i++) { - printf ("************************** uf1 \n"); +printf (">> UF1 TOP [%d]\n", i); //hip_yield(uc->hip); - - hip_sleep(uc->hip, 500000000); - printf ("************************* uf1 1111\n"); +printf (">> UF1 SEC [%d]\n", i); //hip_yield(uc->hip); hip_sleep(uc->hip, 1000000000); } @@ -796,10 +745,10 @@ static void uf2(hip_uctx_t* uc, void* ctx) int i; for (i =0; i < 10; i++) { - printf ("************************** uf2 \n"); +printf (">> UF2 TOP [%d]\n", i); //hip_yield(uc->hip); hip_sleep(uc->hip, 1000000000); - printf ("************************* uf2 2222 XXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxxxxx\n"); +printf (">> UF2 SEC [%d]\n", i); //hip_yield(uc->hip); hip_sleep(uc->hip, 500000000); } @@ -844,14 +793,15 @@ printf ("*********DISCONNECTED>>>>>>>>>>>>>>>\n"); for (i = 0; i < 15; i++) { - printf ("************************** uf3 TOP\n"); +printf (">> UF3 TOP [%d]\n", i); //hip_yield(uc->hip); hip_sleep(uc->hip, 1000000000); - printf ("************************* uf3 3333 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); +printf (">> UF3 SEC [%d]\n", i); //hip_yield(uc->hip); hip_sleep(uc->hip, 1000000000); - if (i == 8) hip_newrtn(uc->hip, uf2, HIP_NULL); + if (i == 8) hip_newrtn(uc->hip, HIP_RTN_FLAG_AUTO_DESTROY, uf2, HIP_NULL); } +printf (">> UF3 DONE DONE\n"); } int main() @@ -860,9 +810,9 @@ int main() hip = hip_open(HIP_FLAG_LAZY); - hip_newrtn(hip, uf1, HIP_NULL); - hip_newrtn(hip, uf2, HIP_NULL); - hip_newrtn(hip, uf3, HIP_NULL); + hip_newrtn(hip, HIP_RTN_FLAG_AUTO_DESTROY, uf1, HIP_NULL); + hip_newrtn(hip, HIP_RTN_FLAG_AUTO_DESTROY, uf2, HIP_NULL); + hip_newrtn(hip, HIP_RTN_FLAG_AUTO_DESTROY, uf3, HIP_NULL); /* jump to the scheduler */ hip_schedule(hip, 0); diff --git a/hip.h b/hip.h new file mode 100644 index 0000000..1353b5b --- /dev/null +++ b/hip.h @@ -0,0 +1,82 @@ +#ifndef _HIP_H_ +#define _HIP_H_ + +#include + +typedef unsigned char hip_uint8_t; +typedef unsigned short hip_uint16_t; +typedef unsigned int hip_uint32_t; +typedef unsigned long long hip_uint64_t; + +typedef signed char hip_int8_t; +typedef signed short hip_int16_t; +typedef signed int hip_int32_t; +typedef signed long long hip_int64_t; + + +typedef hip_uint64_t hip_nsecdur_t; + +#if defined(__ILP32__) || defined(_WIN32) +# define MKCTX_NARGS 1 +typedef hip_uint32_t hip_oow_t; +typedef hip_int32_t hip_ooi_t; +#else +# define MKCTX_NARGS 2 +typedef hip_uint64_t hip_oow_t; +typedef hip_int64_t hip_ooi_t; +#endif + +#define HIP_NULL ((void*)0) +#define HIP_INVALID_FD (-1) + +typedef struct hip_t hip_t; +typedef struct hip_uctx_t hip_uctx_t; +typedef struct hip_uctx_link_t hip_uctx_link_t; +typedef void (*hip_ufun_t) (hip_uctx_t* uc, void* ctx); + +enum hip_io_flag_t +{ + HIP_IO_READ = (1 << 0), + HIP_IO_WRITE = (1 << 1) +}; +typedef enum hip_io_flag_t hip_io_flag_t; + +struct hip_uctx_link_t +{ + hip_uctx_link_t* next; + hip_uctx_link_t* prev; +}; + +#define HIP_OFFSETOF(type, field) ((hip_oow_t)&(((type*)0)->field)) +#define HIP_CONTAINEROF(ptr, type, field) ((type*)((hip_uint8_t*)ptr - HIP_OFFSETOF(type, field))) + +enum hip_flag_t +{ + HIP_FLAG_LAZY = (1 << 0) +}; +typedef enum hip_flag_t hip_flag_t; + +enum hip_rtn_flag_t +{ + HIP_RTN_FLAG_AUTO_DESTROY = (1 << 0) +}; +typedef enum hip_rtn_flag_t hip_rtn_flag_t; + +#if defined(__cplusplus) +extern "C" { +#endif + +hip_t* hip_open(int flags); +void hip_close(hip_t* hip); + +hip_uctx_t* hip_newrtn(hip_t* hip, int flags, hip_ufun_t uf, void* ctx); + + +hip_uctx_t* hip_uctx_open(hip_t* hip, hip_oow_t stack_size, int flags, hip_ufun_t uf, void* ctx); +void hip_uctx_close(hip_uctx_t* uctx); + +#if defined(__cplusplus) +} +#endif + +#endif