Index: ossp-pkg/pth/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/pth/ChangeLog,v rcsdiff -q -kk '-r1.540' '-r1.541' -u '/v/ossp/cvs/ossp-pkg/pth/ChangeLog,v' 2>/dev/null --- ChangeLog 2001/03/24 14:32:14 1.540 +++ ChangeLog 2001/03/24 14:51:03 1.541 @@ -55,6 +55,9 @@ don't have this problem. [Ralf S. Engelschall] + *) Updated copyright messages to cover new year 2001. + [Ralf S. Engelschall] + *) Fixed quoting in configure.in [Ralf S. Engelschall] Index: ossp-pkg/pth/Makefile.in RCS File: /v/ossp/cvs/ossp-pkg/pth/Makefile.in,v rcsdiff -q -kk '-r1.141' '-r1.142' -u '/v/ossp/cvs/ossp-pkg/pth/Makefile.in,v' 2>/dev/null --- Makefile.in 2000/10/05 12:28:06 1.141 +++ Makefile.in 2001/03/24 14:51:03 1.142 @@ -1,6 +1,6 @@ ## ## GNU Pth - The GNU Portable Threads -## Copyright (c) 1999-2000 Ralf S. Engelschall +## Copyright (c) 1999-2001 Ralf S. Engelschall ## ## This file is part of GNU Pth, a non-preemptive thread scheduling ## library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/README RCS File: /v/ossp/cvs/ossp-pkg/pth/README,v rcsdiff -q -kk '-r1.189' '-r1.190' -u '/v/ossp/cvs/ossp-pkg/pth/README,v' 2>/dev/null --- README 2000/10/03 08:00:35 1.189 +++ README 2001/03/24 14:51:03 1.190 @@ -54,7 +54,7 @@ COPYRIGHT AND LICENSE - Copyright (c) 1999-2000 Ralf S. Engelschall + Copyright (c) 1999-2001 Ralf S. Engelschall This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public Index: ossp-pkg/pth/acconfig.h RCS File: /v/ossp/cvs/ossp-pkg/pth/Attic/acconfig.h,v co -q -kk -p'1.27' '/v/ossp/cvs/ossp-pkg/pth/Attic/acconfig.h,v' | diff -u /dev/null - -L'ossp-pkg/pth/acconfig.h' 2>/dev/null --- ossp-pkg/pth/acconfig.h +++ - 2024-05-13 13:57:53.813097464 +0200 @@ -0,0 +1,59 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_acdef.h Autoconf defines +*/ + +#ifndef _PTH_ACDEF_H_ +#define _PTH_ACDEF_H_ + +@TOP@ + +/* the custom Autoconf defines */ +#undef HAVE_SIG_ATOMIC_T +#undef HAVE_PID_T +#undef HAVE_STACK_T +#undef HAVE_SIZE_T +#undef HAVE_SSIZE_T +#undef HAVE_SOCKLEN_T +#undef HAVE_NFDS_T +#undef HAVE_OFF_T +#undef HAVE_GETTIMEOFDAY_ARGS1 +#undef HAVE_STRUCT_TIMESPEC +#undef HAVE_SYS_READ +#undef HAVE_POLLIN +#undef HAVE_SS_SP +#undef HAVE_SS_BASE +#undef HAVE_LONGLONG +#undef HAVE_LONGDOUBLE +#undef PTH_DEBUG +#undef PTH_NSIG +#undef PTH_MCTX_MTH_use +#undef PTH_MCTX_DSP_use +#undef PTH_MCTX_STK_use +#undef PTH_STACKGROWTH +#undef PTH_DMALLOC + +@BOTTOM@ + +#endif /* _PTH_ACDEF_H_ */ + Index: ossp-pkg/pth/acheader.m4 RCS File: /v/ossp/cvs/ossp-pkg/pth/Attic/acheader.m4,v co -q -kk -p'1.6' '/v/ossp/cvs/ossp-pkg/pth/Attic/acheader.m4,v' | diff -u /dev/null - -L'ossp-pkg/pth/acheader.m4' 2>/dev/null --- ossp-pkg/pth/acheader.m4 +++ - 2024-05-13 13:57:53.827203320 +0200 @@ -0,0 +1,47 @@ +dnl ## +dnl ## GNU Pth - The GNU Portable Threads +dnl ## Copyright (c) 1999-2001 Ralf S. Engelschall +dnl ## +dnl ## This file is part of GNU Pth, a non-preemptive thread scheduling +dnl ## library which can be found at http://www.gnu.org/software/pth/. +dnl ## +dnl ## This library is free software; you can redistribute it and/or +dnl ## modify it under the terms of the GNU Lesser General Public +dnl ## License as published by the Free Software Foundation; either +dnl ## version 2.1 of the License, or (at your option) any later version. +dnl ## +dnl ## This library is distributed in the hope that it will be useful, +dnl ## but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl ## Lesser General Public License for more details. +dnl ## +dnl ## You should have received a copy of the GNU Lesser General Public +dnl ## License along with this library; if not, write to the Free Software +dnl ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +dnl ## USA, or contact Ralf S. Engelschall . +dnl ## +dnl ## acheader.m4: Pth Autoheader macros +dnl ## + +dnl # These macros are replacement macros for use with `autoheader' only !! + +define([AC_CHECK_FUNCTION], [# +@@@funcs="$funcs $1"@@@ +ifelse([$2], , , [ +# If it was found, we do: +$2 +# If it was not found, we do: +$3 +]) +]) + +define([AC_CHECK_FUNCTIONS], [# +@@@funcs="$funcs $1"@@@ +ifelse([$2], , , [ +# If it was found, we do: +$2 +# If it was not found, we do: +$3 +]) +]) + Index: ossp-pkg/pth/aclocal.m4 RCS File: /v/ossp/cvs/ossp-pkg/pth/aclocal.m4,v rcsdiff -q -kk '-r1.90' '-r1.91' -u '/v/ossp/cvs/ossp-pkg/pth/aclocal.m4,v' 2>/dev/null --- aclocal.m4 2000/09/16 18:47:10 1.90 +++ aclocal.m4 2001/03/24 14:51:04 1.91 @@ -1,6 +1,6 @@ dnl ## dnl ## GNU Pth - The GNU Portable Threads -dnl ## Copyright (c) 1999-2000 Ralf S. Engelschall +dnl ## Copyright (c) 1999-2001 Ralf S. Engelschall dnl ## dnl ## This file is part of GNU Pth, a non-preemptive thread scheduling dnl ## library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/config.param RCS File: /v/ossp/cvs/ossp-pkg/pth/config.param,v co -q -kk -p'1.15' '/v/ossp/cvs/ossp-pkg/pth/config.param,v' | diff -u /dev/null - -L'ossp-pkg/pth/config.param' 2>/dev/null --- ossp-pkg/pth/config.param +++ - 2024-05-13 13:57:53.835893795 +0200 @@ -0,0 +1,67 @@ +## +## GNU Pth - The GNU Portable Threads +## Copyright (c) 1999-2001 Ralf S. Engelschall +## +## This file is part of GNU Pth, a non-preemptive thread scheduling +## library which can be found at http://www.gnu.org/software/pth/. +## +## This library 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 2.1 of the License, or (at your option) any later version. +## +## This library 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 this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +## USA, or contact Ralf S. Engelschall . +## +## config.param: predefined configure command line parameters +## + # ``Die Abk. fuer Abk. ist Abk.'' (german) + +# Common parameters +common { +} + +# build for testing +# (done on all testing platforms) +test { + --prefix=/tmp/pth + --enable-pthread + --enable-optimize + --enable-syscall-soft +} + +# build for debugging +# (developer machine only) +install { + CC=pgcc IF test -f /sw/bin/pgcc + --prefix=/sw/pkg/pth + --enable-batch + --enable-pthread + --enable-optimize + --enable-syscall-soft + --enable-syscall-hard + --disable-shared +} + +# build for developing +# (developer machine only) +# [Hint: dmalloc -l dmalloc.log -i 1 debug3] +devel { + CC=/sw/bin/egcc IF test -f /sw/bin/egcc + CC=/usr/local/bin/egcc IF test -f /usr/local/bin/egcc + --prefix=/sw/pkg/pth IF test -d /sw/pkg/pth/ + --enable-batch + --enable-debug + --enable-pthread + --enable-maintainer + --enable-syscall-soft + --with-dmalloc=/sw/pkg/dmalloc IF test -d /sw/pkg/dmalloc/ +} + Index: ossp-pkg/pth/configure.in RCS File: /v/ossp/cvs/ossp-pkg/pth/Attic/configure.in,v co -q -kk -p'1.121' '/v/ossp/cvs/ossp-pkg/pth/Attic/configure.in,v' | diff -u /dev/null - -L'ossp-pkg/pth/configure.in' 2>/dev/null --- ossp-pkg/pth/configure.in +++ - 2024-05-13 13:57:53.851921761 +0200 @@ -0,0 +1,607 @@ +dnl ## +dnl ## GNU Pth - The GNU Portable Threads +dnl ## Copyright (c) 1999-2001 Ralf S. Engelschall +dnl ## +dnl ## This file is part of GNU Pth, a non-preemptive thread scheduling +dnl ## library which can be found at http://www.gnu.org/software/pth/. +dnl ## +dnl ## This library is free software; you can redistribute it and/or +dnl ## modify it under the terms of the GNU Lesser General Public +dnl ## License as published by the Free Software Foundation; either +dnl ## version 2.1 of the License, or (at your option) any later version. +dnl ## +dnl ## This library is distributed in the hope that it will be useful, +dnl ## but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl ## Lesser General Public License for more details. +dnl ## +dnl ## You should have received a copy of the GNU Lesser General Public +dnl ## License along with this library; if not, write to the Free Software +dnl ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +dnl ## USA, or contact Ralf S. Engelschall . +dnl ## +dnl ## configure.in: Pth Autoconf specification +dnl ## + +dnl # ``Programming in Bourne-Shell +dnl # is a higher form of masochism.'' +dnl # -- Unknown + +dnl ## +dnl ## PROLOG +dnl ## + +dnl # standard Autoconf prolog +AC_PREREQ(2.12)dnl +AC_REVISION([1.0]) + +dnl # autoconf initialization +AC_INIT(README) +AC_ENABLESUBDIR +AC_SRCDIR_PREFIX(srcdir_prefix) +AC_HEADLINE(dnl +GNU Pth, Portable Threads, dnl +PTH_VERSION, pth_vers.c, dnl +[Copyright (c) 1999-2001 Ralf S. Engelschall ]) +AC_CONFIG_PARAM(config.param) +AC_CONFIG_HEADER(pth_acdef.h)dnl +AC_PREFIX_DEFAULT(/usr/local) +AC_PLATFORM(PLATFORM) + +dnl ## +dnl ## BUILD TOOLS +dnl ## + +AC_MSG_PART(Build Tools) + +AC_PROG_CC +AC_PROG_CPP +AC_SET_MAKE +AC_CHECK_DEBUGGING +AC_CHECK_PROFILING +AC_CHECK_OPTIMIZE +if test -f "$srcdir/ltconfig"; then + AC_PROG_LIBTOOL($PLATFORM) +else + dnl # only for stripped down Pth source tree + AC_CHECK_PROG(AR, ar, ar) + AC_PROG_RANLIB +fi + +dnl ## Support for some special platform/compiler options +case "$PLATFORM:$CC" in + *-sun-solaris2*:cc ) + # shut-up harmless warnings caused by do-while macros on Solaris + test ".$ac_cv_prog_gcc" = ".no" && CFLAGS="$CFLAGS -w" + ;; + *-*-sysv*uw[[27]]*:cc ) + # shut-up harmless warnings caused by do-while macros on UnixWare + CFLAGS="$CFLAGS -w" + ;; + *-hp-hpux*:cc ) + # HPUX needs a few special options to find its ANSI C brain + CFLAGS="$CFLAGS -Ae -O" + ;; + *-hp-hpux*:CC ) + # HPUX outputs useless warnings + CFLAGS="$CFLAGS -w" + ;; + *-sgi-irix6.2:cc ) + # shut-up warnings caused by IRIX brain-dead 32/64 bit stuff + LDFLAGS="$LDFLAGS -woff 85 -Wl,-woff,84 -Wl,-woff,85" + ;; + *-sgi-irix6.5.[[2-9]]:cc ) + # since IRIX 6.5.2 the C compiler is smart enough, + # but the linker is still complaining, of course + LDFLAGS="$LDFLAGS -woff 84,85,134" + ;; + *-sgi-irix6.5:cc ) + # shut-up warnings caused by IRIX brain-dead 32/64 bit stuff + CFLAGS="$CFLAGS -woff 1110,1048" + LDFLAGS="$LDFLAGS -woff 84,85,134" + ;; + *-dec-osf4*:cc ) + # make sure the standard compliant functions are used on Tru64/OSF1 4.x + CFLAGS="$CFLAGS -std" + ;; + *-dec-osf5*:cc ) + # make sure the standard compliant functions are used on Tru64/OSF1 5.x + CFLAGS="$CFLAGS -std -D_XOPEN_SOURCE_EXTENDED" + ;; + *-*-isc*:* ) + # ISC is brain-dead and needs a bunch of options to find its brain + CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE"; + LIBS="$LIBS -lcposix -linet"; + ;; +esac + +dnl ## +dnl ## MANDATORY PLATFORM ENVIRONMENT +dnl ## + +AC_MSG_PART(Mandatory Platform Environment) + +dnl # check for standard headers +AC_HEADER_STDC +AC_HAVE_HEADERS(dnl + stdio.h stdlib.h stdarg.h string.h signal.h unistd.h setjmp.h fcntl.h dnl + errno.h sys/types.h sys/time.h sys/wait.h sys/stat.h sys/socket.h) +AC_CHECK_FUNCTIONS(dnl + gettimeofday select sigaction sigprocmask sigpending sigsuspend) +AC_BEGIN_DECISION([mandatory system headers and functions]) +AC_IFALLYES(dnl + header:stdio.h header:stdlib.h header:stdarg.h header:string.h dnl + header:signal.h header:unistd.h header:setjmp.h header:fcntl.h header:errno.h dnl + header:sys/types.h header:sys/time.h header:sys/wait.h header:sys/stat.h header:sys/socket.h dnl + func:gettimeofday func:select func:sigaction func:sigprocmask dnl + func:sigpending func:sigsuspend, + AC_DECIDE(fine, [all fine])) +AC_END_DECISION + + +dnl ## +dnl ## OPTIONAL PLATFORM ENVIRONMENT +dnl ## + +AC_MSG_PART(Optional Platform Environment) + +dnl # check for the number of signals +AC_CHECK_NSIG(PTH_NSIG) + +dnl # check whether poll(2)'s input stuff has to be faked +AC_CHECK_FUNCTIONS(poll) +AC_CHECK_DEFINE(POLLIN, poll.h) +AC_MSG_CHECKING(whether poll(2) facility has to be faked) +AC_IFALLYES(func:poll define:POLLIN, PTH_FAKE_POLL=0, PTH_FAKE_POLL=1) +if test .$PTH_FAKE_POLL = .1; then + msg="yes" +else + msg="no" +fi +AC_SUBST(PTH_FAKE_POLL) +AC_MSG_RESULT([$msg]) + +dnl # check for readv/writev environment +AC_HAVE_HEADERS(sys/uio.h) +AC_CHECK_FUNCTIONS(readv writev) +AC_MSG_CHECKING(whether readv(2)/writev(2) facility has to be faked) +AC_IFALLYES(func:readv func:writev header:sys/uio.h, PTH_FAKE_RWV=0, PTH_FAKE_RWV=1) +if test .$PTH_FAKE_RWV = .1; then + msg="yes" +else + msg="no" +fi +AC_SUBST(PTH_FAKE_RWV) +AC_MSG_RESULT([$msg]) + +dnl # check for various other functions which would be nice to have +AC_CHECK_FUNCTIONS(usleep strerror) + +dnl # check for various other headers which we might need +AC_HAVE_HEADERS(sys/resource.h net/errno.h paths.h) + +dnl # at least the test programs need some socket stuff +AC_CHECK_LIB(nsl, gethostname) +if test ".`echo $LIBS | grep nsl`" = . ;then + AC_CHECK_LIB(nsl, gethostbyname) +fi +AC_CHECK_LIB(socket, accept) + +dnl # check whether we've to use a non-standard #include to get +dnl # the definition for fd_set under AIX and other brain-dead platforms. +AC_HAVE_HEADERS(sys/select.h) +EXTRA_INCLUDE_SYS_SELECT_H="#include " +if test ".$ac_cv_header_sys_select_h" != .yes; then + EXTRA_INCLUDE_SYS_SELECT_H="/* $EXTRA_INCLUDE_SYS_SELECT_H */" +fi +AC_SUBST(EXTRA_INCLUDE_SYS_SELECT_H) + +dnl # check whether we've to define sig_atomic_t +AC_CHECK_TYPEDEF(sig_atomic_t, signal.h) +FALLBACK_SIG_ATOMIC_T="typedef int sig_atomic_t;" +if test ".$ac_cv_typedef_sig_atomic_t" = .yes; then + FALLBACK_SIG_ATOMIC_T="/* $FALLBACK_SIG_ATOMIC_T */" +fi +AC_SUBST(FALLBACK_SIG_ATOMIC_T) + +dnl # check whether we've to define pid_t +AC_CHECK_TYPEDEF(pid_t, sys/types.h) +FALLBACK_PID_T="typedef int pid_t;" +if test ".$ac_cv_typedef_pid_t" = .yes; then + FALLBACK_PID_T="/* $FALLBACK_PID_T */" +fi +AC_SUBST(FALLBACK_PID_T) + +dnl # check whether we've to define size_t +AC_CHECK_TYPEDEF(size_t, stdlib.h) +FALLBACK_SIZE_T="typedef unsigned int size_t;" +if test ".$ac_cv_typedef_size_t" = .yes; then + FALLBACK_SIZE_T="/* $FALLBACK_SIZE_T */" +fi +AC_SUBST(FALLBACK_SIZE_T) + +dnl # check whether we've to define ssize_t +AC_CHECK_TYPEDEF(ssize_t, sys/types.h) +FALLBACK_SSIZE_T="typedef unsigned int ssize_t;" +if test ".$ac_cv_typedef_ssize_t" = .yes; then + FALLBACK_SSIZE_T="/* $FALLBACK_SSIZE_T */" +fi +AC_SUBST(FALLBACK_SSIZE_T) + +dnl # check whether we've to define off_t +AC_CHECK_TYPEDEF(off_t, sys/types.h) +FALLBACK_OFF_T="typedef int off_t;" +if test ".$ac_cv_typedef_off_t" = .yes; then + FALLBACK_OFF_T="/* $FALLBACK_OFF_T */" +fi +AC_SUBST(FALLBACK_OFF_T) + +dnl # check whether stack_t exists instead of sigaltstack +AC_CHECK_TYPEDEF(stack_t, signal.h) + +dnl # check whether ss_base instead of ss_sp attribute exists +AC_CHECK_STRUCTATTR(ss_base, sigaltstack, sys/signal.h) +AC_CHECK_STRUCTATTR(ss_sp, sigaltstack, sys/signal.h) + +dnl # check for gettimeofday() variant +AC_MSG_CHECKING(for a single-argument based gettimeofday) +cross_compile=no +AC_TRY_COMPILE([ +#include +#include +#include +],[ +struct timeval tv; +(void)gettimeofday(&tv); +], +msg="yes" +, +msg="no" +) +case $PLATFORM in + *-*-aix4* ) msg="no" ;; # on AIX the compiler test doesn't work + *-*-isc* ) msg="no" ;; # on ISC the compiler test doesn't work +esac +if test ".$msg" = .yes; then + AC_DEFINE(HAVE_GETTIMEOFDAY_ARGS1) +fi +AC_MSG_RESULT([$msg]) + +dnl # check for struct timespec +AC_MSG_CHECKING(for struct timespec) +cross_compile=no +AC_TRY_COMPILE([ +#include +#include +],[ +struct timespec ts; +], +msg="yes" +, +msg="no" +) +if test ".$msg" = .yes; then + AC_DEFINE(HAVE_STRUCT_TIMESPEC) +fi +AC_MSG_RESULT([$msg]) + +dnl # check for network/socket size type +AC_CHECK_SOCKLENTYPE([ +FALLBACK_SOCKLEN_T="typedef ${ac_type} socklen_t;" +if test ".$ac_type" = ".socklen_t"; then + FALLBACK_SOCKLEN_T="/* $FALLBACK_SOCKLEN_T */" +fi +AC_SUBST(FALLBACK_SOCKLEN_T) +]) + +dnl # check for filedescriptor number type +AC_CHECK_NFDSTYPE([ +FALLBACK_NFDS_T="typedef ${ac_type} nfds_t;" +if test ".$ac_type" = ".nfds_t"; then + FALLBACK_NFDS_T="/* $FALLBACK_NFDS_T */" +fi +AC_SUBST(FALLBACK_NFDS_T) +]) + +dnl # check for 64-bit types (for pth_snprintf.c) +AC_CHECK_LONGLONG +AC_CHECK_LONGDOUBLE + +dnl ## +dnl ## MACHINE CONTEXT IMPLEMENTATION +dnl ## + +AC_MSG_PART(Machine Context Implementation) + +dnl # +dnl # 1. determine possibilities +dnl # + +dnl # check for MCSC method +AC_CHECK_HEADERS(ucontext.h) +AC_CHECK_FUNCTIONS(makecontext swapcontext getcontext setcontext) +AC_CHECK_MCSC(mcsc=yes, mcsc=no) + +dnl # check for SJLJ method +AC_CHECK_HEADERS(signal.h) +AC_CHECK_FUNCTIONS(sigsetjmp siglongjmp setjmp longjmp _setjmp _longjmp) +AC_CHECK_FUNCTIONS(sigaltstack sigstack) +AC_CHECK_SJLJ(sjlj=yes, sjlj=no, sjlj_type) + +dnl # +dnl # 2. make a general decision +dnl # + +if test ".$mcsc" = .yes; then + mctx_mth=mcsc + mctx_dsp=sc + mctx_stk=mc +elif test ".$sjlj" = .yes; then + mctx_mth=sjlj + mctx_dsp=$sjlj_type + mctx_stk=none + AC_IFALLYES(func:sigstack, mctx_stk=ss) + AC_IFALLYES(func:sigaltstack, mctx_stk=sas) + case $mctx_dsp in + sjljlx|sjljisc|sjljw32 ) mctx_stk=none + esac +else + AC_ERROR([no appropriate mctx method found]) +fi + +dnl # +dnl # 3. allow decision to be overridden by user +dnl # + +AC_ARG_WITH(mctx-mth,dnl +[ --with-mctx-mth=ID force mctx method (mcsc,sjlj)],[ +case $withval in + mcsc|sjlj ) mctx_mth=$withval ;; + * ) AC_ERROR([invalid mctx method -- allowed: mcsc,sjlj]) ;; +esac +])dnl +AC_ARG_WITH(mctx-dsp,dnl +[ --with-mctx-dsp=ID force mctx dispatching (sc,ssjlj,sjlj,usjlj,sjlje,...)],[ +case $withval in + sc|ssjlj|sjlj|usjlj|sjlje|sjljlx|sjljisc|sjljw32 ) mctx_dsp=$withval ;; + * ) AC_ERROR([invalid mctx dispatching -- allowed: sc,ssjlj,sjlj,usjlj,sjlje,sjljlx,sjljisc,sjljw32]) ;; +esac +])dnl +AC_ARG_WITH(mctx-stk,dnl +[ --with-mctx-stk=ID force mctx stack setup (mc,ss,sas,...)],[ +case $withval in + mc|ss|sas|none ) mctx_stk=$withval ;; + * ) AC_ERROR([invalid mctx stack setup -- allowed: mc,ss,sas,none]) ;; +esac +])dnl + +dnl # +dnl # 4. determine a few additional details +dnl # + +dnl # whether sigaltstack has to use stack_t instead of struct sigaltstack +AC_CHECK_TYPEDEF(stack_t, signal.h) + +dnl # direction of stack grow +AC_CHECK_STACKGROWTH(PTH_STACKGROWTH) +if test ".$ac_cv_check_stackgrowth" = ".down"; then + PTH_STACK_GROWTH="down" +else + PTH_STACK_GROWTH="up" +fi +AC_SUBST(PTH_STACK_GROWTH) + +dnl # how to specify stacks for the various functions +AC_CHECK_STACKSETUP(makecontext, pth_skaddr_makecontext, pth_sksize_makecontext) +AC_CHECK_STACKSETUP(sigaltstack, pth_skaddr_sigaltstack, pth_sksize_sigaltstack) +AC_CHECK_STACKSETUP(sigstack, pth_skaddr_sigstack, pth_sksize_sigstack) + +dnl # how to implement POSIX compliant sig{set,long}jmp() +case $mctx_dsp in [ + ssjlj ) + pth_sigjmpbuf='sigjmp_buf' + pth_sigsetjmp='sigsetjmp(buf,1)' + pth_siglongjmp='siglongjmp(buf,val)' + ;; + sjlj ) + pth_sigjmpbuf='jmp_buf' + pth_sigsetjmp='setjmp(buf)' + pth_siglongjmp='longjmp(buf,val)' + ;; + usjlj ) + pth_sigjmpbuf='jmp_buf' + pth_sigsetjmp='_setjmp(buf)' + pth_siglongjmp='_longjmp(buf,val)' + ;; + sjlje ) + pth_sigjmpbuf='jmp_buf' + pth_sigsetjmp='setjmp(buf)' + pth_siglongjmp='longjmp(buf,val)' + ;; + sjljlx|sjljisc|sjljw32 ) + pth_sigjmpbuf='sigjmp_buf' + pth_sigsetjmp='sigsetjmp(buf,1)' + pth_siglongjmp='siglongjmp(buf,val)' + ;; +] esac +pth_sigjmpbuf="#define pth_sigjmpbuf $pth_sigjmpbuf" +pth_sigsetjmp="#define pth_sigsetjmp(buf) $pth_sigsetjmp" +pth_siglongjmp="#define pth_siglongjmp(buf,val) $pth_siglongjmp" +AC_SUBST(pth_sigjmpbuf) +AC_SUBST(pth_sigsetjmp) +AC_SUBST(pth_siglongjmp) + +dnl # +dnl # 5. export the results +dnl # + +AC_DEFINE_UNQUOTED(PTH_MCTX_MTH_use, [PTH_MCTX_MTH_$mctx_mth]) +AC_DEFINE_UNQUOTED(PTH_MCTX_DSP_use, [PTH_MCTX_DSP_$mctx_dsp]) +AC_DEFINE_UNQUOTED(PTH_MCTX_STK_use, [PTH_MCTX_STK_$mctx_stk]) + +PTH_MCTX_ID="$mctx_mth/$mctx_dsp/$mctx_stk" +AC_MSG_RESULT([decision on mctx implementation... ${TB}${PTH_MCTX_ID}${TN}]) +AC_SUBST(PTH_MCTX_ID) + +AC_MSG_VERBOSE([decided mctx method: $mctx_mth]) +AC_MSG_VERBOSE([decided mctx dispatching: $mctx_dsp]) +AC_MSG_VERBOSE([decided mctx stack setup: $mctx_stk]) + + +dnl ## +dnl ## SYSTEM CALL MAPPING +dnl ## + +AC_MSG_PART(System Call Mapping) + +AC_CHECK_FUNCTIONS(syscall) +AC_CHECK_HEADERS(sys/syscall.h sys/socketcall.h) +AC_CHECK_DEFINE(SYS_read, sys/syscall.h) + +AC_MSG_CHECKING([whether soft system call mapping is used]) +AC_ARG_ENABLE(syscall-soft,dnl +[ --enable-syscall-soft enable soft system call mapping (default=no)], +enable_syscall_soft="$enableval", +if test ".$enable_syscall_soft" = .; then + enable_syscall_soft=no +fi +)dnl +if test .$enable_syscall_soft = .yes; then + PTH_SYSCALL_SOFT=1 + msg="yes" +else + PTH_SYSCALL_SOFT=0 + msg="no" +fi +AC_MSG_RESULT([$msg]) +AC_SUBST(PTH_SYSCALL_SOFT) + +AC_MSG_CHECKING([whether hard system call mapping is used]) +AC_ARG_ENABLE(syscall-hard,dnl +[ --enable-syscall-hard enable hard system call mapping (default=no)], +enable_syscall_hard="$enableval",[ +if test ".$enable_syscall_hard" = .; then + enable_syscall_hard=no +fi +])dnl +if test ".$enable_syscall_hard" = .yes; then + AC_IFALLYES(func:syscall header:sys/syscall.h define:SYS_read, + enable_syscall_hard=yes, enable_syscall_hard=no) +fi +if test ".$enable_syscall_hard" = .yes; then + PTH_SYSCALL_HARD=1 + msg="yes" +else + PTH_SYSCALL_HARD=0 + msg="no" +fi +AC_MSG_RESULT([$msg]) +AC_SUBST(PTH_SYSCALL_HARD) +if test ".$enable_syscall_hard" = .yes; then + echo "${TB}Warning: The hard system call mapping variant is still work in progress.${TN}" + echo "${TB} Do neither expect it to compile on all platforms (because of${TN}" + echo "${TB} conflicts with vendor prototypes) nor to actually work!${TN}" +fi + + +dnl ## +dnl ## BUILD PARAMETERS +dnl ## + +AC_MSG_PART(Build Parameters) + +dnl # check for various build parameters +AC_CHECK_BUILDPARAM + +dnl # whether to build Pthread library +AC_MSG_CHECKING(whether to build Pthread library) +AC_ARG_ENABLE(pthread,dnl +[ --enable-pthread build Pthread library (default=no)], +enable_pthread="$enableval", +if test ".$enable_pthread" = .; then + enable_pthread=no +fi +)dnl +AC_MSG_RESULT([$enable_pthread]) +if test ".$enable_pthread" = .yes; then + PTHREAD_O=pthread.o dnl # only for stripped down Pth source tree + LIBPTHREAD_A=libpthread.a dnl # only for stripped down Pth source tree + LIBPTHREAD_LA=libpthread.la + PTHREAD_CONFIG_1='$(S)pthread-config.1' + PTHREAD_3='$(S)pthread.3' + INSTALL_PTHREAD=install-pthread + UNINSTALL_PTHREAD=uninstall-pthread + TEST_PTHREAD=test_pthread + enable_syscall_soft=yes + AC_HAVE_HEADERS(pthread.h) + ac_warn=no + if test ".$ac_cv_header_pthread_h" = .yes; then + warn=yes + changequote(<<,>>) + case $PLATFORM in + *-*-freebsd* ) ac_warn=no ;; + *-*-linux* ) ac_warn=no ;; + *-*-solaris* ) ac_warn=no ;; + *-*-irix* ) ac_warn=no ;; + esac + changequote([,]) + fi + if test ".$ac_warn" = .yes; then + echo "${TB}Warning: You seem to have a vendor Pthread library installed.${TN}" + echo "${TB} There might be conflicts with its pthread.h under compile-time!${TN}" + fi +else + PTHREAD_O="" dnl # only for stripped down Pth source tree + LIBPTHREAD_A="" dnl # only for stripped down Pth source tree + LIBPTHREAD_LA="" + PTHREAD_CONFIG_1="" + PTHREAD_3="" + INSTALL_PTHREAD="" + UNINSTALL_PTHREAD="" + TEST_PTHREAD="" +fi +AC_SUBST(PTHREAD_O) +AC_SUBST(LIBPTHREAD_A) +AC_SUBST(LIBPTHREAD_LA) +AC_SUBST(PTHREAD_CONFIG_1) +AC_SUBST(PTHREAD_3) +AC_SUBST(INSTALL_PTHREAD) +AC_SUBST(UNINSTALL_PTHREAD) +AC_SUBST(TEST_PTHREAD) + +dnl # whether to build against Sfio library +PTH_EXT_SFIO=FALSE +AC_CHECK_EXTLIB(Sfio, sfio, sfdisc, sfio.h, PTH_EXT_SFIO=TRUE) +AC_SUBST(PTH_EXT_SFIO) + +dnl # whether to build against Dmalloc library +AC_CHECK_EXTLIB(Dmalloc, dmalloc, dmalloc_debug, dmalloc.h, AC_DEFINE(PTH_DMALLOC)) + +dnl ## +dnl ## OUTPUT SUBSTITUTION +dnl ## + +AC_MSG_PART(Output Substitution) + +AC_OUTPUT(dnl +Makefile dnl +pthread-config dnl +pthread.h dnl +pth-config dnl +pth.h dnl +pth_acmac.h dnl +,dnl +chmod +rx pthread-config +chmod +rx pth-config +)dnl +if test ".$enable_pthread" = .no; then + rm -f pthread-config + rm -f pthread.h +fi + +if test ".$enable_batch" != .yes; then + echo "" + echo "Now please type \`${TB}make${TN}' to compile. Good luck." + echo "" +fi + Index: ossp-pkg/pth/pth-config.in RCS File: /v/ossp/cvs/ossp-pkg/pth/pth-config.in,v co -q -kk -p'1.22' '/v/ossp/cvs/ossp-pkg/pth/pth-config.in,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth-config.in' 2>/dev/null --- ossp-pkg/pth/pth-config.in +++ - 2024-05-13 13:57:53.855021482 +0200 @@ -0,0 +1,141 @@ +#!/bin/sh +## +## GNU Pth - The GNU Portable Threads +## Copyright (c) 1999-2001 Ralf S. Engelschall +## +## This file is part of GNU Pth, a non-preemptive thread scheduling +## library which can be found at http://www.gnu.org/software/pth/. +## +## This library 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 2.1 of the License, or (at your option) any later version. +## +## This library 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 this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +## USA, or contact Ralf S. Engelschall . +## +## pth-config.in: Pth library build utility +## + +DIFS=' +' + +prefix="@prefix@" +exec_prefix="@exec_prefix@" + +pth_prefix="$prefix" +pth_exec_prefix="$exec_prefix" +pth_bindir="@bindir@" +pth_libdir="@libdir@" +pth_includedir="@includedir@" +pth_mandir="@mandir@" +pth_datadir="@datadir@" +pth_acdir="@datadir@/aclocal" +pth_cflags="@CFLAGS@" +pth_ldflags="@LDFLAGS@" +pth_libs="@LIBS@" +pth_version="@PTH_VERSION_STR@" + +help=no +version=no + +usage="pth-config" +usage="$usage [--help] [--version] [--all]" +usage="$usage [--prefix] [--exec-prefix] [--bindir] [--libdir] [--includedir] [--mandir] [--datadir] [--acdir]" +usage="$usage [--cflags] [--ldflags] [--libs]" +if [ $# -eq 0 ]; then + echo "pth-config:Error: Invalid option" 1>&2 + echo "pth-config:Usage: $usage" 1>&2 + exit 1 +fi +output='' +output_extra='' +all=no +prev='' +OIFS="$IFS" IFS="$DIFS" +for option +do + if [ ".$prev" != . ]; then + eval "$prev=\$option" + prev='' + continue + fi + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg='' ;; + esac + case "$option" in + --help|-h) + echo "Usage: $usage" + echo "Report bugs to bug-pth@gnu.org" + exit 0 + ;; + --version|-v) + echo "GNU Pth $pth_version" + exit 0 + ;; + --all) + all=yes + ;; + --prefix) + output="$output $pth_prefix" + ;; + --exec-prefix) + output="$output $pth_exec_prefix" + ;; + --bindir) + output="$output $pth_bindir" + ;; + --libdir) + output="$output $pth_libdir" + ;; + --includedir) + output="$output $pth_includedir" + ;; + --mandir) + output="$output $pth_mandir" + ;; + --datadir) + output="$output $pth_datadir" + ;; + --acdir) + output="$output $pth_acdir" + ;; + --cflags) + output="$output -I$pth_includedir" + output_extra="$output_extra $pth_cflags" + ;; + --ldflags) + output="$output -L$pth_libdir" + output_extra="$output_extra $pth_ldflags" + ;; + --libs) + output="$output -lpth" + output_extra="$output_extra $pth_libs" + ;; + * ) + echo "pth-config:Error: Invalid option" 1>&2 + echo "pth-config:Usage: $usage" 1>&2 + exit 1; + ;; + esac +done +IFS="$OIFS" +if [ ".$prev" != . ]; then + echo "pth-config:Error: missing argument to --`echo $prev | sed 's/_/-/g'`" 1>&2 + exit 1 +fi +if [ ".$output" != . ]; then + if [ ".$all" = .yes ]; then + output="$output $output_extra" + fi + echo $output +fi + Index: ossp-pkg/pth/pth-config.pod RCS File: /v/ossp/cvs/ossp-pkg/pth/pth-config.pod,v co -q -kk -p'1.19' '/v/ossp/cvs/ossp-pkg/pth/pth-config.pod,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth-config.pod' 2>/dev/null --- ossp-pkg/pth/pth-config.pod +++ - 2024-05-13 13:57:53.857716481 +0200 @@ -0,0 +1,156 @@ +## +## GNU Pth - The GNU Portable Threads +## Copyright (c) 1999-2001 Ralf S. Engelschall +## +## This file is part of GNU Pth, a non-preemptive thread scheduling +## library which can be found at http://www.gnu.org/software/pth/. +## +## This library 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 2.1 of the License, or (at your option) any later version. +## +## This library 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 this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +## USA, or contact Ralf S. Engelschall . +## +## pth-config.pod: Pth library build utility manual page +## + +=pod + +=head1 NAME + +B - Pth library build utility + +=head1 VERSION + +GNU Pth PTH_VERSION_STR + +=head1 SYNOPSIS + +B +[B<--help>] +[B<--version>] +[B<--all>] +[B<--prefix>] +[B<--exec-prefix>] +[B<--bindir>] +[B<--libdir>] +[B<--includedir>] +[B<--mandir>] +[B<--datadir>] +[B<--acdir>] +[B<--cflags>] +[B<--ldflags>] +[B<--libs>] + +=head1 DESCRIPTION + +The B program is a little helper utility for easy configuring and +building applications based on the pth(3) library. It can be used to query the +C compiler and linker flags which are required to correctly compile and link +the application against the pth(3) library. + +=head1 OPTIONS + +B accepts the following options: + +=over 4 + +=item B<--help> + +Prints the short usage information. + +=item B<--version> + +Prints the version number and date of the installed pth(3) library. + +=item B<--all> + +Forces the output of all flags, that is, including extra flags which are not +B specific. + +=item B<--prefix> + +Prints the installation prefix of architecture independent files + +=item B<--exec-prefix> + +Prints the installation prefix of architecture dependent files. + +=item B<--bindir> + +Prints the installation directory of binaries. + +=item B<--libdir> + +Prints the installation directory of libraries. + +=item B<--includedir> + +Prints the installation directory of include headers. + +=item B<--mandir> + +Prints the installation directory of manual pages. + +=item B<--datadir> + +Prints the installation directory of shared data. + +=item B<--acdir> + +Prints the installation directory of B data. + +=item B<--cflags> + +Prints the C compiler flags which are needed to compile the pth(3)-based +application. The output is usually added to the C variable of the +applications C. + +=item B<--ldflags> + +Prints the linker flags (C<-L>) which are needed to link the application with +the pth(3) library. The output is usually added to the C variable of +the applications C. + +=item B<--libs> + +Prints the library flags (C<-l>) which are needed to link the application with +the pth(3) library. The output is usually added to the C variable of the +applications C. + +=back + +=head1 EXAMPLE + + CC = cc + CFLAGS = -O `pth-config --cflags` + LDFLAGS = `pth-config --ldflags` + LIBS = -lm `pth-config --libs` + + all: foo + foo: foo.o + $(CC) $(LDFLAGS) -o foo foo.o $(LIBS) + foo.o: foo.c + $(CC) $(CFLAGS) -c foo.c + +=head1 SEE ALSO + +pth(3), cc(1). + +=head1 AUTHOR + + Ralf S. Engelschall + rse@engelschall.com + www.engelschall.com + +=cut + Index: ossp-pkg/pth/pth.h.in RCS File: /v/ossp/cvs/ossp-pkg/pth/pth.h.in,v rcsdiff -q -kk '-r1.128' '-r1.129' -u '/v/ossp/cvs/ossp-pkg/pth/pth.h.in,v' 2>/dev/null --- pth.h.in 2001/03/24 13:49:06 1.128 +++ pth.h.in 2001/03/24 14:51:04 1.129 @@ -1,6 +1,6 @@ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth.m4 RCS File: /v/ossp/cvs/ossp-pkg/pth/pth.m4,v co -q -kk -p'1.7' '/v/ossp/cvs/ossp-pkg/pth/pth.m4,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth.m4' 2>/dev/null --- ossp-pkg/pth/pth.m4 +++ - 2024-05-13 13:57:53.865782805 +0200 @@ -0,0 +1,403 @@ +dnl ## +dnl ## GNU Pth - The GNU Portable Threads +dnl ## Copyright (c) 1999-2001 Ralf S. Engelschall +dnl ## +dnl ## This file is part of GNU Pth, a non-preemptive thread scheduling +dnl ## library which can be found at http://www.gnu.org/software/pth/. +dnl ## +dnl ## This library is free software; you can redistribute it and/or +dnl ## modify it under the terms of the GNU Lesser General Public +dnl ## License as published by the Free Software Foundation; either +dnl ## version 2.1 of the License, or (at your option) any later version. +dnl ## +dnl ## This library is distributed in the hope that it will be useful, +dnl ## but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl ## Lesser General Public License for more details. +dnl ## +dnl ## You should have received a copy of the GNU Lesser General Public +dnl ## License along with this library; if not, write to the Free Software +dnl ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +dnl ## USA, or contact Ralf S. Engelschall . +dnl ## +dnl ## pth.m4: Autoconf macro for locating GNU Pth from within +dnl ## configure.in of third-party software packages +dnl ## + +dnl ## +dnl ## Synopsis: +dnl ## AC_CHECK_PTH([MIN-VERSION [, # minimum Pth version, e.g. 1.2.0 +dnl ## DEFAULT-WITH-PTH [, # default value for --with-pth option +dnl ## DEFAULT-WITH-PTH-TEST [,# default value for --with-pth-test option +dnl ## EXTEND-VARS [, # whether CFLAGS/LDFLAGS/etc are extended +dnl ## ACTION-IF-FOUND [, # action to perform if Pth was found +dnl ## ACTION-IF-NOT-FOUND # action to perform if Pth was not found +dnl ## ]]]]]]) +dnl ## Examples: +dnl ## AC_CHECK_PTH(1.2.0) +dnl ## AC_CHECK_PTH(1.2.0,,,no,CFLAGS="$CFLAGS -DHAVE_PTH $PTH_CFLAGS") +dnl ## AC_CHECK_PTH(1.2.0,yes,yes,yes,CFLAGS="$CFLAGS -DHAVE_PTH") +dnl ## +dnl +dnl # auxilliary macros +AC_DEFUN(_AC_PTH_ERROR, [dnl +AC_MSG_RESULT([*FAILED*]) +define(_ac_pth_line,dnl +"+------------------------------------------------------------------------+") +echo " _ac_pth_line" 1>&2 +cat <>/ /' 1>&2 +$1 +EOT +echo " _ac_pth_line" 1>&2 +undefine(_ac_pth_line) +exit 1 +]) +AC_DEFUN(_AC_PTH_VERBOSE, [dnl +if test ".$verbose" = .yes; then + AC_MSG_RESULT([ $1]) +fi +]) +dnl # the user macro +AC_DEFUN(AC_CHECK_PTH, [dnl +dnl +dnl # prerequisites +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CPP])dnl +dnl +PTH_CPPFLAGS='' +PTH_CFLAGS='' +PTH_LDFLAGS='' +PTH_LIBS='' +AC_SUBST(PTH_CPPFLAGS) +AC_SUBST(PTH_CFLAGS) +AC_SUBST(PTH_LDFLAGS) +AC_SUBST(PTH_LIBS) +dnl # command line options +AC_MSG_CHECKING(for GNU Pth) +_AC_PTH_VERBOSE([]) +AC_ARG_WITH(pth,dnl +[ --with-pth[=ARG] Build with GNU Pth Library (default=]ifelse([$2],,yes,$2)[)],dnl +,dnl +with_pth="ifelse([$2],,yes,$2)" +)dnl +AC_ARG_WITH(pth-test,dnl +[ --with-pth-test Perform GNU Pth Sanity Test (default=]ifelse([$3],,yes,$3)[)],dnl +,dnl +with_pth_test="ifelse([$3],,yes,$3)" +)dnl +_AC_PTH_VERBOSE([+ Command Line Options:]) +_AC_PTH_VERBOSE([ o --with-pth=$with_pth]) +_AC_PTH_VERBOSE([ o --with-pth-test=$with_pth_test]) +dnl +dnl # configuration +if test ".$with_pth" != .no; then + _pth_subdir=no + _pth_subdir_opts='' + case "$with_pth" in + subdir:* ) + _pth_subdir=yes + changequote(, )dnl + _pth_subdir_opts=`echo $with_pth | sed -e 's/^subdir:[^ ]*[ ]*//'` + with_pth=`echo $with_pth | sed -e 's/^subdir:\([^ ]*\).*$/\1/'` + changequote([, ])dnl + ;; + esac + _pth_version="" + _pth_location="" + _pth_type="" + _pth_cppflags="" + _pth_cflags="" + _pth_ldflags="" + _pth_libs="" + if test ".$with_pth" = .yes; then + # via config script in $PATH + changequote(, )dnl + _pth_version=`(pth-config --version) 2>/dev/null |\ + sed -e 's/^.*\([0-9]\.[0-9]*[ab.][0-9]*\).*$/\1/'` + changequote([, ])dnl + if test ".$_pth_version" != .; then + _pth_location=`pth-config --prefix` + _pth_type='installed' + _pth_cppflags=`pth-config --cflags` + _pth_cflags=`pth-config --cflags` + _pth_ldflags=`pth-config --ldflags` + _pth_libs=`pth-config --libs` + fi + elif test -d "$with_pth"; then + with_pth=`echo $with_pth | sed -e 's;/*$;;'` + _pth_found=no + # via locally included source tree + if test ".$_pth_subdir" = .yes; then + _pth_location="$with_pth" + _pth_type='local' + _pth_cppflags="-I$with_pth" + _pth_cflags="-I$with_pth" + if test -f "$with_pth/ltconfig"; then + _pth_ldflags="-L$with_pth/.libs" + else + _pth_ldflags="-L$with_pth" + fi + _pth_libs="-lpth" + changequote(, )dnl + _pth_version=`grep '^const char PTH_Hello' $with_pth/pth_vers.c |\ + sed -e 's;^.*Version[ ]*\([0-9]*\.[0-9]*[.ab][0-9]*\)[ ].*$;\1;'` + changequote([, ])dnl + _pth_found=yes + ac_configure_args="$ac_configure_args --enable-subdir $_pth_subdir_opts" + with_pth_test=no + fi + # via config script under a specified directory + # (a standard installation, but not a source tree) + if test ".$_pth_found" = .no; then + for _dir in $with_pth/bin $with_pth; do + if test -f "$_dir/pth-config"; then + test -f "$_dir/pth-config.in" && continue # pth-config in source tree! + changequote(, )dnl + _pth_version=`($_dir/pth-config --version) 2>/dev/null |\ + sed -e 's/^.*\([0-9]\.[0-9]*[ab.][0-9]*\).*$/\1/'` + changequote([, ])dnl + if test ".$_pth_version" != .; then + _pth_location=`$_dir/pth-config --prefix` + _pth_type="installed" + _pth_cppflags=`$_dir/pth-config --cflags` + _pth_cflags=`$_dir/pth-config --cflags` + _pth_ldflags=`$_dir/pth-config --ldflags` + _pth_libs=`$_dir/pth-config --libs` + _pth_found=yes + break + fi + fi + done + fi + # in any subarea under a specified directory + # (either a special installation or a Pth source tree) + if test ".$_pth_found" = .no; then + changequote(, )dnl + _pth_found=0 + for _file in x `find $with_pth -name "pth.h" -type f -print`; do + test .$_file = .x && continue + _dir=`echo $_file | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;'` + _pth_version=`($_dir/pth-config --version) 2>/dev/null |\ + sed -e 's/^.*\([0-9]\.[0-9]*[ab.][0-9]*\).*$/\1/'` + if test ".$_pth_version" = .; then + _pth_version=`grep '^#define PTH_VERSION_STR' $_file |\ + sed -e 's;^#define[ ]*PTH_VERSION_STR[ ]*"\([0-9]*\.[0-9]*[.ab][0-9]*\)[ ].*$;\1;'` + fi + _pth_cppflags="-I$_dir" + _pth_cflags="-I$_dir" + _pth_found=`expr $_pth_found + 1` + done + for _file in x `find $with_pth -name "libpth.[aso]" -type f -print`; do + test .$_file = .x && continue + _dir=`echo $_file | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;'` + _pth_ldflags="-L$_dir" + _pth_libs="-lpth" + _pth_found=`expr $_pth_found + 1` + done + changequote([, ])dnl + if test ".$_pth_found" = .2; then + _pth_location="$with_pth" + _pth_type="uninstalled" + else + _pth_version='' + fi + fi + fi + _AC_PTH_VERBOSE([+ Determined Location:]) + _AC_PTH_VERBOSE([ o path: $_pth_location]) + _AC_PTH_VERBOSE([ o type: $_pth_type]) + if test ".$_pth_version" = .; then + if test ".$with_pth" != .yes; then + _AC_PTH_ERROR([dnl + Unable to locate GNU Pth under $with_pth. + Please specify the correct path to either a GNU Pth installation tree + (use --with-pth=DIR if you used --prefix=DIR for installing GNU Pth in + the past) or to a GNU Pth source tree (use --with-pth=DIR if DIR is a + path to a pth-X.Y.Z/ directory; but make sure the package is already + built, i.e., the "configure; make" step was already performed there).]) + else + _AC_PTH_ERROR([dnl + Unable to locate GNU Pth in any system-wide location (see \$PATH). + Please specify the correct path to either a GNU Pth installation tree + (use --with-pth=DIR if you used --prefix=DIR for installing GNU Pth in + the past) or to a GNU Pth source tree (use --with-pth=DIR if DIR is a + path to a pth-X.Y.Z/ directory; but make sure the package is already + built, i.e., the "configure; make" step was already performed there).]) + fi + fi + dnl # + dnl # Check whether the found version is sufficiently new + dnl # + _req_version="ifelse([$1],,1.0.0,$1)" + for _var in _pth_version _req_version; do + eval "_val=\"\$${_var}\"" + _major=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\1/'` + _minor=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\2/'` + _rtype=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\3/'` + _micro=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\4/'` + case $_rtype in + "a" ) _rtype=0 ;; + "b" ) _rtype=1 ;; + "." ) _rtype=2 ;; + esac + _hex=`echo dummy | awk '{ printf("%d%02d%1d%02d", major, minor, rtype, micro); }' \ + "major=$_major" "minor=$_minor" "rtype=$_rtype" "micro=$_micro"` + eval "${_var}_hex=\"\$_hex\"" + done + _AC_PTH_VERBOSE([+ Determined Versions:]) + _AC_PTH_VERBOSE([ o existing: $_pth_version -> 0x$_pth_version_hex]) + _AC_PTH_VERBOSE([ o required: $_req_version -> 0x$_req_version_hex]) + _ok=0 + if test ".$_pth_version_hex" != .; then + if test ".$_req_version_hex" != .; then + if test $_pth_version_hex -ge $_req_version_hex; then + _ok=1 + fi + fi + fi + if test ".$_ok" = .0; then + _AC_PTH_ERROR([dnl + Found Pth version $_pth_version, but required at least version $_req_version. + Upgrade Pth under $_pth_location to $_req_version or higher first, please.]) + fi + dnl # + dnl # Perform Pth Sanity Compile Check + dnl # + if test ".$with_pth_test" = .yes; then + _ac_save_CPPFLAGS="$CPPFLAGS" + _ac_save_CFLAGS="$CFLAGS" + _ac_save_LDFLAGS="$LDFLAGS" + _ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $_pth_cppflags" + CFLAGS="$CFLAGS $_pth_cflags" + LDFLAGS="$LDFLAGS $_pth_ldflags" + LIBS="$LIBS $_pth_libs" + _AC_PTH_VERBOSE([+ Test Build Environment:]) + _AC_PTH_VERBOSE([ o CPPFLAGS=\"$CPPFLAGS\"]) + _AC_PTH_VERBOSE([ o CFLAGS=\"$CFLAGS\"]) + _AC_PTH_VERBOSE([ o LDFLAGS=\"$LDFLAGS\"]) + _AC_PTH_VERBOSE([ o LIBS=\"$LIBS\"]) + cross_compile=no + define(_code1, [dnl + #include + #include + ]) + define(_code2, [dnl + int main(int argc, char *argv[]) + { + FILE *fp; + if (!(fp = fopen("conftestval", "w"))) + exit(1); + fprintf(fp, "hmm"); + fclose(fp); + pth_init(); + pth_kill(); + if (!(fp = fopen("conftestval", "w"))) + exit(1); + fprintf(fp, "yes"); + fclose(fp); + exit(0); + } + ]) + _AC_PTH_VERBOSE([+ Performing Sanity Checks:]) + _AC_PTH_VERBOSE([ o pre-processor test]) + AC_TRY_CPP(_code1, _ok=yes, _ok=no) + if test ".$_ok" != .yes; then + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity pre-processor check. This means + the GNU Pth header pth.h was not found. + We used the following build environment: + >> CPP="$CPP" + >> CPPFLAGS="$CPPFLAGS" + See config.log for possibly more details.]) + fi + _AC_PTH_VERBOSE([ o link check]) + AC_TRY_LINK(_code1, _code2, _ok=yes, _ok=no) + if test ".$_ok" != .yes; then + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity linker check. This means + the GNU Pth library libpth.a was not found. + We used the following build environment: + >> CC="$CC" + >> CFLAGS="$CFLAGS" + >> LDFLAGS="$LDFLAGS" + >> LIBS="$LIBS" + See config.log for possibly more details.]) + fi + _AC_PTH_VERBOSE([ o run-time check]) + AC_TRY_RUN(_code1 _code2, _ok=`cat conftestval`, _ok=no, _ok=no) + if test ".$_ok" != .yes; then + if test ".$_ok" = .no; then + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity execution check. This usually + means that the GNU Pth shared library libpth.so is present + but \$LD_LIBRARY_PATH is incomplete to execute a Pth test. + In this case either disable this test via --without-pth-test, + or extend \$LD_LIBRARY_PATH, or build GNU Pth as a static + library only via its --disable-shared Autoconf option. + We used the following build environment: + >> CC="$CC" + >> CFLAGS="$CFLAGS" + >> LDFLAGS="$LDFLAGS" + >> LIBS="$LIBS" + See config.log for possibly more details.]) + else + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity run-time check. This usually + means that the GNU Pth library failed to work and possibly + caused a core dump in the test program. In this case it + is strongly recommended that you re-install GNU Pth and this + time make sure that it really passes its "make test" procedure. + We used the following build environment: + >> CC="$CC" + >> CFLAGS="$CFLAGS" + >> LDFLAGS="$LDFLAGS" + >> LIBS="$LIBS" + See config.log for possibly more details.]) + fi + fi + _extendvars="ifelse([$4],,yes,$4)" + if test ".$_extendvars" != .yes; then + CPPFLAGS="$_ac_save_CPPFLAGS" + CFLAGS="$_ac_save_CFLAGS" + LDFLAGS="$_ac_save_LDFLAGS" + LIBS="$_ac_save_LIBS" + fi + else + _extendvars="ifelse([$4],,yes,$4)" + if test ".$_extendvars" = .yes; then + if test ".$_pth_subdir" = .yes; then + CPPFLAGS="$CPPFLAGS $_pth_cppflags" + CFLAGS="$CFLAGS $_pth_cflags" + LDFLAGS="$LDFLAGS $_pth_ldflags" + LIBS="$LIBS $_pth_libs" + fi + fi + fi + PTH_CPPFLAGS="$_pth_cppflags" + PTH_CFLAGS="$_pth_cflags" + PTH_LDFLAGS="$_pth_ldflags" + PTH_LIBS="$_pth_libs" + AC_SUBST(PTH_CPPFLAGS) + AC_SUBST(PTH_CFLAGS) + AC_SUBST(PTH_LDFLAGS) + AC_SUBST(PTH_LIBS) + _AC_PTH_VERBOSE([+ Final Results:]) + _AC_PTH_VERBOSE([ o PTH_CPPFLAGS=\"$PTH_CPPFLAGS\"]) + _AC_PTH_VERBOSE([ o PTH_CFLAGS=\"$PTH_CFLAGS\"]) + _AC_PTH_VERBOSE([ o PTH_LDFLAGS=\"$PTH_LDFLAGS\"]) + _AC_PTH_VERBOSE([ o PTH_LIBS=\"$PTH_LIBS\"]) +fi +if test ".$with_pth" != .no; then + AC_MSG_RESULT([version $_pth_version, $_pth_type under $_pth_location]) + ifelse([$5], , :, [$5]) +else + AC_MSG_RESULT([no]) + ifelse([$6], , :, [$6]) +fi +]) + Index: ossp-pkg/pth/pth.pod RCS File: /v/ossp/cvs/ossp-pkg/pth/pth.pod,v rcsdiff -q -kk '-r1.144' '-r1.145' -u '/v/ossp/cvs/ossp-pkg/pth/pth.pod,v' 2>/dev/null --- pth.pod 2001/03/24 13:49:06 1.144 +++ pth.pod 2001/03/24 14:51:04 1.145 @@ -1,6 +1,6 @@ ## ## GNU Pth - The GNU Portable Threads -## Copyright (c) 1999-2000 Ralf S. Engelschall +## Copyright (c) 1999-2001 Ralf S. Engelschall ## ## This file is part of GNU Pth, a non-preemptive thread scheduling ## library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth.spec RCS File: /v/ossp/cvs/ossp-pkg/pth/pth.spec,v rcsdiff -q -kk '-r1.4' '-r1.5' -u '/v/ossp/cvs/ossp-pkg/pth/pth.spec,v' 2>/dev/null --- pth.spec 2000/10/03 08:00:35 1.4 +++ pth.spec 2001/03/24 14:51:04 1.5 @@ -1,6 +1,6 @@ ## ## GNU Pth - The GNU Portable Threads -## Copyright (c) 2000 Ralf S. Engelschall +## Copyright (c) 2000-2001 Ralf S. Engelschall ## ## This file is part of GNU Pth, a non-preemptive thread scheduling ## library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth_acdef.h.in RCS File: /v/ossp/cvs/ossp-pkg/pth/Attic/pth_acdef.h.in,v rcsdiff -q -kk '-r1.15' '-r1.16' -u '/v/ossp/cvs/ossp-pkg/pth/Attic/pth_acdef.h.in,v' 2>/dev/null --- pth_acdef.h.in 2000/10/03 09:26:47 1.15 +++ pth_acdef.h.in 2001/03/24 14:51:04 1.16 @@ -1,7 +1,7 @@ /* pth_acdef.h.in. Generated automatically from - by autoheader. */ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth_acmac.h.in RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_acmac.h.in,v co -q -kk -p'1.7' '/v/ossp/cvs/ossp-pkg/pth/pth_acmac.h.in,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_acmac.h.in' 2>/dev/null --- ossp-pkg/pth/pth_acmac.h.in +++ - 2024-05-13 13:57:53.885675905 +0200 @@ -0,0 +1,64 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_acmac.h: Autoconf macros +*/ + +#ifndef _PTH_ACMAC_H_ +#define _PTH_ACMAC_H_ + +/* sig{set,long}jmp macros */ +@pth_sigjmpbuf@ +@pth_sigsetjmp@ +@pth_siglongjmp@ + +/* stack setup macros */ +#define pth_skaddr(func,skaddr,sksize) pth_skaddr_##func(skaddr,sksize) +#define pth_sksize(func,skaddr,sksize) pth_sksize_##func(skaddr,sksize) +@pth_skaddr_sigstack@ +@pth_sksize_sigstack@ +@pth_skaddr_sigaltstack@ +@pth_sksize_sigaltstack@ +@pth_skaddr_makecontext@ +@pth_sksize_makecontext@ + +/* mctx compile defines */ +#define PTH_MCTX_MTH(which) (PTH_MCTX_MTH_use == (PTH_MCTX_MTH_##which)) +#define PTH_MCTX_DSP(which) (PTH_MCTX_DSP_use == (PTH_MCTX_DSP_##which)) +#define PTH_MCTX_STK(which) (PTH_MCTX_STK_use == (PTH_MCTX_STK_##which)) +#define PTH_MCTX_MTH_mcsc 1 +#define PTH_MCTX_MTH_sjlj 2 +#define PTH_MCTX_DSP_sc 1 +#define PTH_MCTX_DSP_ssjlj 2 +#define PTH_MCTX_DSP_sjlj 3 +#define PTH_MCTX_DSP_usjlj 4 +#define PTH_MCTX_DSP_sjlje 5 +#define PTH_MCTX_DSP_sjljlx 6 +#define PTH_MCTX_DSP_sjljisc 7 +#define PTH_MCTX_DSP_sjljw32 8 +#define PTH_MCTX_STK_mc 1 +#define PTH_MCTX_STK_ss 2 +#define PTH_MCTX_STK_sas 3 +#define PTH_MCTX_STK_none 4 + +#endif /* _PTH_ACMAC_H_ */ + Index: ossp-pkg/pth/pth_attr.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_attr.c,v co -q -kk -p'1.15' '/v/ossp/cvs/ossp-pkg/pth/pth_attr.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_attr.c' 2>/dev/null --- ossp-pkg/pth/pth_attr.c +++ - 2024-05-13 13:57:53.888261857 +0200 @@ -0,0 +1,298 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_attr.c: Pth thread attributes +*/ + /* ``Unix -- where you can do anything + in two keystrokes, or less...'' + -- Unknown */ +#include "pth_p.h" + +#if cpp + +enum { + PTH_ATTR_GET, + PTH_ATTR_SET +}; + +struct pth_attr_st { + pth_t a_tid; + int a_prio; + char a_name[PTH_TCB_NAMELEN]; + int a_joinable; + unsigned int a_cancelstate; + unsigned int a_stacksize; + char *a_stackaddr; +}; + +#endif /* cpp */ + +pth_attr_t pth_attr_of(pth_t t) +{ + pth_attr_t a; + + if (t == NULL) + return_errno(FALSE, EINVAL); + if ((a = (pth_attr_t)malloc(sizeof(struct pth_attr_st))) == NULL) + return_errno(NULL, ENOMEM); + a->a_tid = t; + return a; +} + +pth_attr_t pth_attr_new(void) +{ + pth_attr_t a; + + if ((a = (pth_attr_t)malloc(sizeof(struct pth_attr_st))) == NULL) + return_errno(NULL, ENOMEM); + a->a_tid = NULL; + pth_attr_init(a); + return a; +} + +int pth_attr_destroy(pth_attr_t a) +{ + if (a == NULL) + return_errno(FALSE, EINVAL); + free(a); + return TRUE; +} + +int pth_attr_init(pth_attr_t a) +{ + if (a == NULL) + return_errno(FALSE, EINVAL); + if (a->a_tid != NULL) + return_errno(FALSE, EPERM); + a->a_prio = PTH_PRIO_STD; + pth_util_cpystrn(a->a_name, "unknown", PTH_TCB_NAMELEN); + a->a_joinable = TRUE; + a->a_cancelstate = PTH_CANCEL_DEFAULT; + a->a_stacksize = 64*1024; + a->a_stackaddr = NULL; + return TRUE; +} + +int pth_attr_get(pth_attr_t a, int op, ...) +{ + va_list ap; + int rc; + + va_start(ap, op); + rc = pth_attr_ctrl(PTH_ATTR_GET, a, op, ap); + va_end(ap); + return rc; +} + +int pth_attr_set(pth_attr_t a, int op, ...) +{ + va_list ap; + int rc; + + va_start(ap, op); + rc = pth_attr_ctrl(PTH_ATTR_SET, a, op, ap); + va_end(ap); + return rc; +} + +intern int pth_attr_ctrl(int cmd, pth_attr_t a, int op, va_list ap) +{ + if (a == NULL) + return_errno(FALSE, EINVAL); + switch (op) { + case PTH_ATTR_PRIO: { + /* priority */ + int val, *src, *dst; + if (cmd == PTH_ATTR_SET) { + src = &val; val = va_arg(ap, int); + dst = (a->a_tid != NULL ? &a->a_tid->prio : &a->a_prio); + } + else { + src = (a->a_tid != NULL ? &a->a_tid->prio : &a->a_prio); + dst = va_arg(ap, int *); + } + *dst = *src; + break; + } + case PTH_ATTR_NAME: { + /* name */ + if (cmd == PTH_ATTR_SET) { + char *src, *dst; + src = va_arg(ap, char *); + dst = (a->a_tid != NULL ? a->a_tid->name : a->a_name); + pth_util_cpystrn(dst, src, PTH_TCB_NAMELEN); + } + else { + char *src, **dst; + src = (a->a_tid != NULL ? a->a_tid->name : a->a_name); + dst = va_arg(ap, char **); + *dst = src; + } + break; + } + case PTH_ATTR_JOINABLE: { + /* detachment type */ + int val, *src, *dst; + if (cmd == PTH_ATTR_SET) { + src = &val; val = va_arg(ap, int); + dst = (a->a_tid != NULL ? &a->a_tid->joinable : &a->a_joinable); + } + else { + src = (a->a_tid != NULL ? &a->a_tid->joinable : &a->a_joinable); + dst = va_arg(ap, int *); + } + *dst = *src; + break; + } + case PTH_ATTR_CANCEL_STATE: { + /* cancellation state */ + unsigned int val, *src, *dst; + if (cmd == PTH_ATTR_SET) { + src = &val; val = va_arg(ap, unsigned int); + dst = (a->a_tid != NULL ? &a->a_tid->cancelstate : &a->a_cancelstate); + } + else { + src = (a->a_tid != NULL ? &a->a_tid->cancelstate : &a->a_cancelstate); + dst = va_arg(ap, unsigned int *); + } + *dst = *src; + break; + } + case PTH_ATTR_STACK_SIZE: { + /* stack size */ + unsigned int val, *src, *dst; + if (cmd == PTH_ATTR_SET) { + if (a->a_tid != NULL) + return_errno(FALSE, EPERM); + src = &val; val = va_arg(ap, unsigned int); + dst = &a->a_stacksize; + } + else { + src = (a->a_tid != NULL ? &a->a_tid->stacksize : &a->a_stacksize); + dst = va_arg(ap, unsigned int *); + } + *dst = *src; + break; + } + case PTH_ATTR_STACK_ADDR: { + /* stack address */ + char *val, **src, **dst; + if (cmd == PTH_ATTR_SET) { + if (a->a_tid != NULL) + return_errno(FALSE, EPERM); + src = &val; val = va_arg(ap, char *); + dst = &a->a_stackaddr; + } + else { + src = (a->a_tid != NULL ? &a->a_tid->stack : &a->a_stackaddr); + dst = va_arg(ap, char **); + } + *dst = *src; + break; + } + case PTH_ATTR_TIME_SPAWN: { + pth_time_t *dst; + if (cmd == PTH_ATTR_SET) + return_errno(FALSE, EPERM); + dst = va_arg(ap, pth_time_t *); + if (a->a_tid != NULL) + pth_time_set(dst, &a->a_tid->spawned); + else + pth_time_set(dst, PTH_TIME_ZERO); + break; + } + case PTH_ATTR_TIME_LAST: { + pth_time_t *dst; + if (cmd == PTH_ATTR_SET) + return_errno(FALSE, EPERM); + dst = va_arg(ap, pth_time_t *); + if (a->a_tid != NULL) + pth_time_set(dst, &a->a_tid->lastran); + else + pth_time_set(dst, PTH_TIME_ZERO); + break; + } + case PTH_ATTR_TIME_RAN: { + pth_time_t *dst; + if (cmd == PTH_ATTR_SET) + return_errno(FALSE, EPERM); + dst = va_arg(ap, pth_time_t *); + if (a->a_tid != NULL) + pth_time_set(dst, &a->a_tid->running); + else + pth_time_set(dst, PTH_TIME_ZERO); + break; + } + case PTH_ATTR_START_FUNC: { + void *(**dst)(void *); + if (cmd == PTH_ATTR_SET) + return_errno(FALSE, EPERM); + if (a->a_tid == NULL) + return_errno(FALSE, EACCES); + dst = (void *(**)(void *))va_arg(ap, void *); + *dst = a->a_tid->start_func; + break; + } + case PTH_ATTR_START_ARG: { + void **dst; + if (cmd == PTH_ATTR_SET) + return_errno(FALSE, EPERM); + if (a->a_tid == NULL) + return_errno(FALSE, EACCES); + dst = va_arg(ap, void **); + *dst = a->a_tid->start_arg; + break; + } + case PTH_ATTR_STATE: { + pth_state_t *dst; + if (cmd == PTH_ATTR_SET) + return_errno(FALSE, EPERM); + if (a->a_tid == NULL) + return_errno(FALSE, EACCES); + dst = va_arg(ap, pth_state_t *); + *dst = a->a_tid->state; + break; + } + case PTH_ATTR_EVENTS: { + pth_event_t *dst; + if (cmd == PTH_ATTR_SET) + return_errno(FALSE, EPERM); + if (a->a_tid == NULL) + return_errno(FALSE, EACCES); + dst = va_arg(ap, pth_event_t *); + *dst = a->a_tid->events; + break; + } + case PTH_ATTR_BOUND: { + int *dst; + if (cmd == PTH_ATTR_SET) + return_errno(FALSE, EPERM); + dst = va_arg(ap, int *); + *dst = (a->a_tid != NULL ? TRUE : FALSE); + break; + } + default: + return_errno(FALSE, EINVAL); + } + return TRUE; +} + Index: ossp-pkg/pth/pth_cancel.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_cancel.c,v co -q -kk -p'1.24' '/v/ossp/cvs/ossp-pkg/pth/pth_cancel.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_cancel.c' 2>/dev/null --- ossp-pkg/pth/pth_cancel.c +++ - 2024-05-13 13:57:53.891009012 +0200 @@ -0,0 +1,131 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_cancel.c: Pth thread cancellation +*/ + /* ``Study it forever and you'll still wonder. + Fly it once and you'll know.'' + -- Henry Spencer */ +#include "pth_p.h" + +/* set cancellation state */ +void pth_cancel_state(int newstate, int *oldstate) +{ + if (oldstate != NULL) + *oldstate = pth_current->cancelstate; + if (newstate != 0) + pth_current->cancelstate = newstate; + return; +} + +/* enter a cancellation point */ +void pth_cancel_point(void) +{ + if ( pth_current->cancelreq == TRUE + && pth_current->cancelstate & PTH_CANCEL_ENABLE) { + /* avoid looping if cleanup handlers contain cancellation points */ + pth_current->cancelreq = FALSE; + pth_debug2("pth_cancel_point: terminating cancelled thread \"%s\"", pth_current->name); + pth_exit(PTH_CANCELED); + } + return; +} + +/* cancel a thread (the friendly way) */ +int pth_cancel(pth_t thread) +{ + pth_pqueue_t *q; + + if (thread == NULL) + return_errno(FALSE, EINVAL); + + /* the current thread cannot be cancelled */ + if (thread == pth_current) + return_errno(FALSE, EINVAL); + + /* the thread has to be at least still alive */ + if (thread->state == PTH_STATE_DEAD) + return_errno(FALSE, EPERM); + + /* now mark the thread as cancelled */ + thread->cancelreq = TRUE; + + /* when cancellation is enabled in async mode we cancel the thread immediately */ + if ( thread->cancelstate & PTH_CANCEL_ENABLE + && thread->cancelstate & PTH_CANCEL_ASYNCHRONOUS) { + + /* remove thread from its queue */ + switch (thread->state) { + case PTH_STATE_NEW: q = &pth_NQ; break; + case PTH_STATE_READY: q = &pth_RQ; break; + case PTH_STATE_WAITING: q = &pth_WQ; break; + default: q = NULL; + } + if (q == NULL) + return_errno(FALSE, ESRCH); + if (!pth_pqueue_contains(q, thread)) + return_errno(FALSE, ESRCH); + pth_pqueue_delete(q, thread); + + /* execute cleanups */ + pth_thread_cleanup(thread); + + /* and now either kick it out or move it to dead queue */ + if (!thread->joinable) { + pth_debug2("pth_cancel: kicking out cancelled thread \"%s\" immediately", thread->name); + pth_tcb_free(thread); + } + else { + pth_debug2("pth_cancel: moving cancelled thread \"%s\" to dead queue", thread->name); + thread->join_arg = PTH_CANCELED; + thread->state = PTH_STATE_DEAD; + pth_pqueue_insert(&pth_DQ, PTH_PRIO_STD, thread); + } + } + return TRUE; +} + +/* abort a thread (the cruel way) */ +int pth_abort(pth_t thread) +{ + if (thread == NULL) + return_errno(FALSE, EINVAL); + + /* the current thread cannot be aborted */ + if (thread == pth_current) + return_errno(FALSE, EINVAL); + + if (thread->state == PTH_STATE_DEAD && thread->joinable) { + /* if thread is already terminated, just join it */ + if (!pth_join(thread, NULL)) + return FALSE; + } + else { + /* else force it to be detached and cancel it asynchronously */ + thread->joinable = FALSE; + thread->cancelstate = (PTH_CANCEL_ENABLE|PTH_CANCEL_ASYNCHRONOUS); + if (!pth_cancel(thread)) + return FALSE; + } + return TRUE; +} + Index: ossp-pkg/pth/pth_clean.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_clean.c,v co -q -kk -p'1.15' '/v/ossp/cvs/ossp-pkg/pth/pth_clean.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_clean.c' 2>/dev/null --- ossp-pkg/pth/pth_clean.c +++ - 2024-05-13 13:57:53.893637204 +0200 @@ -0,0 +1,85 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_clean.c: Pth per-thread cleanup handler +*/ + /* ``The concept seems to be clear by now. + It has been defined several times + by example of what it is not.'' + -- Unknown */ +#include "pth_p.h" + +#if cpp + +typedef struct pth_cleanup_st pth_cleanup_t; +struct pth_cleanup_st { + pth_cleanup_t *next; + void (*func)(void *); + void *arg; +}; + +#endif /* cpp */ + +int pth_cleanup_push(void (*func)(void *), void *arg) +{ + pth_cleanup_t *cleanup; + + if (func == NULL) + return_errno(FALSE, EINVAL); + if ((cleanup = (pth_cleanup_t *)malloc(sizeof(pth_cleanup_t))) == NULL) + return_errno(FALSE, ENOMEM); + cleanup->func = func; + cleanup->arg = arg; + cleanup->next = pth_current->cleanups; + pth_current->cleanups = cleanup; + return TRUE; +} + +int pth_cleanup_pop(int execute) +{ + pth_cleanup_t *cleanup; + int rc; + + rc = FALSE; + if ((cleanup = pth_current->cleanups) != NULL) { + pth_current->cleanups = cleanup->next; + if (execute) + cleanup->func(cleanup->arg); + free(cleanup); + rc = TRUE; + } + return rc; +} + +intern void pth_cleanup_popall(pth_t t, int execute) +{ + pth_cleanup_t *cleanup; + + while ((cleanup = t->cleanups) != NULL) { + t->cleanups = cleanup->next; + if (execute) + cleanup->func(cleanup->arg); + free(cleanup); + } + return; +} + Index: ossp-pkg/pth/pth_compat.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_compat.c,v co -q -kk -p'1.8' '/v/ossp/cvs/ossp-pkg/pth/pth_compat.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_compat.c' 2>/dev/null --- ossp-pkg/pth/pth_compat.c +++ - 2024-05-13 13:57:53.896745528 +0200 @@ -0,0 +1,53 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_compat.c: Pth compatibility support +*/ + /* ``Backward compatibility is for + users who don't want to live + on the bleeding edge.'' -- Unknown */ +#include "pth_p.h" + +COMPILER_HAPPYNESS(pth_compat) + +/* + * Replacement for strerror(3) + */ + +#if cpp +#if !defined(HAVE_STRERROR) +char *_pth_compat_strerror(int); +#define strerror(errnum) _pth_compat_strerror(errnum) +#endif +#endif + +#if !defined(HAVE_STRERROR) +extern char *const sys_errlist[]; +char *_pth_compat_strerror(int errnum) +{ + char *cp; + + cp = sys_errlist[errnum]; + return (cp); +} +#endif + Index: ossp-pkg/pth/pth_data.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_data.c,v co -q -kk -p'1.27' '/v/ossp/cvs/ossp-pkg/pth/pth_data.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_data.c' 2>/dev/null --- ossp-pkg/pth/pth_data.c +++ - 2024-05-13 13:57:53.899318441 +0200 @@ -0,0 +1,131 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_data.c: Pth per-thread specific data +*/ + /* ``Breakthrough ideas + are not from teams.'' + --- Hans von Ohain */ +#include "pth_p.h" + +struct pth_keytab_st { + int used; + void (*destructor)(void *); +}; + +static struct pth_keytab_st pth_keytab[PTH_KEY_MAX]; + +int pth_key_create(pth_key_t *key, void (*func)(void *)) +{ + for ((*key) = 0; (*key) < PTH_KEY_MAX; (*key)++) { + if (pth_keytab[(*key)].used == FALSE) { + pth_keytab[(*key)].used = TRUE; + pth_keytab[(*key)].destructor = func; + return TRUE; + } + } + return_errno(FALSE, EAGAIN); +} + +int pth_key_delete(pth_key_t key) +{ + if (key >= PTH_KEY_MAX) + return_errno(FALSE, EINVAL); + if (!pth_keytab[key].used) + return_errno(FALSE, EINVAL); + pth_keytab[key].used = FALSE; + return TRUE; +} + +int pth_key_setdata(pth_key_t key, const void *value) +{ + if (key >= PTH_KEY_MAX) + return_errno(FALSE, EINVAL); + if (!pth_keytab[key].used) + return_errno(FALSE, EINVAL); + if (pth_current->data_value == NULL) { + pth_current->data_value = (const void **)calloc(1, sizeof(void *)*PTH_KEY_MAX); + if (pth_current->data_value == NULL) + return_errno(FALSE, ENOMEM); + } + if (pth_current->data_value[key] == NULL) { + if (value != NULL) + pth_current->data_count++; + } + else { + if (value == NULL) + pth_current->data_count--; + } + pth_current->data_value[key] = value; + return TRUE; +} + +void *pth_key_getdata(pth_key_t key) +{ + if (key >= PTH_KEY_MAX) + return_errno(NULL, EINVAL); + if (!pth_keytab[key].used) + return_errno(NULL, EINVAL); + if (pth_current->data_value == NULL) + return NULL; + return (void *)pth_current->data_value[key]; +} + +intern void pth_key_destroydata(pth_t t) +{ + void *data; + int key; + int itr; + void (*destructor)(void *); + + if (t == NULL) + return; + if (t->data_value == NULL) + return; + /* POSIX thread iteration scheme */ + for (itr = 0; itr < PTH_DESTRUCTOR_ITERATIONS; itr++) { + for (key = 0; key < PTH_KEY_MAX; key++) { + if (t->data_count > 0) { + destructor = NULL; + data = NULL; + if (pth_keytab[key].used) { + if (t->data_value[key] != NULL) { + data = (void *)t->data_value[key]; + t->data_value[key] = NULL; + t->data_count--; + destructor = pth_keytab[key].destructor; + } + } + if (destructor != NULL) + destructor(data); + } + if (t->data_count == 0) + break; + } + if (t->data_count == 0) + break; + } + free(t->data_value); + t->data_value = NULL; + return; +} + Index: ossp-pkg/pth/pth_debug.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_debug.c,v co -q -kk -p'1.25' '/v/ossp/cvs/ossp-pkg/pth/pth_debug.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_debug.c' 2>/dev/null --- ossp-pkg/pth/pth_debug.c +++ - 2024-05-13 13:57:53.901987294 +0200 @@ -0,0 +1,114 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_debug.c: Pth debugging support +*/ + /* ``MY HACK: This universe. + Just one little problem: + core keeps dumping.'' + -- Unknown */ +#include "pth_p.h" + +#if cpp + +#ifndef PTH_DEBUG + +#define pth_debug1(a1) /* NOP */ +#define pth_debug2(a1, a2) /* NOP */ +#define pth_debug3(a1, a2, a3) /* NOP */ +#define pth_debug4(a1, a2, a3, a4) /* NOP */ +#define pth_debug5(a1, a2, a3, a4, a5) /* NOP */ +#define pth_debug6(a1, a2, a3, a4, a5, a6) /* NOP */ + +#else + +#define pth_debug1(a1) pth_debug(__FILE__, __LINE__, 1, a1) +#define pth_debug2(a1, a2) pth_debug(__FILE__, __LINE__, 2, a1, a2) +#define pth_debug3(a1, a2, a3) pth_debug(__FILE__, __LINE__, 3, a1, a2, a3) +#define pth_debug4(a1, a2, a3, a4) pth_debug(__FILE__, __LINE__, 4, a1, a2, a3, a4) +#define pth_debug5(a1, a2, a3, a4, a5) pth_debug(__FILE__, __LINE__, 5, a1, a2, a3, a4, a5) +#define pth_debug6(a1, a2, a3, a4, a5, a6) pth_debug(__FILE__, __LINE__, 6, a1, a2, a3, a4, a5, a6) + +#endif /* PTH_DEBUG */ + +#endif /* cpp */ + +intern void pth_debug(const char *file, int line, int argc, const char *fmt, ...) +{ + va_list ap; + static char str[1024]; + size_t n; + + errno_shield { + va_start(ap, fmt); + if (file != NULL) + pth_snprintf(str, sizeof(str), "%d:%s:%04d: ", (int)getpid(), file, line); + else + str[0] = NUL; + n = strlen(str); + if (argc == 1) + pth_util_cpystrn(str+n, fmt, sizeof(str)-n); + else + pth_vsnprintf(str+n, sizeof(str)-n, fmt, ap); + va_end(ap); + n = strlen(str); + str[n++] = '\n'; + pth_sc(write)(STDERR_FILENO, str, n); + } + return; +} + +/* dump out a page to stderr summarizing the internal state of Pth */ +intern void pth_dumpstate(FILE *fp) +{ + fprintf(fp, "+----------------------------------------------------------------------\n"); + fprintf(fp, "| Pth Version: %s\n", PTH_VERSION_STR); + fprintf(fp, "| Load Average: %.2f\n", pth_loadval); + pth_dumpqueue(fp, "NEW", &pth_NQ); + pth_dumpqueue(fp, "READY", &pth_RQ); + fprintf(fp, "| Thread Queue RUNNING:\n"); + fprintf(fp, "| 1. thread 0x%lx (\"%s\")\n", + (unsigned long)pth_current, pth_current->name); + pth_dumpqueue(fp, "WAITING", &pth_WQ); + pth_dumpqueue(fp, "SUSPENDED", &pth_SQ); + pth_dumpqueue(fp, "DEAD", &pth_DQ); + fprintf(fp, "+----------------------------------------------------------------------\n"); + return; +} + +intern void pth_dumpqueue(FILE *fp, const char *qn, pth_pqueue_t *q) +{ + pth_t t; + int n; + int i; + + fprintf(fp, "| Thread Queue %s:\n", qn); + n = pth_pqueue_elements(q); + if (n == 0) + fprintf(fp, "| no threads\n"); + i = 1; + for (t = pth_pqueue_head(q); t != NULL; t = pth_pqueue_walk(q, t, PTH_WALK_NEXT)) { + fprintf(fp, "| %d. thread 0x%lx (\"%s\")\n", i++, (unsigned long)t, t->name); + } + return; +} + Index: ossp-pkg/pth/pth_errno.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_errno.c,v co -q -kk -p'1.22' '/v/ossp/cvs/ossp-pkg/pth/pth_errno.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_errno.c' 2>/dev/null --- ossp-pkg/pth/pth_errno.c +++ - 2024-05-13 13:57:53.904641058 +0200 @@ -0,0 +1,56 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_errno.c: Pth errno support +*/ + /* Steinbach's Guideline for Systems Programming: + ``Never test for an error condition + you don't know how to handle.'' */ +#include "pth_p.h" + +#if cpp + +/* enclose errno in a block */ +#define errno_shield \ + for ( pth_errno_storage = errno, \ + pth_errno_flag = TRUE; \ + pth_errno_flag; \ + errno = pth_errno_storage, \ + pth_errno_flag = FALSE ) + +/* return plus setting an errno value */ +#if defined(PTH_DEBUG) +#define return_errno(return_val,errno_val) \ + do { errno = (errno_val); \ + pth_debug4("return 0x%lx with errno %d(\"%s\")", \ + (unsigned long)(return_val), (errno), strerror((errno))); \ + return (return_val); } while (0) +#else +#define return_errno(return_val,errno_val) \ + do { errno = (errno_val); return (return_val); } while (0) +#endif + +#endif /* cpp */ + +intern int pth_errno_storage = 0; +intern int pth_errno_flag = 0; + Index: ossp-pkg/pth/pth_event.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_event.c,v co -q -kk -p'1.55' '/v/ossp/cvs/ossp-pkg/pth/pth_event.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_event.c' 2>/dev/null --- ossp-pkg/pth/pth_event.c +++ - 2024-05-13 13:57:53.907247585 +0200 @@ -0,0 +1,425 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_event.c: Pth event handling +*/ + /* ``Those of you who think they + know everything are very annoying + to those of us who do.'' + -- Unknown */ +#include "pth_p.h" + +#if cpp + +/* event structure */ +struct pth_event_st { + struct pth_event_st *ev_next; + struct pth_event_st *ev_prev; + int ev_occurred; + int ev_type; + int ev_goal; + union { + struct { int fd; } FD; + struct { int *n; int nfd; fd_set *rfds, *wfds, *efds; } SELECT; + struct { sigset_t *sigs; int *sig; } SIGS; + struct { pth_time_t tv; } TIME; + struct { pth_msgport_t mp; } MSG; + struct { pth_mutex_t *mutex; } MUTEX; + struct { pth_cond_t *cond; } COND; + struct { pth_t tid; } TID; + struct { int (*func)(void *); void *arg; pth_time_t tv; } FUNC; + } ev_args; +}; + +#endif /* cpp */ + +/* event structure destructor */ +static void pth_event_destructor(void *vp) +{ + /* free this single(!) event. That it is just a single event is a + requirement for pth_event(PTH_MODE_STATIC, ...), or else we would + get into horrible trouble on asychronous cleanups */ + pth_event_free((pth_event_t)vp, PTH_FREE_THIS); + return; +} + +/* event structure constructor */ +pth_event_t pth_event(unsigned long spec, ...) +{ + pth_event_t ev; + pth_key_t *ev_key; + va_list ap; + + va_start(ap, spec); + + /* allocate new or reuse static or supplied event structure */ + if (spec & PTH_MODE_REUSE) { + /* reuse supplied event structure */ + ev = va_arg(ap, pth_event_t); + } + else if (spec & PTH_MODE_STATIC) { + /* reuse static event structure */ + ev_key = va_arg(ap, pth_key_t *); + if (*ev_key == PTH_KEY_INIT) + pth_key_create(ev_key, pth_event_destructor); + ev = (pth_event_t)pth_key_getdata(*ev_key); + if (ev == NULL) { + ev = (pth_event_t)malloc(sizeof(struct pth_event_st)); + pth_key_setdata(*ev_key, ev); + } + } + else { + /* allocate new dynamic event structure */ + ev = (pth_event_t)malloc(sizeof(struct pth_event_st)); + } + if (ev == NULL) + return NULL; /* errno is already set */ + + /* create new event ring out of event or insert into existing ring */ + if (spec & PTH_MODE_CHAIN) { + pth_event_t ch = va_arg(ap, pth_event_t); + ev->ev_prev = ch->ev_prev; + ev->ev_next = ch; + ev->ev_prev->ev_next = ev; + ev->ev_next->ev_prev = ev; + } + else { + ev->ev_prev = ev; + ev->ev_next = ev; + } + + /* initialize common ingredients */ + ev->ev_occurred = FALSE; + + /* initialize event specific ingredients */ + if (spec & PTH_EVENT_FD) { + /* filedescriptor event */ + int fd = va_arg(ap, int); + ev->ev_type = PTH_EVENT_FD; + ev->ev_goal = (int)(spec & (PTH_UNTIL_FD_READABLE|\ + PTH_UNTIL_FD_WRITEABLE|\ + PTH_UNTIL_FD_EXCEPTION)); + ev->ev_args.FD.fd = fd; + } + else if (spec & PTH_EVENT_SELECT) { + /* filedescriptor set select event */ + int *n = va_arg(ap, int *); + int nfd = va_arg(ap, int); + fd_set *rfds = va_arg(ap, fd_set *); + fd_set *wfds = va_arg(ap, fd_set *); + fd_set *efds = va_arg(ap, fd_set *); + ev->ev_type = PTH_EVENT_SELECT; + ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); + ev->ev_args.SELECT.n = n; + ev->ev_args.SELECT.nfd = nfd; + ev->ev_args.SELECT.rfds = rfds; + ev->ev_args.SELECT.wfds = wfds; + ev->ev_args.SELECT.efds = efds; + } + else if (spec & PTH_EVENT_SIGS) { + /* signal set event */ + sigset_t *sigs = va_arg(ap, sigset_t *); + int *sig = va_arg(ap, int *); + ev->ev_type = PTH_EVENT_SIGS; + ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); + ev->ev_args.SIGS.sigs = sigs; + ev->ev_args.SIGS.sig = sig; + } + else if (spec & PTH_EVENT_TIME) { + /* interrupt request event */ + pth_time_t tv = va_arg(ap, pth_time_t); + ev->ev_type = PTH_EVENT_TIME; + ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); + ev->ev_args.TIME.tv = tv; + } + else if (spec & PTH_EVENT_MSG) { + /* message port event */ + pth_msgport_t mp = va_arg(ap, pth_msgport_t); + ev->ev_type = PTH_EVENT_MSG; + ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); + ev->ev_args.MSG.mp = mp; + } + else if (spec & PTH_EVENT_MUTEX) { + /* mutual exclusion lock */ + pth_mutex_t *mutex = va_arg(ap, pth_mutex_t *); + ev->ev_type = PTH_EVENT_MUTEX; + ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); + ev->ev_args.MUTEX.mutex = mutex; + } + else if (spec & PTH_EVENT_COND) { + /* condition variable */ + pth_cond_t *cond = va_arg(ap, pth_cond_t *); + ev->ev_type = PTH_EVENT_COND; + ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); + ev->ev_args.COND.cond = cond; + } + else if (spec & PTH_EVENT_TID) { + /* thread id event */ + pth_t tid = va_arg(ap, pth_t); + int goal; + ev->ev_type = PTH_EVENT_TID; + if (spec & PTH_UNTIL_TID_NEW) + goal = PTH_STATE_NEW; + else if (spec & PTH_UNTIL_TID_READY) + goal = PTH_STATE_READY; + else if (spec & PTH_UNTIL_TID_WAITING) + goal = PTH_STATE_WAITING; + else if (spec & PTH_UNTIL_TID_DEAD) + goal = PTH_STATE_DEAD; + else + goal = PTH_STATE_READY; + ev->ev_goal = goal; + ev->ev_args.TID.tid = tid; + } + else if (spec & PTH_EVENT_FUNC) { + /* custom function event */ + ev->ev_type = PTH_EVENT_FUNC; + ev->ev_goal = (int)(spec & (PTH_UNTIL_OCCURRED)); + ev->ev_args.FUNC.func = (int (*)(void *))va_arg(ap, void *); + ev->ev_args.FUNC.arg = va_arg(ap, void *); + ev->ev_args.FUNC.tv = va_arg(ap, pth_time_t); + } + else + return_errno(NULL, EINVAL); + + va_end(ap); + + /* return event */ + return ev; +} + +/* determine type of event */ +unsigned long pth_event_typeof(pth_event_t ev) +{ + if (ev == NULL) + return_errno(0, EINVAL); + return (ev->ev_type | ev->ev_goal); +} + +/* event extractor */ +int pth_event_extract(pth_event_t ev, ...) +{ + va_list ap; + + if (ev == NULL) + return_errno(FALSE, EINVAL); + va_start(ap, ev); + + /* extract event specific ingredients */ + if (ev->ev_type & PTH_EVENT_FD) { + /* filedescriptor event */ + int *fd = va_arg(ap, int *); + *fd = ev->ev_args.FD.fd; + } + else if (ev->ev_type & PTH_EVENT_SIGS) { + /* signal set event */ + sigset_t **sigs = va_arg(ap, sigset_t **); + int **sig = va_arg(ap, int **); + *sigs = ev->ev_args.SIGS.sigs; + *sig = ev->ev_args.SIGS.sig; + } + else if (ev->ev_type & PTH_EVENT_TIME) { + /* interrupt request event */ + pth_time_t *tv = va_arg(ap, pth_time_t *); + *tv = ev->ev_args.TIME.tv; + } + else if (ev->ev_type & PTH_EVENT_MSG) { + /* message port event */ + pth_msgport_t *mp = va_arg(ap, pth_msgport_t *); + *mp = ev->ev_args.MSG.mp; + } + else if (ev->ev_type & PTH_EVENT_MUTEX) { + /* mutual exclusion lock */ + pth_mutex_t **mutex = va_arg(ap, pth_mutex_t **); + *mutex = ev->ev_args.MUTEX.mutex; + } + else if (ev->ev_type & PTH_EVENT_COND) { + /* condition variable */ + pth_cond_t **cond = va_arg(ap, pth_cond_t **); + *cond = ev->ev_args.COND.cond; + } + else if (ev->ev_type & PTH_EVENT_TID) { + /* thread id event */ + pth_t *tid = va_arg(ap, pth_t *); + *tid = ev->ev_args.TID.tid; + } + else if (ev->ev_type & PTH_EVENT_FUNC) { + /* custom function event */ + void **func = va_arg(ap, void **); + void **arg = va_arg(ap, void **); + pth_time_t *tv = va_arg(ap, pth_time_t *); + *func = (int (**)(void *))ev->ev_args.FUNC.func; + *arg = ev->ev_args.FUNC.arg; + *tv = ev->ev_args.FUNC.tv; + } + else + return_errno(FALSE, EINVAL); + va_end(ap); + return TRUE; +} + +/* concatenate one or more events or event rings */ +pth_event_t pth_event_concat(pth_event_t evf, ...) +{ + pth_event_t evc; /* current event */ + pth_event_t evn; /* next event */ + pth_event_t evl; /* last event */ + pth_event_t evt; /* temporary event */ + va_list ap; + + if (evf == NULL) + return_errno(NULL, EINVAL); + + /* open ring */ + va_start(ap, evf); + evc = evf; + evl = evc->ev_next; + + /* attach additional rings */ + while ((evn = va_arg(ap, pth_event_t)) != NULL) { + evc->ev_next = evn; + evt = evn->ev_prev; + evn->ev_prev = evc; + evc = evt; + } + + /* close ring */ + evc->ev_next = evl; + evl->ev_prev = evc; + va_end(ap); + + return evf; +} + +/* isolate one event from a possible appended event ring */ +pth_event_t pth_event_isolate(pth_event_t ev) +{ + pth_event_t ring; + + if (ev == NULL) + return_errno(NULL, EINVAL); + ring = NULL; + if (!(ev->ev_next == ev && ev->ev_prev == ev)) { + ring = ev->ev_next; + ev->ev_prev->ev_next = ev->ev_next; + ev->ev_next->ev_prev = ev->ev_prev; + ev->ev_prev = ev; + ev->ev_next = ev; + } + return ring; +} + +/* determine whether the event is occurred */ +int pth_event_occurred(pth_event_t ev) +{ + if (ev == NULL) + return_errno(FALSE, EINVAL); + return ev->ev_occurred; +} + +/* walk to next or previous event in an event ring */ +pth_event_t pth_event_walk(pth_event_t ev, unsigned int direction) +{ + if (ev == NULL) + return_errno(NULL, EINVAL); + do { + if (direction & PTH_WALK_NEXT) + ev = ev->ev_next; + else if (direction & PTH_WALK_PREV) + ev = ev->ev_prev; + else + return_errno(NULL, EINVAL); + } while ((direction & PTH_UNTIL_OCCURRED) && !(ev->ev_occurred)); + return ev; +} + +/* deallocate an event structure */ +int pth_event_free(pth_event_t ev, int mode) +{ + pth_event_t evc; + pth_event_t evn; + + if (ev == NULL) + return_errno(FALSE, EINVAL); + if (mode == PTH_FREE_THIS) { + ev->ev_prev->ev_next = ev->ev_next; + ev->ev_next->ev_prev = ev->ev_prev; + free(ev); + } + else if (mode == PTH_FREE_ALL) { + evc = ev; + do { + evn = evc->ev_next; + free(evc); + evc = evn; + } while (evc != ev); + } + return TRUE; +} + +/* wait for one or more events */ +int pth_wait(pth_event_t ev_ring) +{ + int occurred; + pth_event_t ev; + + /* at least a waiting ring is required */ + if (ev_ring == NULL) + return_errno(-1, EINVAL); + pth_debug2("pth_wait: enter from thread \"%s\"", pth_current->name); + + /* mark all events in waiting ring as still not occurred */ + ev = ev_ring; + do { + ev->ev_occurred = FALSE; + pth_debug2("pth_wait: waiting on event 0x%lx", (unsigned long)ev); + ev = ev->ev_next; + } while (ev != ev_ring); + + /* link event ring to current thread */ + pth_current->events = ev_ring; + + /* move thread into waiting state + and transfer control to scheduler */ + pth_current->state = PTH_STATE_WAITING; + pth_yield(NULL); + + /* check for cancellation */ + pth_cancel_point(); + + /* unlink event ring from current thread */ + pth_current->events = NULL; + + /* count number of actually occurred events */ + ev = ev_ring; + occurred = 0; + do { + occurred++; + pth_debug2("pth_wait: occurred event 0x%lx", (unsigned long)ev); + ev = ev->ev_next; + } while (ev != ev_ring); + + /* leave to current thread with number of occurred events */ + pth_debug2("pth_wait: leave to thread \"%s\"", pth_current->name); + return occurred; +} + Index: ossp-pkg/pth/pth_ext.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_ext.c,v co -q -kk -p'1.9' '/v/ossp/cvs/ossp-pkg/pth/pth_ext.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_ext.c' 2>/dev/null --- ossp-pkg/pth/pth_ext.c +++ - 2024-05-13 13:57:53.910126204 +0200 @@ -0,0 +1,103 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_ext.c: Pth extensions +*/ + /* ``Killing for peace is + like fucking for virginity.'' + -- Unknown */ +#include "pth_p.h" + +/* + * Sfio Extension: + * + * We provide an Sfio discipline which can be pushed on an Sfio_t* stream + * to use the Pth thread-aware I/O routines (pth_read/pth_write). + */ + +#if PTH_EXT_SFIO + +static ssize_t pth_sfio_read(Sfio_t *f, Void_t *buf, size_t n, Sfdisc_t *disc) +{ + ssize_t rv; + + rv = pth_read(sffileno(f), buf, n); + return rv; +} + +static ssize_t pth_sfio_write(Sfio_t *f, const Void_t *buf, size_t n, Sfdisc_t *disc) +{ + ssize_t rv; + + rv = pth_write(sffileno(f), buf, n); + return rv; +} + +static Sfoff_t pth_sfio_seek(Sfio_t *f, Sfoff_t addr, int type, Sfdisc_t *disc) +{ + return sfsk(f, addr, type, disc); +} + +static int pth_sfio_except(Sfio_t *f, int type, Void_t* data, Sfdisc_t *disc) +{ + int rv; + + switch (type) { + case SF_LOCKED: + case SF_READ: + case SF_WRITE: + case SF_SEEK: + case SF_NEW: + case SF_CLOSE: + case SF_FINAL: + case SF_DPUSH: + case SF_DPOP: + case SF_DBUFFER: + case SF_DPOLL: + case SF_READY: + case SF_SYNC: + case SF_PURGE: + default: + rv = 0; /* perform default action */ + } + return rv; +} + +#endif /* PTH_EXT_SFIO */ + +Sfdisc_t *pth_sfiodisc(void) +{ +#if PTH_EXT_SFIO + Sfdisc_t *disc; + + if ((disc = (Sfdisc_t *)malloc(sizeof(Sfdisc_t))) == NULL) + return NULL; + disc->readf = pth_sfio_read; + disc->writef = pth_sfio_write; + disc->seekf = pth_sfio_seek; + disc->exceptf = pth_sfio_except; + return disc; +#else + return_errno(NULL, ENOSYS); +#endif /* PTH_EXT_SFIO */ +} + Index: ossp-pkg/pth/pth_fork.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_fork.c,v rcsdiff -q -kk '-r1.11' '-r1.12' -u '/v/ossp/cvs/ossp-pkg/pth/pth_fork.c,v' 2>/dev/null --- pth_fork.c 2000/10/03 09:26:47 1.11 +++ pth_fork.c 2001/03/24 14:51:04 1.12 @@ -1,6 +1,6 @@ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth_high.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_high.c,v rcsdiff -q -kk '-r1.75' '-r1.76' -u '/v/ossp/cvs/ossp-pkg/pth/pth_high.c,v' 2>/dev/null --- pth_high.c 2000/10/03 09:26:47 1.75 +++ pth_high.c 2001/03/24 14:51:04 1.76 @@ -1,6 +1,6 @@ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth_lib.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_lib.c,v rcsdiff -q -kk '-r1.45' '-r1.46' -u '/v/ossp/cvs/ossp-pkg/pth/pth_lib.c,v' 2>/dev/null --- pth_lib.c 2001/03/24 14:27:28 1.45 +++ pth_lib.c 2001/03/24 14:51:04 1.46 @@ -1,6 +1,6 @@ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth_mctx.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_mctx.c,v co -q -kk -p'1.55' '/v/ossp/cvs/ossp-pkg/pth/pth_mctx.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_mctx.c' 2>/dev/null --- ossp-pkg/pth/pth_mctx.c +++ - 2024-05-13 13:57:53.927574728 +0200 @@ -0,0 +1,557 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_mctx.c: Pth machine context handling +*/ + /* ``If you can't do it in + ANSI C, it isn't worth doing.'' + -- Unknown */ +#include "pth_p.h" + +#if cpp + +/* + * machine context state structure + * + * In `jb' the CPU registers, the program counter, the stack + * pointer and (usually) the signals mask is stored. When the + * signal mask cannot be implicitly stored in `jb', it's + * alternatively stored explicitly in `sigs'. The `error' stores + * the value of `errno'. + */ + +#if PTH_MCTX_MTH(mcsc) +#include +#endif + +typedef struct pth_mctx_st pth_mctx_t; +struct pth_mctx_st { +#if PTH_MCTX_MTH(mcsc) + ucontext_t uc; +#elif PTH_MCTX_MTH(sjlj) + pth_sigjmpbuf jb; +#else +#error "unknown mctx method" +#endif + sigset_t sigs; +#if PTH_MCTX_DSP(sjlje) + sigset_t block; +#endif + int error; +}; + +/* +** ____ MACHINE STATE SWITCHING ______________________________________ +*/ + +/* + * save the current machine context + */ +#if PTH_MCTX_MTH(mcsc) +#define pth_mctx_save(mctx) \ + ( (mctx)->error = errno, \ + getcontext(&(mctx)->uc) ) +#elif PTH_MCTX_MTH(sjlj) && PTH_MCTX_DSP(sjlje) +#define pth_mctx_save(mctx) \ + ( (mctx)->error = errno, \ + pth_sc(sigprocmask)(SIG_SETMASK, &((mctx)->block), NULL), \ + pth_sigsetjmp((mctx)->jb) ) +#elif PTH_MCTX_MTH(sjlj) +#define pth_mctx_save(mctx) \ + ( (mctx)->error = errno, \ + pth_sigsetjmp((mctx)->jb) ) +#else +#error "unknown mctx method" +#endif + +/* + * restore the current machine context + * (at the location of the old context) + */ +#if PTH_MCTX_MTH(mcsc) +#define pth_mctx_restore(mctx) \ + ( errno = (mctx)->error, \ + (void)setcontext(&(mctx)->uc) ) +#elif PTH_MCTX_MTH(sjlj) +#define pth_mctx_restore(mctx) \ + ( errno = (mctx)->error, \ + (void)pth_siglongjmp((mctx)->jb, 1) ) +#else +#error "unknown mctx method" +#endif + +/* + * restore the current machine context + * (at the location of the new context) + */ +#if PTH_MCTX_MTH(sjlj) && PTH_MCTX_DSP(sjlje) +#define pth_mctx_restored(mctx) \ + pth_sc(sigprocmask)(SIG_SETMASK, &((mctx)->sigs), NULL) +#else +#define pth_mctx_restored(mctx) \ + /*nop*/ +#endif + +/* + * switch from one machine context to another + */ +#define SWITCH_DEBUG_LINE \ + "==== THREAD CONTEXT SWITCH ===========================================" +#ifdef PTH_DEBUG +#define _pth_mctx_switch_debug pth_debug(NULL, 0, 1, SWITCH_DEBUG_LINE); +#else +#define _pth_mctx_switch_debug /*NOP*/ +#endif +#if PTH_MCTX_MTH(mcsc) +#define pth_mctx_switch(old,new) \ + _pth_mctx_switch_debug \ + swapcontext(&((old)->uc), &((new)->uc)); +#elif PTH_MCTX_MTH(sjlj) +#define pth_mctx_switch(old,new) \ + _pth_mctx_switch_debug \ + if (pth_mctx_save(old) == 0) \ + pth_mctx_restore(new); \ + pth_mctx_restored(old); +#else +#error "unknown mctx method" +#endif + +#endif /* cpp */ + +/* +** ____ MACHINE STATE INITIALIZATION ________________________________ +*/ + +#if PTH_MCTX_MTH(mcsc) + +/* + * VARIANT 1: THE STANDARDIZED SVR4/SUSv2 APPROACH + * + * This is the preferred variant, because it uses the standardized + * SVR4/SUSv2 makecontext(2) and friends which is a facility intended + * for user-space context switching. The thread creation therefore is + * straight-foreward. + */ + +intern int pth_mctx_set( + pth_mctx_t *mctx, void (*func)(void), char *sk_addr_lo, char *sk_addr_hi) +{ + /* fetch current context */ + if (getcontext(&(mctx->uc)) != 0) + return FALSE; + + /* remove parent link */ + mctx->uc.uc_link = NULL; + + /* configure new stack */ + mctx->uc.uc_stack.ss_sp = pth_skaddr(makecontext, sk_addr_lo, sk_addr_hi-sk_addr_lo); + mctx->uc.uc_stack.ss_size = pth_sksize(makecontext, sk_addr_lo, sk_addr_hi-sk_addr_lo); + mctx->uc.uc_stack.ss_flags = 0; + + /* configure startup function (with no arguments) */ + makecontext(&(mctx->uc), func, 0+1); + + return TRUE; +} + +#elif PTH_MCTX_MTH(sjlj) &&\ + !PTH_MCTX_DSP(sjljlx) &&\ + !PTH_MCTX_DSP(sjljisc) &&\ + !PTH_MCTX_DSP(sjljw32) + +/* + * VARIANT 2: THE SIGNAL STACK TRICK + * + * This uses sigstack/sigaltstack() and friends and is really the + * most tricky part of Pth. When you understand the following + * stuff you're a good Unix hacker and then you've already + * understood the gory ingredients of Pth. So, either welcome to + * the club of hackers, or do yourself a favor and skip this ;) + * + * The ingenious fact is that this variant runs really on _all_ POSIX + * compliant systems without special platform kludges. But be _VERY_ + * carefully when you change something in the following code. The slightest + * change or reordering can lead to horribly broken code. Really every + * function call in the following case is intended to be how it is, doubt + * me... + * + * For more details we strongly recommend you to read the companion + * paper ``Portable Multithreading -- The Signal Stack Trick for + * User-Space Thread Creation'' from Ralf S. Engelschall. A copy of the + * draft of this paper you can find in the file rse-pmt.ps inside the + * GNU Pth distribution. + */ + +#if !defined(SA_ONSTACK) && defined(SV_ONSTACK) +#define SA_ONSTACK SV_ONSTACK +#endif +#if !defined(SS_DISABLE) && defined(SA_DISABLE) +#define SS_DISABLE SA_DISABLE +#endif +#if PTH_MCTX_STK(sas) && !defined(HAVE_SS_SP) && defined(HAVE_SS_BASE) +#define ss_sp ss_base +#endif + +static volatile jmp_buf mctx_trampoline; + +static volatile pth_mctx_t mctx_caller; +static volatile sig_atomic_t mctx_called; + +static pth_mctx_t * volatile mctx_creating; +static void (* volatile mctx_creating_func)(void); +static volatile sigset_t mctx_creating_sigs; + +static void pth_mctx_set_trampoline(int); +static void pth_mctx_set_bootstrap(void); + +/* initialize a machine state */ +intern int pth_mctx_set( + pth_mctx_t *mctx, void (*func)(void), char *sk_addr_lo, char *sk_addr_hi) +{ + struct sigaction sa; + struct sigaction osa; +#if PTH_MCTX_STK(sas) && defined(HAVE_STACK_T) + stack_t ss; + stack_t oss; +#elif PTH_MCTX_STK(sas) + struct sigaltstack ss; + struct sigaltstack oss; +#elif PTH_MCTX_STK(ss) + struct sigstack ss; + struct sigstack oss; +#else +#error "unknown mctx stack setup" +#endif + sigset_t osigs; + sigset_t sigs; + + pth_debug1("pth_mctx_set: enter"); + + /* + * Preserve the SIGUSR1 signal state, block SIGUSR1, + * and establish our signal handler. The signal will + * later transfer control onto the signal stack. + */ + sigemptyset(&sigs); + sigaddset(&sigs, SIGUSR1); + pth_sc(sigprocmask)(SIG_BLOCK, &sigs, &osigs); + sa.sa_handler = pth_mctx_set_trampoline; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_ONSTACK; + if (sigaction(SIGUSR1, &sa, &osa) != 0) + return FALSE; + + /* + * Set the new stack. + * + * For sigaltstack we're lucky [from sigaltstack(2) on + * FreeBSD 3.1]: ``Signal stacks are automatically adjusted + * for the direction of stack growth and alignment + * requirements'' + * + * For sigstack we have to decide ourself [from sigstack(2) + * on Solaris 2.6]: ``The direction of stack growth is not + * indicated in the historical definition of struct sigstack. + * The only way to portably establish a stack pointer is for + * the application to determine stack growth direction.'' + */ +#if PTH_MCTX_STK(sas) + ss.ss_sp = pth_skaddr(sigaltstack, sk_addr_lo, sk_addr_hi-sk_addr_lo); + ss.ss_size = pth_sksize(sigaltstack, sk_addr_lo, sk_addr_hi-sk_addr_lo); + ss.ss_flags = 0; + if (sigaltstack(&ss, &oss) < 0) + return FALSE; +#elif PTH_MCTX_STK(ss) + ss.ss_sp = pth_skaddr(sigstack, sk_addr_lo, sk_addr_hi-sk_addr_lo); + ss.ss_onstack = 0; + if (sigstack(&ss, &oss) < 0) + return FALSE; +#else +#error "unknown mctx stack setup" +#endif + + /* + * Now transfer control onto the signal stack and set it up. + * It will return immediately via "return" after the setjmp() + * was performed. Be careful here with race conditions. The + * signal can be delivered the first time sigsuspend() is + * called. + */ + mctx_called = FALSE; + kill(getpid(), SIGUSR1); + sigfillset(&sigs); + sigdelset(&sigs, SIGUSR1); + while (!mctx_called) + sigsuspend(&sigs); + + /* + * Inform the system that we are back off the signal stack by + * removing the alternative signal stack. Be careful here: It + * first has to be disabled, before it can be removed. + */ +#if PTH_MCTX_STK(sas) + sigaltstack(NULL, &ss); + ss.ss_flags = SS_DISABLE; + if (sigaltstack(&ss, NULL) < 0) + return FALSE; + sigaltstack(NULL, &ss); + if (!(ss.ss_flags & SS_DISABLE)) + return_errno(FALSE, EIO); + if (!(oss.ss_flags & SS_DISABLE)) + sigaltstack(&oss, NULL); +#elif PTH_MCTX_STK(ss) + if (sigstack(&oss, NULL)) + return FALSE; +#endif + + /* + * Restore the old SIGUSR1 signal handler and mask + */ + sigaction(SIGUSR1, &osa, NULL); + pth_sc(sigprocmask)(SIG_SETMASK, &osigs, NULL); + + /* + * Initialize additional ingredients of the machine + * context structure. + */ +#if PTH_MCTX_DSP(sjlje) + sigemptyset(&mctx->block); +#endif + sigemptyset(&mctx->sigs); + mctx->error = 0; + + /* + * Tell the trampoline and bootstrap function where to dump + * the new machine context, and what to do afterwards... + */ + mctx_creating = mctx; + mctx_creating_func = func; + memcpy((void *)&mctx_creating_sigs, &osigs, sizeof(sigset_t)); + + /* + * Now enter the trampoline again, but this time not as a signal + * handler. Instead we jump into it directly. The functionally + * redundant ping-pong pointer arithmentic is neccessary to avoid + * type-conversion warnings related to the `volatile' qualifier and + * the fact that `jmp_buf' usually is an array type. + */ + if (pth_mctx_save((pth_mctx_t *)&mctx_caller) == 0) + longjmp(*((jmp_buf *)&mctx_trampoline), 1); + + /* + * Ok, we returned again, so now we're finished + */ + pth_debug1("pth_mctx_set: leave"); + return TRUE; +} + +/* trampoline signal handler */ +static void pth_mctx_set_trampoline(int sig) +{ + /* + * Save current machine state and _immediately_ go back with + * a standard "return" (to stop the signal handler situation) + * to let him remove the stack again. Notice that we really + * have do a normal "return" here, or the OS would consider + * the thread to be running on a signal stack which isn't + * good (for instance it wouldn't allow us to spawn a thread + * from within a thread, etc.) + * + * The functionally redundant ping-pong pointer arithmentic is again + * neccessary to avoid type-conversion warnings related to the + * `volatile' qualifier and the fact that `jmp_buf' usually is an + * array type. + * + * Additionally notice that we INTENTIONALLY DO NOT USE pth_mctx_save() + * here. Instead we use a plain setjmp(3) call because we have to make + * sure the alternate signal stack environment is _NOT_ saved into the + * machine context (which can be the case for sigsetjmp(3) on some + * platforms). + */ + if (setjmp(*((jmp_buf *)&mctx_trampoline)) == 0) { + pth_debug1("pth_mctx_set_trampoline: return to caller"); + mctx_called = TRUE; + return; + } + pth_debug1("pth_mctx_set_trampoline: reentered from caller"); + + /* + * Ok, the caller has longjmp'ed back to us, so now prepare + * us for the real machine state switching. We have to jump + * into another function here to get a new stack context for + * the auto variables (which have to be auto-variables + * because the start of the thread happens later). Else with + * PIC (i.e. Position Independent Code which is used when PTH + * is built as a shared library) most platforms would + * horrible core dump as experience showed. + */ + pth_mctx_set_bootstrap(); +} + +/* boot function */ +static void pth_mctx_set_bootstrap(void) +{ + pth_mctx_t * volatile mctx_starting; + void (* volatile mctx_starting_func)(void); + + /* + * Switch to the final signal mask (inherited from parent) + */ + pth_sc(sigprocmask)(SIG_SETMASK, (sigset_t *)&mctx_creating_sigs, NULL); + + /* + * Move startup details from static storage to local auto + * variables which is necessary because it has to survive in + * a local context until the thread is scheduled for real. + */ + mctx_starting = mctx_creating; + mctx_starting_func = mctx_creating_func; + + /* + * Save current machine state (on new stack) and + * go back to caller until we're scheduled for real... + */ + pth_debug1("pth_mctx_set_trampoline_jumpin: switch back to caller"); + pth_mctx_switch((pth_mctx_t *)mctx_starting, (pth_mctx_t *)&mctx_caller); + + /* + * The new thread is now running: GREAT! + * Now we just invoke its init function.... + */ + pth_debug1("pth_mctx_set_trampoline_jumpin: reentered from scheduler"); + mctx_starting_func(); + abort(); +} + +#elif PTH_MCTX_MTH(sjlj) && PTH_MCTX_DSP(sjljlx) + +/* + * VARIANT 3: LINUX SPECIFIC JMP_BUF FIDDLING + * + * Oh hell, I really love it when Linux guys talk about their "POSIX + * compliant system". It's far away from POSIX compliant, IMHO. Autoconf + * finds sigstack/sigaltstack() on Linux, yes. But it doesn't work. Why? + * Because on Linux below version 2.2 and glibc versions below 2.1 these + * two functions are nothing more than silly stub functions which always + * return just -1. Very useful, yeah... + */ + +#include + +intern int pth_mctx_set( + pth_mctx_t *mctx, void (*func)(void), char *sk_addr_lo, char *sk_addr_hi) +{ + pth_mctx_save(mctx); +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && defined(JB_PC) && defined(JB_SP) + mctx->jb[0].__jmpbuf[JB_PC] = (int)func; + mctx->jb[0].__jmpbuf[JB_SP] = (int)sk_addr_hi; +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && defined(__mc68000__) + mctx->jb[0].__jmpbuf[0].__aregs[0] = (long int)func; + mctx->jb[0].__jmpbuf[0].__sp = (int *)sk_addr_hi; +#elif defined(__GNU_LIBRARY__) && defined(__i386__) + mctx->jb[0].__jmpbuf[0].__pc = (char *)func; + mctx->jb[0].__jmpbuf[0].__sp = sk_addr_hi; +#else +#error "Unsupported Linux (g)libc version and/or platform" +#endif + sigemptyset(&mctx->sigs); + mctx->error = 0; + return TRUE; +} + +/* + * VARIANT 4: INTERACTIVE SPECIFIC JMP_BUF FIDDLING + * + * No wonder, Interactive Unix (ISC) 4.x contains Microsoft code, so + * it's clear that this beast lacks both sigstack and sigaltstack (about + * makecontext we not even have to talk). So our only chance is to + * fiddle with it's jmp_buf ingredients, of course. We support only i386 + * boxes. + */ + +#elif PTH_MCTX_MTH(sjlj) && PTH_MCTX_DSP(sjljisc) +intern int +pth_mctx_set(pth_mctx_t *mctx, void (*func)(void), + char *sk_addr_lo, char *sk_addr_hi) +{ + pth_mctx_save(mctx); +#if i386 + mctx->jb[4] = (int)sk_addr_hi - sizeof(mctx->jb); + mctx->jb[5] = (int)func; +#else +#error "Unsupported ISC architecture" +#endif + sigemptyset(&mctx->sigs); + mctx->error = 0; + return TRUE; +} + +/* + * VARIANT 5: WIN32 SPECIFIC JMP_BUF FIDDLING + * + * Oh hell, Win32 has setjmp(3), but no sigstack(2) or sigaltstack(2). + * So we have to fiddle around with the jmp_buf here too... + */ + +#elif PTH_MCTX_MTH(sjlj) && PTH_MCTX_DSP(sjljw32) +intern int +pth_mctx_set(pth_mctx_t *mctx, void (*func)(void), + char *sk_addr_lo, char *sk_addr_hi) +{ + pth_mctx_save(mctx); +#if i386 + mctx->jb[7] = (int)sk_addr_hi; + mctx->jb[8] = (int)func; +#else +#error "Unsupported Win32 architecture" +#endif + sigemptyset(&mctx->sigs); + mctx->error = 0; + return TRUE; +} + +/* + * VARIANT X: JMP_BUF FIDDLING FOR ONE MORE ESOTERIC OS + * Add the jmp_buf fiddling for your esoteric OS here... + * +#elif PTH_MCTX_MTH(sjlj) && PTH_MCTX_DSP(sjljeso) +intern int +pth_mctx_set(pth_mctx_t *mctx, void (*func)(void), + char *sk_addr_lo, char *sk_addr_hi) +{ + pth_mctx_save(mctx); + sigemptyset(&mctx->sigs); + mctx->error = 0; + ...start hacking here... + mctx->.... = func; + mctx->.... = sk_addr_hi; + mctx->.... = sk_addr_lo; + return TRUE; +} +*/ + +#else +#error "unknown mctx method" +#endif + Index: ossp-pkg/pth/pth_msg.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_msg.c,v co -q -kk -p'1.21' '/v/ossp/cvs/ossp-pkg/pth/pth_msg.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_msg.c' 2>/dev/null --- ossp-pkg/pth/pth_msg.c +++ - 2024-05-13 13:57:53.930567400 +0200 @@ -0,0 +1,148 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_msg.c: Pth message port facility +*/ + /* ``Those who do not understand Unix + are condemned to reinvent it, poorly.'' + -- Henry Spencer */ +#include "pth_p.h" + +#if cpp + +/* message port structure */ +struct pth_msgport_st { + pth_ringnode_t mp_node; /* maintainance node handle */ + const char *mp_name; /* optional name of message port */ + pth_t mp_tid; /* corresponding thread */ + pth_ring_t mp_queue; /* queue of messages pending on port */ +}; + +#endif /* cpp */ + +static pth_ring_t pth_msgport = PTH_RING_INIT; + +/* create a new message port */ +pth_msgport_t pth_msgport_create(const char *name) +{ + pth_msgport_t mp; + + /* check input */ + if (name == NULL) + return_errno(NULL, EINVAL); + + /* allocate message port structure */ + if ((mp = (pth_msgport_t)malloc(sizeof(struct pth_msgport_st))) == NULL) + return_errno(NULL, ENOMEM); + + /* initialize structure */ + mp->mp_name = name; + mp->mp_tid = pth_current; + pth_ring_init(&mp->mp_queue); + + /* insert into list of existing message ports */ + pth_ring_append(&pth_msgport, &mp->mp_node); + + return mp; +} + +/* delete a message port */ +void pth_msgport_destroy(pth_msgport_t mp) +{ + pth_message_t *m; + + /* check input */ + if (mp == NULL) + return; + + /* first reply to all pending messages */ + while ((m = pth_msgport_get(mp)) != NULL) + pth_msgport_reply(m); + + /* remove from list of existing message ports */ + pth_ring_delete(&pth_msgport, &mp->mp_node); + + /* deallocate message port structure */ + free(mp); + + return; +} + +/* find a known message port through name */ +pth_msgport_t pth_msgport_find(const char *name) +{ + pth_msgport_t mp, mpf; + + /* check input */ + if (name == NULL) + return_errno(NULL, EINVAL); + + /* iterate over message ports */ + mp = mpf = (pth_msgport_t)pth_ring_first(&pth_msgport); + while (mp != NULL) { + if (strcmp(mp->mp_name, name) == 0) + break; + mp = (pth_msgport_t)pth_ring_next(&pth_msgport, (pth_ringnode_t *)mp); + if (mp == mpf) { + mp = NULL; + break; + } + } + return mp; +} + +/* number of message on a port */ +int pth_msgport_pending(pth_msgport_t mp) +{ + if (mp == NULL) + return_errno(-1, EINVAL); + return pth_ring_elements(&mp->mp_queue); +} + +/* put a message on a port */ +int pth_msgport_put(pth_msgport_t mp, pth_message_t *m) +{ + if (mp == NULL) + return_errno(FALSE, EINVAL); + pth_ring_append(&mp->mp_queue, (pth_ringnode_t *)m); + return TRUE; +} + +/* get top message from a port */ +pth_message_t *pth_msgport_get(pth_msgport_t mp) +{ + pth_message_t *m; + + if (mp == NULL) + return_errno(FALSE, EINVAL); + m = (pth_message_t *)pth_ring_pop(&mp->mp_queue); + return m; +} + +/* reply message to sender */ +int pth_msgport_reply(pth_message_t *m) +{ + if (m == NULL) + return_errno(FALSE, EINVAL); + return pth_msgport_put(m->m_replyport, m); +} + Index: ossp-pkg/pth/pth_p.h.in RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_p.h.in,v rcsdiff -q -kk '-r1.27' '-r1.28' -u '/v/ossp/cvs/ossp-pkg/pth/pth_p.h.in,v' 2>/dev/null --- pth_p.h.in 2000/10/03 09:26:47 1.27 +++ pth_p.h.in 2001/03/24 14:51:04 1.28 @@ -1,6 +1,6 @@ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth_pqueue.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_pqueue.c,v co -q -kk -p'1.28' '/v/ossp/cvs/ossp-pkg/pth/pth_pqueue.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_pqueue.c' 2>/dev/null --- ossp-pkg/pth/pth_pqueue.c +++ - 2024-05-13 13:57:53.937236791 +0200 @@ -0,0 +1,256 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_pqueue.c: Pth thread priority queues +*/ + /* ``Real hackers can write assembly + code in any language'' + -- Unknown */ +#include "pth_p.h" + +#if cpp + +/* thread priority queue */ +struct pth_pqueue_st { + pth_t q_head; + int q_num; +}; +typedef struct pth_pqueue_st pth_pqueue_t; + +#endif /* cpp */ + +/* initialize a priorit queue; O(1) */ +intern void pth_pqueue_init(pth_pqueue_t *q) +{ + if (q != NULL) { + q->q_head = NULL; + q->q_num = 0; + } + return; +} + +/* insert thread into priority queue; O(n) */ +intern void pth_pqueue_insert(pth_pqueue_t *q, int prio, pth_t t) +{ + pth_t c; + int p; + + if (q == NULL) + return; + if (q->q_head == NULL || q->q_num == 0) { + /* add as first element */ + t->q_prev = t; + t->q_next = t; + t->q_prio = prio; + q->q_head = t; + } + else if (q->q_head->q_prio < prio) { + /* add as new head of queue */ + t->q_prev = q->q_head->q_prev; + t->q_next = q->q_head; + t->q_prev->q_next = t; + t->q_next->q_prev = t; + t->q_prio = prio; + t->q_next->q_prio = prio - t->q_next->q_prio; + q->q_head = t; + } + else { + /* insert after elements with greater or equal priority */ + c = q->q_head; + p = c->q_prio; + while ((p - c->q_next->q_prio) >= prio && c->q_next != q->q_head) { + c = c->q_next; + p -= c->q_prio; + } + t->q_prev = c; + t->q_next = c->q_next; + t->q_prev->q_next = t; + t->q_next->q_prev = t; + t->q_prio = p - prio; + if (t->q_next != q->q_head) + t->q_next->q_prio -= t->q_prio; + } + q->q_num++; + return; +} + +/* remove thread with maximum priority from priority queue; O(1) */ +intern pth_t pth_pqueue_delmax(pth_pqueue_t *q) +{ + pth_t t; + + if (q == NULL) + return NULL; + if (q->q_head == NULL) + t = NULL; + else if (q->q_head->q_next == q->q_head) { + /* remove the last element and make queue empty */ + t = q->q_head; + t->q_next = NULL; + t->q_prev = NULL; + t->q_prio = 0; + q->q_head = NULL; + q->q_num = 0; + } + else { + /* remove head of queue */ + t = q->q_head; + t->q_prev->q_next = t->q_next; + t->q_next->q_prev = t->q_prev; + t->q_next->q_prio = t->q_prio - t->q_next->q_prio; + t->q_prio = 0; + q->q_head = t->q_next; + q->q_num--; + } + return t; +} + +/* remove thread from priority queue; O(n) */ +intern void pth_pqueue_delete(pth_pqueue_t *q, pth_t t) +{ + if (q == NULL) + return; + if (q->q_head == NULL) + return; + else if (q->q_head == t) { + if (t->q_next == t) { + /* remove the last element and make queue empty */ + t->q_next = NULL; + t->q_prev = NULL; + t->q_prio = 0; + q->q_head = NULL; + q->q_num = 0; + } + else { + /* remove head of queue */ + t->q_prev->q_next = t->q_next; + t->q_next->q_prev = t->q_prev; + t->q_next->q_prio = t->q_prio - t->q_next->q_prio; + t->q_prio = 0; + q->q_head = t->q_next; + q->q_num--; + } + } + else { + t->q_prev->q_next = t->q_next; + t->q_next->q_prev = t->q_prev; + if (t->q_next != q->q_head) + t->q_next->q_prio += t->q_prio; + t->q_prio = 0; + q->q_num--; + } + return; +} + +/* determine priority required to favorite a thread; O(1) */ +#if cpp +#define pth_pqueue_favorite_prio(q) \ + ((q)->q_head != NULL ? (q)->q_head->q_prio + 1 : PTH_PRIO_MAX) +#endif + +/* move a thread inside queue to the top; O(n) */ +intern int pth_pqueue_favorite(pth_pqueue_t *q, pth_t t) +{ + if (q == NULL) + return FALSE; + if (q->q_head == NULL || q->q_num == 0) + return FALSE; + /* element is already at top */ + if (q->q_num == 1) + return TRUE; + /* move to top */ + pth_pqueue_delete(q, t); + pth_pqueue_insert(q, pth_pqueue_favorite_prio(q), t); + return TRUE; +} + +/* increase priority of all(!) threads in queue; O(1) */ +intern void pth_pqueue_increase(pth_pqueue_t *q) +{ + if (q == NULL) + return; + if (q->q_head == NULL) + return; + /* yes, that's all ;-) */ + q->q_head->q_prio += 1; + return; +} + +/* return number of elements in priority queue: O(1) */ +#if cpp +#define pth_pqueue_elements(q) \ + ((q) == NULL ? (-1) : (q)->q_num) +#endif + +/* walk to first thread in queue; O(1) */ +#if cpp +#define pth_pqueue_head(q) \ + ((q) == NULL ? NULL : (q)->q_head) +#endif + +/* walk to last thread in queue */ +intern pth_t pth_pqueue_tail(pth_pqueue_t *q) +{ + if (q == NULL) + return NULL; + if (q->q_head == NULL) + return NULL; + return q->q_head->q_prev; +} + +/* walk to next or previous thread in queue; O(1) */ +intern pth_t pth_pqueue_walk(pth_pqueue_t *q, pth_t t, int direction) +{ + pth_t tn; + + if (q == NULL || t == NULL) + return NULL; + tn = NULL; + if (direction == PTH_WALK_PREV) { + if (t != q->q_head) + tn = t->q_prev; + } + else if (direction == PTH_WALK_NEXT) { + tn = t->q_next; + if (tn == q->q_head) + tn = NULL; + } + return tn; +} + +/* check whether a thread is in a queue; O(n) */ +intern int pth_pqueue_contains(pth_pqueue_t *q, pth_t t) +{ + pth_t tc; + int found; + + found = FALSE; + for (tc = pth_pqueue_head(q); tc != NULL; + tc = pth_pqueue_walk(q, tc, PTH_WALK_NEXT)) { + if (tc == t) { + found = TRUE; + break; + } + } + return found; +} + Index: ossp-pkg/pth/pth_ring.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_ring.c,v co -q -kk -p'1.20' '/v/ossp/cvs/ossp-pkg/pth/pth_ring.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_ring.c' 2>/dev/null --- ossp-pkg/pth/pth_ring.c +++ - 2024-05-13 13:57:53.939943161 +0200 @@ -0,0 +1,245 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_ring.c: Pth ring data structure +*/ + /* ``Unix was not designed to stop people + from doing stupid things, because that + would also stop them from doing clever + things.'' --Doug Gwyn */ + +/* + * This is a "ring" data structure, a special case of a list. It is + * implemented through double-chained nodes. The link structure is part + * of the nodes, i.e. no extra memory is required for the ring itself + * and the ring can contain as many nodes as fit into memory. The main + * advantage of using a ring instead of a plain list is to make the ring + * operations easier (less special cases!). The ring is usually used + * in Pth to represent a "set" of something. All operations are O(1), + * except for the check whether a node is part of the ring (which is + * O(N)). + */ + +#include "pth_p.h" + +/* initialize ring; O(1) */ +intern void pth_ring_init(pth_ring_t *r) +{ + if (r == NULL) + return; + r->r_hook = NULL; + r->r_nodes = 0; + return; +} + +/* return number of nodes in ring; O(1) */ +#if cpp +#define pth_ring_elements(r) \ + ((r) == NULL ? (-1) : (r)->r_nodes) +#endif + +/* return first node in ring; O(1) */ +#if cpp +#define pth_ring_first(r) \ + ((r) == NULL ? NULL : (r)->r_hook) +#endif + +/* return last node in ring; O(1) */ +#if cpp +#define pth_ring_last(r) \ + ((r) == NULL ? NULL : ((r)->r_hook == NULL ? NULL : (r)->r_hook->rn_prev)) +#endif + +/* walk to next node in ring; O(1) */ +#if cpp +#define pth_ring_next(r, rn) \ + (((r) == NULL || (rn) == NULL) ? NULL : ((rn)->rn_next == (r)->r_hook ? NULL : (rn)->rn_next)) +#endif + +/* walk to previous node in ring; O(1) */ +#if cpp +#define pth_ring_prev(r, rn) \ + (((r) == NULL || (rn) == NULL) ? NULL : ((rn)->rn_prev == (r)->r_hook->rn_prev ? NULL : (rn)->rn_prev)) +#endif + +/* insert node into ring; O(1) */ +#if cpp +#define pth_ring_insert(r, rn) \ + pth_ring_append((r), (rn)) +#endif + +/* insert node after a second node in ring; O(1) */ +intern void pth_ring_insert_after(pth_ring_t *r, pth_ringnode_t *rn1, pth_ringnode_t *rn2) +{ + if (r == NULL || rn1 == NULL || rn2 == NULL) + return; + rn2->rn_prev = rn1; + rn2->rn_next = rn1->rn_next; + rn2->rn_prev->rn_next = rn2; + rn2->rn_next->rn_prev = rn2; + r->r_nodes++; + return; +} + +/* insert node before a second node in ring; O(1) */ +intern void pth_ring_insert_before(pth_ring_t *r, pth_ringnode_t *rn1, pth_ringnode_t *rn2) +{ + if (r == NULL || rn1 == NULL || rn2 == NULL) + return; + rn2->rn_next = rn1; + rn2->rn_prev = rn1->rn_prev; + rn2->rn_prev->rn_next = rn2; + rn2->rn_next->rn_prev = rn2; + r->r_nodes++; + return; +} + +/* delete an node from ring; O(1) */ +intern void pth_ring_delete(pth_ring_t *r, pth_ringnode_t *rn) +{ + if (r == NULL || rn == NULL) + return; + if (r->r_hook == rn && rn->rn_prev == rn && rn->rn_next == rn) + r->r_hook = NULL; + else { + if (r->r_hook == rn) + r->r_hook = rn->rn_next; + rn->rn_prev->rn_next = rn->rn_next; + rn->rn_next->rn_prev = rn->rn_prev; + } + r->r_nodes--; + return; +} + +/* prepend an node to ring; O(1) */ +intern void pth_ring_prepend(pth_ring_t *r, pth_ringnode_t *rn) +{ + if (r == NULL || rn == NULL) + return; + if (r->r_hook == NULL) { + r->r_hook = rn; + rn->rn_next = rn; + rn->rn_prev = rn; + } + else { + rn->rn_next = r->r_hook; + rn->rn_prev = r->r_hook->rn_prev; + rn->rn_next->rn_prev = rn; + rn->rn_prev->rn_next = rn; + r->r_hook = rn; + } + r->r_nodes++; + return; +} + +/* append an node to ring; O(1) */ +intern void pth_ring_append(pth_ring_t *r, pth_ringnode_t *rn) +{ + if (r == NULL || rn == NULL) + return; + if (r->r_hook == NULL) { + r->r_hook = rn; + rn->rn_next = rn; + rn->rn_prev = rn; + } + else { + rn->rn_next = r->r_hook; + rn->rn_prev = r->r_hook->rn_prev; + rn->rn_next->rn_prev = rn; + rn->rn_prev->rn_next = rn; + } + r->r_nodes++; + return; +} + +/* treat ring as stack: push node onto stack; O(1) */ +#if cpp +#define pth_ring_push(r, rn) \ + pth_ring_prepend((r), (rn)) +#endif + +/* treat ring as stack: pop node from stack; O(1) */ +intern pth_ringnode_t *pth_ring_pop(pth_ring_t *r) +{ + pth_ringnode_t *rn; + + rn = pth_ring_first(r); + if (rn != NULL) + pth_ring_delete(r, rn); + return rn; +} + +/* treat ring as queue: favorite a node in the ring; O(1) */ +intern int pth_ring_favorite(pth_ring_t *r, pth_ringnode_t *rn) +{ + if (r == NULL) + return FALSE; + if (r->r_hook == NULL) + return FALSE; + /* element is perhaps already at ring hook */ + if (r->r_hook == rn) + return TRUE; + /* move to hook of ring */ + pth_ring_delete(r, rn); + pth_ring_prepend(r, rn); + return TRUE; +} + +/* treat ring as queue: enqueue node; O(1) */ +#if cpp +#define pth_ring_enqueue(r, rn) \ + pth_ring_prepend((r), (rn)) +#endif + +/* treat ring as queue: dequeue node; O(1) */ +intern pth_ringnode_t *pth_ring_dequeue(pth_ring_t *r) +{ + pth_ringnode_t *rn; + + rn = pth_ring_last(r); + if (rn != NULL) + pth_ring_delete(r, rn); + return rn; +} + +/* check whether node is contained in ring; O(n) */ +intern int pth_ring_contains(pth_ring_t *r, pth_ringnode_t *rns) +{ + pth_ringnode_t *rn; + int rc; + + if (r == NULL || rns == NULL) + return_errno(FALSE, EINVAL); + rc = FALSE; + rn = r->r_hook; + if (rn != NULL) { + do { + if (rn == rns) { + rc = TRUE; + break; + } + rn = rn->rn_next; + } while (rn != r->r_hook); + } + return rc; +} + Index: ossp-pkg/pth/pth_sched.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_sched.c,v rcsdiff -q -kk '-r1.79' '-r1.80' -u '/v/ossp/cvs/ossp-pkg/pth/pth_sched.c,v' 2>/dev/null --- pth_sched.c 2001/02/25 17:08:07 1.79 +++ pth_sched.c 2001/03/24 14:51:04 1.80 @@ -1,6 +1,6 @@ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth_string.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_string.c,v co -q -kk -p'1.5' '/v/ossp/cvs/ossp-pkg/pth/pth_string.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_string.c' 2>/dev/null --- ossp-pkg/pth/pth_string.c +++ - 2024-05-13 13:57:53.948243282 +0200 @@ -0,0 +1,706 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_string.c: Pth replacement string functions +*/ + /* ``A new release is where old bad + assumptions are replaced by new + bad assumptions.'' */ + +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions. + */ + +/* + * This code contains numerious changes and enhancements which were + * made by lots of contributors over the last years to Patrick Powell's + * original code: + * + * o Patrick Powell (1995) + * o Brandon Long (1996, for Mutt) + * o Thomas Roessler (1998, for Mutt) + * o Michael Elkins (1998, for Mutt) + * o Andrew Tridgell (1998, for Samba) + * o Luke Mewburn (1999, for LukemFTP) + * o Ralf S. Engelschall (1999, for OSSP) + */ + +#include "pth_p.h" + +#if HAVE_LONGLONG +#define LLONG long long +#else +#define LLONG long +#endif + +#if HAVE_LONGDOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif + +static void fmtstr (char *, size_t *, size_t, char *, int, int, int); +static void fmtint (char *, size_t *, size_t, LLONG, int, int, int, int); +static void fmtfp (char *, size_t *, size_t, LDOUBLE, int, int, int); +static void dopr_outch (char *, size_t *, size_t, int); + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* conversion flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 +#define DP_C_LLONG 4 + +/* some handy macros */ +#define char_to_int(p) (p - '0') +#define MAX(p,q) ((p >= q) ? p : q) +#define NUL '\0' + +static void +dopr( + char *buffer, + size_t maxlen, + size_t *retlen, + const char *format, + va_list args) +{ + char ch; + LLONG value; + LDOUBLE fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + + state = DP_S_DEFAULT; + flags = currlen = cflags = min = 0; + max = -1; + ch = *format++; + + if (maxlen == -1) + /* possible maximum size in a size_t */ + maxlen = (~(1<<((sizeof(size_t)*8)-2))); + + while (state != DP_S_DONE) { + if ((ch == NUL) || (currlen >= maxlen)) + state = DP_S_DONE; + + switch (state) { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + dopr_outch(buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + min = 10 * min + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + min = va_arg(args, int); + ch = *format++; + state = DP_S_DOT; + } else + state = DP_S_DOT; + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else + state = DP_S_MOD; + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (max < 0) + max = 0; + max = 10 * max + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + max = va_arg(args, int); + ch = *format++; + state = DP_S_MOD; + } else + state = DP_S_MOD; + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + if (*format == 'l') { + cflags = DP_C_LLONG; + format++; + } else + cflags = DP_C_LONG; + ch = *format++; + break; + case 'q': + cflags = DP_C_LLONG; + ch = *format++; + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) { + case 'd': + case 'i': + switch (cflags) { + case DP_C_SHORT: + value = (short int)va_arg(args, int); + break; + case DP_C_LONG: + value = va_arg(args, long int); + break; + case DP_C_LLONG: + value = va_arg(args, LLONG); + break; + default: + value = va_arg(args, int); + break; + } + fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + /* FALLTHROUGH */ + case 'x': + case 'o': + case 'u': + flags |= DP_F_UNSIGNED; + switch (cflags) { + case DP_C_SHORT: + value = (unsigned short int)va_arg(args, unsigned int); + break; + case DP_C_LONG: + value = (LLONG)va_arg(args, unsigned long int); + break; + case DP_C_LLONG: + value = va_arg(args, unsigned LLONG); + break; + default: + value = (LLONG)va_arg(args, unsigned int); + break; + } + fmtint(buffer, &currlen, maxlen, value, + ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), + min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + break; + case 'c': + dopr_outch(buffer, &currlen, maxlen, va_arg(args, int)); + break; + case 's': + strvalue = va_arg(args, char *); + if (max < 0) + max = maxlen; + fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max); + break; + case 'p': + value = (long)va_arg(args, void *); + fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags); + break; + case 'n': /* XXX */ + if (cflags == DP_C_SHORT) { + short int *num; + num = va_arg(args, short int *); + *num = currlen; + } else if (cflags == DP_C_LONG) { /* XXX */ + long int *num; + num = va_arg(args, long int *); + *num = (long int) currlen; + } else if (cflags == DP_C_LLONG) { /* XXX */ + LLONG *num; + num = va_arg(args, LLONG *); + *num = (LLONG) currlen; + } else { + int *num; + num = va_arg(args, int *); + *num = currlen; + } + break; + case '%': + dopr_outch(buffer, &currlen, maxlen, ch); + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + break; + } + } + if (currlen >= maxlen - 1) + currlen = maxlen - 1; + if (buffer != NULL) + buffer[currlen] = NUL; + *retlen = currlen; + return; +} + +static void +fmtstr( + char *buffer, + size_t *currlen, + size_t maxlen, + char *value, + int flags, + int min, + int max) +{ + int padlen, strln; + int cnt = 0; + + if (value == 0) + value = ""; + for (strln = 0; value[strln] != '\0'; strln++) + ; + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; + + while ((padlen > 0) && (cnt < max)) { + dopr_outch(buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) { + dopr_outch(buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) { + dopr_outch(buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +static void +fmtint( + char *buffer, + size_t *currlen, + size_t maxlen, + LLONG value, + int base, + int min, + int max, + int flags) +{ + int signvalue = 0; + unsigned LLONG uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; + int zpadlen = 0; + int caps = 0; + + if (max < 0) + max = 0; + uvalue = value; + if (!(flags & DP_F_UNSIGNED)) { + if (value < 0) { + signvalue = '-'; + uvalue = -value; + } else if (flags & DP_F_PLUS) + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + if (flags & DP_F_UP) + caps = 1; + do { + convert[place++] = + (caps ? "0123456789ABCDEF" : "0123456789abcdef") + [uvalue % (unsigned) base]; + uvalue = (uvalue / (unsigned) base); + } while (uvalue && (place < 20)); + if (place == 20) + place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX(max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) + zpadlen = 0; + if (spadlen < 0) + spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; + + /* spaces */ + while (spadlen > 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* sign */ + if (signvalue) + dopr_outch(buffer, currlen, maxlen, signvalue); + + /* zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + dopr_outch(buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + /* digits */ + while (place > 0) + dopr_outch(buffer, currlen, maxlen, convert[--place]); + + /* left justified spaces */ + while (spadlen < 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + ++spadlen; + } + return; +} + +static LDOUBLE +abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + if (value < 0) + result = -value; + return result; +} + +static LDOUBLE +pow10(int exp) +{ + LDOUBLE result = 1; + while (exp) { + result *= 10; + exp--; + } + return result; +} + +static long +round(LDOUBLE value) +{ + long intpart; + intpart = (long) value; + value = value - intpart; + if (value >= 0.5) + intpart++; + return intpart; +} + +static void +fmtfp( + char *buffer, + size_t *currlen, + size_t maxlen, + LDOUBLE fvalue, + int min, + int max, + int flags) +{ + int signvalue = 0; + LDOUBLE ufvalue; + char iconvert[20]; + char fconvert[20]; + int iplace = 0; + int fplace = 0; + int padlen = 0; + int zpadlen = 0; + int caps = 0; + long intpart; + long fracpart; + + if (max < 0) + max = 6; + ufvalue = abs_val(fvalue); + if (fvalue < 0) + signvalue = '-'; + else if (flags & DP_F_PLUS) + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + + intpart = (long)ufvalue; + + /* sorry, we only support 9 digits past the decimal because of our + conversion method */ + if (max > 9) + max = 9; + + /* we "cheat" by converting the fractional part to integer by + multiplying by a factor of 10 */ + fracpart = round((pow10(max)) * (ufvalue - intpart)); + + if (fracpart >= pow10(max)) { + intpart++; + fracpart -= pow10(max); + } + + /* convert integer part */ + do { + iconvert[iplace++] = + (caps ? "0123456789ABCDEF" + : "0123456789abcdef")[intpart % 10]; + intpart = (intpart / 10); + } while (intpart && (iplace < 20)); + if (iplace == 20) + iplace--; + iconvert[iplace] = 0; + + /* convert fractional part */ + do { + fconvert[fplace++] = + (caps ? "0123456789ABCDEF" + : "0123456789abcdef")[fracpart % 10]; + fracpart = (fracpart / 10); + } while (fracpart && (fplace < 20)); + if (fplace == 20) + fplace--; + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) + zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + dopr_outch(buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch(buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch(buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]); + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0) { + dopr_outch(buffer, currlen, maxlen, '.'); + + while (fplace > 0) + dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]); + } + while (zpadlen > 0) { + dopr_outch(buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (padlen < 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + ++padlen; + } + return; +} + +static void +dopr_outch( + char *buffer, + size_t *currlen, + size_t maxlen, + int c) +{ + if (*currlen < maxlen) { + if (buffer != NULL) + buffer[(*currlen)] = (char)c; + (*currlen)++; + } + return; +} + +intern int +pth_vsnprintf( + char *str, + size_t count, + const char *fmt, + va_list args) +{ + size_t retlen; + + if (str != NULL) + str[0] = NUL; + dopr(str, count, &retlen, fmt, args); + return retlen; +} + +intern int +pth_snprintf( + char *str, + size_t count, + const char *fmt, + ...) +{ + va_list ap; + int rv; + + va_start(ap, fmt); + rv = pth_vsnprintf(str, count, fmt, ap); + va_end(ap); + return rv; +} + +intern char * +pth_vasprintf( + const char *fmt, + va_list ap) +{ + char *rv; + int n; + + n = pth_vsnprintf(NULL, -1, fmt, ap); + if ((rv = (char *)malloc(n+1)) == NULL) + return NULL; + pth_vsnprintf(rv, n+1, fmt, ap); + return rv; +} + +intern char * +pth_asprintf( + const char *fmt, + ...) +{ + va_list ap; + char *rv; + + va_start(ap, fmt); + rv = pth_vasprintf(fmt, ap); + va_end(ap); + return rv; +} + Index: ossp-pkg/pth/pth_sync.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_sync.c,v co -q -kk -p'1.35' '/v/ossp/cvs/ossp-pkg/pth/pth_sync.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_sync.c' 2>/dev/null --- ossp-pkg/pth/pth_sync.c +++ - 2024-05-13 13:57:53.951194304 +0200 @@ -0,0 +1,382 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_sync.c: Pth synchronization facilities +*/ + /* ``It is hard to fly with + the eagles when you work + with the turkeys.'' + -- Unknown */ +#include "pth_p.h" + +/* +** Mutual Exclusion Locks +*/ + +int pth_mutex_init(pth_mutex_t *mutex) +{ + if (mutex == NULL) + return_errno(FALSE, EINVAL); + mutex->mx_state = PTH_MUTEX_INITIALIZED; + mutex->mx_owner = NULL; + mutex->mx_count = 0; + return TRUE; +} + +int pth_mutex_acquire(pth_mutex_t *mutex, int tryonly, pth_event_t ev_extra) +{ + static pth_key_t ev_key = PTH_KEY_INIT; + pth_event_t ev; + + pth_debug2("pth_mutex_acquire: called from thread \"%s\"", pth_current->name); + + /* consistency checks */ + if (mutex == NULL) + return_errno(FALSE, EINVAL); + if (!(mutex->mx_state & PTH_MUTEX_INITIALIZED)) + return_errno(FALSE, EDEADLK); + + /* still not locked, so simply acquire mutex? */ + if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) { + mutex->mx_state |= PTH_MUTEX_LOCKED; + mutex->mx_owner = pth_current; + mutex->mx_count = 1; + pth_ring_append(&(pth_current->mutexring), &(mutex->mx_node)); + pth_debug1("pth_mutex_acquire: immediately locking mutex"); + return TRUE; + } + + /* already locked by caller? */ + if (mutex->mx_count >= 1 && mutex->mx_owner == pth_current) { + /* recursive lock */ + mutex->mx_count++; + pth_debug1("pth_mutex_acquire: recursive locking"); + return TRUE; + } + + /* should we just tryonly? */ + if (tryonly) + return_errno(FALSE, EBUSY); + + /* else wait for mutex to become unlocked.. */ + pth_debug1("pth_mutex_acquire: wait until mutex is unlocked"); + for (;;) { + ev = pth_event(PTH_EVENT_MUTEX|PTH_MODE_STATIC, &ev_key, mutex); + if (ev_extra != NULL) + pth_event_concat(ev, ev_extra, NULL); + pth_wait(ev); + if (ev_extra != NULL) { + pth_event_isolate(ev); + if (!pth_event_occurred(ev)) + return_errno(FALSE, EINTR); + } + if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) + break; + } + + /* now it's again unlocked, so acquire mutex */ + pth_debug1("pth_mutex_acquire: locking mutex"); + mutex->mx_state |= PTH_MUTEX_LOCKED; + mutex->mx_owner = pth_current; + mutex->mx_count = 1; + pth_ring_append(&(pth_current->mutexring), &(mutex->mx_node)); + return TRUE; +} + +int pth_mutex_release(pth_mutex_t *mutex) +{ + /* consistency checks */ + if (mutex == NULL) + return_errno(FALSE, EINVAL); + if (!(mutex->mx_state & PTH_MUTEX_INITIALIZED)) + return_errno(FALSE, EDEADLK); + if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) + return_errno(FALSE, EDEADLK); + if (mutex->mx_owner != pth_current) + return_errno(FALSE, EACCES); + + /* decrement recursion counter and release mutex */ + mutex->mx_count--; + if (mutex->mx_count <= 0) { + mutex->mx_state &= ~(PTH_MUTEX_LOCKED); + mutex->mx_owner = NULL; + mutex->mx_count = 0; + pth_ring_delete(&(pth_current->mutexring), &(mutex->mx_node)); + } + return TRUE; +} + +intern void pth_mutex_releaseall(pth_t thread) +{ + pth_ringnode_t *rn, *rnf; + + if (thread == NULL) + return; + /* iterate over all mutexes of thread */ + rn = rnf = pth_ring_first(&(thread->mutexring)); + while (rn != NULL) { + pth_mutex_release((pth_mutex_t *)rn); + rn = pth_ring_next(&(thread->mutexring), rn); + if (rn == rnf) + break; + } + return; +} + +/* +** Read-Write Locks +*/ + +int pth_rwlock_init(pth_rwlock_t *rwlock) +{ + if (rwlock == NULL) + return_errno(FALSE, EINVAL); + rwlock->rw_state = PTH_RWLOCK_INITIALIZED; + rwlock->rw_readers = 0; + pth_mutex_init(&(rwlock->rw_mutex_rd)); + pth_mutex_init(&(rwlock->rw_mutex_rw)); + return TRUE; +} + +int pth_rwlock_acquire(pth_rwlock_t *rwlock, int op, int tryonly, pth_event_t ev_extra) +{ + /* consistency checks */ + if (rwlock == NULL) + return_errno(FALSE, EINVAL); + if (!(rwlock->rw_state & PTH_RWLOCK_INITIALIZED)) + return_errno(FALSE, EDEADLK); + + /* acquire lock */ + if (op == PTH_RWLOCK_RW) { + /* read-write lock is simple */ + if (!pth_mutex_acquire(&(rwlock->rw_mutex_rw), tryonly, ev_extra)) + return FALSE; + rwlock->rw_mode = PTH_RWLOCK_RW; + } + else { + /* read-only lock is more complicated to get right */ + if (!pth_mutex_acquire(&(rwlock->rw_mutex_rd), tryonly, ev_extra)) + return FALSE; + rwlock->rw_readers++; + if (rwlock->rw_readers == 1) { + if (!pth_mutex_acquire(&(rwlock->rw_mutex_rw), tryonly, ev_extra)) { + rwlock->rw_readers--; + errno_shield { pth_mutex_release(&(rwlock->rw_mutex_rd)); } + return FALSE; + } + } + rwlock->rw_mode = PTH_RWLOCK_RD; + pth_mutex_release(&(rwlock->rw_mutex_rd)); + } + return TRUE; +} + +int pth_rwlock_release(pth_rwlock_t *rwlock) +{ + /* consistency checks */ + if (rwlock == NULL) + return_errno(FALSE, EINVAL); + if (!(rwlock->rw_state & PTH_RWLOCK_INITIALIZED)) + return_errno(FALSE, EDEADLK); + + /* release lock */ + if (rwlock->rw_mode == PTH_RWLOCK_RW) { + /* read-write unlock is simple */ + if (!pth_mutex_release(&(rwlock->rw_mutex_rw))) + return FALSE; + } + else { + /* read-only unlock is more complicated to get right */ + if (!pth_mutex_acquire(&(rwlock->rw_mutex_rd), FALSE, NULL)) + return FALSE; + rwlock->rw_readers--; + if (rwlock->rw_readers == 0) { + if (!pth_mutex_release(&(rwlock->rw_mutex_rw))) { + rwlock->rw_readers++; + errno_shield { pth_mutex_release(&(rwlock->rw_mutex_rd)); } + return FALSE; + } + } + rwlock->rw_mode = PTH_RWLOCK_RD; + pth_mutex_release(&(rwlock->rw_mutex_rd)); + } + return TRUE; +} + +/* +** Condition Variables +*/ + +int pth_cond_init(pth_cond_t *cond) +{ + if (cond == NULL) + return_errno(FALSE, EINVAL); + cond->cn_state = PTH_COND_INITIALIZED; + cond->cn_waiters = 0; + return TRUE; +} + +static void pth_cond_cleanup_handler(void *_cleanvec) +{ + pth_mutex_t *mutex = (pth_mutex_t *)(((void **)_cleanvec)[0]); + pth_cond_t *cond = (pth_cond_t *)(((void **)_cleanvec)[1]); + + /* re-acquire mutex when pth_cond_await() is cancelled + in order to restore the condition variable semantics */ + pth_mutex_acquire(mutex, FALSE, NULL); + + /* fix number of waiters */ + cond->cn_waiters--; + return; +} + +int pth_cond_await(pth_cond_t *cond, pth_mutex_t *mutex, pth_event_t ev_extra) +{ + static pth_key_t ev_key = PTH_KEY_INIT; + void *cleanvec[2]; + pth_event_t ev; + + /* consistency checks */ + if (cond == NULL || mutex == NULL) + return_errno(FALSE, EINVAL); + if (!(cond->cn_state & PTH_COND_INITIALIZED)) + return_errno(FALSE, EDEADLK); + + /* check whether we can do a short-circuit wait */ + if ( (cond->cn_state & PTH_COND_SIGNALED) + && !(cond->cn_state & PTH_COND_BROADCAST)) { + cond->cn_state &= ~(PTH_COND_SIGNALED); + cond->cn_state &= ~(PTH_COND_BROADCAST); + cond->cn_state &= ~(PTH_COND_HANDLED); + return TRUE; + } + + /* add us to the number of waiters */ + cond->cn_waiters++; + + /* release mutex (caller had to acquire it first) */ + pth_mutex_release(mutex); + + /* wait until the condition is signaled */ + ev = pth_event(PTH_EVENT_COND|PTH_MODE_STATIC, &ev_key, cond); + if (ev_extra != NULL) + pth_event_concat(ev, ev_extra, NULL); + cleanvec[0] = mutex; + cleanvec[1] = cond; + pth_cleanup_push(pth_cond_cleanup_handler, cleanvec); + pth_wait(ev); + pth_cleanup_pop(FALSE); + if (ev_extra != NULL) + pth_event_isolate(ev); + + /* reacquire mutex */ + pth_mutex_acquire(mutex, FALSE, NULL); + + /* remove us from the number of waiters */ + cond->cn_waiters--; + + /* release mutex (caller had to acquire it first) */ + return TRUE; +} + +int pth_cond_notify(pth_cond_t *cond, int broadcast) +{ + /* consistency checks */ + if (cond == NULL) + return_errno(FALSE, EINVAL); + if (!(cond->cn_state & PTH_COND_INITIALIZED)) + return_errno(FALSE, EDEADLK); + + /* do something only if there is at least one waiters (POSIX semantics) */ + if (cond->cn_waiters > 0) { + /* signal the condition */ + cond->cn_state |= PTH_COND_SIGNALED; + if (broadcast) + cond->cn_state |= PTH_COND_BROADCAST; + else + cond->cn_state &= ~(PTH_COND_BROADCAST); + cond->cn_state &= ~(PTH_COND_HANDLED); + + /* and give other threads a chance to awake */ + pth_yield(NULL); + } + + /* return to caller */ + return TRUE; +} + +/* +** Barriers +*/ + +int pth_barrier_init(pth_barrier_t *barrier, int threshold) +{ + if (barrier == NULL || threshold <= 0) + return_errno(FALSE, EINVAL); + if (!pth_mutex_init(&(barrier->br_mutex))) + return FALSE; + if (!pth_cond_init(&(barrier->br_cond))) + return FALSE; + barrier->br_state = PTH_BARRIER_INITIALIZED; + barrier->br_threshold = threshold; + barrier->br_count = threshold; + barrier->br_cycle = FALSE; + return TRUE; +} + +int pth_barrier_reach(pth_barrier_t *barrier) +{ + int cancel, cycle; + int rv; + + if (barrier == NULL) + return_errno(FALSE, EINVAL); + if (!(barrier->br_state & PTH_BARRIER_INITIALIZED)) + return_errno(FALSE, EINVAL); + + if (!pth_mutex_acquire(&(barrier->br_mutex), FALSE, NULL)) + return FALSE; + cycle = barrier->br_cycle; + if (--(barrier->br_count) == 0) { + /* last thread reached the barrier */ + barrier->br_cycle = !(barrier->br_cycle); + barrier->br_count = barrier->br_threshold; + if ((rv = pth_cond_notify(&(barrier->br_cond), TRUE))) + rv = PTH_BARRIER_TAILLIGHT; + } + else { + /* wait until remaining threads have reached the barrier, too */ + pth_cancel_state(PTH_CANCEL_DISABLE, &cancel); + if (barrier->br_threshold == barrier->br_count) + rv = PTH_BARRIER_HEADLIGHT; + else + rv = TRUE; + while (cycle == barrier->br_cycle) { + if (!(rv = pth_cond_await(&(barrier->br_cond), &(barrier->br_mutex), NULL))) + break; + } + pth_cancel_state(cancel, NULL); + } + pth_mutex_release(&(barrier->br_mutex)); + return rv; +} + Index: ossp-pkg/pth/pth_syscall.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_syscall.c,v rcsdiff -q -kk '-r1.20' '-r1.21' -u '/v/ossp/cvs/ossp-pkg/pth/pth_syscall.c,v' 2>/dev/null --- pth_syscall.c 2000/10/03 09:26:47 1.20 +++ pth_syscall.c 2001/03/24 14:51:05 1.21 @@ -1,6 +1,6 @@ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth_tcb.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_tcb.c,v co -q -kk -p'1.35' '/v/ossp/cvs/ossp-pkg/pth/pth_tcb.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_tcb.c' 2>/dev/null --- ossp-pkg/pth/pth_tcb.c +++ - 2024-05-13 13:57:53.958748005 +0200 @@ -0,0 +1,144 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_tcb.c: Pth thread control block handling +*/ + /* Patient: Doctor, it hurts when I do this! + Doctor: Well, then don't do it. */ +#include "pth_p.h" + +#if cpp + +#define PTH_TCB_NAMELEN 40 + + /* thread control block */ +struct pth_st { + /* priority queue handling */ + pth_t q_next; /* next thread in pool */ + pth_t q_prev; /* previous thread in pool */ + int q_prio; /* (relative) priority of thread when queued */ + + /* standard thread control block ingredients */ + int prio; /* base priority of thread */ + char name[PTH_TCB_NAMELEN];/* name of thread (mainly for debugging) */ + pth_state_t state; /* current state indicator for thread */ + + /* timing */ + pth_time_t spawned; /* time point at which thread was spawned */ + pth_time_t lastran; /* time point at which thread was last running */ + pth_time_t running; /* time range the thread was already running */ + + /* event handling */ + pth_event_t events; /* events the tread is waiting for */ + + /* per-thread signal handling */ + sigset_t sigpending; /* set of pending signals */ + int sigpendcnt; /* number of pending signals */ + + /* machine context */ + pth_mctx_t mctx; /* last saved machine state of thread */ + char *stack; /* pointer to thread stack */ + unsigned int stacksize; /* size of thread stack */ + long *stackguard; /* stack overflow guard */ + int stackloan; /* stack type */ + void *(*start_func)(void *); /* start routine */ + void *start_arg; /* start argument */ + + /* thread joining */ + int joinable; /* whether thread is joinable */ + void *join_arg; /* joining argument */ + + /* per-thread specific storage */ + const void **data_value; /* thread specific values */ + int data_count; /* number of stored values */ + + /* cancellation support */ + int cancelreq; /* cancellation request is pending */ + unsigned int cancelstate; /* cancellation state of thread */ + pth_cleanup_t *cleanups; /* stack of thread cleanup handlers */ + + /* mutex ring */ + pth_ring_t mutexring; /* ring of aquired mutex structures */ +}; + +#endif /* cpp */ + +intern const char *pth_state_names[] = { + "scheduler", "new", "ready", "running", "waiting", "dead" +}; + +#if defined(MINSIGSTKSZ) && !defined(SIGSTKSZ) +#define SIGSTKSZ MINSIGSTKSZ +#endif +#if !defined(SIGSTKSZ) +#define SIGSTKSZ 8192 +#endif + +/* allocate a thread control block */ +intern pth_t pth_tcb_alloc(unsigned int stacksize, void *stackaddr) +{ + pth_t t; + + if (stacksize > 0 && stacksize < SIGSTKSZ) + stacksize = SIGSTKSZ; + if ((t = (pth_t)malloc(sizeof(struct pth_st))) == NULL) + return NULL; + t->stacksize = stacksize; + t->stack = NULL; + t->stackguard = NULL; + t->stackloan = (stackaddr != NULL ? TRUE : FALSE); + if (stacksize > 0) { /* stacksize == 0 means "main" thread */ + if (stackaddr != NULL) + t->stack = (char *)(stackaddr); + else { + if ((t->stack = (char *)malloc(stacksize)) == NULL) { + errno_shield { free(t); } + return NULL; + } + } +#if PTH_STACKGROWTH < 0 + /* guard is at lowest address (alignment is guarrantied) */ + t->stackguard = (long *)((long)t->stack); /* double cast to avoid alignment warning */ +#else + /* guard is at highest address (be careful with alignment) */ + t->stackguard = (long *)(t->stack+(((stacksize/sizeof(long))-1)*sizeof(long))); +#endif + *t->stackguard = 0xDEAD; + } + return t; +} + +/* free a thread control block */ +intern void pth_tcb_free(pth_t t) +{ + if (t == NULL) + return; + if (t->stack != NULL && !t->stackloan) + free(t->stack); + if (t->data_value != NULL) + free(t->data_value); + if (t->cleanups != NULL) + pth_cleanup_popall(t, FALSE); + free(t); + return; +} + Index: ossp-pkg/pth/pth_time.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_time.c,v rcsdiff -q -kk '-r1.25' '-r1.26' -u '/v/ossp/cvs/ossp-pkg/pth/pth_time.c,v' 2>/dev/null --- pth_time.c 2000/07/28 19:18:46 1.25 +++ pth_time.c 2001/03/24 14:51:05 1.26 @@ -1,6 +1,6 @@ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pth_util.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pth_util.c,v co -q -kk -p'1.19' '/v/ossp/cvs/ossp-pkg/pth/pth_util.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/pth_util.c' 2>/dev/null --- ossp-pkg/pth/pth_util.c +++ - 2024-05-13 13:57:53.965554988 +0200 @@ -0,0 +1,174 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth_util.c: Pth utility functions +*/ + /* ``Premature optimization is + the root of all evil.'' + -- D.E.Knuth */ +#include "pth_p.h" + +/* calculate numerical mimimum */ +#if cpp +#define pth_util_min(a,b) \ + ((a) > (b) ? (b) : (a)) +#endif + +/* delete a pending signal */ +static void pth_util_sigdelete_sighandler(int _sig) +{ + /* nop */ + return; +} +intern int pth_util_sigdelete(int sig) +{ + sigset_t ss, oss; + struct sigaction sa, osa; + + /* check status of signal */ + sigpending(&ss); + if (!sigismember(&ss, sig)) + return FALSE; + + /* block signal and remember old mask */ + sigemptyset(&ss); + sigaddset(&ss, sig); + pth_sc(sigprocmask)(SIG_BLOCK, &ss, &oss); + + /* set signal action to our dummy handler */ + sa.sa_handler = pth_util_sigdelete_sighandler; + sigfillset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(sig, &sa, &osa) != 0) { + pth_sc(sigprocmask)(SIG_SETMASK, &oss, NULL); + return FALSE; + } + + /* now let signal be delivered */ + sigfillset(&ss); + sigdelset(&ss, sig); + sigsuspend(&ss); + + /* restore signal mask and handler */ + sigaction(sig, &osa, NULL); + pth_sc(sigprocmask)(SIG_SETMASK, &oss, NULL); + return TRUE; +} + +/* copy a string like strncpy() but always null-terminate */ +intern char *pth_util_cpystrn(char *dst, const char *src, size_t dst_size) +{ + register char *d, *end; + + if (dst_size == 0) + return dst; + d = dst; + end = dst + dst_size - 1; + for (; d < end; ++d, ++src) { + if ((*d = *src) == '\0') + return d; + } + *d = '\0'; + return d; +} + +/* merge input fd set into output fds */ +intern void pth_util_fds_merge(int nfd, + fd_set *ifds1, fd_set *ofds1, + fd_set *ifds2, fd_set *ofds2, + fd_set *ifds3, fd_set *ofds3) +{ + register int s; + + for (s = 0; s < nfd; s++) { + if (ifds1 != NULL) + if (FD_ISSET(s, ifds1)) + FD_SET(s, ofds1); + if (ifds2 != NULL) + if (FD_ISSET(s, ifds2)) + FD_SET(s, ofds2); + if (ifds3 != NULL) + if (FD_ISSET(s, ifds3)) + FD_SET(s, ofds3); + } + return; +} + +/* test whether fds in the input fd sets occurred in the output fds */ +intern int pth_util_fds_test(int nfd, + fd_set *ifds1, fd_set *ofds1, + fd_set *ifds2, fd_set *ofds2, + fd_set *ifds3, fd_set *ofds3) +{ + register int s; + + for (s = 0; s < nfd; s++) { + if (ifds1 != NULL) + if (FD_ISSET(s, ifds1) && FD_ISSET(s, ofds1)) + return TRUE; + if (ifds2 != NULL) + if (FD_ISSET(s, ifds2) && FD_ISSET(s, ofds2)) + return TRUE; + if (ifds3 != NULL) + if (FD_ISSET(s, ifds3) && FD_ISSET(s, ofds3)) + return TRUE; + } + return FALSE; +} + +/* + * clear fds in input fd sets if not occurred in output fd sets and return + * number of remaining input fds. This number uses BSD select(2) semantics: a + * fd in two set counts twice! + */ +intern int pth_util_fds_select(int nfd, + fd_set *ifds1, fd_set *ofds1, + fd_set *ifds2, fd_set *ofds2, + fd_set *ifds3, fd_set *ofds3) +{ + register int s; + register int n; + + n = 0; + for (s = 0; s < nfd; s++) { + if (ifds1 != NULL && FD_ISSET(s, ifds1)) { + if (!FD_ISSET(s, ofds1)) + FD_CLR(s, ifds1); + else + n++; + } + if (ifds2 != NULL && FD_ISSET(s, ifds2)) { + if (!FD_ISSET(s, ofds2)) + FD_CLR(s, ifds2); + else + n++; + } + if (ifds3 != NULL && FD_ISSET(s, ifds3)) { + if (!FD_ISSET(s, ofds3)) + FD_CLR(s, ifds3); + else + n++; + } + } + return n; +} + Index: ossp-pkg/pth/pthread-config.in RCS File: /v/ossp/cvs/ossp-pkg/pth/pthread-config.in,v co -q -kk -p'1.18' '/v/ossp/cvs/ossp-pkg/pth/pthread-config.in,v' | diff -u /dev/null - -L'ossp-pkg/pth/pthread-config.in' 2>/dev/null --- ossp-pkg/pth/pthread-config.in +++ - 2024-05-13 13:57:53.968203689 +0200 @@ -0,0 +1,133 @@ +#!/bin/sh +## +## GNU Pth - The GNU Portable Threads +## Copyright (c) 1999-2001 Ralf S. Engelschall +## +## This file is part of GNU Pth, a non-preemptive thread scheduling +## library which can be found at http://www.gnu.org/software/pth/. +## +## This library 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 2.1 of the License, or (at your option) any later version. +## +## This library 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 this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +## USA, or contact Ralf S. Engelschall . +## +## pthread-config.in: Pth library build utility [Pthread API] +## + +DIFS=' +' + +prefix="@prefix@" +exec_prefix="@exec_prefix@" + +pth_prefix="$prefix" +pth_exec_prefix="$exec_prefix" +pth_bindir="@bindir@" +pth_libdir="@libdir@" +pth_includedir="@includedir@" +pth_mandir="@mandir@" +pth_cflags="@CFLAGS@" +pth_ldflags="@LDFLAGS@" +pth_libs="@LIBS@" +pth_version="@PTH_VERSION_STR@" + +help=no +version=no + +usage="pthread-config" +usage="$usage [--help] [--version] [--all]" +usage="$usage [--prefix] [--exec-prefix] [--bindir] [--libdir] [--includedir] [--mandir]" +usage="$usage [--cflags] [--ldflags] [--libs]" +if [ $# -eq 0 ]; then + echo "pthread-config:Error: Invalid option" 1>&2 + echo "pthread-config:Usage: $usage" 1>&2 + exit 1 +fi +output="" +output_extra="" +all=no +prev='' +OIFS="$IFS" IFS="$DIFS" +for option +do + if [ ".$prev" != . ]; then + eval "$prev=\$option" + prev="" + continue + fi + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg='' ;; + esac + case "$option" in + --help|-h) + echo "Usage: $usage" + echo "Report bugs to bug-pth@gnu.org" + exit 0 + ;; + --version|-v) + echo "GNU Pth $pth_version [Pthread API]" + exit 0 + ;; + --all) + all=yes + ;; + --prefix) + output="$output $pth_prefix" + ;; + --exec-prefix) + output="$output $pth_exec_prefix" + ;; + --bindir) + output="$output $pth_bindir" + ;; + --libdir) + output="$output $pth_libdir" + ;; + --includedir) + output="$output $pth_includedir" + ;; + --mandir) + output="$output $pth_mandir" + ;; + --cflags) + output="$output -I$pth_includedir" + output_extra="$output_extra $pth_cflags" + ;; + --ldflags) + output="$output -L$pth_libdir" + output_extra="$output_extra $pth_ldflags" + ;; + --libs) + output="$output -lpthread" + output_extra="$output_extra $pth_libs" + ;; + * ) + echo "pthread-config:Error: Invalid option" 1>&2 + echo "pthread-config:Usage: $usage" 1>&2 + exit 1; + ;; + esac +done +IFS="$OIFS" +if [ ".$prev" != . ]; then + echo "pthread-config:Error: missing argument to --`echo $prev | sed 's/_/-/g'`" 1>&2 + exit 1 +fi +if [ ".$output" != . ]; then + if [ ".$all" = .yes ]; then + output="$output $output_extra" + fi + echo $output +fi + Index: ossp-pkg/pth/pthread-config.pod RCS File: /v/ossp/cvs/ossp-pkg/pth/pthread-config.pod,v co -q -kk -p'1.15' '/v/ossp/cvs/ossp-pkg/pth/pthread-config.pod,v' | diff -u /dev/null - -L'ossp-pkg/pth/pthread-config.pod' 2>/dev/null --- ossp-pkg/pth/pthread-config.pod +++ - 2024-05-13 13:57:53.970807718 +0200 @@ -0,0 +1,147 @@ +## +## GNU Pth - The GNU Portable Threads +## Copyright (c) 1999-2001 Ralf S. Engelschall +## +## This file is part of GNU Pth, a non-preemptive thread scheduling +## library which can be found at http://www.gnu.org/software/pth/. +## +## This library 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 2.1 of the License, or (at your option) any later version. +## +## This library 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 this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +## USA, or contact Ralf S. Engelschall . +## +## pthread-config.pod: pthread library build utility manual page +## + +=pod + +=head1 NAME + +B - Pth pthread library build utility + +=head1 VERSION + +GNU Pth PTH_VERSION_STR + +=head1 SYNOPSIS + +B +[B<--help>] +[B<--version>] +[B<--all>] +[B<--prefix>] +[B<--exec-prefix>] +[B<--bindir>] +[B<--libdir>] +[B<--includedir>] +[B<--mandir>] +[B<--cflags>] +[B<--ldflags>] +[B<--libs>] + +=head1 DESCRIPTION + +The B program is a little helper utility for easy configuring +and building applications based on the pthread emulation API of the GNU +Portable Threads (pth) library. It can be used to query the C compiler and +linker flags which are required to correctly compile and link the application +against the pth(3) library. + +=head1 OPTIONS + +B accepts the following options: + +=over 4 + +=item B<--help> + +Prints the short usage information. + +=item B<--version> + +Prints the version number and date of the installed pth(3) library. + +=item B<--all> + +Forces the output of all flags, that is, including extra flags which are not +B specific. + +=item B<--prefix> + +Prints the installation prefix of architecture independent files + +=item B<--exec-prefix> + +Prints the installation prefix of architecture dependent files. + +=item B<--bindir> + +Prints the installation directory of binaries. + +=item B<--libdir> + +Prints the installation directory of libraries. + +=item B<--includedir> + +Prints the installation directory of include headers. + +=item B<--mandir> + +Prints the installation directory of manual pages. + +=item B<--cflags> + +Prints the C compiler flags which are needed to compile the pth(3)-based +application. The output is usually added to the C variable of the +applications C. + +=item B<--ldflags> + +Prints the linker flags (C<-L>) which are needed to link the application with +the pth(3) library. The output is usually added to the C variable of +the applications C. + +=item B<--libs> + +Prints the library flags (C<-l>) which are needed to link the application with +the pth(3) library. The output is usually added to the C variable of the +applications C. + +=back + +=head1 EXAMPLE + + CC = cc + CFLAGS = -O `pthread-config --cflags` + LDFLAGS = `pthread-config --ldflags` + LIBS = -lm `pthread-config --libs` + + all: foo + foo: foo.o + $(CC) $(LDFLAGS) -o foo foo.o $(LIBS) + foo.o: foo.c + $(CC) $(CFLAGS) -c foo.c + +=head1 SEE ALSO + +pthread(3), cc(1). + +=head1 AUTHOR + + Ralf S. Engelschall + rse@engelschall.com + www.engelschall.com + +=cut + Index: ossp-pkg/pth/pthread.c RCS File: /v/ossp/cvs/ossp-pkg/pth/pthread.c,v rcsdiff -q -kk '-r1.53' '-r1.54' -u '/v/ossp/cvs/ossp-pkg/pth/pthread.c,v' 2>/dev/null --- pthread.c 2001/03/24 14:37:06 1.53 +++ pthread.c 2001/03/24 14:51:05 1.54 @@ -1,6 +1,6 @@ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pthread.h.in RCS File: /v/ossp/cvs/ossp-pkg/pth/pthread.h.in,v rcsdiff -q -kk '-r1.56' '-r1.57' -u '/v/ossp/cvs/ossp-pkg/pth/pthread.h.in,v' 2>/dev/null --- pthread.h.in 2001/03/24 14:37:06 1.56 +++ pthread.h.in 2001/03/24 14:51:05 1.57 @@ -1,6 +1,6 @@ /* ** GNU Pth - The GNU Portable Threads -** Copyright (c) 1999-2000 Ralf S. Engelschall +** Copyright (c) 1999-2001 Ralf S. Engelschall ** ** This file is part of GNU Pth, a non-preemptive thread scheduling ** library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/pthread.pod RCS File: /v/ossp/cvs/ossp-pkg/pth/pthread.pod,v rcsdiff -q -kk '-r1.20' '-r1.21' -u '/v/ossp/cvs/ossp-pkg/pth/pthread.pod,v' 2>/dev/null --- pthread.pod 2001/03/24 14:27:29 1.20 +++ pthread.pod 2001/03/24 14:51:05 1.21 @@ -1,6 +1,6 @@ ## ## GNU Pth - The GNU Portable Threads -## Copyright (c) 1999-2000 Ralf S. Engelschall +## Copyright (c) 1999-2001 Ralf S. Engelschall ## ## This file is part of GNU Pth, a non-preemptive thread scheduling ## library which can be found at http://www.gnu.org/software/pth/. Index: ossp-pkg/pth/striptease.mk RCS File: /v/ossp/cvs/ossp-pkg/pth/striptease.mk,v co -q -kk -p'1.5' '/v/ossp/cvs/ossp-pkg/pth/striptease.mk,v' | diff -u /dev/null - -L'ossp-pkg/pth/striptease.mk' 2>/dev/null --- ossp-pkg/pth/striptease.mk +++ - 2024-05-13 13:57:53.995077644 +0200 @@ -0,0 +1,74 @@ +## +## GNU Pth - The GNU Portable Threads +## Copyright (c) 1999-2001 Ralf S. Engelschall +## +## This file is part of GNU Pth, a non-preemptive thread scheduling +## library which can be found at http://www.gnu.org/software/pth/. +## +## This library 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 2.1 of the License, or (at your option) any later version. +## +## This library 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 this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +## USA, or contact Ralf S. Engelschall . +## +## striptease.mk: Pth Makefile input for stripped down version +## + # ``The "micro" in "microkernel" was + # originally intended to mean 'small': + # Believe it or not.'' -- Ripley +@SET_MAKE@ + +CC = @CC@ +CPPFLAGS = @CPPFLAGS@ -I. +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ -L. +LIBS = @LIBS@ +AR = @AR@ +RANLIB = @RANLIB@ +SHTOOL = ./shtool +RM = rm -f + +LIBS = libpth.a @LIBPTHREAD_A@ +OBJS = pth.o pth_vers.o @PTHREAD_O@ +SRCS = pth.c pth_vers.c + +all: pth_p.h $(LIBS) + +.SUFFIXES: +.SUFFIXES: .c .o .lo +.c.o: + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< + +pth_p.h: pth_p.h.in + $(SHTOOL) scpp -o pth_p.h -t pth_p.h.in -Dcpp -Cintern -M '==#==' $(SRCS) + +libpth.a: pth.o pth_vers.o + $(AR) rc libpth.a pth.o pth_vers.o + $(RANLIB) libpth.a + +libpthread.a: pth.o pth_vers.o pthread.o + $(AR) rc libpthread.a pth.o pth_vers.o pthread.o + $(RANLIB) libpthread.a + +clean: + $(RM) $(LIBS) + $(RM) $(OBJS) + +distclean: clean + $(RM) config.cache config.log config.status + $(RM) pth_p.h pth.h pthread.h pth_acdef.h pth_acmac.h + $(RM) Makefile + +test: +check: +install: + Index: ossp-pkg/pth/striptease.pl RCS File: /v/ossp/cvs/ossp-pkg/pth/striptease.pl,v co -q -kk -p'1.10' '/v/ossp/cvs/ossp-pkg/pth/striptease.pl,v' | diff -u /dev/null - -L'ossp-pkg/pth/striptease.pl' 2>/dev/null --- ossp-pkg/pth/striptease.pl +++ - 2024-05-13 13:57:53.997746036 +0200 @@ -0,0 +1,163 @@ +## +## Copyright (c) 1999-2001 Ralf S. Engelschall, All Rights Reserved. +## +## GNU Pth - The GNU Portable Threads +## Copyright (c) 1999-2001 Ralf S. Engelschall +## +## This file is part of GNU Pth, a non-preemptive thread scheduling +## library which can be found at http://www.gnu.org/software/pth/. +## +## This library 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 2.1 of the License, or (at your option) any later version. +## +## This library 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 this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +## USA, or contact Ralf S. Engelschall . +## +## striptease.pl: Strip down the Pth source tree to its minimum +## + # ``Mobius strippers never + # show you their back side.'' +require 5.000; + +$|++; + +my $src = '.'; +my $tmp = $ENV{'TMPDIR'} || '/tmp'; +my $dst = "$tmp/pth-striptease"; + +sub kbof { + my ($dir) = @_; + my ($b); + + $b = 0; + for $file (glob("$dir/*")) { + my @S = stat($file); + $b += $S[7]; + } + return $b / 1024; +} + +printf("Stripping down source tree from %d KB to its minimum... ", &kbof($src)); + +system("rm -rf $dst") if (-d $dst); +system("mkdir $dst") if (not -d $dst); + +open(FP, ">$dst/README.1st"); +print FP <<"EOT"; + + This is a heavily stripped down version of the GNU Pth + (GNU Portable Threads) package. It was automatically + generated by a call to ``make striptease'' from within + a full-sized GNU Pth source tree. DO NOT EDIT ANYTHING + HERE. CHANGES WILL BE LOST IF AN UPDATED STRIPPED DOWN + VERSION IS IMPORTED NEXT TIME TO THIS AREA. For the + complete source go to http://www.gnu.org/software/pth/. + +EOT +close(FP); + +@files = (qw( + COPYING + README + config.guess config.sub + pth.h.in + pth_p.h.in + pth_acdef.h.in pth_acmac.h.in + pth_vers.c + pthread.c + pthread.h.in +)); + +@source = (qw( + pth_compat.c pth_debug.c pth_syscall.c pth_errno.c pth_ring.c pth_mctx.c + pth_clean.c pth_time.c pth_tcb.c pth_util.c pth_pqueue.c pth_event.c + pth_sched.c pth_data.c pth_msg.c pth_cancel.c pth_sync.c pth_attr.c pth_lib.c + pth_fork.c pth_high.c pth_ext.c +)); + +foreach $f (@files) { + system("cp -p $src/$f $dst/$f"); +} + +$pth_c = <<'EOT'; +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** pth.c: Pth all-in-one source (AUTO-GENERATED, DO NOT EDIT!) +*/ + +#include "pth_p.h" + +EOT + +foreach $s (@source) { + open(FP, "<$src/$s"); + $st = ''; + $st .= $_ while (); + close(FP); + $st =~ s|^.+?#include "pth_p.h"\s*\n|/* ==== $s ==== */\n\n|si; + $pth_c .= $st; +} +open(FP, ">$dst/pth.c"); +print FP $pth_c; +close(FP); + +open(FP, "<$src/configure"); +$c = ''; +$c .= $_ while (); +close(FP); +$c =~ s|chmod \+rx pth-config||s; +$c =~ s|chmod \+rx pthread-config||s; +$c =~ s|rm -f pthread-config||s; +$c =~ s|pth-config||sg; +$c =~ s|pthread-config||sg; +$c =~ s|TB=`.+?`|TB=''|s; +$c =~ s|TN=`.+?`|TN=''|s; +$c =~ s|echo \"\$ac_t\"\"\" 1>\&6||sg; +$c =~ s|echo \"\$ac_t\"\"\$\{TB\}.+?:\$\{TN\}" 1>&6||sg; +$c =~ s|enable_batch=no|enable_batch=yes|sg; +open(FP, ">$dst/configure"); +print FP $c; +close(FP); +system("chmod a+rx $dst/configure"); + +system("shtoolize -q -o $dst/shtool version scpp"); +system("cp $src/striptease.mk $dst/Makefile.in"); + +system("$src/shtool fixperm $dst"); +system("rm -rf $src/* && cp -rp $dst/* $src/"); +system("rm -rf $dst"); + +print "done.\n"; + +printf("Resulting source tree: %d KB\n", &kbof($src)); +system("ls -l $src"); + Index: ossp-pkg/pth/test_common.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_common.c,v co -q -kk -p'1.13' '/v/ossp/cvs/ossp-pkg/pth/test_common.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_common.c' 2>/dev/null --- ossp-pkg/pth/test_common.c +++ - 2024-05-13 13:57:54.000428401 +0200 @@ -0,0 +1,124 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_common.c: Pth common test program stuff +*/ + /* ``It doesn't need to be tested, + because it works.'' + -- Richard Holloway */ +#include +#include +#include +#include + +#include "pth.h" + +#include "test_common.h" + +/* + * implementation of a convinient greedy tread-safe line reading function to + * avoid slow byte-wise reading from filedescriptors - which is important for + * high-performance situations. + */ + +#define READLINE_MAXLEN 1024 +static pth_key_t readline_key; +static pth_once_t readline_once_ctrl = PTH_ONCE_INIT; + +typedef struct { + int rl_cnt; + char *rl_bufptr; + char rl_buf[READLINE_MAXLEN]; +} readline_buf; + +static void readline_buf_destroy(void *vp) +{ + free(vp); + return; +} + +static void readline_init(void *vp) +{ + pth_key_create(&readline_key, readline_buf_destroy); + return; +} + +ssize_t pth_readline(int fd, void *buf, size_t buflen) +{ + return pth_readline_ev(fd, buf, buflen, NULL); +} + +ssize_t pth_readline_ev(int fd, void *buf, size_t buflen, pth_event_t ev_extra) +{ + size_t n; + ssize_t rc; + char c = '\0', *cp; + readline_buf *rl; + + pth_once(&readline_once_ctrl, readline_init, NULL); + if ((rl = (readline_buf *)pth_key_getdata(readline_key)) == NULL) { + rl = (readline_buf *)malloc(sizeof(readline_buf)); + rl->rl_cnt = 0; + rl->rl_bufptr = NULL; + pth_key_setdata(readline_key, rl); + } + cp = (char *)buf; + for (n = 1; n < buflen; n++) { + + /* fetch one character (but read more) */ + rc = 1; + if (rl->rl_cnt <= 0) { + if ((rl->rl_cnt = pth_read_ev(fd, rl->rl_buf, READLINE_MAXLEN, ev_extra)) < 0) + rc = -1; + else if (rl->rl_cnt == 0) + rc = 0; + else + rl->rl_bufptr = rl->rl_buf; + } + if (rc == 1) { + rl->rl_cnt--; + c = *rl->rl_bufptr++; + } + + /* act on fetched character */ + if (rc == 1) { + if (c == '\r') { + n--; + continue; + } + *cp++ = c; + if (c == '\n') + break; + } + else if (rc == 0) { + if (n == 1) + return 0; + else + break; + } + else + return -1; + } + *cp = NUL; + return n; +} + Index: ossp-pkg/pth/test_common.h RCS File: /v/ossp/cvs/ossp-pkg/pth/test_common.h,v co -q -kk -p'1.6' '/v/ossp/cvs/ossp-pkg/pth/test_common.h,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_common.h' 2>/dev/null --- ossp-pkg/pth/test_common.h +++ - 2024-05-13 13:57:54.003068240 +0200 @@ -0,0 +1,32 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_common.h : Pth common test program stuff (header) +*/ + +#ifndef _TEST_COMMON_H_ +#define _TEST_COMMON_H_ + +ssize_t pth_readline(int, void *, size_t); +ssize_t pth_readline_ev(int, void *, size_t, pth_event_t); + +#endif /* _TEST_COMMON_H_ */ Index: ossp-pkg/pth/test_httpd.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_httpd.c,v co -q -kk -p'1.51' '/v/ossp/cvs/ossp-pkg/pth/test_httpd.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_httpd.c' 2>/dev/null --- ossp-pkg/pth/test_httpd.c +++ - 2024-05-13 13:57:54.005618365 +0200 @@ -0,0 +1,230 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_httpd.c: Pth test program (faked HTTP daemon) +*/ + /* ``Unix is simple. It just takes a + genius to understand its simplicity.'' + --- Dennis Ritchie */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pth.h" + +#include "test_common.h" + +/* + * The HTTP request handler + */ + +#define MAXREQLINE 1024 + +static void *handler(void *_arg) +{ + int fd = (int)((long)_arg); + char caLine[MAXREQLINE]; + char str[1024]; + int n; + + /* read request */ + for (;;) { + n = pth_readline(fd, caLine, MAXREQLINE); + if (n < 0) { + fprintf(stderr, "read error: errno=%d\n", errno); + close(fd); + return NULL; + } + if (n == 0) + break; + if (n == 1 && caLine[0] == '\n') + break; + caLine[n-1] = NUL; + } + + /* simulate a little bit of processing ;) */ + pth_yield(NULL); + + /* generate response */ + sprintf(str, "HTTP/1.0 200 Ok\r\n" + "Server: test_httpd/%x\r\n" + "Connection: close\r\n" + "Content-type: text/plain\r\n" + "\r\n" + "Just a trivial test for GNU Pth\n" + "to show that it's serving data.\r\n", PTH_VERSION); + pth_write(fd, str, strlen(str)); + + /* close connection and let thread die */ + fprintf(stderr, "connection shutdown (fd: %d)\n", fd); + close(fd); + return NULL; +} + +/* + * A useless ticker we let run just for fun in parallel + */ + +static void *ticker(void *_arg) +{ + time_t now; + char *ct; + float avload; + + for (;;) { + pth_sleep(5); + now = time(NULL); + ct = ctime(&now); + ct[strlen(ct)-1] = NUL; + pth_ctrl(PTH_CTRL_GETAVLOAD, &avload); + fprintf(stderr, "ticker woken up on %s, average load: %.2f\n", + ct, avload); + } + /* NOTREACHED */ + return NULL; +} + +/* + * And the server main procedure + */ + +#if defined(FD_SETSIZE) +#define REQ_MAX FD_SETSIZE-100 +#else +#define REQ_MAX 100 +#endif + +static int s; +pth_attr_t attr; + +static void myexit(int sig) +{ + close(s); + pth_attr_destroy(attr); + pth_kill(); + fprintf(stderr, "**Break\n"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + struct sockaddr_in sar; + struct protoent *pe; + struct sockaddr_in peer_addr; + socklen_t peer_len; + int sr; + int port; + + /* initialize scheduler */ + pth_init(); + signal(SIGPIPE, SIG_IGN); + signal(SIGINT, myexit); + signal(SIGTERM, myexit); + + /* argument line parsing */ + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + port = atoi(argv[1]); + if (port <= 0 || port >= 65535) { + fprintf(stderr, "Illegal port: %d\n", port); + exit(1); + } + + fprintf(stderr, "This is TEST_HTTPD, a Pth test using socket I/O.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Multiple connections are accepted on the specified port.\n"); + fprintf(stderr, "For each connection a separate thread is spawned which\n"); + fprintf(stderr, "reads a HTTP request the socket and writes back a constant\n"); + fprintf(stderr, "(and useless) HTTP response to the socket.\n"); + fprintf(stderr, "Additionally a useless ticker thread awakens every 5s.\n"); + fprintf(stderr, "Watch the average scheduler load the ticker displays.\n"); + fprintf(stderr, "Hit CTRL-C for stopping this test.\n"); + fprintf(stderr, "\n"); + + /* run a just for fun ticker thread */ + attr = pth_attr_new(); + pth_attr_set(attr, PTH_ATTR_NAME, "ticker"); + pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); + pth_attr_set(attr, PTH_ATTR_STACK_SIZE, 64*1024); + pth_spawn(attr, ticker, NULL); + + /* create TCP socket */ + if ((pe = getprotobyname("tcp")) == NULL) { + perror("getprotobyname"); + exit(1); + } + if ((s = socket(AF_INET, SOCK_STREAM, pe->p_proto)) == -1) { + perror("socket"); + exit(1); + } + + /* bind socket to port */ + sar.sin_family = AF_INET; + sar.sin_addr.s_addr = INADDR_ANY; + sar.sin_port = htons(port); + if (bind(s, (struct sockaddr *)&sar, sizeof(struct sockaddr_in)) == -1) { + perror("socket"); + exit(1); + } + + /* start listening on the socket with a queue of 10 */ + if (listen(s, REQ_MAX) == -1) { + perror("listen"); + exit(1); + } + + /* finally loop for requests */ + pth_attr_set(attr, PTH_ATTR_NAME, "handler"); + fprintf(stderr, "listening on port %d (max %d simultaneous connections)\n", port, REQ_MAX); + for (;;) { + /* accept next connection */ + peer_len = sizeof(peer_addr); + if ((sr = pth_accept(s, (struct sockaddr *)&peer_addr, &peer_len)) == -1) { + perror("accept"); + pth_sleep(1); + continue; + } + if (pth_ctrl(PTH_CTRL_GETTHREADS) >= REQ_MAX) { + fprintf(stderr, "currently no more connections acceptable\n"); + continue; + } + fprintf(stderr, "connection established (fd: %d, ip: %s, port: %d)\n", + sr, inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port)); + + /* spawn new handling thread for connection */ + pth_spawn(attr, handler, (void *)((long)sr)); + } + +} + Index: ossp-pkg/pth/test_misc.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_misc.c,v co -q -kk -p'1.32' '/v/ossp/cvs/ossp-pkg/pth/test_misc.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_misc.c' 2>/dev/null --- ossp-pkg/pth/test_misc.c +++ - 2024-05-13 13:57:54.008343861 +0200 @@ -0,0 +1,145 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_misc.c: Pth test program (misc functions) +*/ + /* ``Study it forever and you'll still wonder. + Fly it once and you'll know.'' + -- Henry Spencer */ +#include +#include +#include + +#include "pth.h" + +pth_mutex_t mutex = PTH_MUTEX_INIT; + +static void *my_reader(void *_arg) +{ + char buf[3]; + int n; + + for (;;) { + n = pth_read(STDIN_FILENO, buf, 1); + if (n < 0) { + fprintf(stderr, "reader: error\n"); + break; + } + if (n == 0) { + fprintf(stderr, "reader: EOF\n"); + break; + } + if (n == 1 && buf[0] == '\n') { + buf[0] = '\\'; + buf[1] = 'n'; + n = 2; + } + buf[n] = NUL; + fprintf(stderr, "reader: bytes=%d, char='%s'\n", n, buf); + if (buf[0] == 'Q' || buf[0] == 'q') + break; + if (buf[0] == 'L' || buf[0] == 'l') { + fprintf(stderr, "reader: ACQUIRE MUTEX\n"); + pth_mutex_acquire(&mutex, FALSE, NULL); + } + if (buf[0] == 'U' || buf[0] == 'u') { + fprintf(stderr, "reader: RELEASE MUTEX\n"); + pth_mutex_release(&mutex); + } + fflush(stderr); + } + return NULL; +} + +static void *my_child(void *_arg) +{ + int i; + char *name = (char *)_arg; + + for (i = 0; i < 10; ++i) { + pth_mutex_acquire(&mutex, FALSE, NULL); + fprintf(stderr, "%s: %d\n", name, i); + pth_mutex_release(&mutex); + pth_usleep(500000); + } + return NULL; +} + +int main(int argc, char *argv[]) +{ + pth_t child[10]; + pth_attr_t t_attr; + pth_attr_t t_attr2; + long n; + + pth_init(); + + fprintf(stderr, "This is TEST_MISC, a Pth test using various stuff.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "A stdin reader child and various looping childs are\n"); + fprintf(stderr, "spawned. When you enter 'l' you can lock a mutex which\n"); + fprintf(stderr, "blocks the looping childs. 'u' unlocks this mutex.\n"); + fprintf(stderr, "Enter 'q' to quit.\n"); + fprintf(stderr, "\n"); + + fprintf(stderr, "Main Startup (%ld total threads running)\n", pth_ctrl(PTH_CTRL_GETTHREADS)); + + t_attr = pth_attr_new(); + pth_attr_set(t_attr, PTH_ATTR_JOINABLE, FALSE); + pth_attr_set(t_attr, PTH_ATTR_NAME, "foo"); + child[0] = pth_spawn(t_attr, my_child, (void *)"foo"); + pth_attr_set(t_attr, PTH_ATTR_NAME, "bar"); + child[1] = pth_spawn(t_attr, my_child, (void *)"bar"); + pth_attr_set(t_attr, PTH_ATTR_NAME, "baz"); + child[2] = pth_spawn(t_attr, my_child, (void *)"baz"); + pth_attr_set(t_attr, PTH_ATTR_NAME, "quux"); + child[3] = pth_spawn(t_attr, my_child, (void *)"quux"); + pth_attr_set(t_attr, PTH_ATTR_NAME, "killer"); + pth_attr_set(t_attr, PTH_ATTR_PRIO, 4); + child[4] = pth_spawn(t_attr, my_child, (void *)"killer"); + pth_attr_set(t_attr, PTH_ATTR_NAME, "killer II"); + pth_attr_set(t_attr, PTH_ATTR_PRIO, 5); + child[5] = pth_spawn(t_attr, my_child, (void *)"killer II"); + pth_attr_set(t_attr, PTH_ATTR_NAME, "reader"); + pth_attr_set(t_attr, PTH_ATTR_PRIO, PTH_PRIO_STD); + child[6] = pth_spawn(t_attr, my_reader, (void *)"reader"); + pth_attr_destroy(t_attr); + + t_attr2 = pth_attr_of(child[0]); + pth_attr_set(t_attr2, PTH_ATTR_PRIO, -1); + pth_attr_destroy(t_attr2); + t_attr2 = pth_attr_of(child[3]); + pth_attr_set(t_attr2, PTH_ATTR_PRIO, +1); + pth_attr_destroy(t_attr2); + + fprintf(stderr, "Main Loop (%ld total threads running)\n", pth_ctrl(PTH_CTRL_GETTHREADS)); + + while ((n = pth_ctrl(PTH_CTRL_GETTHREADS)) > 1) { + fprintf(stderr, "Main Loop (%ld total threads still running)\n", n); + pth_usleep(500000); + } + fprintf(stderr, "Main Exit (%ld total threads running)\n", pth_ctrl(PTH_CTRL_GETTHREADS)); + + pth_kill(); + return 0; +} + Index: ossp-pkg/pth/test_mp.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_mp.c,v co -q -kk -p'1.39' '/v/ossp/cvs/ossp-pkg/pth/test_mp.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_mp.c' 2>/dev/null --- ossp-pkg/pth/test_mp.c +++ - 2024-05-13 13:57:54.011001063 +0200 @@ -0,0 +1,182 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_mp.c: Pth test program (message port handling) +*/ + +#include +#include +#include +#include +#include + +#include "pth.h" + +#include "test_common.h" + +/* our simple query structure */ +struct query { + pth_message_t head; /* the standard message header */ + char *string; /* the query ingredients */ +}; + +/* our worker thread which translates the string to upper case */ +typedef struct { + pth_msgport_t mp; + pth_event_t ev; +} worker_cleanup_t; +static void worker_cleanup(void *arg) +{ + worker_cleanup_t *wc = (worker_cleanup_t *)arg; + pth_event_free(wc->ev, PTH_FREE_THIS); + pth_msgport_destroy(wc->mp); + return; +} +static void *worker(void *_dummy) +{ + worker_cleanup_t wc; + pth_msgport_t mp; + pth_event_t ev; + struct query *q; + int i; + + fprintf(stderr, "worker: start\n"); + wc.mp = mp = pth_msgport_create("worker"); + wc.ev = ev = pth_event(PTH_EVENT_MSG, mp); + pth_cleanup_push(worker_cleanup, &wc); + for (;;) { + if ((i = pth_wait(ev)) != 1) + continue; + while ((q = (struct query *)pth_msgport_get(mp)) != NULL) { + fprintf(stderr, "worker: recv query <%s>\n", q->string); + for (i = 0; q->string[i] != NUL; i++) + q->string[i] = toupper(q->string[i]); + fprintf(stderr, "worker: send reply <%s>\n", q->string); + pth_msgport_reply((pth_message_t *)q); + } + } + return NULL; +} + +/* a useless ticker thread */ +static void *ticker(void *_arg) +{ + time_t now; + fprintf(stderr, "ticker: start\n"); + for (;;) { + pth_sleep(5); + now = time(NULL); + fprintf(stderr, "ticker was woken up on %s", ctime(&now)); + } + /* NOTREACHED */ + return NULL; +} + +#define MAXLINELEN 1024 + +int main(int argc, char *argv[]) +{ + char caLine[MAXLINELEN]; + pth_event_t ev = NULL; + pth_event_t evt = NULL; + pth_t t_worker = NULL; + pth_t t_ticker = NULL; + pth_attr_t t_attr; + pth_msgport_t mp = NULL; + pth_msgport_t mp_worker = NULL; + struct query *q = NULL; + int n; + + if (!pth_init()) { + perror("pth_init"); + exit(1); + } + + fprintf(stderr, "This is TEST_MP, a Pth test using message ports.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Lines on stdin are send to a worker thread via message\n"); + fprintf(stderr, "ports, translated to upper case by the worker thread and\n"); + fprintf(stderr, "send back to the main thread via message ports.\n"); + fprintf(stderr, "Additionally a useless ticker thread awakens every 5s.\n"); + fprintf(stderr, "Enter \"quit\" on stdin for stopping this test.\n"); + fprintf(stderr, "\n"); + + t_attr = pth_attr_new(); + pth_attr_set(t_attr, PTH_ATTR_NAME, "worker"); + pth_attr_set(t_attr, PTH_ATTR_JOINABLE, TRUE); + pth_attr_set(t_attr, PTH_ATTR_STACK_SIZE, 16*1024); + t_worker = pth_spawn(t_attr, worker, NULL); + pth_attr_set(t_attr, PTH_ATTR_NAME, "ticker"); + t_ticker = pth_spawn(t_attr, ticker, NULL); + pth_attr_destroy(t_attr); + pth_yield(NULL); + + mp_worker = pth_msgport_find("worker"); + mp = pth_msgport_create("main"); + q = (struct query *)malloc(sizeof(struct query)); + ev = pth_event(PTH_EVENT_MSG, mp); + + evt = NULL; + for (;;) { + if (evt == NULL) + evt = pth_event(PTH_EVENT_TIME, pth_timeout(20,0)); + else + evt = pth_event(PTH_EVENT_TIME|PTH_MODE_REUSE, evt, pth_timeout(20,0)); + n = pth_readline_ev(STDIN_FILENO, caLine, MAXLINELEN, evt); + if (n == -1 && pth_event_occurred(evt)) { + fprintf(stderr, "main: Hey, what are you waiting for? Type in something!\n"); + continue; + } + if (n < 0) { + fprintf(stderr, "main: I/O read error on stdin\n"); + break; + } + if (n == 0) { + fprintf(stderr, "main: EOF on stdin\n"); + break; + } + caLine[n-1] = NUL; + if (strcmp(caLine, "quit") == 0) { + fprintf(stderr, "main: quit\n"); + break; + } + fprintf(stderr, "main: out --> <%s>\n", caLine); + q->string = caLine; + q->head.m_replyport = mp; + pth_msgport_put(mp_worker, (pth_message_t *)q); + pth_wait(ev); + q = (struct query *)pth_msgport_get(mp); + fprintf(stderr, "main: in <-- <%s>\n", q->string); + } + + free(q); + pth_event_free(ev, PTH_FREE_THIS); + pth_event_free(evt, PTH_FREE_THIS); + pth_msgport_destroy(mp); + pth_cancel(t_worker); + pth_join(t_worker, NULL); + pth_cancel(t_ticker); + pth_join(t_ticker, NULL); + pth_kill(); + return 0; +} + Index: ossp-pkg/pth/test_philo.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_philo.c,v co -q -kk -p'1.17' '/v/ossp/cvs/ossp-pkg/pth/test_philo.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_philo.c' 2>/dev/null --- ossp-pkg/pth/test_philo.c +++ - 2024-05-13 13:57:54.013664671 +0200 @@ -0,0 +1,214 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_philo.c: Pth test application showing the 5 philosopher problem +*/ + /* ``It's not enough to be a great programmer; + you have to find a great problem.'' + -- Charles Simonyi */ + +/* + * Reference: E.W. Dijkstra, + * ``Hierarchical Ordering of Sequential Processes'', + * Acta Informatica 1, 1971, 115-138. + */ + +#include +#include +#include +#include +#include + +#include "pth.h" + +#include "test_common.h" + +#define PHILNUM 5 + +typedef enum { + thinking, + hungry, + eating +} philstat; + +static const char *philstatstr[3] = { + "thinking", + "hungry ", + "EATING " +}; + +typedef struct tablestruct { + pth_t tid[PHILNUM]; + int self[PHILNUM]; + pth_mutex_t mutex; + pth_cond_t condition[PHILNUM]; + philstat status[PHILNUM]; +} table; + +static table *tab; + +static void printstate(void) +{ + int i; + + for (i = 0; i < PHILNUM; i++) + printf("| %s ", philstatstr[(int)(tab->status)[i]]); + printf("|\n"); + return; +} + +static int test(unsigned int i) +{ + if ( ((tab->status)[i] == hungry) + && ((tab->status)[(i + 1) % PHILNUM] != eating) + && ((tab->status)[(i - 1 + PHILNUM) % PHILNUM] != eating)) { + (tab->status)[i] = eating; + pth_cond_notify(&((tab->condition)[i]), FALSE); + return TRUE; + } + return FALSE; +} + +static void pickup(unsigned int k) +{ + pth_mutex_acquire(&(tab->mutex), FALSE, NULL); + (tab->status)[k] = hungry; + printstate(); + if (!test(k)) + pth_cond_await(&((tab->condition)[k]), &(tab->mutex), NULL); + printstate(); + pth_mutex_release(&(tab->mutex)); + return; +} + +static void putdown(unsigned int k) +{ + pth_mutex_acquire(&(tab->mutex), FALSE, NULL); + (tab->status)[k] = thinking; + printstate(); + test((k + 1) % PHILNUM); + test((k - 1 + PHILNUM) % PHILNUM); + pth_mutex_release(&(tab->mutex)); + return; +} + +static void *philosopher(void *_who) +{ + unsigned int *who = (unsigned int *)_who; + + /* For simplicity, all philosophers eat for the same amount of time + and think for a time that is simply related to their position at + the table. The parameter who identifies the philosopher: 0,1,2,.. */ + for (;;) { + pth_sleep((*who) + 1); + pickup((*who)); + pth_sleep(1); + putdown((*who)); + } + return NULL; +} + +int main(int argc, char *argv[]) +{ + int i; + sigset_t ss; + int sig; + pth_event_t ev; + + /* initialize Pth library */ + pth_init(); + + /* display test program header */ + printf("This is TEST_PHILO, a Pth test showing the Five Dining Philosophers\n"); + printf("\n"); + printf("This is a demonstration showing the famous concurrency problem of the\n"); + printf("Five Dining Philosophers as analysed 1965 by E.W.Dijkstra:\n"); + printf("\n"); + printf("Five philosophers are sitting around a round table, each with a bowl of\n"); + printf("Chinese food in front of him. Between periods of talking they may start\n"); + printf("eating whenever they want to, with their bowls being filled frequently.\n"); + printf("But there are only five chopsticks available, one each to the left of\n"); + printf("each bowl - and for eating Chinese food one needs two chopsticks. When\n"); + printf("a philosopher wants to start eating, he must pick up the chopstick to\n"); + printf("the left of his bowl and the chopstick to the right of his bowl. He\n"); + printf("may find, however, that either one (or even both) of the chopsticks is\n"); + printf("unavailable as it is being used by another philosopher sitting on his\n"); + printf("right or left, so he has to wait.\n"); + printf("\n"); + printf("This situation shows classical contention under concurrency (the\n"); + printf("philosophers want to grab the chopsticks) and the possibility of a\n"); + printf("deadlock (all philosophers wait that the chopstick to their left becomes\n"); + printf("available).\n"); + printf("\n"); + printf("The demonstration runs max. 60 seconds. To stop before, press CTRL-C.\n"); + printf("\n"); + printf("+----P1----+----P2----+----P3----+----P4----+----P5----+\n"); + + /* initialize the control table */ + tab = (table *)malloc(sizeof(table)); + if (!pth_mutex_init(&(tab->mutex))) { + perror("pth_mutex_init"); + exit(1); + } + for (i = 0; i < PHILNUM; i++) { + (tab->self)[i] = i; + (tab->status)[i] = thinking; + if (!pth_cond_init(&((tab->condition)[i]))) { + perror("pth_cond_init"); + exit(1); + } + } + + /* spawn the philosopher threads */ + for (i = 0; i < PHILNUM; i++) { + if (((tab->tid)[i] = + pth_spawn(PTH_ATTR_DEFAULT, philosopher, + &((tab->self)[i]))) == NULL) { + perror("pth_spawn"); + exit(1); + } + } + + /* wait until 60 seconds have elapsed or CTRL-C was pressed */ + sigemptyset(&ss); + sigaddset(&ss, SIGINT); + ev = pth_event(PTH_EVENT_TIME, pth_timeout(60,0)); + pth_sigwait_ev(&ss, &sig, ev); + pth_event_free(ev, PTH_FREE_ALL); + + /* cancel and join the philosopher threads */ + for (i = 0; i < PHILNUM; i++) + pth_cancel((tab->tid)[i]); + while (pth_join(NULL, NULL)); + + /* finish display */ + printf("+----------+----------+----------+----------+----------+\n"); + + /* free the control table */ + free(tab); + + /* shutdown Pth library */ + pth_kill(); + + return 0; +} + Index: ossp-pkg/pth/test_pthread.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_pthread.c,v co -q -kk -p'1.12' '/v/ossp/cvs/ossp-pkg/pth/test_pthread.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_pthread.c' 2>/dev/null --- ossp-pkg/pth/test_pthread.c +++ - 2024-05-13 13:57:54.016301268 +0200 @@ -0,0 +1,109 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_pthread.c: Pth test program (pthread API) +*/ + +#ifdef GLOBAL +#include +#else +#include "pthread.h" +#endif + +#include +#include +#include +#include +#include + +#define die(str) \ + do { \ + fprintf(stderr, "**die: %s: errno=%d\n", str, errno); \ + exit(1); \ + } while (0) + +static void *child(void *_arg) +{ + char *name = (char *)_arg; + int i; + + fprintf(stderr, "child: startup %s\n", name); + for (i = 0; i < 100; i++) { + if (i++ % 10 == 0) + sleep(1); + fprintf(stderr, "child: %s counts i=%d\n", name, i); + } + fprintf(stderr, "child: shutdown %s\n", name); + return _arg; +} + +int main(int argc, char *argv[]) +{ + pthread_attr_t thread_attr; + pthread_t thread[4]; + char *rc; + + fprintf(stderr, "main: init\n"); + + fprintf(stderr, "main: initializing attribute object\n"); + if (pthread_attr_init(&thread_attr) != 0) + die("pthread_attr_init"); + if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE) != 0) + die("pthread_attr_setdetachstate"); + + fprintf(stderr, "main: create thread 1\n"); + if (pthread_create(&thread[0], &thread_attr, child, (void *)"foo") != 0) + die("pthread_create"); + fprintf(stderr, "main: create thread 2\n"); + if (pthread_create(&thread[1], &thread_attr, child, (void *)"bar") != 0) + die("pthread_create"); + fprintf(stderr, "main: create thread 3\n"); + if (pthread_create(&thread[2], &thread_attr, child, (void *)"baz") != 0) + die("pthread_create"); + fprintf(stderr, "main: create thread 4\n"); + if (pthread_create(&thread[3], &thread_attr, child, (void *)"quux") != 0) + die("pthread_create"); + + fprintf(stderr, "main: destroying attribute object\n"); + if (pthread_attr_destroy(&thread_attr) != 0) + die("pthread_attr_destroy"); + + sleep(3); + + fprintf(stderr, "main: joining...\n"); + if (pthread_join(thread[0], (void **)&rc) != 0) + die("pthread_join"); + fprintf(stderr, "main: joined thread: %s\n", rc); + if (pthread_join(thread[1], (void **)&rc) != 0) + die("pthread_join"); + fprintf(stderr, "main: joined thread: %s\n", rc); + if (pthread_join(thread[2], (void **)&rc) != 0) + die("pthread_join"); + fprintf(stderr, "main: joined thread: %s\n", rc); + if (pthread_join(thread[3], (void **)&rc) != 0) + die("pthread_join"); + fprintf(stderr, "main: joined thread: %s\n", rc); + + fprintf(stderr, "main: exit\n"); + return 0; +} + Index: ossp-pkg/pth/test_select.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_select.c,v co -q -kk -p'1.13' '/v/ossp/cvs/ossp-pkg/pth/test_select.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_select.c' 2>/dev/null --- ossp-pkg/pth/test_select.c +++ - 2024-05-13 13:57:54.018909498 +0200 @@ -0,0 +1,101 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_select.c: Pth test program (select) +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pth.h" + +/* a useless ticker thread */ +static void *ticker(void *_arg) +{ + time_t now; + fprintf(stderr, "ticker: start\n"); + for (;;) { + pth_sleep(5); + now = time(NULL); + fprintf(stderr, "ticker was woken up on %s", ctime(&now)); + } + /* NOTREACHED */ + return NULL; +} + +int main(int argc, char *argv[]) +{ + pth_event_t evt; + pth_t t_ticker; + pth_attr_t t_attr; + fd_set rfds; + char c; + int n; + + pth_init(); + + fprintf(stderr, "This is TEST_SELECT, a Pth test using select.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Enter data. Hit CTRL-C to stop this test.\n"); + fprintf(stderr, "\n"); + + t_attr = pth_attr_new(); + pth_attr_set(t_attr, PTH_ATTR_NAME, "ticker"); + t_ticker = pth_spawn(t_attr, ticker, NULL); + pth_attr_destroy(t_attr); + pth_yield(NULL); + + evt = NULL; + for (;;) { + if (evt == NULL) + evt = pth_event(PTH_EVENT_TIME, pth_timeout(10,0)); + else + evt = pth_event(PTH_EVENT_TIME|PTH_MODE_REUSE, evt, pth_timeout(10,0)); + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + n = pth_select_ev(STDIN_FILENO+1, &rfds, NULL, NULL, NULL, evt); + if (n == -1 && errno == EINTR) { + fprintf(stderr, "main: timeout - repeating\n"); + continue; + } + if (!FD_ISSET(STDIN_FILENO, &rfds)) { + fprintf(stderr, "main: Hmmmm... strange situation: bit not set\n"); + exit(1); + } + fprintf(stderr, "main: select returned %d\n", n); + while (pth_read(STDIN_FILENO, &c, 1) > 0) + fprintf(stderr, "main: read stdin '%c'\n", c); + } + + pth_cancel(t_ticker); + pth_join(t_ticker, NULL); + pth_event_free(evt, PTH_FREE_THIS); + pth_kill(); + return 0; +} + Index: ossp-pkg/pth/test_sfio.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_sfio.c,v co -q -kk -p'1.10' '/v/ossp/cvs/ossp-pkg/pth/test_sfio.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_sfio.c' 2>/dev/null --- ossp-pkg/pth/test_sfio.c +++ - 2024-05-13 13:57:54.021463356 +0200 @@ -0,0 +1,129 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_sfio.c: Pth test program (Sfio support) +*/ + /* ``No, I'm not going to explain it. + If you can't figure it out, you + didn't want to know anyway...'' + -- Larry Wall */ +#include +#include +#include + +#include "pth.h" + +#if PTH_EXT_SFIO + +/* a worker thread */ +static void *worker(void *_dummy) +{ + char line[1024]; + int c; + int i; + + for (;;) { + i = 0; + while (!sfeof(sfstdin)) { + c = sfgetc(sfstdin); + if (c == '\n') { + line[i] = '\0'; + break; + } + line[i++] = (char)c; + } + sfprintf(sfstderr, "you entered '%s' on sfstdin\n", line); + } + return NULL; +} + +/* a useless ticker thread */ +static void *ticker(void *_arg) +{ + time_t now; + sfprintf(sfstderr, "ticker: start\n"); + for (;;) { + pth_sleep(5); + now = time(NULL); + sfprintf(sfstderr, "ticker was woken up on %s", ctime(&now)); + } + /* NOTREACHED */ + return NULL; +} + +int main(int argc, char *argv[]) +{ + Sfdisc_t *disc; + pth_attr_t a; + pth_t w; + pth_t t; + + pth_init(); + + /* get an Sfio discipline for Pth */ + if ((disc = pth_sfiodisc()) == NULL) { + perror("pth_sfioiodc"); + exit(1); + } + + /* push it onto Sfio's input/output streams */ + if (sfdisc(sfstdin, disc) != disc) { + perror("sfdisc"); + exit(1); + } + if (sfdisc(sfstdout, disc) != disc) { + perror("sfdisc"); + exit(1); + } + + sfprintf(sfstderr, "This is TEST_SFIO, a Pth test using Sfio disciplines.\n"); + sfprintf(sfstderr, "\n"); + sfprintf(sfstderr, "Stdout/Stdin are connected to Sfio streams with a Pth\n"); + sfprintf(sfstderr, "discipline on top of the streams in order to use Pth's\n"); + sfprintf(sfstderr, "I/O operations. It demonstrates that the process this\n"); + sfprintf(sfstderr, "way does not block. Instead only one thread blocks.\n"); + sfprintf(sfstderr, "\n"); + + a = pth_attr_new(); + pth_attr_set(a, PTH_ATTR_NAME, "worker"); + pth_attr_set(a, PTH_ATTR_JOINABLE, FALSE); + pth_attr_set(a, PTH_ATTR_STACK_SIZE, 16*1024); + w = pth_spawn(a, worker, NULL); + pth_attr_set(a, PTH_ATTR_NAME, "ticker"); + t = pth_spawn(a, ticker, NULL); + pth_attr_destroy(a); + + pth_exit(NULL); + + return 0; +} + +#else + +int main(int argc, char *argv[]) +{ + fprintf(stderr, "You have to build Pth with --with-sfio to run this test!\n"); + return 0; +} + +#endif + Index: ossp-pkg/pth/test_sig.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_sig.c,v co -q -kk -p'1.18' '/v/ossp/cvs/ossp-pkg/pth/test_sig.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_sig.c' 2>/dev/null --- ossp-pkg/pth/test_sig.c +++ - 2024-05-13 13:57:54.024056375 +0200 @@ -0,0 +1,150 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_sig.c: Pth test program (signal handling) +*/ + +#include +#include +#include +#include +#include +#include + +#include "pth.h" + +static pth_t child1; +static pth_t child2; + +static void *inthandler(void *_arg) +{ + sigset_t sigs; + int sig; + int n; + + fprintf(stderr, "inthandler: enter\n"); + + /* unblock interrupt signal only here */ + sigemptyset(&sigs); + sigaddset(&sigs, SIGINT); + pth_sigmask(SIG_UNBLOCK, &sigs, NULL); + + /* but the user has to hit CTRL-C three times */ + for (n = 0; n < 3; n++) { + pth_sigwait(&sigs, &sig); + fprintf(stderr, "inthandler: SIGINT received (#%d)\n", n); + } + + fprintf(stderr, "inthandler: cancelling child1 and child2\n"); + pth_cancel(child1); + pth_cancel(child2); + + fprintf(stderr, "inthandler: leave\n"); + return NULL; +} + +static void child_cleanup(void *arg) +{ + fprintf(stderr, "%s: running cleanup\n", (char *)arg); + return; +} + +static void *child(void *_arg) +{ + sigset_t sigs; + char *name = (char *)_arg; + int i; + + fprintf(stderr, "%s: enter\n", name); + + /* establish cleanup handler */ + pth_cleanup_push(child_cleanup, name); + + /* block different types of signals */ + pth_sigmask(SIG_SETMASK, NULL, &sigs); + sigaddset(&sigs, SIGINT); + if (strcmp(name, "child1") == 0) { + sigaddset(&sigs, SIGUSR1); + sigdelset(&sigs, SIGUSR2); + } + else { + sigdelset(&sigs, SIGUSR1); + sigaddset(&sigs, SIGUSR2); + } + pth_sigmask(SIG_SETMASK, &sigs, NULL); + + /* do a little bit of processing and show signal states */ + for (i = 0; i < 10; i++) { + pth_sigmask(SIG_SETMASK, NULL, &sigs); + fprintf(stderr, "%s: SIGUSR1: %s\n", name, + sigismember(&sigs, SIGUSR1) ? "blocked" : "unblocked"); + fprintf(stderr, "%s: SIGUSR2: %s\n", name, + sigismember(&sigs, SIGUSR2) ? "blocked" : "unblocked"); + fprintf(stderr, "%s: leave to scheduler\n", name); + pth_sleep(1); + fprintf(stderr, "%s: reentered from scheduler\n", name); + } + + fprintf(stderr, "%s: leave\n", name); + return NULL; +} + +int main(int argc, char *argv[]) +{ + pth_attr_t attr; + sigset_t sigs; + + pth_init(); + + fprintf(stderr, "This is TEST_SIG, a Pth test using signals.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Hit CTRL-C three times to stop this test.\n"); + fprintf(stderr, "But only after all threads were terminated.\n"); + fprintf(stderr, "\n"); + + fprintf(stderr, "main: init\n"); + + /* block signals */ + pth_sigmask(SIG_SETMASK, NULL, &sigs); + sigaddset(&sigs, SIGUSR1); + sigaddset(&sigs, SIGUSR2); + sigaddset(&sigs, SIGINT); + pth_sigmask(SIG_SETMASK, &sigs, NULL); + + /* spawn childs */ + attr = pth_attr_new(); + pth_attr_set(attr, PTH_ATTR_NAME, "child1"); + child1 = pth_spawn(attr, child, (void *)"child1"); + pth_attr_set(attr, PTH_ATTR_NAME, "child2"); + child2 = pth_spawn(attr, child, (void *)"child2"); + pth_attr_set(attr, PTH_ATTR_NAME, "inthandler"); + pth_spawn(attr, inthandler, (void *)"inthandler"); + pth_attr_destroy(attr); + + /* wait until childs are finished */ + while (pth_join(NULL, NULL)); + + fprintf(stderr, "main: exit\n"); + pth_kill(); + return 0; +} + Index: ossp-pkg/pth/test_std.c RCS File: /v/ossp/cvs/ossp-pkg/pth/test_std.c,v co -q -kk -p'1.15' '/v/ossp/cvs/ossp-pkg/pth/test_std.c,v' | diff -u /dev/null - -L'ossp-pkg/pth/test_std.c' 2>/dev/null --- ossp-pkg/pth/test_std.c +++ - 2024-05-13 13:57:54.026672671 +0200 @@ -0,0 +1,150 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2001 Ralf S. Engelschall +** +** This file is part of GNU Pth, a non-preemptive thread scheduling +** library which can be found at http://www.gnu.org/software/pth/. +** +** This library 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 2.1 of the License, or (at your option) any later version. +** +** This library 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 this library; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact Ralf S. Engelschall . +** +** test_std.c: Pth standard test program +*/ + +#include +#include +#include +#include +#include +#include + +#include "pth.h" + +#define FAILED_IF(expr) \ + if (expr) { \ + fprintf(stderr, "*** ERROR, TEST FAILED:\n*** errno=%d\n\n", errno); \ + exit(1); \ + } + +static void *t1_func(void *arg) +{ + int i; + long val; + + val = (long)arg; + FAILED_IF(val != 123) + for (i = 0; i < 100; i++) { + val += 10; + pth_yield(NULL); + } + return (void *)val; +} + +static void *t2_func(void *arg) +{ + long val; + pth_t tid; + void *rval; + int rc; + + val = (long)arg; + if (val < 9) { + val++; + fprintf(stderr, "Spawning thread %ld\n", val); + tid = pth_spawn(PTH_ATTR_DEFAULT, t2_func, (void *)(val)); + FAILED_IF(tid == NULL) + rc = pth_join(tid, &rval); + fprintf(stderr, "Joined thread %ld\n", val); + FAILED_IF(rc == FALSE) + rval = (void *)((long)arg * (long)rval); + } + else + rval = arg; + return rval; +} + +int main(int argc, char *argv[]) +{ + fprintf(stderr, "\n=== TESTING GLOBAL LIBRARY API ===\n\n"); + { + int version; + + fprintf(stderr, "Fetching library version\n"); + version = pth_version(); + FAILED_IF(version == 0x0) + fprintf(stderr, "version = 0x%X\n", version); + } + + fprintf(stderr, "\n=== TESTING BASIC OPERATION ===\n\n"); + { + int rc; + + fprintf(stderr, "Initializing Pth system (spawns scheduler and main thread)\n"); + rc = pth_init(); + FAILED_IF(rc == FALSE) + fprintf(stderr, "Killing Pth system for testing purposes\n"); + pth_kill(); + fprintf(stderr, "Re-Initializing Pth system\n"); + rc = pth_init(); + FAILED_IF(rc == FALSE) + } + + fprintf(stderr, "\n=== TESTING BASIC THREAD OPERATION ===\n\n"); + { + pth_attr_t attr; + pth_t tid; + void *val; + int rc; + + fprintf(stderr, "Creating attribute object\n"); + attr = pth_attr_new(); + FAILED_IF(attr == NULL) + rc = pth_attr_set(attr, PTH_ATTR_NAME, "test1"); + FAILED_IF(rc == FALSE) + rc = pth_attr_set(attr, PTH_ATTR_PRIO, PTH_PRIO_MAX); + FAILED_IF(rc == FALSE) + + fprintf(stderr, "Spawning thread\n"); + tid = pth_spawn(attr, t1_func, (void *)(123)); + FAILED_IF(tid == NULL) + pth_attr_destroy(attr); + + fprintf(stderr, "Joining thread\n"); + rc = pth_join(tid, &val); + FAILED_IF(rc == FALSE) + FAILED_IF(val != (void *)(1123)) + } + + fprintf(stderr, "\n=== TESTING NESTED THREAD OPERATION ===\n\n"); + { + pth_t tid; + void *val; + int rc; + + fprintf(stderr, "Spawning thread 1\n"); + tid = pth_spawn(PTH_ATTR_DEFAULT, t2_func, (void *)(1)); + FAILED_IF(tid == NULL) + + rc = pth_join(tid, &val); + fprintf(stderr, "Joined thread 1\n"); + FAILED_IF(rc == FALSE) + FAILED_IF(val != (void *)(1*2*3*4*5*6*7*8*9)) + } + + pth_kill(); + fprintf(stderr, "\nOK - ALL TESTS SUCCESSFULLY PASSED.\n\n"); + exit(0); +} +