Add an internal _once() method. This works identical to pthread_once(3)

with the additional property that it is safe for routines in libc to use
in both single-threaded and multi-threaded processes.  Multi-threaded
processes use the pthread_once() implementation from the threading library
while single-threaded processes use a simplified "stub" version internal
to libc.  The libc stub-version of pthread_once() now also uses the
simplified "stub" version as well instead of being a nop.

Reviewed by:	deischen, Matthew Fleming @ Isilon
Suggested by:	alc
MFC after:	1 week
This commit is contained in:
John Baldwin 2009-11-20 19:19:51 +00:00
parent 908d88b03b
commit 5bcfe82e47
4 changed files with 78 additions and 2 deletions

View File

@ -5,7 +5,8 @@
.PATH: ${.CURDIR}/${MACHINE_ARCH}/gen ${.CURDIR}/gen
SRCS+= __getosreldate.c __xuname.c \
_pthread_stubs.c _rand48.c _spinlock_stub.c _thread_init.c \
_once_stub.c _pthread_stubs.c _rand48.c _spinlock_stub.c \
_thread_init.c \
alarm.c arc4random.c assert.c basename.c check_utility_compat.c \
clock.c closedir.c confstr.c \
crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \

67
lib/libc/gen/_once_stub.c Normal file
View File

@ -0,0 +1,67 @@
/*-
* Copyright (c) 2009 Advanced Computing Technologies LLC
* Written by: John H. Baldwin <jhb@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <pthread.h>
#include "un-namespace.h"
#include "libc_private.h"
/*
* This implements pthread_once() for the single-threaded case. It is
* non-static so that it can be used by _pthread_stubs.c.
*/
int
_libc_once(pthread_once_t *once_control, void (*init_routine)(void))
{
if (once_control->state == PTHREAD_DONE_INIT)
return (0);
init_routine();
once_control->state = PTHREAD_DONE_INIT;
return (0);
}
/*
* This is the internal interface provided to libc. It will use
* pthread_once() from the threading library in a multi-threaded
* process and _libc_once() for a single-threaded library. Because
* _libc_once() uses the same ABI for the values in the pthread_once_t
* structure as the threading library, it is safe for a process to
* switch from _libc_once() to pthread_once() when threading is
* enabled.
*/
int
_once(pthread_once_t *once_control, void (*init_routine)(void))
{
if (__isthreaded)
return (_pthread_once(once_control, init_routine));
return (_libc_once(once_control, init_routine));
}

View File

@ -105,7 +105,7 @@ pthread_func_entry_t __thr_jtable[PJT_MAX] = {
{PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_LOCK */
{PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_TRYLOCK */
{PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_UNLOCK */
{PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ONCE */
{PJT_DUAL_ENTRY(_libc_once)}, /* PJT_ONCE */
{PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_DESTROY */
{PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_INIT */
{PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_RDLOCK */

View File

@ -34,6 +34,7 @@
#ifndef _LIBC_PRIVATE_H_
#define _LIBC_PRIVATE_H_
#include <sys/_pthreadtypes.h>
/*
* This global flag is non-zero when a process has created one
@ -146,6 +147,13 @@ int _yp_check(char **);
*/
void _init_tls(void);
/*
* Provides pthread_once()-like functionality for both single-threaded
* and multi-threaded applications.
*/
int _once(pthread_once_t *, void (*)(void));
int _libc_once(pthread_once_t *, void (*)(void));
/*
* Set the TLS thread pointer
*/