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