Bill Allombert on Tue, 04 Oct 2005 19:20:55 +0200


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

Re: PARI and POSIX threads


On Thu, Sep 29, 2005 at 04:35:59PM +0200, Bill Allombert wrote:
> Since the best way is to try, here a patch that seems to allow to run
> concurrent PARI threads assuming thread-local storage is supported:
> 
> This:
> 1) add a THREAD macro that default to the empty string
> 2) mark avma,top and bot with THREAD (as a storage class).
> 3) add 2 public functions pari_thread_init() and pari_thread_close().
> 
> As such the patch does absolutly nothing until you compile PARI
> with -DTHREAD=__thread on a system that support thread-local storage.
> (You probably also want -D_REENTRANT).

Here a new patch that add a --enable-tls flag to configure
that do the equivalent of -DTHREAD=__thread, so is easier to use.

This patch also try to address the problem of gpi, geuler and glog2 that
are automatically updated. If gpi is updated and the old gpi is freed at
the same time another thread read gpi, this will cause a memory
corruption. (This is an unlikely event, though.)

The simplest way to do that is to declare gpi thread-local. This way, 
each thread has its own private gpi variables and will not break other
threads. This patch does this.  The drawback being that gpi will be
recomputed in each thread (if necessary). On the other hand, this avoid
linking libpari with libpthread.

For that purpose, I have added a flag to constpi to tell it to free
gpi. One alternative would be to use a negative precision instead
(constpi(-1) --> free gpi), that would avoid breaking the API.
pari_thread_close() automatically free the local gpi.

Cheers,
Bill.
? amd64
? patch
? thread
? thread.c
Index: config/get_config_options
===================================================================
RCS file: /home/cvs/pari/config/get_config_options,v
retrieving revision 1.27
diff -u -r1.27 get_config_options
--- config/get_config_options	23 Sep 2005 10:53:03 -0000	1.27
+++ config/get_config_options	4 Oct 2005 15:02:03 -0000
@@ -107,6 +107,9 @@
   --with-fltk) with_fltk=yes ;;
   --with-fltk=*)
       with_fltk=`echo "$1" | sed -e 's/[-a-z]*=//'` ;;
+  --enable-tls) enable_tls=yes;;
+  --enable-tls=*) enable_tls=`echo "$1" | sed -e 's/[-a-z]*=//'` ;;
+  --disable-tls) enable_tls=no;;
   *) echo "*** Unrecognized option $1." >&2; error=true;;
   esac
   shift
@@ -146,6 +149,7 @@
 Additional developer options:
   -g              creates debugging version (in Oxxx.dbg)
   -pg             creates profiling version (in Oxxx.prf)
+  --enable-tls	  (*experimental*) enable thread-local stack
 
 Installation directories:
   --prefix=<dir>        install files in <dir> (default $prefix)
Index: config/paricfg.h.SH
===================================================================
RCS file: /home/cvs/pari/config/paricfg.h.SH,v
retrieving revision 1.24
diff -u -r1.24 paricfg.h.SH
--- config/paricfg.h.SH	6 Jun 2005 13:55:10 -0000	1.24
+++ config/paricfg.h.SH	4 Oct 2005 15:02:03 -0000
@@ -198,4 +198,8 @@
 yes) echo '#define HAS_STAT' >> $file;;
 esac
 
+case $enable_tls in
+yes) echo '#define ENABLE_TLS' >> $file;;
+esac
+
 echo '#endif' >> $file
Index: src/basemath/trans1.c
===================================================================
RCS file: /home/cvs/pari/src/basemath/trans1.c,v
retrieving revision 1.187
diff -u -r1.187 trans1.c
--- src/basemath/trans1.c	3 Oct 2005 17:18:46 -0000	1.187
+++ src/basemath/trans1.c	4 Oct 2005 15:02:03 -0000
@@ -88,11 +88,20 @@
 }
 /* Gauss - Brent-Salamin AGM iteration */
 void
