interim commit with incomplete tasking routines
This commit is contained in:
parent
5840c7193c
commit
55ee23a255
14
qse/configure
vendored
14
qse/configure
vendored
@ -16070,7 +16070,7 @@ fi
|
|||||||
|
|
||||||
done
|
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 :
|
do :
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
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"
|
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||||
@ -16260,6 +16260,18 @@ _ACEOF
|
|||||||
fi
|
fi
|
||||||
done
|
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
|
for ac_func in if_nametoindex if_indextoname
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
|
@ -83,7 +83,7 @@ AC_SUBST(LIBM, $LIBM)
|
|||||||
dnl check header files.
|
dnl check header files.
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h signal.h fcntl.h dirent.h])
|
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/resource.h sys/wait.h sys/syscall.h sys/sendfile.h sys/epoll.h])
|
||||||
AC_CHECK_HEADERS([sys/ioctl.h net/if.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([backtrace backtrace_symbols])
|
||||||
AC_CHECK_FUNCS([fdopendir])
|
AC_CHECK_FUNCS([fdopendir])
|
||||||
AC_CHECK_FUNCS([fork vfork posix_spawn gettid])
|
AC_CHECK_FUNCS([fork vfork posix_spawn gettid])
|
||||||
|
AC_CHECK_FUNCS([makecontext swapcontext getcontext setcontext])
|
||||||
AC_CHECK_FUNCS([if_nametoindex if_indextoname])
|
AC_CHECK_FUNCS([if_nametoindex if_indextoname])
|
||||||
|
|
||||||
OLDLIBS="$LIBS"
|
OLDLIBS="$LIBS"
|
||||||
|
@ -36,6 +36,7 @@ pkginclude_HEADERS = \
|
|||||||
slmb.h \
|
slmb.h \
|
||||||
stdio.h \
|
stdio.h \
|
||||||
str.h \
|
str.h \
|
||||||
|
task.h \
|
||||||
time.h \
|
time.h \
|
||||||
tio.h \
|
tio.h \
|
||||||
tre.h \
|
tre.h \
|
||||||
|
@ -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 \
|
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 \
|
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 \
|
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
|
StdMmgr.hpp Mmged.hpp
|
||||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
am__vpath_adj = case $$p in \
|
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 \
|
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 \
|
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 \
|
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
|
all: all-am
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
54
qse/include/qse/cmn/task.h
Normal file
54
qse/include/qse/cmn/task.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _QSE_CMN_TASK_H_
|
||||||
|
#define _QSE_CMN_TASK_H_
|
||||||
|
|
||||||
|
#include <qse/types.h>
|
||||||
|
#include <qse/macros.h>
|
||||||
|
|
||||||
|
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
|
@ -112,6 +112,9 @@
|
|||||||
/* Define to 1 if you have the `ftruncate64' function. */
|
/* Define to 1 if you have the `ftruncate64' function. */
|
||||||
#undef HAVE_FTRUNCATE64
|
#undef HAVE_FTRUNCATE64
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getcontext' function. */
|
||||||
|
#undef HAVE_GETCONTEXT
|
||||||
|
|
||||||
/* Define to 1 if you have the `gethostbyname' function. */
|
/* Define to 1 if you have the `gethostbyname' function. */
|
||||||
#undef HAVE_GETHOSTBYNAME
|
#undef HAVE_GETHOSTBYNAME
|
||||||
|
|
||||||
@ -160,6 +163,9 @@
|
|||||||
/* Define to 1 if you have the `lstat64' function. */
|
/* Define to 1 if you have the `lstat64' function. */
|
||||||
#undef HAVE_LSTAT64
|
#undef HAVE_LSTAT64
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `makecontext' function. */
|
||||||
|
#undef HAVE_MAKECONTEXT
|
||||||
|
|
||||||
/* Define to 1 if you have the `mbrlen' function. */
|
/* Define to 1 if you have the `mbrlen' function. */
|
||||||
#undef HAVE_MBRLEN
|
#undef HAVE_MBRLEN
|
||||||
|
|
||||||
@ -226,6 +232,9 @@
|
|||||||
/* Define to 1 if you have the `sendfilev64' function. */
|
/* Define to 1 if you have the `sendfilev64' function. */
|
||||||
#undef HAVE_SENDFILEV64
|
#undef HAVE_SENDFILEV64
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `setcontext' function. */
|
||||||
|
#undef HAVE_SETCONTEXT
|
||||||
|
|
||||||
/* Define to 1 if you have the <signal.h> header file. */
|
/* Define to 1 if you have the <signal.h> header file. */
|
||||||
#undef HAVE_SIGNAL_H
|
#undef HAVE_SIGNAL_H
|
||||||
|
|
||||||
@ -289,6 +298,9 @@
|
|||||||
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
|
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
|
||||||
#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
#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. */
|
/* Define to 1 if you have the `sysconf' function. */
|
||||||
#undef HAVE_SYSCONF
|
#undef HAVE_SYSCONF
|
||||||
|
|
||||||
@ -348,6 +360,9 @@
|
|||||||
/* Define to 1 if you have the `towctrans' function. */
|
/* Define to 1 if you have the `towctrans' function. */
|
||||||
#undef HAVE_TOWCTRANS
|
#undef HAVE_TOWCTRANS
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ucontext.h> header file. */
|
||||||
|
#undef HAVE_UCONTEXT_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
#undef HAVE_UNISTD_H
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
@ -92,6 +92,7 @@ libqsecmn_la_SOURCES = \
|
|||||||
str-tok.c \
|
str-tok.c \
|
||||||
str-trm.c \
|
str-trm.c \
|
||||||
str-word.c \
|
str-word.c \
|
||||||
|
task.c \
|
||||||
time.c \
|
time.c \
|
||||||
tio.c \
|
tio.c \
|
||||||
tre.c \
|
tre.c \
|
||||||
|
@ -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-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-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 \
|
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-match-backtrack.lo tre-match-parallel.lo tre-parse.lo \
|
||||||
tre-stack.lo uri.lo utf8.lo xma.lo
|
tre-stack.lo uri.lo utf8.lo xma.lo
|
||||||
libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
|
libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
|
||||||
@ -382,6 +382,7 @@ libqsecmn_la_SOURCES = \
|
|||||||
str-tok.c \
|
str-tok.c \
|
||||||
str-trm.c \
|
str-trm.c \
|
||||||
str-word.c \
|
str-word.c \
|
||||||
|
task.c \
|
||||||
time.c \
|
time.c \
|
||||||
tio.c \
|
tio.c \
|
||||||
tre.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-tok.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-trm.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)/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)/time.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tio.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@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tre-ast.Plo@am__quote@
|
||||||
|
@ -518,9 +518,9 @@ and restores it after interrupt.
|
|||||||
*/
|
*/
|
||||||
#define QSE_SYSCALL1(ret,num,arg1) \
|
#define QSE_SYSCALL1(ret,num,arg1) \
|
||||||
__asm__ volatile ( \
|
__asm__ volatile ( \
|
||||||
"push %%ebx\n" \
|
"push %%ebx\n\t" \
|
||||||
"movl %2, %%ebx\n" \
|
"movl %2, %%ebx\n\t" \
|
||||||
"int $0x80\n" \
|
"int $0x80\n\t" \
|
||||||
"pop %%ebx\n" \
|
"pop %%ebx\n" \
|
||||||
: "=a"(ret) \
|
: "=a"(ret) \
|
||||||
: "a"((qse_uint32_t)num), "r"((qse_uint32_t)arg1) \
|
: "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) \
|
#define QSE_SYSCALL2(ret,num,arg1,arg2) \
|
||||||
__asm__ volatile ( \
|
__asm__ volatile ( \
|
||||||
"push %%ebx\n" \
|
"push %%ebx\n\t" \
|
||||||
"movl %2, %%ebx\n" \
|
"movl %2, %%ebx\n\t" \
|
||||||
"int $0x80\n" \
|
"int $0x80\n\t" \
|
||||||
"pop %%ebx\n" \
|
"pop %%ebx\n" \
|
||||||
: "=a"(ret) \
|
: "=a"(ret) \
|
||||||
: "a"((qse_uint32_t)num), "r"((qse_uint32_t)arg1), "c"((qse_uint32_t)arg2) \
|
: "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) \
|
#define QSE_SYSCALL3(ret,num,arg1,arg2,arg3) \
|
||||||
__asm__ volatile ( \
|
__asm__ volatile ( \
|
||||||
"push %%ebx\n" \
|
"push %%ebx\n\t" \
|
||||||
"movl %2, %%ebx\n" \
|
"movl %2, %%ebx\n\t" \
|
||||||
"int $0x80\n" \
|
"int $0x80\n\t" \
|
||||||
"pop %%ebx\n" \
|
"pop %%ebx\n" \
|
||||||
: "=a"(ret) \
|
: "=a"(ret) \
|
||||||
: "a"((qse_uint32_t)num), "r"((qse_uint32_t)arg1), "c"((qse_uint32_t)arg2), "d"((qse_uint32_t)arg3) \
|
: "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) \
|
#define QSE_SYSCALL4(ret,num,arg1,arg2,arg3,arg4) \
|
||||||
__asm__ volatile ( \
|
__asm__ volatile ( \
|
||||||
"push %%ebx\n" \
|
"push %%ebx\n\t" \
|
||||||
"movl %2, %%ebx\n" \
|
"movl %2, %%ebx\n\t" \
|
||||||
"int $0x80\n" \
|
"int $0x80\n\t" \
|
||||||
"pop %%ebx\n" \
|
"pop %%ebx\n" \
|
||||||
: "=a"(ret) \
|
: "=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) \
|
: "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) \
|
||||||
|
460
qse/lib/cmn/task.c
Normal file
460
qse/lib/cmn/task.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <qse/cmn/task.h>
|
||||||
|
|
||||||
|
#if defined(_WIN64)
|
||||||
|
# include <windows.h>
|
||||||
|
#else
|
||||||
|
# if defined(HAVE_UCONTEXT_H)
|
||||||
|
# include <ucontext.h>
|
||||||
|
# endif
|
||||||
|
# include <setjmp.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
@ -470,10 +470,6 @@ static int cgi_add_env (
|
|||||||
qse_nwadtombs (&client->remote_addr, buf, QSE_COUNTOF(buf), QSE_NWADTOMBS_ADDR);
|
qse_nwadtombs (&client->remote_addr, buf, QSE_COUNTOF(buf), QSE_NWADTOMBS_ADDR);
|
||||||
qse_env_insertmbs (env, QSE_MT("REMOTE_ADDR"), buf);
|
qse_env_insertmbs (env, QSE_MT("REMOTE_ADDR"), buf);
|
||||||
|
|
||||||
#if 0
|
|
||||||
qse_env_insertmbs (env, "REMOTE_USER",
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ctx.httpd = httpd;
|
ctx.httpd = httpd;
|
||||||
ctx.env = env;
|
ctx.env = env;
|
||||||
if (qse_htre_walkheaders (req, cgi_capture_client_header, &ctx) <= -1) return -1;
|
if (qse_htre_walkheaders (req, cgi_capture_client_header, &ctx) <= -1) return -1;
|
||||||
|
Loading…
Reference in New Issue
Block a user