diff --git a/qse/configure b/qse/configure index d21f2f64..705bcadf 100755 --- a/qse/configure +++ b/qse/configure @@ -16070,7 +16070,7 @@ fi done -for ac_header in time.h sys/time.h utime.h spawn.h execinfo.h +for ac_header in time.h sys/time.h utime.h spawn.h execinfo.h ucontext.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -16260,6 +16260,18 @@ _ACEOF fi done +for ac_func in makecontext swapcontext getcontext setcontext +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + for ac_func in if_nametoindex if_indextoname do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` diff --git a/qse/configure.ac b/qse/configure.ac index 2729cb4e..6232ada7 100644 --- a/qse/configure.ac +++ b/qse/configure.ac @@ -83,7 +83,7 @@ AC_SUBST(LIBM, $LIBM) dnl check header files. AC_HEADER_STDC AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h signal.h fcntl.h dirent.h]) -AC_CHECK_HEADERS([time.h sys/time.h utime.h spawn.h execinfo.h]) +AC_CHECK_HEADERS([time.h sys/time.h utime.h spawn.h execinfo.h ucontext.h]) AC_CHECK_HEADERS([sys/resource.h sys/wait.h sys/syscall.h sys/sendfile.h sys/epoll.h]) AC_CHECK_HEADERS([sys/ioctl.h net/if.h]) @@ -107,6 +107,7 @@ AC_CHECK_FUNCS([sysconf]) AC_CHECK_FUNCS([backtrace backtrace_symbols]) AC_CHECK_FUNCS([fdopendir]) AC_CHECK_FUNCS([fork vfork posix_spawn gettid]) +AC_CHECK_FUNCS([makecontext swapcontext getcontext setcontext]) AC_CHECK_FUNCS([if_nametoindex if_indextoname]) OLDLIBS="$LIBS" diff --git a/qse/include/qse/cmn/Makefile.am b/qse/include/qse/cmn/Makefile.am index 62a72011..fe5649ea 100644 --- a/qse/include/qse/cmn/Makefile.am +++ b/qse/include/qse/cmn/Makefile.am @@ -36,6 +36,7 @@ pkginclude_HEADERS = \ slmb.h \ stdio.h \ str.h \ + task.h \ time.h \ tio.h \ tre.h \ diff --git a/qse/include/qse/cmn/Makefile.in b/qse/include/qse/cmn/Makefile.in index 62b8690a..070b1091 100644 --- a/qse/include/qse/cmn/Makefile.in +++ b/qse/include/qse/cmn/Makefile.in @@ -55,7 +55,7 @@ am__pkginclude_HEADERS_DIST = alg.h chr.h cp949.h cp950.h dll.h env.h \ fio.h fma.h fmt.h fs.h gdl.h glob.h htb.h hton.h ipad.h lda.h \ main.h map.h mbwc.h mem.h nwad.h nwif.h nwio.h oht.h opt.h \ path.h pio.h pma.h rbt.h rex.h sio.h sll.h slmb.h stdio.h \ - str.h time.h tio.h tre.h uri.h utf8.h xma.h Mmgr.hpp \ + str.h task.h time.h tio.h tre.h uri.h utf8.h xma.h Mmgr.hpp \ StdMmgr.hpp Mmged.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ @@ -247,7 +247,7 @@ pkginclude_HEADERS = alg.h chr.h cp949.h cp950.h dll.h env.h fio.h \ fma.h fmt.h fs.h gdl.h glob.h htb.h hton.h ipad.h lda.h main.h \ map.h mbwc.h mem.h nwad.h nwif.h nwio.h oht.h opt.h path.h \ pio.h pma.h rbt.h rex.h sio.h sll.h slmb.h stdio.h str.h \ - time.h tio.h tre.h uri.h utf8.h xma.h $(am__append_1) + task.h time.h tio.h tre.h uri.h utf8.h xma.h $(am__append_1) all: all-am .SUFFIXES: diff --git a/qse/include/qse/cmn/task.h b/qse/include/qse/cmn/task.h new file mode 100644 index 00000000..f8bae567 --- /dev/null +++ b/qse/include/qse/cmn/task.h @@ -0,0 +1,54 @@ +/* + * $Id$ + * + Copyright 2006-2012 Chung, Hyung-Hwan. + This file is part of QSE. + + QSE is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + QSE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with QSE. If not, see . + */ + +#ifndef _QSE_CMN_TASK_H_ +#define _QSE_CMN_TASK_H_ + +#include +#include + +typedef void (*qse_task_fnc_t) (void* ctx); + +typedef struct qse_task_t qse_task_t; + +#ifdef __cplusplus +extern "C" { +#endif + +int qse_gettaskid ( + qse_task_t* task +); + +qse_task_t* qse_maketask ( + qse_task_fnc_t fnc, + void* ctx, + qse_size_t stsize +); + +int qse_task_boot ( + void +); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/qse/include/qse/config.h.in b/qse/include/qse/config.h.in index 3e384ae2..f20ba3fd 100644 --- a/qse/include/qse/config.h.in +++ b/qse/include/qse/config.h.in @@ -112,6 +112,9 @@ /* Define to 1 if you have the `ftruncate64' function. */ #undef HAVE_FTRUNCATE64 +/* Define to 1 if you have the `getcontext' function. */ +#undef HAVE_GETCONTEXT + /* Define to 1 if you have the `gethostbyname' function. */ #undef HAVE_GETHOSTBYNAME @@ -160,6 +163,9 @@ /* Define to 1 if you have the `lstat64' function. */ #undef HAVE_LSTAT64 +/* Define to 1 if you have the `makecontext' function. */ +#undef HAVE_MAKECONTEXT + /* Define to 1 if you have the `mbrlen' function. */ #undef HAVE_MBRLEN @@ -226,6 +232,9 @@ /* Define to 1 if you have the `sendfilev64' function. */ #undef HAVE_SENDFILEV64 +/* Define to 1 if you have the `setcontext' function. */ +#undef HAVE_SETCONTEXT + /* Define to 1 if you have the header file. */ #undef HAVE_SIGNAL_H @@ -289,6 +298,9 @@ /* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC +/* Define to 1 if you have the `swapcontext' function. */ +#undef HAVE_SWAPCONTEXT + /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF @@ -348,6 +360,9 @@ /* Define to 1 if you have the `towctrans' function. */ #undef HAVE_TOWCTRANS +/* Define to 1 if you have the header file. */ +#undef HAVE_UCONTEXT_H + /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H diff --git a/qse/lib/cmn/Makefile.am b/qse/lib/cmn/Makefile.am index f9863ff1..3d0dda25 100644 --- a/qse/lib/cmn/Makefile.am +++ b/qse/lib/cmn/Makefile.am @@ -92,6 +92,7 @@ libqsecmn_la_SOURCES = \ str-tok.c \ str-trm.c \ str-word.c \ + task.c \ time.c \ tio.c \ tre.c \ diff --git a/qse/lib/cmn/Makefile.in b/qse/lib/cmn/Makefile.in index 888cfda8..10f3013d 100644 --- a/qse/lib/cmn/Makefile.in +++ b/qse/lib/cmn/Makefile.in @@ -94,7 +94,7 @@ am_libqsecmn_la_OBJECTS = alg-base64.lo alg-rand.lo alg-search.lo \ str-incl.lo str-len.lo str-pac.lo str-pbrk.lo str-put.lo \ str-rev.lo str-rot.lo str-set.lo str-spl.lo str-spn.lo \ str-str.lo str-subst.lo str-tok.lo str-trm.lo str-word.lo \ - time.lo tio.lo tre.lo tre-ast.lo tre-compile.lo \ + task.lo time.lo tio.lo tre.lo tre-ast.lo tre-compile.lo \ tre-match-backtrack.lo tre-match-parallel.lo tre-parse.lo \ tre-stack.lo uri.lo utf8.lo xma.lo libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS) @@ -382,6 +382,7 @@ libqsecmn_la_SOURCES = \ str-tok.c \ str-trm.c \ str-word.c \ + task.c \ time.c \ tio.c \ tre.c \ @@ -550,6 +551,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-tok.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-trm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-word.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tre-ast.Plo@am__quote@ diff --git a/qse/lib/cmn/syscall.h b/qse/lib/cmn/syscall.h index a1382eec..ed893e0f 100644 --- a/qse/lib/cmn/syscall.h +++ b/qse/lib/cmn/syscall.h @@ -518,9 +518,9 @@ and restores it after interrupt. */ #define QSE_SYSCALL1(ret,num,arg1) \ __asm__ volatile ( \ - "push %%ebx\n" \ - "movl %2, %%ebx\n" \ - "int $0x80\n" \ + "push %%ebx\n\t" \ + "movl %2, %%ebx\n\t" \ + "int $0x80\n\t" \ "pop %%ebx\n" \ : "=a"(ret) \ : "a"((qse_uint32_t)num), "r"((qse_uint32_t)arg1) \ @@ -538,9 +538,9 @@ and restores it after interrupt. */ #define QSE_SYSCALL2(ret,num,arg1,arg2) \ __asm__ volatile ( \ - "push %%ebx\n" \ - "movl %2, %%ebx\n" \ - "int $0x80\n" \ + "push %%ebx\n\t" \ + "movl %2, %%ebx\n\t" \ + "int $0x80\n\t" \ "pop %%ebx\n" \ : "=a"(ret) \ : "a"((qse_uint32_t)num), "r"((qse_uint32_t)arg1), "c"((qse_uint32_t)arg2) \ @@ -558,9 +558,9 @@ and restores it after interrupt. */ #define QSE_SYSCALL3(ret,num,arg1,arg2,arg3) \ __asm__ volatile ( \ - "push %%ebx\n" \ - "movl %2, %%ebx\n" \ - "int $0x80\n" \ + "push %%ebx\n\t" \ + "movl %2, %%ebx\n\t" \ + "int $0x80\n\t" \ "pop %%ebx\n" \ : "=a"(ret) \ : "a"((qse_uint32_t)num), "r"((qse_uint32_t)arg1), "c"((qse_uint32_t)arg2), "d"((qse_uint32_t)arg3) \ @@ -569,9 +569,9 @@ and restores it after interrupt. #define QSE_SYSCALL4(ret,num,arg1,arg2,arg3,arg4) \ __asm__ volatile ( \ - "push %%ebx\n" \ - "movl %2, %%ebx\n" \ - "int $0x80\n" \ + "push %%ebx\n\t" \ + "movl %2, %%ebx\n\t" \ + "int $0x80\n\t" \ "pop %%ebx\n" \ : "=a"(ret) \ : "a"((qse_uint32_t)num), "r"((qse_uint32_t)arg1), "c"((qse_uint32_t)arg2), "d"((qse_uint32_t)arg3), "S"((qse_uint32_t)arg4) \ diff --git a/qse/lib/cmn/task.c b/qse/lib/cmn/task.c new file mode 100644 index 00000000..a676083d --- /dev/null +++ b/qse/lib/cmn/task.c @@ -0,0 +1,460 @@ +/* + * $Id$ + * + Copyright 2006-2012 Chung, Hyung-Hwan. + This file is part of QSE. + + QSE is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + QSE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with QSE. If not, see . + */ + +#include + +#if defined(_WIN64) +# include +#else +# if defined(HAVE_UCONTEXT_H) +# include +# endif +# include +#endif + +typedef struct tmgr_t tmgr_t; +struct tmgr_t +{ + int count; + int idinc; + + qse_task_t* dead; + qse_task_t* current; + qse_task_t* head; + qse_task_t* tail; + +#if defined(_WIN64) + void* fiber; +#elif defined(HAVE_SWAPCONTEXT) + ucontext_t uctx; +#else + jmp_buf backjmp; +#endif +}; + +struct qse_task_t +{ + /* queue */ + tmgr_t* tmgr; + + int id; + + qse_task_fnc_t fnc; + void* ctx; + qse_size_t stsize; + +#if defined(_WIN64) + void* fiber; +#elif defined(HAVE_SWAPCONTEXT) + ucontext_t uctx; +#else + jmp_buf jmpbuf; +#endif + + qse_task_t* prev; + qse_task_t* next; +}; + +static tmgr_t* tmgr; + +qse_task_t* qse_task_alloc (qse_task_fnc_t fnc, void* ctx, qse_size_t stsize) +{ + qse_task_t* task; + + task = malloc (QSE_SIZEOF(*task) + stsize); + if (task == QSE_NULL) return QSE_NULL; + + //QSE_MEMSET (task, 0, QSE_SIZEOF(*task)); + QSE_MEMSET (task, 0, QSE_SIZEOF(*task) + stsize); + task->tmgr = tmgr; + task->fnc = fnc; + task->ctx = ctx; + task->stsize = stsize; + + if (tmgr->head) + { + task->next= tmgr->head; + tmgr->head->prev = task; + tmgr->head = task; + } + else + { + tmgr->head = task; + tmgr->tail = task; + } + + task->id = tmgr->idinc; + tmgr->count++; + tmgr->idinc++; + + return task; +} + +static void purge_dead_tasks (void) +{ + qse_task_t* x; + + while (tmgr->dead) + { + x = tmgr->dead; + tmgr->dead = x->next; +#if defined(_WIN64) + DeleteFiber (x->fiber); +#endif + free (x); + } +} + +void qse_task_schedule (void) +{ + qse_task_t* current; + + current = tmgr->current; /* old current */ + tmgr->current = current->next? current->next: tmgr->head; + +#if defined(_WIN64) + /* current->fiber is handled by SwitchToFiber() implicitly */ + SwitchToFiber (tmgr->current->fiber); + purge_dead_tasks (); +#elif defined(HAVE_SWAPCONTEXT) + swapcontext (¤t->uctx, &tmgr->current->uctx); + purge_dead_tasks (); +#else +//printf ("switch from %d to %d\n", current->id, tmgr->current->id); + if (setjmp (current->jmpbuf) != 0) + { + purge_dead_tasks (); + return; + } + longjmp (tmgr->current->jmpbuf, 1); +#endif +} + +static void purge_current_task (void) +{ + qse_task_t* current; + + if (tmgr->count == 1) + { + /* to purge later */ + tmgr->current->next = tmgr->dead; + tmgr->dead = tmgr->current; + + tmgr->current = QSE_NULL; + tmgr->head = QSE_NULL; + tmgr->tail = QSE_NULL; + tmgr->count = 0; + tmgr->idinc = 0; + +#if defined(_WIN64) + SwitchToFiber (tmgr->fiber); +#elif defined(HAVE_SWAPCONTEXT) + setcontext (&tmgr->uctx); +#else + longjmp (tmgr->backjmp, 1); +#endif + assert (!"must not reach here...."); + } + + current = tmgr->current; + tmgr->current = current->next? current->next: tmgr->head; + + if (current->prev) current->prev->next = current->next; + if (current->next) current->next->prev = current->prev; + if (current == tmgr->head) tmgr->head = current->next; + if (current == tmgr->tail) tmgr->tail = current->prev; + tmgr->count--; + + /* to purge later */ + current->next = tmgr->dead; + tmgr->dead = current; + +#if defined(_WIN64) + SwitchToFiber (tmgr->current->fiber); +#elif defined(HAVE_SWAPCONTEXT) + setcontext (&tmgr->current->uctx); +#else + longjmp (tmgr->current->jmpbuf, 1); +#endif +} + +#if defined(_WIN64) +static void __stdcall execute_current_task (void* task) +{ + assert (tmgr->current != QSE_NULL); + tmgr->current->fnc (tmgr->current->ctx); + purge_current_task (); +} +#else + +static void execute_current_task (void) +{ + assert (tmgr->current != QSE_NULL); + + tmgr->current->fnc (tmgr->current->ctx); + + /* the task function is now terminated. we need to + * purge it from the task list */ + purge_current_task (); +} +#endif + +static qse_task_t* xxtask; +static void* xxoldsp; + +#if defined(__WATCOMC__) +/* for watcom, i support i386/32bit only */ +extern void* set_sp (void*); +#pragma aux set_sp = \ + "xchg eax, esp" \ + parm [eax] value [eax] modify [esp] +#endif + +qse_task_t* qse_maketask (qse_task_fnc_t fnc, void* ctx, qse_size_t stsize) +{ + qse_task_t* task; + void* newsp; + + +#if defined(_WIN64) + task = qse_task_alloc (fnc, ctx, 0); + if (task == QSE_NULL) return QSE_NULL; + + task->fiber = CreateFiberEx (stsize, stsize, FIBER_FLAG_FLOAT_SWITCH, execute_current_task, QSE_NULL); + if (task->fiber == QSE_NULL) + { +/* TODO: delete task */ + return QSE_NULL; + } + +#elif defined(HAVE_SWAPCONTEXT) + + task = qse_task_alloc (fnc, ctx, stsize); + if (task == QSE_NULL) return QSE_NULL; + + if (getcontext (&task->uctx) <= -1) + { +/* TODO: delete task */ + return QSE_NULL; + } + task->uctx.uc_stack.ss_sp = task + 1; + task->uctx.uc_stack.ss_size = stsize; + task->uctx.uc_link = QSE_NULL; + makecontext (&task->uctx, execute_current_task, 0); + +#else + + task = qse_task_alloc (fnc, ctx, stsize); + if (task == QSE_NULL) return QSE_NULL; + + /* setjmp() doesn't allow different stacks for + * each execution content. let me use some assembly + * to change the stack pointer so that setjmp() remembers + * the new stack pointer for longjmp() later. + * + * this stack is used for the task function when + * longjmp() is made. */ + xxtask = task; + newsp = ((qse_uint8_t*)(task + 1)) + stsize - QSE_SIZEOF(void*); + +#if defined(__WATCOMC__) + + xxoldsp = set_sp (newsp); + +#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64)) + + /* + __asm__ volatile ( + "xchgq %0, %%rsp\n" + : "=r"(xxoldsp) + : "0"(newsp) + : "%rsp" + ); + */ + + __asm__ volatile ( + "movq %%rsp, %0\n\t" + "movq %1, %%rsp\n" + : "=m"(xxoldsp) + : "r"(newsp) + : "%rsp", "memory" + ); + +#elif defined(__GNUC__) && (defined(__i386) || defined(i386)) + __asm__ volatile ( + "xchgl %0, %%esp\n" + : "=r"(xxoldsp) + : "0"(newsp) + : "%esp" + ); +#elif defined(__GNUC__) && (defined(__mips) || defined(mips)) + __asm__ volatile ( + "sw $sp, %0\n\t" /* store $sp to xxoldsp */ + "move $sp, %1\n" /* move the register content for newsp to $sp */ + : "=m"(xxoldsp) + : "r"(newsp) + : "$sp", "memory" + ); + /* + __asm__ volatile ( + "move %0, $sp\n\t" + "move $sp, %1\n" + : "=&r"(xxoldsp) + : "r"(newsp) + : "$sp", "memory" + ); + */ + +#elif defined(__GNUC__) && defined(__arm__) + __asm__ volatile ( + "str sp, %0\n\t" + "mov sp, %1\n" + : "=m"(xxoldsp) + : "r"(newsp) + : "sp", "memory" + ); + +/* TODO: support more architecture */ +#else + + /* TODO: destroy task */ + //tmgr->errnum = QSE_TMGR_ENOIMPL; + return QSE_NULL; + +#endif /* __WATCOMC__ */ + + /* + * automatic variables like 'task' and 'newsp' exist + * in the old stack. i can't access them. + * i access some key informaton via the global + * variables stored before stack pointer switching. + * + * this approach makes this function thread-unsafe. + */ + + /* when qse_maketask() is called, + * setjmp() saves the context and return 0. + * + * subsequently, when longjmp() is made + * for this saved context, setjmp() returns + * a non-zero value. + */ + if (setjmp (xxtask->jmpbuf) != 0) + { + /* longjmp() is made to here. */ + execute_current_task (); + assert (!"must never reach here....\n"); + } + + /* restore the stack pointer once i finish saving the longjmp() context. + * this part is reached only when qse_maketask() is invoked. */ +#if defined(__WATCOMC__) + + set_sp (xxoldsp); + +#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64)) + __asm__ volatile ( + "movq %0, %%rsp\n" + : + : "m"(xxoldsp) /*"r"(xxoldsp)*/ + : "%rsp" + ); + +#elif defined(__GNUC__) && (defined(__i386) || defined(i386)) + __asm__ volatile ( + "movl %0, %%esp\n" + : + : "r"(xxoldsp) + : "%esp" + ); + +#elif defined(__GNUC__) && (defined(__mips) || defined(mips)) + __asm__ volatile ( + "lw $sp, %0\n" /*"move $sp, %0\n" */ + : + : "m"(xxoldsp) /* "r"(xxoldsp) */ + : "$sp" + ); +#elif defined(__GNUC__) && defined(__arm__) + __asm__ volatile ( + "ldr sp, %0\n" + : + : "m"(xxoldsp) + : "sp" + ); +#endif /* __WATCOMC__ */ + +#endif + + return task; +} + +int qse_gettaskid (qse_task_t* task) +{ + return task->id; +} + +int qse_task_boot (void) +{ + if (tmgr->count <= 0) return -1; + +#if defined(_WIN64) + tmgr->fiber = ConvertThreadToFiberEx (QSE_NULL, FIBER_FLAG_FLOAT_SWITCH); + if (tmgr->fiber == QSE_NULL) + { +/*TODO: destroy all the tasks created */ + return -1; + } + + tmgr->current = tmgr->tail; + SwitchToFiber (tmgr->current->fiber); + ConvertFiberToThread (); + +#elif defined(HAVE_SWAPCONTEXT) + + tmgr->current = tmgr->tail; + if (swapcontext (&tmgr->uctx, &tmgr->current->uctx) <= -1) + { +/*TODO: destroy all the tasks created */ + return -1; + } + +#else + if (setjmp (tmgr->backjmp) != 0) + { + /* longjmp() back */ + goto done; + } + + tmgr->current = tmgr->tail; + longjmp (tmgr->current->jmpbuf, 1); + assert (!"must never reach here"); + +done: +#endif + + assert (tmgr->current == QSE_NULL); + assert (tmgr->count == 0); + + purge_dead_tasks (); + printf ("END OF TASK_BOOT...\n"); + return 0; +} + diff --git a/qse/lib/net/httpd-cgi.c b/qse/lib/net/httpd-cgi.c index 705ac4e4..73c8c506 100644 --- a/qse/lib/net/httpd-cgi.c +++ b/qse/lib/net/httpd-cgi.c @@ -470,10 +470,6 @@ static int cgi_add_env ( qse_nwadtombs (&client->remote_addr, buf, QSE_COUNTOF(buf), QSE_NWADTOMBS_ADDR); qse_env_insertmbs (env, QSE_MT("REMOTE_ADDR"), buf); -#if 0 - qse_env_insertmbs (env, "REMOTE_USER", -#endif - ctx.httpd = httpd; ctx.env = env; if (qse_htre_walkheaders (req, cgi_capture_client_header, &ctx) <= -1) return -1;