-constpi(long prec)
+constpi(long prec, long flag)
 {
   GEN A, B, C, tmppi;
   long i, G;
   pari_sp av, av2;
+  if (flag)
+  { 
+    if (gpi) 
+    {
+      gunclone(gpi);
+      gpi=NULL;
+    }
+    return;
+  }
 
   if (gpi && lg(gpi) >= prec) return;
 
@@ -125,7 +134,7 @@
 mppi(long prec)
 {
   GEN x = cgetr(prec);
-  constpi(prec); affrr(gpi,x); return x;
+  constpi(prec,0); affrr(gpi,x); return x;
 }
 
 /* Pi * 2^n */
@@ -156,11 +165,20 @@
 /********************************************************************/
 
 void
-consteuler(long prec)
+consteuler(long prec, long flag)
 {
   GEN u,v,a,b,tmpeuler;
   long l, n1, n, k, x;
   pari_sp av1, av2;
+  if (flag)
+  {
+    if (geuler)
+    {
+      gunclone(geuler);
+      geuler=NULL;
+    }
+    return;
+  }
 
   if (geuler && lg(geuler) >= prec) return;
 
@@ -222,7 +240,7 @@
 mpeuler(long prec)
 {
   GEN x = cgetr(prec);
-  consteuler(prec); affrr(geuler,x); return x;
+  consteuler(prec,0); affrr(geuler,x); return x;
 }
 
 /********************************************************************/
@@ -1589,12 +1607,21 @@
 }
 /* cf logagmr_abs(). Compute Pi/2agm(1, 4/2^n) ~ log(2^n) = n log(2) */
 GEN
-constlog2(long prec)
+constlog2(long prec, long flag)
 {
-  static GEN glog2 = NULL;
+  static THREAD GEN glog2 = NULL;
   pari_sp av;
   long l, n;
   GEN y, tmplog2;
+  if (flag)
+  {
+    if (glog2)
+    {
+      gunclone(glog2);
+      glog2=NULL;
+    }
+    return NULL;
+  }
 
   if (glog2 && lg(glog2) >= prec) return glog2;
 
@@ -1613,7 +1640,7 @@
 mplog2(long prec)
 {
   GEN x = cgetr(prec);
-  affrr(constlog2(prec), x); return x;
+  affrr(constlog2(prec,0), x); return x;
 }
 
 /*return log(|x|), assuming x != 0 */
Index: src/headers/paricom.h
===================================================================
RCS file: /home/cvs/pari/src/headers/paricom.h,v
retrieving revision 1.85
diff -u -r1.85 paricom.h
--- src/headers/paricom.h	12 Jul 2005 20:43:40 -0000	1.85
+++ src/headers/paricom.h	4 Oct 2005 15:02:03 -0000
@@ -89,7 +89,7 @@
 /* Common global variables: */
 extern ulong DEBUGFILES, DEBUGLEVEL, DEBUGMEM, precdl;
 extern long  *ordvar;
-extern GEN   bernzone,gpi,geuler;
+extern THREAD GEN  bernzone,gpi,geuler;
 extern GEN   polvar,*polun,*polx,primetab;
 extern GEN   gen_m1,gen_1,gen_2,ghalf,gi,gen_0,gnil;
 
Index: src/headers/paridecl.h
===================================================================
RCS file: /home/cvs/pari/src/headers/paridecl.h,v
retrieving revision 1.514
diff -u -r1.514 paridecl.h
--- src/headers/paridecl.h	3 Oct 2005 15:32:31 -0000	1.514
+++ src/headers/paridecl.h	4 Oct 2005 15:02:03 -0000
@@ -1198,6 +1198,8 @@
 void    err_leave(void **v);
 GEN     forcecopy(GEN x);
 void    freeall(void);
+void    pari_thread_init(size_t parisize);
+void    pari_thread_close(void);
 GEN     gcopy(GEN x);
 GEN     gcopy_i(GEN x, long lx);
 GEN     gerepile(pari_sp ltop, pari_sp lbot, GEN q);
@@ -1792,8 +1794,9 @@
 GEN     Pi2n(long n, long prec);
 GEN     PiI2(long prec);
 GEN     PiI2n(long n, long prec);
-void    consteuler(long prec);
-void    constpi(long prec);
+void    consteuler(long prec, long flag);
+GEN     constlog2(long prec, long flag);
+void    constpi(long prec, long flag);
 GEN     exp_Ir(GEN x);
 GEN     gcos(GEN x, long prec);
 GEN     gcotan(GEN x, long prec);
Index: src/headers/paristio.h
===================================================================
RCS file: /home/cvs/pari/src/headers/paristio.h,v
retrieving revision 1.30
diff -u -r1.30 paristio.h
--- src/headers/paristio.h	6 Jul 2005 19:12:32 -0000	1.30
+++ src/headers/paristio.h	4 Oct 2005 15:02:03 -0000
@@ -74,7 +74,7 @@
 #define TEXSTYLE_PAREN	2
 #define TEXSTYLE_BREAK	4
 
-extern pari_sp avma,bot,top;
+extern pari_sp THREAD avma,bot,top;
 #define DISABLE_MEMUSED (size_t)-1
 extern size_t memused;
 extern byteptr diffptr;
Index: src/headers/parisys.h
===================================================================
RCS file: /home/cvs/pari/src/headers/parisys.h,v
retrieving revision 1.10
diff -u -r1.10 parisys.h
--- src/headers/parisys.h	1 Sep 2005 17:02:43 -0000	1.10
+++ src/headers/parisys.h	4 Oct 2005 15:02:03 -0000
@@ -57,6 +57,11 @@
 #  define INLINE_IS_STATIC
 #  define INLINE static
 #endif
+#ifdef ENABLE_TLS
+#  define THREAD __thread
+#else
+#  define THREAD
+#endif
 
 #if defined(_WIN32) || defined(__CYGWIN32__)
 /* ANSI C does not allow to longjmp() out of a signal handler, in particular,
Index: src/language/init.c
===================================================================
RCS file: /home/cvs/pari/src/language/init.c,v
retrieving revision 1.272
diff -u -r1.272 init.c
--- src/language/init.c	3 Sep 2005 16:36:12 -0000	1.272
+++ src/language/init.c	4 Oct 2005 15:02:03 -0000
@@ -34,7 +34,7 @@
 ulong   logstyle = logstyle_none;
 GEN     *polun, *polx;
 GEN     gnil, gen_0, gen_1, gen_m1, gen_2, ghalf, polvar, gi;
-GEN     gpi=NULL, geuler=NULL, bernzone=NULL;
+THREAD GEN gpi=NULL, geuler=NULL, bernzone=NULL;
 GEN     primetab; /* private primetable */
 byteptr diffptr;
 char    *current_logfile, *current_psfile, *pari_datadir = NULL;
@@ -48,7 +48,7 @@
 ulong   DEBUGFILES, DEBUGLEVEL, DEBUGMEM, compatible;
 ulong   prec, precdl;
 ulong   init_opts = INIT_JMPm | INIT_SIGm;
-pari_sp bot = 0, top = 0, avma;
+THREAD  pari_sp bot = 0, top = 0, avma;
 size_t memused;
 
 gp_data *GP_DATA = NULL;
@@ -638,6 +638,21 @@
 {
   return gp_init_entrees(new_fun_set? pari_modules: pari_oldmodules,
                          functions_hash, force);
+}
+
+void
+pari_thread_init(size_t parisize)
+{
+  init_stack(parisize);
+}
+
+void
+pari_thread_close(void)
+{
+  free((void *)bot);
+  constpi(0,1);
+  consteuler(0,1);
+  constlog2(0,1);
 }
 
 /* initialize PARI data. You can call pari_addfunctions() first to add other