diff --git a/.gitmodules b/.gitmodules index 2d8a1b0..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "coroutine"] - path = multitasking/coro - url = https://github.com/clibs/coro.git diff --git a/Makefile b/Makefile index 3a7ad4c..840c76d 100644 --- a/Makefile +++ b/Makefile @@ -29,15 +29,15 @@ CFLAGS += $(call if_coverage,--coverage) # TODO: Remove those warnings only for generated files CFLAGS += -Wno-implicit-fallthrough -Wno-unused-const-variable -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter TARGET_ARCH := -mtune=native -march=native -LDLIBS := +LDLIBS := -lnpth LDFLAGS ?= -flto LDFLAGS += $(call if_coverage,--coverage) # Project configuration ######################################################## -RL_C := wireprotocol.c frontend.c header.c body.c attrs.c frame.c +RL_C := wireprotocol.c header.c body.c attrs.c frame.c RL_O := $(RL_C:.c=.o) -CFILES := main.c log.c utils.c serialization.c autoresponder.c sighandler.c controller.c ucspi.c s6notify.c +CFILES := main.c log.c utils.c serialization.c ucspi.c OFILES := $(RL_O) $(CFILES:.c=.o) UT_C := ut.c serialization.c log.c utils.c contextring.c UT_O := $(UT_C:.c=.o) header.o body.o frame.o attrs.o @@ -46,9 +46,6 @@ NORMAL_O := $(RL_O) ut.o log.o ALL_C := $(CFILES) $(UT_C) ALL_PLIST := $(ALL_C:.c=.plist) -LIBCOMULTI_C := coro.c contextring.c eventloop.c suspendables.c -LIBCOMULTI_O := $(LIBCOMULTI_C:.c=.o) - HOSTNAME := $(shell hostname -f) BUILD_DIR ?= build @@ -69,7 +66,7 @@ clang-analyze: $(ALL_PLIST) tcp-server: frob | d5.txt s6-tcpserver -vd -b2 0.0.0.0 5002 s6-tcpserver-access -t200 -v3 -rp -B "Welcome!\r\n" $(realpath $<) 1000 $| tcp-client: frob | d5.txt - s6-tcpclient -rv localhost 5002 rlwrap $(realpath $<) 1000 $| 2>&1 | s6-tai64n | s6-tai64nlocal + s6-tcpclient -rv localhost 5002 $(realpath $<) 1000 $| tls-server: frob server.cer server.key | d5.txt env -i PATH=/bin CERTFILE=$(word 2,$^) KEYFILE=$(word 3,$^) s6-tlsserver 0.0.0.0 6666 $(realpath $<) -f $(word 1,$^) tls-client: frob server.cer | d5.txt @@ -87,7 +84,7 @@ dir-%: | $(BUILD_DIR)/ # Internal targets ############################################################# tags: - ctags --kinds-C=+p -R . /usr/include/{sys,}/*.h + ctags --kinds-C=+p -R . /usr/include/{sys,bits,}/*.h /usr/local/src/npth test-random: frob pv -Ss100M /dev/urandom | ./$< 1 2>/dev/null 1>/dev/null test-unit: ut @@ -109,12 +106,11 @@ mut: $(NORMAL_O) mutated $(LINK.o) -o $@ $(NORMAL_O) $(MUTATED_O) $(LDLIBS) mutated: CFLAGS += -fexperimental-new-pass-manager -fpass-plugin=/usr/local/lib/mull-ir-frontend-15 -grecord-command-line mutated: $(MUTATED_O) -frob: $(OFILES) libcomulti.a +frob: $(OFILES) $(LINK.o) -o $@ $^ $(LDLIBS) objcopy --only-keep-debug $@ $@.debug strip --strip-unneeded $@ objcopy --add-gnu-debuglink=$@.debug $@ -libcomulti.a: libcomulti.a($(LIBCOMULTI_O)) %.c: %.rl ragel -G2 -L -o $@ $< %.s: %.c diff --git a/frob.h b/frob.h index 9a98b6a..685f9b9 100644 --- a/frob.h +++ b/frob.h @@ -319,7 +319,7 @@ struct s6_notify_args { const int fd; }; -int fsm_wireformat(void*); +void* fsm_wireformat(const struct fsm_wireformat_args*); int fsm_frontend_foreign(struct fsm_frontend_foreign_args*); int fsm_frontend_internal(struct fsm_frontend_internal_args*); int fsm_frontend_timer(struct fsm_frontend_timer_args*); diff --git a/fsm/wireprotocol.rl b/fsm/wireprotocol.rl index abdf3d0..91d97b8 100644 --- a/fsm/wireprotocol.rl +++ b/fsm/wireprotocol.rl @@ -1,9 +1,9 @@ -#include "multitasking/sus.h" #include "frob.h" #include "utils.h" #include "log.h" #include #include +#include %%{ machine wireformat; @@ -18,9 +18,9 @@ } action LRC_Check { if (lrc != fc) { - sus_lend(0, 1, "\x03"); + //sus_lend(0, 1, "\x03"); } else { - sus_lend(0, fpc - start, buf); + //sus_lend(0, fpc - start, buf); } } action Frame_Start { @@ -33,7 +33,7 @@ %% write data; -int fsm_wireformat(void*) { +void* fsm_wireformat(const struct fsm_wireformat_args* const args) { unsigned char* start = NULL; char lrc; ssize_t bytes; @@ -41,8 +41,7 @@ int fsm_wireformat(void*) { int cs; unsigned char* p = buf, * pe = p; %% write init; - set_nonblocking(7); - while ((bytes = sus_read(7, buf, sizeof buf)) > 0) { + while ((bytes = npth_read(args->infd, buf, sizeof buf)) > 0) { pe = (p = buf) + bytes; LOGDXP(char tmp[4*bytes], "→ % 4zd %s", bytes, PRETTY(p, pe, tmp)); %% write exec; @@ -51,6 +50,6 @@ int fsm_wireformat(void*) { LOGE("read"); close(7); LOGIX("FSM state: current/entry/error/final %d/%d/%d/%d", cs, wireformat_en_main, wireformat_error, wireformat_first_final); - sus_disable(0); - return cs == wireformat_error ? -1 : 0; + //sus_disable(0); + return cs == wireformat_error ? NULL + 1 : NULL; } diff --git a/gent1.tcl b/gent1.tcl index 7d918ca..ca4352f 100755 --- a/gent1.tcl +++ b/gent1.tcl @@ -1,5 +1,5 @@ #!/usr/bin/tclsh source ../testsuite/lib/frob.exp -puts [msg T2] +puts [msg T1] after 10000 diff --git a/log.c b/log.c index 31d4345..8a1a200 100644 --- a/log.c +++ b/log.c @@ -7,12 +7,6 @@ int g_log_level = LOG_DEBUG; const char* g_errname; #endif -void init_log(void) { -#ifdef NO_LOGS_ON_STDERR - xfclose(stderr); -#endif -} - char* to_printable(const unsigned char* const p, const unsigned char* const pe, const size_t s, char b[static const s]) { // TODO: Add support for regional characters, ie from 0x80 to 0xFF diff --git a/main.c b/main.c index 15cbd18..7670538 100644 --- a/main.c +++ b/main.c @@ -1,10 +1,24 @@ #include "log.h" #include "utils.h" -#include "multitasking/sus.h" #include "frob.h" #include #include #include +#include + +struct ThreadBag { + npth_t handle; + const char* const name; + void* (* const entry)(void*); + void* const arg; +}; + +int npth_sigwait(const sigset_t *set, int *sig) { + npth_unprotect(); + const int res = sigwait(set, sig); + npth_protect(); + return res; +} static void adjust_rlimit(void) { // This will force syscalls that allocate file descriptors to fail if it @@ -18,29 +32,33 @@ static void adjust_rlimit(void) { } int main(const int ac, const char* av[static const ac]) { - init_log(); if (ac != 3) return 1; adjust_rlimit(); int fd_fo_main = STDOUT_FILENO, fd_fi_main = STDIN_FILENO; ucsp_info_and_adjust_fds(&fd_fo_main, &fd_fi_main); - struct sus_registation_form tasks[] = { - sus_registration(fsm_wireformat, fd_fi_main), - sus_registration(fsm_frontend_foreign), - sus_registration(fsm_frontend_timer), - sus_registration(autoresponder, av[2], 1, fd_fo_main), - sus_registration(sighandler), - sus_registration(s6_notify, -1), - sus_registration(controller), - sus_registration(sus_ioloop, .timeout = atoi(av[1])) + LOGDX("%d %d", fd_fo_main, fd_fi_main); + struct ThreadBag thr[] = { + { .entry = fsm_wireformat, .name = "wireprotocol", .arg = &(struct fsm_wireformat_args){fd_fi_main}} }; - if (sus_runall(lengthof(tasks), &tasks) != 0) - EXITF("Can't start"); - int ret = 0; - for (size_t i = 0; i < lengthof(tasks); i++) { - LOGDX("task %zu returned % 2d (%s)", i, tasks[i].result, tasks[i].name); - if (tasks[i].result) - ret = 100; + npth_init(); + npth_sigev_init(); + npth_sigev_add(SIGINT); + npth_sigev_fini(); + for (size_t i = 0; i < lengthof(thr); i++) { + xnpth_create(&thr[i].handle, NULL, thr[i].entry, thr[i].arg); + xnpth_setname_np(thr[i].handle, thr[i].name); + } + for (;;) { + int sig; + xnpth_sigwait(npth_sigev_sigmask(), &sig); + switch (sig) { + case SIGINT: + LOGD("got %s", strsignal(sig)); + break; + default: + break; + } } - return ret; + return 0; } diff --git a/multitasking/contextring.c b/multitasking/contextring.c deleted file mode 100644 index 0c7e755..0000000 --- a/multitasking/contextring.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "contextring.h" -#include "../utils.h" -#include - -void insert(struct coro_context_ring** const cursor, struct coro_context* const ctx, const char* const name) { - assert(ctx); - assert(cursor); - struct coro_context_ring* const new = xmalloc(sizeof (struct coro_context_ring)); - memset(new, 0, sizeof *new); - if (*cursor) { - const struct coro_context_ring tmp = { - .name = name, - .ctx = ctx, - .next = (*cursor)->next, - .prev = *cursor - }; - memcpy(new, &tmp, sizeof tmp); - (*cursor)->next->prev = new; - (*cursor)->next = new; - *cursor = new; - } else { - const struct coro_context_ring tmp = { - .name = name, - .ctx = ctx, - .next = new, - .prev = new - }; - memcpy(new, &tmp, sizeof tmp); - } - *cursor = new; -} - -void shrink(struct coro_context_ring** const cursor) { - assert(cursor && *cursor); - if ((*cursor)->next == (*cursor)) { - *cursor = NULL; - } else { - (*cursor)->prev->next = (*cursor)->next; - (*cursor)->next->prev = (*cursor)->prev; - *cursor = (*cursor)->next; - } - // FIXME: Free memory! -} diff --git a/multitasking/contextring.h b/multitasking/contextring.h deleted file mode 100644 index b7cd75c..0000000 --- a/multitasking/contextring.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "coro/coro.h" - -struct coro_context_ring { - struct coro_context_ring* prev, * next; - struct coro_context* const ctx; - int visited; - const char* const name; -}; - -void insert(struct coro_context_ring** cursor, struct coro_context* ctx, const char* name) __attribute__((nonnull (1,2))); -void shrink(struct coro_context_ring** cursor) __attribute__((nonnull (1))); diff --git a/multitasking/coro b/multitasking/coro deleted file mode 160000 index 9c50c56..0000000 --- a/multitasking/coro +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9c50c56c3c4a099a2782f316c3366c551bdd7b67 diff --git a/multitasking/eventloop.c b/multitasking/eventloop.c deleted file mode 100644 index 99e4ad4..0000000 --- a/multitasking/eventloop.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "eventloop.h" -#include "../utils.h" -#include -#include -#include -#include - -static char* print_ioparams(const struct io_params* const iop, const size_t size, char buf[static const size]) { - FILE* const s = fmemopen(buf, size, "w"); - assert(s); - for (int i = 0; i < 3; i++) { - xfprintf(s, "%c:", (i == 0 ? 'r' : i == 1 ? 'w' : 'e')); - for (unsigned short fd = 0; fd < iop->maxfd; fd++) - xfprintf(s, "%d", FD_ISSET(fd, &iop->set[i])); - xfputs(" ", s); - } - xfclose(s); - return buf; -} - -static inline int iselect(struct io_params* const iop, struct timeval* const deadline) { - LOGDXP(char tmp[64], "%s", print_ioparams(iop, sizeof tmp, tmp)); - return xselect(iop->maxfd, &iop->set[0], &iop->set[1], &iop->set[2], deadline); -} - -static int io_wait_indefinitely(struct io_params* const iop) { - return iselect(iop, NULL); -} - -static int io_nowait(struct io_params* const iop) { - return iselect(iop, &(struct timeval){}); -} - -static int io_wait_timeout(struct io_params* const iop) { - struct timeval now, relative_timeout; - gettimeofday(&now, NULL); - if (timercmp(&now, &iop->deadline, >=)) - goto timeout; - timersub(&iop->deadline, &now, &relative_timeout); - const int l = iselect(iop, &relative_timeout); - if (l == 0) - goto timeout; - return l; -timeout: - errno = ETIME; - return 0; -} - - __attribute__((__pure__)) -io_wait_f* get_io_wait(const time_t timeout) { - return timeout < 0 ? io_wait_indefinitely : (timeout > 0 ? io_wait_timeout : io_nowait); -} - -struct timeval comp_deadline(const time_t relative) { - struct timeval tmp = { .tv_sec = relative, .tv_usec = 0 }; - if (tmp.tv_sec > 0) { - struct timeval now; - gettimeofday(&now, NULL); - timeradd(&now, &tmp, &tmp); - } - return tmp; -} diff --git a/multitasking/eventloop.h b/multitasking/eventloop.h deleted file mode 100644 index 6a771a3..0000000 --- a/multitasking/eventloop.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -// TODO: Rename to select_parameters -struct io_params { - fd_set set[3]; - const unsigned short maxfd; - const struct timeval deadline; -}; - -typedef int io_wait_f(struct io_params*) __attribute__((nonnull(1))); - -struct timeval comp_deadline(time_t relative); - - __attribute__((__pure__)) -io_wait_f* get_io_wait(time_t timeout); diff --git a/multitasking/gdb.scm b/multitasking/gdb.scm deleted file mode 100644 index e9267f2..0000000 --- a/multitasking/gdb.scm +++ /dev/null @@ -1,8 +0,0 @@ -(use-modules (gdb)) - -; The idea is to set a breakpoint at coro_transfer and each time it is hit – -; save relevant registers to a data structure, then define a command that should -; print backtrace for every item in the data structure. Ideally it should -; replace default bt command. -; -; Similar thing: https://gitlab.com/qemu-project/qemu/-/raw/master/scripts/qemugdb/coroutine.py diff --git a/multitasking/sus.h b/multitasking/sus.h deleted file mode 100644 index f0e8117..0000000 --- a/multitasking/sus.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#define sus_registration(Entry, ...) (struct sus_registation_form){\ - .name = #Entry,\ - .stack_size = 0,\ - .entry = (sus_entry)Entry,\ - .args = &(struct Entry ## _args){ __VA_ARGS__ }\ -} - -typedef int (* sus_entry)(const void*); - -struct sus_registation_form { - const char* const name; - const size_t stack_size; - int result; - const sus_entry entry; - const void* const args; -}; - -struct sus_ioloop_args { - const time_t timeout; -}; - -/** Start and schedule all tasks. - * - * Currently uses round-robin scheduling scheme. In well-written program order - * of tasks in the input array shouldn't matter. - * - * Another idea is to reorder tasks to improve shceduling - */ -int sus_runall(size_t s, struct sus_registation_form (* c)[s]) __attribute__((nonnull (2))); - -ssize_t sus_read(int fd, void* data, size_t size) __attribute__((nonnull(2))); -ssize_t sus_write(int fd, const void* data, size_t size) __attribute__((nonnull(2))); -int sus_ioloop(struct sus_ioloop_args* args) __attribute__((nonnull(1))); - -void sus_lend(uint8_t ch, size_t size, void* data) __attribute__((nonnull(3))); -ssize_t sus_borrow(uint8_t id, void** value) __attribute__((nonnull(2))); -void sus_return(uint8_t id, const void* data, size_t size); -void sus_disable(uint8_t id); diff --git a/multitasking/suspendables.c b/multitasking/suspendables.c deleted file mode 100644 index 2888e09..0000000 --- a/multitasking/suspendables.c +++ /dev/null @@ -1,265 +0,0 @@ -#include "sus.h" -#include "coro/coro.h" -#include "contextring.h" -#include "eventloop.h" -#include "../log.h" -#include "../utils.h" -#include -#include -#include -#include -#include - -enum ioset { IOSET_READ, IOSET_WRITE, IOSET_OOB }; - -struct coro_stuff { - struct coro_stack stack; - struct coro_context ctx; -}; - -union fdset { - fd_set a[3]; - struct { - fd_set r, w, e; - }; -}; - -struct iowork { - size_t size; - void* data; -#ifndef NDEBUG - bool borrowed; // This field is need exclusively for assertions -#endif - bool disabled; -}; - -static struct coro_context s_end; -static struct coro_context_ring* s_current; -static struct iowork s_iow[UINT8_MAX]; -static bool s_io_surrended; - -static struct fdsets { - union fdset scheduled, active; -} s_iop; - -static const char* ioset_to_method(const enum ioset set) { - switch (set) { - case IOSET_READ: return "read"; - case IOSET_WRITE: return "write"; - case IOSET_OOB: return "oob"; - } - return NULL; -} - -static void suspend(void) { - assert(s_current->visited < 100); // EDEADLK - s_current->visited++; - coro_transfer(s_current->ctx, &s_end); -} - -static void suspend_only(const char* const method) { - LOGDX("suspended %s at %s", s_current->name, method); - suspend(); - LOGDX("awaken %s at %s", s_current->name, method); -} - -static void suspend_io(const int fd, const enum ioset set) { - const char* const method = ioset_to_method(set); - LOGDX("suspended %s at %s fd %d", s_current->name, method, fd); - suspend(); - LOGDX("awaken %s at %s fd %d", s_current->name, method, fd); -} - -static void suspend_io_errno(const int fd, const enum ioset set) { - const char* const method = ioset_to_method(set); - LOGD("suspended %s at %s fd %d", s_current->name, method, fd); - suspend(); - LOGDX("awaken %s at %s fd %d", s_current->name, method, fd); -} - -static void suspend_id(const char* const method, const int id) { - LOGDX("suspended %s at %s id %d", s_current->name, method, id); - suspend(); - LOGDX("awaken %s at %s id %d", s_current->name, method, id); -} - -static void suspend_until_active(const int fd, const enum ioset set) { - if (s_io_surrended) { - LOGEX("I/O imposible"); - return; - } - while (!FD_ISSET(fd, &s_iop.active.a[set])) { - if (s_io_surrended) { - LOGEX("I/O imposible"); - return; - } - FD_SET(fd, &s_iop.scheduled.a[set]); - suspend_io(fd, set); - } -} - -ssize_t sus_write(const int fd, const void* const data, const size_t size) { -again: - suspend_until_active(fd, IOSET_WRITE); - const ssize_t r = write(fd, data, size); - if (r < 0 && errno == EAGAIN) { - suspend_io_errno(fd, IOSET_WRITE); - goto again; - } - s_current->visited = 0; - return r; -} - -ssize_t sus_read(const int fd, void* const data, const size_t size) { -again: - suspend_until_active(fd, IOSET_READ); - const ssize_t r = read(fd, data, size); - if (r < 0 && errno == EAGAIN) { - suspend_io_errno(fd, IOSET_READ); - goto again; - } - s_current->visited = 0; - FD_CLR(fd, &s_iop.active.r); - //FD_CLR(fd, &s_iop.scheduled.r); - return r; -} - -void sus_disable(const uint8_t id) { - s_iow[id].disabled = true; -} - -void sus_lend(const uint8_t id, const size_t size, void* const data) { - assert(data != NULL); - assert(!s_iow[id].borrowed); - assert(s_iow[id].data == NULL); - assert(s_iow[id].size == 0); - s_iow[id] = (struct iowork){ .data = data, .size = size }; - //LOGDX("s_iow[%d].data = %p, data = %p", id, s_iow[id].data, data); - while (s_iow[id].data != NULL) { - //LOGDX("suspend because s_iow[%d].data (%p) != NULL", id, s_iow[id].data); - suspend_id("lend", id); - } - //LOGDX("wakeup [%d] = %p", id, s_iow[id].data); - assert(s_iow[id].data == NULL); - assert(s_iow[id].size == 0); - s_current->visited = 0; -} - -ssize_t sus_borrow(const uint8_t id, void** const data) { - //LOGDX("s_iow[%d].data = %p, data = %p", id, s_iow[id].data, data); - assert(data != NULL); - assert(!s_iow[id].borrowed); - if (s_iow[id].disabled) { - errno = EIDRM; - return -1; - } - while (s_iow[id].data == NULL) { - //LOGDX("suspend because s_iow[%d].data (%p) == NULL", id, s_iow[id].data); - if (s_iow[id].disabled) { - errno = EIDRM; - return -1; - } - suspend_id("borrow", id); - } - //LOGDX("wakeup [%d] = %p", id, s_iow[id].data); -# ifndef NDEBUG - s_iow[id].borrowed = true; -# endif - *data = s_iow[id].data; - s_current->visited = 0; - return s_iow[id].size; -} - -void sus_return(const uint8_t id, const void* const data, const size_t size) { - assert(data != NULL); - assert(s_iow[id].borrowed); - assert(s_iow[id].data != NULL); - assert(s_iow[id].data == data); - assert(s_iow[id].size == size); - //LOGDX("[%d] %p –> (nil)", id, s_iow[id].data); - s_iow[id] = (struct iowork){}; - s_current->visited = 0; - //suspend("return"); -} - -// Transfer to scheduler and forget about current coroutine -__attribute__((noreturn)) -static inline void sus_exit(void) { - coro_context* const origin = s_current->ctx; - shrink(&s_current); - coro_transfer(origin, &s_end); - assert(0); -} - -__attribute__((noreturn)) -static void starter(struct sus_registation_form* const reg) { - LOGDX("started task %s", reg->name); - reg->result = reg->entry(reg->args); - LOGDX("ended task %s", reg->name); - sus_exit(); -} - -int sus_ioloop(struct sus_ioloop_args* const args) { - io_wait_f* const iowait = get_io_wait(args->timeout); - struct io_params iop = { - .maxfd = 10, - .deadline = comp_deadline(args->timeout) - }; - int ret = 0; - do { -again: - if (s_current == s_current->next) { - LOGEX("No more tasks left"); - break; - } - s_iop = (struct fdsets){ .active = { .r = iop.set[0], .w = iop.set[1], .e = iop.set[2] }}; - suspend_only("iowait"); - bool ok = false; - for (int i = 0; i < 3; i++) { - iop.set[i] = s_iop.scheduled.a[i]; - for (int j = 0; j < iop.maxfd; j++) { - ok |= FD_ISSET(j, &iop.set[i]); - //LOGDX("%d:%c:%s", j, (FD_ISSET(j, &iop.set[i]) ? '+' : ' '), ioset_to_method(i)); - } - } - if (!ok) { - //LOGDX("continue"); - goto again; - } - assert(ok); - LOGDX("Waiting for I/O..."); - } while ((ret = iowait(&iop)) > 0); - if (ret < 0) - LOGE("iowait failed"); - else if (ret == 0) - LOGI("iowait done"); - for (int i = 0; i < 10; i++) - close(i); - LOGWX("surrended"); - s_io_surrended = true; - return -1; -} - -int sus_runall(const size_t length, struct sus_registation_form (* const h)[length]) { - assert(h); - int ret = -1; - struct coro_stuff stuff[length] = {}; - coro_create(&s_end, NULL, NULL, NULL, 0); - for (size_t i = 0; i < length; i++) { - if (!coro_stack_alloc(&stuff[i].stack, (*h)[i].stack_size)) - goto end; - coro_create(&stuff[i].ctx, (coro_func)starter, &(*h)[i], stuff[i].stack.sptr, stuff[i].stack.ssze); - } - for (size_t i = 0; i < length; i++) - insert(&s_current, &stuff[i].ctx, (*h)[i].name); - for (; s_current; s_current = s_current ? s_current->next : NULL) - coro_transfer(&s_end, s_current->ctx); - ret = 0; -end: - for (size_t i = 0; i < length; i++) { - (void)coro_destroy(&stuff[i].ctx); - coro_stack_free(&stuff[i].stack); - } - (void)coro_destroy(&s_end); - return ret; -} diff --git a/multitasking/ut.c.t b/multitasking/ut.c.t deleted file mode 100644 index 9826496..0000000 --- a/multitasking/ut.c.t +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include "contextring.h" -#include "../utils.h" - -int g_log_level = LOG_DEBUG; - -#suite context_ring - -#test single_element_can_be_added_and_removed - struct coro_context tmp = {}; - struct coro_context_ring* ring = NULL; - insert(&ring, &tmp, NULL); - ck_assert_ptr_nonnull(ring); - ck_assert_ptr_eq(ring->ctx, &tmp); - ck_assert_ptr_eq(ring->next, ring); - ck_assert_ptr_eq(ring->prev, ring); - shrink(&ring); - ck_assert_ptr_null(ring); - -#test multiple_elements_can_be_added_and_removed - struct coro_context_ring* ring = NULL; - const int max = 1000; - for (int i = 1; i <= max; i++) { - struct coro_context tmp[i] = {}; - for (size_t i = 0; i < lengthof(tmp); i++) - insert(&ring, &tmp[i], NULL); - struct coro_context_ring* p = ring; - for (size_t i = 0; i < lengthof(tmp); i++) { - //ck_assert_ptr_eq(p->ctx, &tmp[(i + max) % max]); - ck_assert_ptr_eq(p, p->next->prev); - ck_assert_ptr_eq(p, p->prev->next); - } - for (size_t i = 0; i < lengthof(tmp); i++) - shrink(&ring); - ck_assert_ptr_null(ring); - } - -#suite coroutines - -#test coroutine1 - diff --git a/utils.h b/utils.h index 66bf869..3fac565 100644 --- a/utils.h +++ b/utils.h @@ -64,6 +64,9 @@ v;\ }) +#define xnpth_setname_np(...) XCALL(npth_setname_np, __VA_ARGS__) +#define xnpth_create(...) XCALL(npth_create, __VA_ARGS__) +#define xnpth_sigwait(...) XCALL(npth_sigwait, __VA_ARGS__) #define xfprintf(...) XCALL(fprintf, __VA_ARGS__) #define xfputs(...) XCALL(fputs, __VA_ARGS__) #define xfflush(...) XCALL(fflush, __VA_ARGS__)