delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2006/12/21/01:11:06

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: <OF2C14ED08.0F595EC7-ON8725724B.001143D1-8725724B.002187A3@seagate.com>
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
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 <sys/signal.h>
+],[
+sigset_t sst;
+],
+msg="yes"
+,
+msg="no"
+)
+AC_MSG_RESULT([$msg])
+if test ".$msg" = .yes; then
+    INCLUDE_FOR_SIGSET_T="#include <sys/signal.h>    /* for sigset_t
*/"
+else
+    AC_MSG_CHECKING(for sigset_t in signal.h)
+    AC_TRY_COMPILE([
+#include <signal.h>
+],[
+sigset_t sst;
+],
+msg="yes"
+,
+msg="no"
+)
+    AC_MSG_RESULT([$msg])
+    if test ".$msg" = .yes; then
+        INCLUDE_FOR_SIGSET_T="#include <signal.h>        /* 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 <time.h>          /* for struct
timespec */"
+else
+    AC_TRY_COMPILE([
+#include <sys/wtime.h>
+],[
+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 <sys/wtime.h>     /* 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 <unistd.h>
+],[
+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 <sys/types.h>     /* for ssize_t, off_t  */
-#include <time.h>          /* for struct timespec */
+@INCLUDE_FOR_TIMESPEC@
 #include <sys/time.h>      /* for struct timeval  */
 #include <sys/socket.h>    /* for sockaddr        */
-#include <sys/signal.h>    /* 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 <paths.h> header file. */
 #undef HAVE_PATHS_H

+/* Define to 1 if you have the <features.h> 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 <stdint.h> header file. */
+#ifndef HAVE_STDINT_H
 #undef HAVE_STDINT_H
+#endif

 /* Define to 1 if you have the <stdio.h> 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 <features.h>
+#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 <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
-#include <time.h>

 /* 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 <rse AT engelschall DOT com>
+**  This file copyright (c) 2006 Gordon Schumacher <whiplash AT pobox DOT com>
+**
+**  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 <rse AT engelschall DOT com>.
+**
+**  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 <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#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 <sys/types.h>     /* for ssize_t         */
 #include <sys/time.h>      /* for struct timeval  */
 #include <sys/socket.h>    /* for sockaddr        */
-#include <sys/signal.h>    /* for sigset_t        */
-#include <time.h>          /* for struct timespec */
+@INCLUDE_FOR_SIGSET_T@
+@INCLUDE_FOR_TIMESPEC@
 #include <unistd.h>        /* for off_t           */
 @EXTRA_INCLUDE_SYS_SELECT_H@


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019