X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f Subject: Patch to port Pth-2.0.7 To: pth-users AT engelschall DOT com, djgpp AT delorie DOT com Cc: bug-shtool AT gnu DOT org X-Mailer: Lotus Notes Release 6.5.4 CCH5 September 12, 2005 Message-ID: From: Gordon DOT Schumacher AT seagate DOT com Date: Wed, 20 Dec 2006 23:06:13 -0700 X-MIMETrack: Serialize by Router on SV-GW1/Seagate Internet(Release 7.0.1 HF29|March 07, 2006) at 12/20/2006 10:06:24 PM MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII X-Proofpoint-FWRule: outbound2 X-Proofpoint-Virus-Version: vendor=fsecure engine=4.65.5446:2.3.11,1.2.37,4.0.164 definitions=2006-12-20_06:2006-12-20,2006-12-19,2006-12-20 signatures=0 I've added some code which should provide DOS DJGPP support to Pth version 2.0.7. The patch isn't too large, and is based off of the quite old 1.3.7 port with some additions for new support that was not provided by that version, which proved necessary to add in order to work with DJGPP v2.04 and still have acceptable performance. DJGPP v2.04 adds support for the pipe() function, simulating it with a temp file. This is less than ideal for performance reasons in a threading library, so I've added a simulated pipe via a circular buffer for platforms without pipe(), and it can be force-enabled with a configure switch. I've also added a few other autoconf detections for other conditions that I see in DJGPP (but might be useful on other systems as well). I'm using the Watt-32 library to provide socket support, and have also added detection of a header specific to this library into autoconf. The last change required to get it to build is actually to shtool, not to Pth at all, but I've included it here for archival completeness. So, that's the good news. The bad news is that I haven't tracked down why yet, but I'm seeing a *big* performance drop compared to my hacked-up build of 1.3.7 (changed to simply remove the usage of the pipe completely, but that shouldn't impact performance unless using signals). I'm so far just testing pth_yield() and seeing how many switches I can do per second and I'm seeing a 6-7x drop, which doesn't make sense to me... more work to do clearly. Perhaps I commented out something in 1.3.7 which I shouldn't have (but everything except signals still seems to work...) Anyway, here are my patches - comments welcome! First the shtool diff: --- pth-2.0.7-orig/shtool 2006-06-08 18:14:44 +0000 +++ pth-2.0.7/shtool 2006-12-20 22:12:26 +0000 @@ -1274,11 +1274,21 @@ # find a reasonable Awk awk='' - paths=`echo $PATH |\ - sed -e 's%/*:%:%g' -e 's%/$%%' \ - -e 's/^:/.:/' -e 's/::/:.:/g' -e 's/:$/:./' \ - -e 's/:/ /g'` - for name in gawk nawk awk; do + sysname=`uname -s` + if [ ".$sysname" = ".MS-DOS" ]; then + paths=`echo $PATH |\ + sed -e 's%/*;%;%g' -e 's%/$%%' \ + -e 's/^;/.;/' -e 's/;;/;.;/g' -e 's/;$/;./' \ + -e 's/;/ /g'` + awknames="gawk gawk.exe nawk nawk.exe awk awk.exe" + else + paths=`echo $PATH |\ + sed -e 's%/*:%:%g' -e 's%/$%%' \ + -e 's/^:/.:/' -e 's/::/:.:/g' -e 's/:$/:./' \ + -e 's/:/ /g'` + awknames="gawk nawk awk" + fi + for name in $awknames; do for path in $paths; do if [ -r "$path/$name" ]; then awk="$path/$name" Now the Pth diff itself: diff -uN pth-2.0.7-orig/Makefile.in pth-2.0.7/Makefile.in --- pth-2.0.7-orig/Makefile.in 2006-06-08 17:54:00 +0000 +++ pth-2.0.7/Makefile.in 2006-12-20 18:37:12 +0000 @@ -95,14 +95,15 @@ LOBJS = pth_debug.lo pth_ring.lo pth_pqueue.lo pth_time.lo pth_errno.lo pth_mctx.lo \ pth_uctx.lo pth_tcb.lo pth_sched.lo pth_attr.lo pth_lib.lo pth_event.lo \ pth_data.lo pth_clean.lo pth_cancel.lo pth_msg.lo pth_sync.lo pth_fork.lo \ - pth_util.lo pth_high.lo pth_syscall.lo pth_ext.lo pth_compat.lo pth_string.lo + pth_util.lo pth_high.lo pth_syscall.lo pth_ext.lo pth_compat.lo pth_string.lo \ + @SIMULATE_PIPE_LOBJS@ # source files for header generation # (order is important and has to follow dependencies in pth_p.h) HSRCS = $(S)pth_compat.c $(S)pth_debug.c $(S)pth_syscall.c $(S)pth_errno.c $(S)pth_ring.c $(S)pth_mctx.c \ $(S)pth_uctx.c $(S)pth_clean.c $(S)pth_time.c $(S)pth_tcb.c $(S)pth_util.c $(S)pth_pqueue.c $(S)pth_event.c \ $(S)pth_sched.c $(S)pth_data.c $(S)pth_msg.c $(S)pth_cancel.c $(S)pth_sync.c $(S)pth_attr.c $(S)pth_lib.c \ - $(S)pth_fork.c $(S)pth_high.c $(S)pth_ext.c $(S)pth_string.c $(S)pthread.c + $(S)pth_fork.c $(S)pth_high.c $(S)pth_ext.c $(S)pth_string.c $(S)pthread.c @SIMULATE_PIPE_HSRCS@ ## ## ____ UTILITY DEFINITIONS _________________________________________ @@ -444,6 +445,7 @@ pth_ring.lo: pth_ring.c pth_p.h pth_vers.c pth.h pth_acdef.h pth_acmac.h pth_sched.lo: pth_sched.c pth_p.h pth_vers.c pth.h pth_acdef.h pth_acmac.h pth_string.lo: pth_string.c pth_p.h pth_vers.c pth.h pth_acdef.h pth_acmac.h +pth_sympipe.lo: pth_sympipe.c pth_p.h pth_vers.c pth.h pth_acdef.h pth_acmac.h pth_sync.lo: pth_sync.c pth_p.h pth_vers.c pth.h pth_acdef.h pth_acmac.h pth_syscall.lo: pth_syscall.c pth_p.h pth_vers.c pth.h pth_acdef.h pth_acmac.h pth_tcb.lo: pth_tcb.c pth_p.h pth_vers.c pth.h pth_acdef.h pth_acmac.h diff -uN pth-2.0.7-orig/configure.ac pth-2.0.7/configure.ac --- pth-2.0.7-orig/configure.ac 2006-06-08 17:54:00 +0000 +++ pth-2.0.7/configure.ac 2006-12-20 19:19:00 +0000 @@ -138,6 +138,42 @@ errno.h sys/types.h sys/time.h sys/wait.h sys/stat.h sys/socket.h) AC_CHECK_FUNCS(dnl gettimeofday select sigaction sigprocmask sigpending sigsuspend) + +dnl # check for sigset_t in sys/signal.h, then in signal.h +AC_MSG_CHECKING(for sigset_t in sys/signal.h) +cross_compile=no +AC_TRY_COMPILE([ +#include +],[ +sigset_t sst; +], +msg="yes" +, +msg="no" +) +AC_MSG_RESULT([$msg]) +if test ".$msg" = .yes; then + INCLUDE_FOR_SIGSET_T="#include /* for sigset_t */" +else + AC_MSG_CHECKING(for sigset_t in signal.h) + AC_TRY_COMPILE([ +#include +],[ +sigset_t sst; +], +msg="yes" +, +msg="no" +) + AC_MSG_RESULT([$msg]) + if test ".$msg" = .yes; then + INCLUDE_FOR_SIGSET_T="#include /* for sigset_t */" + else + AC_MSG_ERROR([couldn't find typedef sigset_t]) + fi +fi +AC_SUBST(INCLUDE_FOR_SIGSET_T) + AC_BEGIN_DECISION([mandatory system headers and functions]) AC_IFALLYES(dnl header:stdio.h header:stdlib.h header:stdarg.h header:string.h dnl @@ -191,7 +227,7 @@ AC_CHECK_FUNCS(usleep strerror) dnl # check for various other headers which we might need -AC_HAVE_HEADERS(sys/resource.h net/errno.h paths.h) +AC_HAVE_HEADERS(sys/resource.h net/errno.h paths.h features.h) dnl # at least the test programs need some socket stuff AC_CHECK_LIB(nsl, gethostname) @@ -295,9 +331,40 @@ ) if test ".$msg" = .yes; then AC_DEFINE(HAVE_STRUCT_TIMESPEC, 1, [define if exists "struct timespec"]) + INCLUDE_FOR_TIMESPEC="#include /* for struct timespec */" +else + AC_TRY_COMPILE([ +#include +],[ +struct timespec ts; +], +msg="yes" +, +msg="no" +) + if test ".$msg" = .yes; then + AC_DEFINE(HAVE_STRUCT_TIMESPEC, 1, [define if exists "struct timespec"]) + INCLUDE_FOR_TIMESPEC="#include /* for struct timespec */" + fi fi +AC_SUBST(INCLUDE_FOR_TIMESPEC) AC_MSG_RESULT([$msg]) +dnl # check for pipe() function +AC_MSG_CHECKING(for pipe) +cross_compile=yes +AC_TRY_COMPILE([ +#include +],[ +int fd[2]; +(void)pipe(fd); +], +ac_use_pipe="yes" +, +ac_use_pipe="no" +) +AC_MSG_RESULT([$ac_use_pipe]) + dnl # check for network/socket size type AC_CHECK_SOCKLENTYPE([ FALLBACK_SOCKLEN_T="typedef ${ac_type} socklen_t;" @@ -316,6 +383,9 @@ AC_SUBST(FALLBACK_NFDS_T) ]) +dnl # check for SIGCHLD definition +AC_CHECK_DEFINE(SIGCHLD,signal.h) + dnl # check for 64-bit types (for pth_snprintf.c) AC_CHECK_LONGLONG AC_CHECK_LONGDOUBLE @@ -387,6 +457,17 @@ * ) AC_ERROR([invalid mctx stack setup -- allowed: mc,ss,sas,none]) ;; esac ])dnl +AC_ARG_ENABLE(pipe,dnl +[ --disable-pipe simulate use of pipes instead of using pipe()],[ +ac_use_pipe="$enableval" +])dnl +if test ".$ac_use_pipe" = ".no"; then + AC_DEFINE(SIMULATE_PIPE, 1, [define to simulate use of pipes instead of using pipe()]) + SIMULATE_PIPE_LOBJS=pth_sympipe.lo + SIMULATE_PIPE_HSRCS='$(S)pth_sympipe.c' +fi +AC_SUBST(SIMULATE_PIPE_LOBJS) +AC_SUBST(SIMULATE_PIPE_HSRCS) dnl # dnl # 4. determine a few additional details diff -uN pth-2.0.7-orig/pth.h.in pth-2.0.7/pth.h.in --- pth-2.0.7-orig/pth.h.in 2006-06-08 17:54:02 +0000 +++ pth-2.0.7/pth.h.in 2006-12-18 16:29:22 +0000 @@ -40,10 +40,10 @@ /* essential headers */ #include /* for ssize_t, off_t */ -#include /* for struct timespec */ +@INCLUDE_FOR_TIMESPEC@ #include /* for struct timeval */ #include /* for sockaddr */ -#include /* for sigset_t */ +@INCLUDE_FOR_SIGSET_T@ @EXTRA_INCLUDE_SYS_SELECT_H@ /* fallbacks for essential typedefs */ diff -uN pth-2.0.7-orig/pth_acdef.h.in pth-2.0.7/pth_acdef.h.in --- pth-2.0.7-orig/pth_acdef.h.in 2006-06-08 17:54:02 +0000 +++ pth-2.0.7/pth_acdef.h.in 2006-12-20 14:29:08 +0000 @@ -81,6 +81,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_PATHS_H +/* Define to 1 if you have the header file. */ +#undef HAVE_FEATURES_H + /* define if typedef pid_t exists in header sys/types.h */ #undef HAVE_PID_T @@ -153,6 +156,9 @@ /* define if typedef ssize_t exists in header sys/types.h */ #undef HAVE_SSIZE_T +/* define if pre-processor define SIGCHLD exists in header signal.h */ +#undef HAVE_SIGCHLD + /* define if attribute ss_base exists in struct sigaltstack from header sys/signal.h */ #undef HAVE_SS_BASE @@ -168,7 +174,9 @@ #undef HAVE_STDARG_H /* Define to 1 if you have the header file. */ +#ifndef HAVE_STDINT_H #undef HAVE_STDINT_H +#endif /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H @@ -188,6 +196,9 @@ /* define if exists "struct timespec" */ #undef HAVE_STRUCT_TIMESPEC +/* define to simulate use of pipes instead of using pipe() */ +#undef SIMULATE_PIPE + /* Define to 1 if you have the `swapcontext' function. */ #undef HAVE_SWAPCONTEXT diff -uN pth-2.0.7-orig/pth_high.c pth-2.0.7/pth_high.c --- pth-2.0.7-orig/pth_high.c 2006-06-08 17:54:02 +0000 +++ pth-2.0.7/pth_high.c 2006-12-19 11:08:32 +0000 @@ -235,10 +235,12 @@ sigaction(SIGINT, &sa_ign, &sa_int); sigaction(SIGQUIT, &sa_ign, &sa_quit); +#ifdef HAVE_SIGCHLD /* block SIGCHLD signal */ sigemptyset(&ss_block); sigaddset(&ss_block, SIGCHLD); pth_sc(sigprocmask)(SIG_BLOCK, &ss_block, &ss_old); +#endif /* fork the current process */ pstat = -1; @@ -250,7 +252,9 @@ /* restore original signal dispositions and execute the command */ sigaction(SIGINT, &sa_int, NULL); sigaction(SIGQUIT, &sa_quit, NULL); +#ifdef HAVE_SIGCHLD pth_sc(sigprocmask)(SIG_SETMASK, &ss_old, NULL); +#endif /* stop the Pth scheduling */ pth_scheduler_kill(); @@ -270,7 +274,9 @@ /* restore original signal dispositions and execute the command */ sigaction(SIGINT, &sa_int, NULL); sigaction(SIGQUIT, &sa_quit, NULL); +#ifdef HAVE_SIGCHLD pth_sc(sigprocmask)(SIG_SETMASK, &ss_old, NULL); +#endif /* return error or child process result code */ return (pid == -1 ? -1 : pstat); diff -uN pth-2.0.7-orig/pth_mctx.c pth-2.0.7/pth_mctx.c --- pth-2.0.7-orig/pth_mctx.c 2006-06-08 17:54:02 +0000 +++ pth-2.0.7/pth_mctx.c 2006-12-19 10:38:54 +0000 @@ -459,7 +459,9 @@ * return just -1. Very useful, yeah... */ +#ifdef HAVE_FEATURES_H #include +#endif intern int pth_mctx_set( pth_mctx_t *mctx, void (*func)(void), char *sk_addr_lo, char *sk_addr_hi) @@ -476,6 +478,9 @@ #elif defined(__GNU_LIBRARY__) && defined(__i386__) mctx->jb[0].__jmpbuf[0].__pc = (char *)func; mctx->jb[0].__jmpbuf[0].__sp = sk_addr_hi; +#elif defined(__DJGPP__) + mctx->jb[0].__eip = (unsigned long) func; + mctx->jb[0].__esp = (unsigned long) sk_addr_hi; #else #error "Unsupported Linux (g)libc version and/or platform" #endif diff -uN pth-2.0.7-orig/pth_p.h.in pth-2.0.7/pth_p.h.in --- pth-2.0.7-orig/pth_p.h.in 2006-06-08 17:54:02 +0000 +++ pth-2.0.7/pth_p.h.in 2006-12-19 10:33:30 +0000 @@ -42,7 +42,6 @@ #include #include #include -#include /* library version */ #define _PTH_VERS_C_AS_HEADER_ diff -uN pth-2.0.7-orig/pth_sched.c pth-2.0.7/pth_sched.c --- pth-2.0.7-orig/pth_sched.c 2006-06-08 17:54:02 +0000 +++ pth-2.0.7/pth_sched.c 2006-12-20 14:17:06 +0000 @@ -51,12 +51,17 @@ intern int pth_scheduler_init(void) { /* create the internal signal pipe */ +#if !defined(SIMULATE_PIPE) if (pipe(pth_sigpipe) == -1) return pth_error(FALSE, errno); if (pth_fdmode(pth_sigpipe[0], PTH_FDMODE_NONBLOCK) == PTH_FDMODE_ERROR) return pth_error(FALSE, errno); if (pth_fdmode(pth_sigpipe[1], PTH_FDMODE_NONBLOCK) == PTH_FDMODE_ERROR) return pth_error(FALSE, errno); +#else + if (sympipe_open(pth_sigpipe) == -1) + return pth_error(FALSE, errno); +#endif /* initialize the essential threads */ pth_sched = NULL; @@ -118,8 +123,12 @@ pth_scheduler_drop(); /* remove the internal signal pipe */ +#if !defined(SIMULATE_PIPE) close(pth_sigpipe[0]); close(pth_sigpipe[1]); +#else + sympipe_close(pth_sigpipe[0]); // there isn't a pair in the simulated pipe +#endif return; } @@ -598,10 +607,14 @@ } /* clear pipe and let select() wait for the read-part of the pipe */ +#if !defined(SIMULATE_PIPE) while (pth_sc(read)(pth_sigpipe[0], minibuf, sizeof(minibuf)) > 0) ; FD_SET(pth_sigpipe[0], &rfds); if (fdmax < pth_sigpipe[0]) fdmax = pth_sigpipe[0]; +#else + while (sympipe_read(pth_sigpipe[0], minibuf, sizeof(minibuf)) > 0) ; +#endif /* replace signal actions for signals we've to catch for events */ for (sig = 1; sig < PTH_NSIG; sig++) { @@ -646,11 +659,13 @@ } } +#if !defined(SIMULATE_PIPE) /* if the internal signal pipe was used, adjust the select() results */ if (!dopoll && rc > 0 && FD_ISSET(pth_sigpipe[0], &rfds)) { FD_CLR(pth_sigpipe[0], &rfds); rc--; } +#endif /* if an error occurred, avoid confusion in the cleanup loop */ if (rc <= 0) { @@ -848,7 +863,11 @@ /* write signal to signal pipe in order to awake the select() */ c = (int)sig; +#if !defined(SIMULATE_PIPE) pth_sc(write)(pth_sigpipe[1], &c, sizeof(char)); +#else + sympipe_write(pth_sigpipe[1], &c, sizeof(char)); +#endif return; } diff -uN pth-2.0.7-orig/pth_sympipe.c pth-2.0.7/pth_sympipe.c --- pth-2.0.7-orig/pth_sympipe.c 1970-01-01 00:00:00 +0000 +++ pth-2.0.7/pth_sympipe.c 2006-12-20 20:03:30 +0000 @@ -0,0 +1,202 @@ +/* +** GNU Pth - The GNU Portable Threads +** Copyright (c) 1999-2006 Ralf S. Engelschall +** This file copyright (c) 2006 Gordon Schumacher +** +** 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_sympipe.c: Simulate a pipe using a memory buffer for platforms +** that do not support them (currently DJGPP) +*/ + /* ``The difficulty of communicating does + not alleviate its necessity.'' + -- Albert Cahn */ + +#include +#include +#include +#include +#include "pth_p.h" + +#define MAX_PIPE 16 // Maximum number of pseudo-pipes +#define DEF_PIPE_ALLOC 512 // Default size of pipe buffer, in bytes + +#ifndef MIN +#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) +#endif + +typedef struct +{ + char* buf; + char* start; + char* end; + ssize_t buflen; +} __pipedef; + +static __pipedef pipes[MAX_PIPE]; + +/* Emulate a pipe using a buffer in memory */ +/* Note that you cannot treat it as halves */ +intern int sympipe_open(int pipedes[2]) +{ + int i; + for (i = 0; i < MAX_PIPE; i++) + { + if (pipes[i].buf == NULL) + { + pipedes[0] = pipedes[1] = i; + pipes[i].start = pipes[i].end = pipes[i].buf = (char*) malloc(DEF_PIPE_ALLOC); + if (pipes[i].buf == NULL) + { + errno = ENOMEM; + return -1; + } + pipes[i].buflen = DEF_PIPE_ALLOC; + return 0; + } + } + errno = EMFILE; + return -1; +} + + +intern int sympipe_close(int pd) +{ + if (pipes[pd].buf == NULL) + { + errno = EBADF; + return -1; + } + free(pipes[pd].buf); + pipes[pd].buf = NULL; + return 0; +} + + +intern ssize_t sympipe_read(int pd, void *buffer, size_t length) +{ + ssize_t actlength; + + if (pipes[pd].buf == NULL) + { + errno = EBADF; + return -1; + } + if (pipes[pd].start == pipes[pd].end) + return 0; + if (pipes[pd].end > pipes[pd].start) + { + actlength = MIN(length, pipes[pd].end - pipes[pd].start); + memcpy(buffer, pipes[pd].start, actlength); + pipes[pd].start += actlength; + } + else + { + ssize_t firstlength; + ssize_t secondlength = 0; + + firstlength = MIN(length, (pipes[pd].buf + pipes[pd].buflen) - pipes[pd].start); + if (length > firstlength) + secondlength = MIN(length - firstlength, pipes[pd].end - pipes[pd].buf); + actlength = firstlength + secondlength; + memcpy(buffer, pipes[pd].start, firstlength); + if (secondlength > 0) + { + memcpy((char*) buffer + firstlength, pipes[pd].buf, secondlength); + pipes[pd].start = pipes[pd].buf + secondlength; + } + else + pipes[pd].start += firstlength; + } + if (pipes[pd].start == pipes[pd].end) + pipes[pd].start = pipes[pd].end = pipes[pd].buf; + return actlength; +} + + +intern int sympipe_write(int pd, const void *buffer, unsigned length) +{ + ssize_t firstlength; + ssize_t secondlength; + + if (pipes[pd].buf == NULL) + { + errno = EBADF; + return -1; + } + if (length == 0) + return 0; + + do + { + secondlength = 0; + // Get our transfer lengths + if (pipes[pd].end >= pipes[pd].start) + { + firstlength = MIN(length, (pipes[pd].buf + pipes[pd].buflen) - pipes[pd].end); + if (firstlength < length) + secondlength = MIN(length - firstlength, pipes[pd].start - pipes[pd].buf); + } + else + firstlength = MIN(length, pipes[pd].start - pipes[pd].end); + + // Reallocate if it won't fit + if (firstlength + secondlength < length) + { + ssize_t newbuflen = MAX(length * 2, pipes[pd].buflen * 2); + ssize_t datalen; + char* newbuf = (char*) malloc(newbuflen); + + if (pipes[pd].end >= pipes[pd].start) + { + datalen = pipes[pd].end - pipes[pd].start; + memcpy(newbuf, pipes[pd].start, datalen); + } + else + { + datalen = (pipes[pd].buf + pipes[pd].buflen) - pipes[pd].start; + memcpy(newbuf, pipes[pd].start, datalen); + memcpy(newbuf + datalen, pipes[pd].buf, pipes[pd].end - pipes[pd].buf); + datalen += pipes[pd].end - pipes[pd].buf; + } + free(pipes[pd].buf); + pipes[pd].buf = newbuf; + pipes[pd].start = pipes[pd].buf; + pipes[pd].end = pipes[pd].start + datalen; + pipes[pd].buflen = newbuflen; + } + } while (firstlength + secondlength < length); + + // Now copy it in + memcpy(pipes[pd].end, buffer, firstlength); + if (secondlength > 0) + { + memcpy(pipes[pd].buf, (char*) buffer + firstlength, secondlength); + pipes[pd].end = pipes[pd].buf + secondlength; + } + else + pipes[pd].end += firstlength; + + return (int) length; +} + diff -uN pth-2.0.7-orig/pthread.h.in pth-2.0.7/pthread.h.in --- pth-2.0.7-orig/pthread.h.in 2006-06-08 17:54:04 +0000 +++ pth-2.0.7/pthread.h.in 2006-12-18 16:30:56 +0000 @@ -111,8 +111,8 @@ #include /* for ssize_t */ #include /* for struct timeval */ #include /* for sockaddr */ -#include /* for sigset_t */ -#include /* for struct timespec */ +@INCLUDE_FOR_SIGSET_T@ +@INCLUDE_FOR_TIMESPEC@ #include /* for off_t */ @EXTRA_INCLUDE_SYS_SELECT_H@