[Gc] Re[5]: implement GC_get_stack_base by thr_stksegment in solaris

Ivan Maidanski ivmai at mail.ru
Fri Apr 16 03:49:38 PDT 2010


Thu, 15 Apr 2010 10:36:57 +0400 Ivan Maidanski <ivmai at mail.ru>:

> 
> Wed, 14 Apr 2010 17:27:43 +0000 (UTC) Louis Zhuang <louis.zhuang at acm.org>:
> 
> > > It seems a Solaris JDK specific bug. In such situation, we've cached main stack
> > > base in GC_stackbottom @ misc:845, is it safe to assume we only call
> > > GC_get_stack_base once in primordial thread? Following patch is generated
> > > against latest CVS version. Thanks, Louis
> 
> This is a public function so we can't assume it is never called by the user for the main thread. (I can't make a decision myself whether it's ok to ignore the bug or add a workaround (caching+locking) for it.)

It's possible to use caching here w/o locking.

> 
> > > 
> > Pls apply following patch with ANSI C guard the same as solaris header.
> > Rgds, Louis
> 
> Is the whole bdwgc really compilable with -D _STRICT_STDC on Solaris? (If not then there is no need for testing _STRICT_STDC/__EXTENSIONS__).

Yes, it works with -D _STRICT_STDC.

> 
> > +++ os_dep.c    2010-04-14 18:25:55.000000000 +0100
> > @@ -1306,6 +1306,31 @@
> > 
> >  #endif /* GC_OPENBSD_THREADS */
> > 
> > +#if defined(GC_SOLARIS_THREADS) \
> > +    && (!defined(_STRICT_STDC) || defined(__EXTENSIONS__))
> 
> I think it's better to have a macro to fall back to the default strategy
> (e.g. NO_THR_STKSEGMENT).

I left only a check for _STRICT_STDC (not a big deal).

> > +
> > +# define HAVE_GET_STACK_BASE

I also defined GC_get_main_stack_base which uses GC_ge_stack_base().

> > ...

I've checked my edition of this patch (with caching to prevent thr_stksegment() double call for the primordial thread).

Bye.

diff -ru CVS/bdwgc/os_dep.c updated/bdwgc/os_dep.c
--- CVS/bdwgc/os_dep.c	2010-03-19 23:21:02.000000000 +0400
+++ updated/bdwgc/os_dep.c	2010-04-16 14:23:30.000000000 +0400
@@ -1140,7 +1140,8 @@
 
 #if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
     && !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) \
-    && !defined(CYGWIN32) && !defined(GC_OPENBSD_THREADS)
+    && !defined(CYGWIN32) && !defined(GC_OPENBSD_THREADS) \
+    && (!defined(GC_SOLARIS_THREADS) || defined(_STRICT_STDC))
 
 ptr_t GC_get_main_stack_base(void)
 {
@@ -1306,6 +1307,69 @@
 
 #endif /* GC_OPENBSD_THREADS */
 
+#if defined(GC_SOLARIS_THREADS) && !defined(_STRICT_STDC)
+
+# include <thread.h>
+# include <signal.h>
+# include <pthread.h>
+
+  /* These variables are used to cache ss_sp value for the primordial   */
+  /* thread (it's better not to call thr_stksegment() twice for this    */
+  /* thread - see JDK bug #4352906).                                    */
+  static pthread_t stackbase_main_self = 0;
+                        /* 0 means stackbase_main_ss_sp value is unset. */
+  static void *stackbase_main_ss_sp = NULL;
+
+  GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
+  {
+    stack_t s;
+    pthread_t self = pthread_self();
+    if (self == stackbase_main_self)
+      {
+        /* If the client calls GC_get_stack_base() from the main thread */
+        /* then just return the cached value.                           */
+        b -> mem_base = stackbase_main_ss_sp;
+        GC_ASSERT(b -> mem_base != NULL);
+        return GC_SUCCESS;
+      }
+
+    if (thr_stksegment(&s)) {
+      /* According to the manual, the only failure error code returned  */
+      /* is EAGAIN meaning "the information is not available due to the */
+      /* thread is not yet completely initialized or it is an internal  */
+      /* thread" - this shouldn't happen here.                          */
+      ABORT("thr_stksegment failed");
+    }
+    /* s.ss_sp holds the pointer to the stack bottom. */
+    GC_ASSERT((void *)&s HOTTER_THAN s.ss_sp);
+
+    if (!stackbase_main_self)
+      {
+        /* Cache the stack base value for the primordial thread (this   */
+        /* is done during GC_init, so there is no race).                */
+        stackbase_main_ss_sp = s.ss_sp;
+        stackbase_main_self = self;
+      }
+
+    b -> mem_base = s.ss_sp;
+    return GC_SUCCESS;
+  }
+
+# define HAVE_GET_STACK_BASE
+
+  /* This is always called from the main thread.  The above             */
+  /* implementation of GC_get_stack_base() requires the latter to be    */
+  /* first called from GC_get_main_stack_base() (to cache the proper    */
+  /* ss_sp value).                                                      */
+  ptr_t GC_get_main_stack_base(void)
+  {
+    struct GC_stack_base sb;
+    GC_get_stack_base(&sb);
+    return (ptr_t)sb.mem_base;
+  }
+
+#endif /* GC_SOLARIS_THREADS */
+
 #ifndef HAVE_GET_STACK_BASE
 /* Retrieve stack base.                                         */
 /* Using the GC_find_limit version is risky.                    */



More information about the Gc mailing list