Loic Grenie on Sun, 19 Nov 2006 17:35:16 +0100


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Kludge for cygwin


    Hi,

    I've observed that gp's ?? and ??? commands are very slow under cygwin
  when gp uses more than half of the RAM. The reason is the popen()
  function that uses vfork() that copies memory (contrary to the UNIX
  semantic) => swap. I've designed a kludge that should work as long as
  it is not overused. It is very mean, but should fit the bill.

    Loïc
Index: src/language/es.c
===================================================================
RCS file: /home/cvs/pari/src/language/es.c,v
retrieving revision 1.229
diff -c -r1.229 es.c
*** src/language/es.c	14 Oct 2006 06:05:56 -0000	1.229
--- src/language/es.c	19 Nov 2006 16:05:08 -0000
***************
*** 2611,2616 ****
--- 2611,2654 ----
    return file;
  }
  
+ #ifdef __CYGWIN32__
+ struct pfd {
+   int pid;
+   int fd;
+ } *pfds = NULL;
+ static int numpfds = 0, maxpfds = 0;
+ 
+ static int
+ _pclose(FILE *f)
+ {
+   int i;
+   struct pfd *ppfd;
+   for (i = 0, ppfd = pfds; i < numpfds; i++, ppfd++)
+     if (ppfd->fd == fileno(f))
+       break;
+   if (i < numpfds)
+     kill(ppfd->pid, SIGTERM);
+   else
+     ppfd = NULL;
+   fclose(f);
+   if (ppfd && kill(ppfd->pid, SIGCONT) == 0) {
+     sleep(5);
+     kill(ppfd->pid, SIGKILL);
+   }
+   if (ppfd)
+   {
+     while (++i < numpfds)
+     {
+       *ppfd = ppfd[1];
+       ppfd++;
+     }
+     numpfds--;
+   }
+   return 0;
+ }
+ #define pclose _pclose
+ #endif
+ 
  static void
  pari_kill_file(pariFILE *f)
  {
***************
*** 2635,2640 ****
--- 2673,2682 ----
    gpfree(f);
  }
  
+ #ifdef __CYGWIN32__
+ #undef pclose
+ #endif
+ 
  void
  pari_fclose(pariFILE *f)
  {
***************
*** 2763,2768 ****
--- 2805,2869 ----
    return 1;
  }
  
+ #ifdef __CYGWIN32__
+ #include <process.h>
+ static FILE *
+ _popen(char *cmd, char *mode)
+ {
+   int fd[2];
+ 
+   if (!pipe(fd)) {
+     char *str, *p, *q;
+     int pid;
+ 
+     str = gpmalloc(2*strlen(cmd)+64);
+     strcpy(str, "eval \"");
+     for (p = str+strlen(str), q = cmd; *q; )
+     {
+       if (*q == '$' || *q == '`' || *q == '"')
+ 	*p++ = '\\';
+       *p++ = *q++;
+     }
+     if (*mode == 'r')
+     {
+       sprintf(p, "\" >&%d %d>&-", fd[1], fd[0]);
+       if (fd[1] != 1)
+ 	sprintf(p + strlen(p), " %d>&-", fd[1]);
+     }
+     else
+     {
+       sprintf(p, "\" <&%d %d>&-", fd[0], fd[1]);
+       if (fd[0] != 0)
+ 	sprintf(p + strlen(p), " %d>&-", fd[0]);
+     }
+     pid = spawnlp(_P_NOWAIT, "bash", "bash", "-c", str, NULL);
+     gpfree(str);
+     if (!pfds)
+     {
+       maxpfds = 10;
+       pfds = (struct pfd *)gpmalloc(maxpfds*sizeof(struct pfd));
+     }
+     else if (numpfds == maxpfds)
+     {
+       maxpfds += 10;
+       pfds = (struct pfd *)gprealloc(pfds, maxpfds*sizeof(struct pfd));
+     }
+     pfds[numpfds].pid = pid;
+     pfds[numpfds].fd = fd[*mode == 'w'];
+     if (*mode == 'r') {
+ 	close(fd[1]);
+ 	return fdopen(fd[0], "r");
+     }
+     else {
+ 	close(fd[0]);
+ 	return fdopen(fd[1], "w");
+     }
+   }
+   return NULL;
+ }
+ #define popen _popen
+ #endif
+ 
  pariFILE *
  try_pipe(char *cmd, int fl)
  {
***************
*** 2800,2805 ****
--- 2901,2910 ----
  #endif
  }
  
+ #ifdef __CYGWIN32__
+ #undef popen
+ #endif
+ 
  void
  os_close(long fd)
  {