From owner-freebsd-threads@FreeBSD.ORG Thu Nov 19 17:02:39 2009 Return-Path: Delivered-To: threads@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B904F10656A6; Thu, 19 Nov 2009 17:02:39 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [65.122.17.42]) by mx1.freebsd.org (Postfix) with ESMTP id 7488F8FC08; Thu, 19 Nov 2009 17:02:39 +0000 (UTC) Received: from bigwig.baldwin.cx (66.111.2.69.static.nyinternet.net [66.111.2.69]) by cyrus.watson.org (Postfix) with ESMTPSA id 2462246B35; Thu, 19 Nov 2009 12:02:39 -0500 (EST) Received: from jhbbsd.hudson-trading.com (unknown [209.249.190.8]) by bigwig.baldwin.cx (Postfix) with ESMTPA id 6BB1A8A021; Thu, 19 Nov 2009 12:02:38 -0500 (EST) From: John Baldwin To: Daniel Eischen Date: Thu, 19 Nov 2009 12:02:30 -0500 User-Agent: KMail/1.9.7 References: <200911191030.14151.jhb@freebsd.org> In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200911191202.30738.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.0.1 (bigwig.baldwin.cx); Thu, 19 Nov 2009 12:02:38 -0500 (EST) X-Virus-Scanned: clamav-milter 0.95.1 at bigwig.baldwin.cx X-Virus-Status: Clean X-Spam-Status: No, score=-2.5 required=4.2 tests=AWL,BAYES_00,RDNS_NONE autolearn=no version=3.2.5 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on bigwig.baldwin.cx Cc: threads@freebsd.org Subject: Re: Using pthread_once() in libc X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 19 Nov 2009 17:02:39 -0000 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