Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 19 Nov 2009 12:02:30 -0500
From:      John Baldwin <jhb@freebsd.org>
To:        Daniel Eischen <deischen@freebsd.org>
Cc:        threads@freebsd.org
Subject:   Re: Using pthread_once() in libc
Message-ID:  <200911191202.30738.jhb@freebsd.org>
In-Reply-To: <Pine.GSO.4.64.0911191143300.8401@sea.ntplx.net>
References:  <200911191030.14151.jhb@freebsd.org> <Pine.GSO.4.64.0911191143300.8401@sea.ntplx.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thursday 19 November 2009 11:48:54 am Daniel Eischen wrote:
> On Thu, 19 Nov 2009, John Baldwin wrote:
> 
> > I would like to provide a pthread_once()-like facility in libc that library
> > bits can use to initialize data safely rather than trying to home-roll their
> > own variants (see the recent commit to stdtime in libc).  Ideally what I
> > would like to do is have libc use the "real" pthread_once() when libthr is
> > linked in and fall back to a simple stub without libthr linked in.  I know we
> > already do something like this for _spinlock() and friends.  My question is
> > what is the most correct way to do this?  Should libc grow a new _once()
> > symbol ala _spinlock() that is a weak symbol to a stub version and
> > pthread_once() in thr_once.c would override that, or should there be a
> > _pthread_once() in libc that is a stub in place of the current stub_zero?  I
> > noticed a comment in thr_spinlock.c saying the spinlock stuff is kept for
> > backwards compat.  Does this mean that for the future we would like to expose
> > pthread symbols directly in libc?  Meaning would we rather have libc export a
> > pthread_once() and that ideally libc would be using pthread_mutex_lock/unlock
> > instead of _spinlock/unlock?
> 
> pthread_once() is already a stub in libc that gets overloaded with the
> real thing when libthr is linked.  See libc/gen/_pthread_stubs.c.
> Isn't that what you want or does it not serve your purpose?

Hmm, the libc stub will never run the init routine.  I would like to do
something like this:

Index: stdtime/localtime.c
===================================================================
--- stdtime/localtime.c	(revision 199529)
+++ stdtime/localtime.c	(working copy)
@@ -235,9 +235,8 @@
 
 static char		lcl_TZname[TZ_STRLEN_MAX + 1];
 static int		lcl_is_set;
-static int		gmt_is_set;
+static pthread_once_t	gmt_once = PTHREAD_ONCE_INIT;
 static pthread_rwlock_t	lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER;
-static pthread_mutex_t	gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 char *			tzname[2] = {
 	wildabbr,
@@ -1464,6 +1463,17 @@
 	return tmp;
 }
 
+static void
+gmt_init(void)
+{
+
+#ifdef ALL_STATE
+	gmtptr = (struct state *) malloc(sizeof *gmtptr);
+	if (gmtptr != NULL)
+#endif /* defined ALL_STATE */
+		gmtload(gmtptr);
+}
+
 /*
 ** gmtsub is to gmtime as localsub is to localtime.
 */
@@ -1476,16 +1486,7 @@
 {
 	register struct tm *	result;
 
-	_MUTEX_LOCK(&gmt_mutex);
-	if (!gmt_is_set) {
-#ifdef ALL_STATE
-		gmtptr = (struct state *) malloc(sizeof *gmtptr);
-		if (gmtptr != NULL)
-#endif /* defined ALL_STATE */
-			gmtload(gmtptr);
-		gmt_is_set = TRUE;
-	}
-	_MUTEX_UNLOCK(&gmt_mutex);
+	_pthread_once(&gmt_once, gmt_init);
 	result = timesub(timep, offset, gmtptr, tmp);
 #ifdef TM_ZONE
 	/*


-- 
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911191202.30738.jhb>