changeset 3864:2ae506652d11

PSARC 2007/129 thr_keycreate_once 6513516 double checked locking code needs a memory barrier
author raf
date Tue, 20 Mar 2007 17:29:57 -0700
parents d56571426115
children 6dfee3b4c9ff
files usr/src/cmd/dcs/sparc/sun4u/dcs_ses.c usr/src/cmd/nscd/nscd_switch.c usr/src/cmd/sgs/libelf/Makefile.targ usr/src/cmd/sgs/libelf/common/error.c usr/src/head/pthread.h usr/src/head/thread.h usr/src/lib/common/inc/c_synonyms.h usr/src/lib/libc/inc/libc.h usr/src/lib/libc/inc/mtlib.h usr/src/lib/libc/inc/priv_private.h usr/src/lib/libc/inc/synonyms.h usr/src/lib/libc/inc/thr_uberdata.h usr/src/lib/libc/port/gen/crypt.c usr/src/lib/libc/port/gen/getauxv.c usr/src/lib/libc/port/gen/getenv.c usr/src/lib/libc/port/gen/nss_common.c usr/src/lib/libc/port/gen/nss_dbdefs.c usr/src/lib/libc/port/gen/privlib.c usr/src/lib/libc/port/gen/tsdalloc.c usr/src/lib/libc/port/mapfile-vers usr/src/lib/libc/port/threads/pthread.c usr/src/lib/libc/port/threads/rtsched.c usr/src/lib/libc/port/threads/tdb_agent.c usr/src/lib/libc/port/threads/tsd.c usr/src/lib/libcrypt/common/des_crypt.c usr/src/lib/libexacct/common/exacct_ops.c usr/src/lib/libgen/common/bgets.c usr/src/lib/libgen/common/bufsplit.c usr/src/lib/libgen/common/pathfind.c usr/src/lib/libgen/common/reg_compile.c usr/src/lib/libgen/common/reg_step.c usr/src/lib/libnsl/common/common.c usr/src/lib/libnsl/netdir/netdir.c usr/src/lib/libnsl/netselect/netselect.c usr/src/lib/libnsl/nis/gen/nis_callback.c usr/src/lib/libnsl/nis/gen/nis_groups.c usr/src/lib/libnsl/nis/gen/nis_perror.c usr/src/lib/libnsl/nis/gen/nis_subr.c usr/src/lib/libnsl/nsl/_errlst.c usr/src/lib/libnsl/rpc/clnt_perror.c usr/src/lib/libnsl/rpc/clnt_simple.c usr/src/lib/libnsl/rpc/clnt_vc.c usr/src/lib/libnsl/rpc/inet_ntoa.c usr/src/lib/libnsl/rpc/key_call.c usr/src/lib/libnsl/rpc/mt_misc.c usr/src/lib/libnsl/rpc/rpc_generic.c usr/src/lib/libnsl/rpc/rpc_soc.c usr/src/lib/libnsl/rpc/rpcsec_gss_if.c usr/src/lib/libpool/common/pool.c usr/src/lib/libproc/common/Pcontrol.c usr/src/lib/libresolv2/common/irs/gai_strerror.c usr/src/lib/libresolv2/common/irs/irs_data.c usr/src/lib/libsasl/lib/common.c usr/src/lib/libscf/common/error.c usr/src/lib/libsocket/inet/ether_addr.c usr/src/lib/libtnfprobe/probe_cntl.c usr/src/lib/libuutil/common/uu_misc.c usr/src/lib/rpcsec_gss/rpcsec_gss.c
diffstat 58 files changed, 704 insertions(+), 755 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/dcs/sparc/sun4u/dcs_ses.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/cmd/dcs/sparc/sun4u/dcs_ses.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,9 +18,10 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -59,6 +59,7 @@
 
 #ifdef DCS_MULTI_THREAD
 #include <thread.h>
+#include <pthread.h>
 #else /* DCS_MULTI_THREAD */
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -96,8 +97,7 @@
  * session information.
  */
 #ifdef DCS_MULTI_THREAD
-thread_key_t	ses_key;
-static int	thr_key_created = 0;
+thread_key_t	ses_key = THR_ONCE_KEY;
 #else /* DCS_MULTI_THREAD */
 session_t	*ses;
 #endif /* DCS_MULTI_THREAD */
@@ -499,13 +499,7 @@
 {
 #ifdef DCS_MULTI_THREAD
 
-	session_t	*sp;
-	int		thr_err;
-
-
-	thr_err = thr_getspecific(ses_key, (void **)&sp);
-
-	return ((thr_err) ? NULL : sp);
+	return (pthread_getspecific(ses_key));
 
 #else /* DCS_MULTI_THREAD */
 
@@ -777,16 +771,9 @@
 
 	int		thr_err;
 
-
-	if (!thr_key_created) {
-		thr_err = thr_keycreate(&ses_key, NULL);
-
-		if (thr_err) {
-			return (-1);
-		}
-
-		thr_key_created = 1;
-	}
+	thr_err = thr_keycreate_once(&ses_key, NULL);
+	if (thr_err)
+		return (-1);
 
 #endif /* DCS_MULTI_THREAD */
 
--- a/usr/src/cmd/nscd/nscd_switch.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/cmd/nscd/nscd_switch.c	Tue Mar 20 17:29:57 2007 -0700
@@ -18,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -29,6 +30,7 @@
 #include <assert.h>
 #include <unistd.h>
 #include <string.h>
+#include <pthread.h>
 #include <dlfcn.h>
 #include <nss_dbdefs.h>
 #include <exec_attr.h>
@@ -86,9 +88,7 @@
 	return (0);
 }
 
-static thread_key_t loopback_key;
-static mutex_t loopback_key_lock = DEFAULTMUTEX;
-static int loopback_key_created = 0;
+static thread_key_t loopback_key = THR_ONCE_KEY;
 typedef struct lb_key {
 	int		srci;
 	int		dbi;
@@ -99,25 +99,12 @@
 static int
 set_loopback_key(lb_key_t *key) {
 
-	int		rc = 0;
-	lb_key_t	*k;
+	int		rc;
 
-	if (!loopback_key_created) {
-		(void) mutex_lock(&loopback_key_lock);
-		if (!loopback_key_created) {
-			if ((rc = thr_keycreate(&loopback_key,
-					NULL)) == 0)
-				loopback_key_created = 1;
-		}
-		(void) mutex_unlock(&loopback_key_lock);
-	}
-	if (rc == 0) {
-		/* set key if not already set */
-		if (thr_getspecific(loopback_key, (void **)&k) == 0 &&
-				k == NULL) {
-			rc = thr_setspecific(loopback_key, key);
-		}
-	}
+	rc = thr_keycreate_once(&loopback_key, NULL);
+	/* set key if not already set */
+	if (rc == 0 && pthread_getspecific(loopback_key) == NULL)
+		rc = thr_setspecific(loopback_key, key);
 
 	return (rc);
 }
@@ -126,21 +113,14 @@
 get_loopback_key(void) {
 
 	char		*me = "get_loopback_key";
-	int 		rc = 0;
 	lb_key_t	*k = NULL;
 
-	if (!loopback_key_created)
-		return (NULL);
-
-	rc = thr_getspecific(loopback_key, (void **)&k);
+	k = pthread_getspecific(loopback_key);
 
 	_NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
-	(me, "get loopback key rc= %d, key = %p\n", rc, k);
+	(me, "get loopback key, key = %p\n", k);
 
-	if (rc == 0 && k != NULL)
-		return (k);
-
-	return (NULL);
+	return (k);
 }
 
 static void
@@ -148,7 +128,7 @@
 
 	char		*me = "clear_loopback_key";
 
-	if (loopback_key_created && key != 0) {
+	if (loopback_key != THR_ONCE_KEY && key != NULL) {
 		/*
 		 * key->lb_flagp points to the location of the
 		 * flag, check_flag, in the stack where it was
@@ -163,23 +143,14 @@
 	(me, "key %p cleared\n", key);
 }
 
-static thread_key_t initf_key;
-static mutex_t initf_key_lock = DEFAULTMUTEX;
-static int initf_key_created = 0;
+static thread_key_t initf_key = THR_ONCE_KEY;
 
 static int
 set_initf_key(void *pbuf) {
 
-	int		rc = 0;
+	int		rc;
 
-	if (!initf_key_created) {
-		(void) mutex_lock(&initf_key_lock);
-		if (!initf_key_created) {
-			if ((rc = thr_keycreate(&initf_key, NULL)) == 0)
-				initf_key_created = 1;
-		}
-		(void) mutex_unlock(&initf_key_lock);
-	}
+	rc = thr_keycreate_once(&initf_key, NULL);
 	if (rc == 0)
 		rc = thr_setspecific(initf_key, pbuf);
 
@@ -191,20 +162,13 @@
 
 	char		*me = "get_initf_key";
 	void		*pbuf;
-	int 		rc = 0;
 
-	if (!initf_key_created)
-		return (NULL);
-
-	rc = thr_getspecific(initf_key, (void **)&pbuf);
+	pbuf = pthread_getspecific(initf_key);
 
 	_NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
-	(me, "got initf pbuf rc= %d, key = %p\n", rc, pbuf);
+	(me, "got initf pbuf, key = %p\n", pbuf);
 
-	if (rc == 0 && pbuf != NULL)
-		return (pbuf);
-
-	return (NULL);
+	return (pbuf);
 }
 
 static void
@@ -212,8 +176,7 @@
 
 	char		*me = "clear_initf_key";
 
-	if (initf_key_created)
-		(void) thr_setspecific(initf_key, NULL);
+	(void) thr_setspecific(initf_key, NULL);
 
 	_NSCD_LOG(NSCD_LOG_SWITCH_ENGINE, NSCD_LOG_LEVEL_DEBUG)
 	(me, "initf pbuf cleared\n");
--- a/usr/src/cmd/sgs/libelf/Makefile.targ	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/cmd/sgs/libelf/Makefile.targ	Tue Mar 20 17:29:57 2007 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -132,6 +132,8 @@
 
 native:		$(SGSPROTO)/$(DYNLIB)
 
+native :=	CPPFLAGS += -DNATIVE_BUILD
+
 $(SGSPROTO)/$(DYNLIB): \
 		pics .WAIT $$(PICS)
 		$(BUILD.SO)
--- a/usr/src/cmd/sgs/libelf/common/error.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/cmd/sgs/libelf/common/error.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2001-2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -30,14 +30,15 @@
 #pragma weak	elf_errmsg = _elf_errmsg
 #pragma weak	elf_errno = _elf_errno
 
-#include	"syn.h"
-#include	<thread.h>
-#include	<stdlib.h>
-#include	<string.h>
-#include	<stdio.h>
-#include	<libelf.h>
-#include	"msg.h"
-#include	"decl.h"
+#include "syn.h"
+#include <thread.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <libelf.h>
+#include "msg.h"
+#include "decl.h"
 
 #define	ELFERRSHIFT	16
 #define	SYSERRMASK	0xffff
@@ -50,15 +51,48 @@
  */
 static int		_elf_err = 0;
 
-static mutex_t		keylock;
-static mutex_t		buflock;
-static thread_key_t	errkey;
-static thread_key_t	bufkey;
-static int		keyonce = 0;
-static int		bufonce = 0;
-NOTE(DATA_READABLE_WITHOUT_LOCK(keyonce))
-NOTE(DATA_READABLE_WITHOUT_LOCK(bufonce))
+#if !defined(NATIVE_BUILD)
+
+static thread_key_t	errkey = THR_ONCE_KEY;
+static thread_key_t	bufkey = THR_ONCE_KEY;
+
+#else	/* NATIVE_BUILD */
+
+/*
+ * This code is here to enable the building of a native version
+ * of libelf.so when the build machine has not yet been upgraded
+ * to a version of libc that provides thr_keycreate_once().
+ * It should be deleted when solaris_nevada ships.
+ * The code is not MT-safe in a relaxed memory model.
+ */
+
+static thread_key_t	errkey = 0;
+static thread_key_t	bufkey = 0;
 
+int
+thr_keycreate_once(thread_key_t *keyp, void (*destructor)(void *))
+{
+	static mutex_t key_lock = DEFAULTMUTEX;
+	thread_key_t key;
+	int error;
+
+	if (*keyp == 0) {
+		mutex_lock(&key_lock);
+		if (*keyp == 0) {
+			error = thr_keycreate(&key, destructor);
+			if (error) {
+				mutex_unlock(&key_lock);
+				return (error);
+			}
+			*keyp = key;
+		}
+		mutex_unlock(&key_lock);
+	}
+
+	return (0);
+}
+
+#endif	/* NATIVE_BUILD */
 
 extern char *_dgettext(const char *, const char *);
 
@@ -83,31 +117,17 @@
 		return;
 	}
 #endif
-	if (keyonce == 0) {
-		(void) mutex_lock(&keylock);
-		if (keyonce == 0) {
-			(void) thr_keycreate(&errkey, 0);
-			keyonce++;
-		}
-		(void) mutex_unlock(&keylock);
-	}
-
+	(void) thr_keycreate_once(&errkey, 0);
 	(void) thr_setspecific(errkey, (void *)encerr);
 }
 
 int
 _elf_geterr() {
-	intptr_t	rc;
-
 #ifndef	__lock_lint
 	if (thr_main())
 		return (_elf_err);
 #endif
-	if (keyonce == 0)
-		return (0);
-
-	(void) thr_getspecific(errkey, (void **)(&rc));
-	return ((int)rc);
+	return ((uintptr_t)pthread_getspecific(errkey));
 }
 
 const char *
@@ -138,19 +158,9 @@
 		 *
 		 * Each thread has its own private buffer.
 		 */
-		if (bufonce == 0) {
-			(void) mutex_lock(&buflock);
-			if (bufonce == 0) {
-				if (thr_keycreate(&bufkey, free) != 0) {
-					(void) mutex_unlock(&buflock);
-					return (MSG_INTL(EBUG_THRDKEY));
-				}
-				bufonce++;
-			}
-			(void) mutex_unlock(&buflock);
-		}
-
-		(void) thr_getspecific(bufkey, (void **)&buffer);
+		if (thr_keycreate_once(&bufkey, free) != 0)
+			return (MSG_INTL(EBUG_THRDKEY));
+		buffer = pthread_getspecific(bufkey);
 
 		if (!buffer) {
 			if ((buffer = malloc(MAXELFERR)) == 0)
--- a/usr/src/head/pthread.h	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/head/pthread.h	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -130,6 +130,13 @@
 #define	PTHREAD_ONCE_DONE	1
 #define	PTHREAD_ONCE_INIT	{0, 0, 0, PTHREAD_ONCE_NOTDONE}
 
+/*
+ * The key to be created by pthread_key_create_once_np()
+ * must be statically initialized with PTHREAD_ONCE_KEY_NP.
+ * This must be the same as THR_ONCE_KEY in <thread.h>
+ */
+#define	PTHREAD_ONCE_KEY_NP	(pthread_key_t)(-1)
+
 /* barriers */
 #define	PTHREAD_BARRIER_SERIAL_THREAD	-2
 
@@ -232,6 +239,7 @@
 extern void pthread_testcancel(void);
 extern int pthread_equal(pthread_t, pthread_t);
 extern int pthread_key_create(pthread_key_t *, void (*)(void *));
+extern int pthread_key_create_once_np(pthread_key_t *, void (*)(void *));
 extern int pthread_key_delete(pthread_key_t);
 extern int pthread_setspecific(pthread_key_t, const void *);
 extern void *pthread_getspecific(pthread_key_t);
@@ -370,6 +378,7 @@
 extern void pthread_testcancel();
 extern int pthread_equal();
 extern int pthread_key_create();
+extern int pthread_key_create_once_np();
 extern int pthread_key_delete();
 extern int pthread_setspecific();
 extern void *pthread_getspecific();
--- a/usr/src/head/thread.h	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/head/thread.h	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -87,6 +87,7 @@
 extern int thr_setprio(thread_t, int);
 extern int thr_getprio(thread_t, int *);
 extern int thr_keycreate(thread_key_t *, void(*)(void *));
+extern int thr_keycreate_once(thread_key_t *, void(*)(void *));
 extern int thr_setspecific(thread_key_t, void *);
 extern int thr_getspecific(thread_key_t, void **);
 extern size_t thr_min_stack(void);
@@ -109,6 +110,7 @@
 extern int thr_setprio();
 extern int thr_getprio();
 extern int thr_keycreate();
+extern int thr_keycreate_once();
 extern int thr_setspecific();
 extern int thr_getspecific();
 extern size_t thr_min_stack();
@@ -133,6 +135,13 @@
 #define	THR_DAEMON		0x00000100
 
 /*
+ * The key to be created by thr_keycreate_once()
+ * must be statically initialized with THR_ONCE_KEY.
+ * This must be the same as PTHREAD_ONCE_KEY_NP in <pthread.h>
+ */
+#define	THR_ONCE_KEY	(thread_key_t)(-1)
+
+/*
  * The available register states returned by thr_getstate().
  */
 #define	TRS_VALID	0
--- a/usr/src/lib/common/inc/c_synonyms.h	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/common/inc/c_synonyms.h	Tue Mar 20 17:29:57 2007 -0700
@@ -655,6 +655,7 @@
 #define	pthread_getspecific		_pthread_getspecific
 #define	pthread_join			_pthread_join
 #define	pthread_key_create		_pthread_key_create
+#define	pthread_key_create_once_np	_pthread_key_create_once_np
 #define	pthread_key_delete		_pthread_key_delete
 #define	pthread_kill			_pthread_kill
 #define	pthread_mutexattr_destroy	_pthread_mutexattr_destroy
@@ -905,6 +906,7 @@
 #define	thr_getstate			_thr_getstate
 #define	thr_join			_thr_join
 #define	thr_keycreate			_thr_keycreate
+#define	thr_keycreate_once		_thr_keycreate_once
 #define	thr_kill			_thr_kill
 #define	thr_main			_thr_main
 #define	thr_min_stack			_thr_min_stack
--- a/usr/src/lib/libc/inc/libc.h	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/inc/libc.h	Tue Mar 20 17:29:57 2007 -0700
@@ -80,6 +80,7 @@
 extern int _thr_getspecific(thread_key_t key, void **valuep);
 extern int _thr_setspecific(unsigned int key, void *value);
 extern int _thr_keycreate(thread_key_t *pkey, void (*destructor)(void *));
+extern int _thr_keycreate_once(thread_key_t *pkey, void (*destructor)(void *));
 extern void *_pthread_getspecific(thread_key_t);
 extern int _pollsys(struct pollfd *, nfds_t, const timespec_t *,
 	const sigset_t *);
--- a/usr/src/lib/libc/inc/mtlib.h	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/inc/mtlib.h	Tue Mar 20 17:29:57 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -104,6 +104,7 @@
 extern	int	_thr_create(void *, size_t, void *(*)(void *), void *, long,
 			thread_t *);
 extern	int	_thr_keycreate(thread_key_t *, void (*)(void *));
+extern	int	_thr_keycreate_once(thread_key_t *, void (*)(void *));
 extern	int	_thr_setspecific(thread_key_t, void *);
 extern	int	_thr_getspecific(thread_key_t, void **);
 extern	void	*_pthread_getspecific(thread_key_t);
--- a/usr/src/lib/libc/inc/priv_private.h	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/inc/priv_private.h	Tue Mar 20 17:29:57 2007 -0700
@@ -18,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -40,8 +41,8 @@
 extern "C" {
 #endif
 
-#define	LOADPRIVDATA(d)		if ((d = privdata) == NULL) d = __priv_getdata()
-#define	GETPRIVDATA()		(privdata == NULL ? __priv_getdata() : privdata)
+#define	LOADPRIVDATA(d)		d = __priv_getdata()
+#define	GETPRIVDATA()		__priv_getdata()
 #define	LOCKPRIVDATA()		{ \
 					/* Data already allocated */ \
 					(void) lock_data(); \
--- a/usr/src/lib/libc/inc/synonyms.h	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/inc/synonyms.h	Tue Mar 20 17:29:57 2007 -0700
@@ -762,6 +762,7 @@
 #define	pthread_getspecific		_pthread_getspecific
 #define	pthread_join			_pthread_join
 #define	pthread_key_create		_pthread_key_create
+#define	pthread_key_create_once_np	_pthread_key_create_once_np
 #define	pthread_key_delete		_pthread_key_delete
 #define	pthread_kill			_pthread_kill
 #define	pthread_mutexattr_destroy	_pthread_mutexattr_destroy
@@ -1038,6 +1039,7 @@
 #define	thr_getstate		_thr_getstate
 #define	thr_join		_thr_join
 #define	thr_keycreate		_thr_keycreate
+#define	thr_keycreate_once	_thr_keycreate_once
 #define	thr_kill		_thr_kill
 #define	thr_main		_thr_main
 #define	thr_min_stack		_thr_min_stack
--- a/usr/src/lib/libc/inc/thr_uberdata.h	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/inc/thr_uberdata.h	Tue Mar 20 17:29:57 2007 -0700
@@ -1289,6 +1289,11 @@
 extern	int	rw_read_is_held(rwlock_t *);
 extern	int	rw_write_is_held(rwlock_t *);
 
+extern	void	_membar_enter(void);
+extern	void	_membar_exit(void);
+extern	void	_membar_producer(void);
+extern	void	_membar_consumer(void);
+
 extern	int	_thr_continue(thread_t);
 extern	int	_thr_create(void *, size_t, void *(*)(void *), void *, long,
 			thread_t *);
@@ -1298,6 +1303,7 @@
 extern	int	_thr_getspecific(thread_key_t, void **);
 extern	int	_thr_join(thread_t, thread_t *, void **);
 extern	int	_thr_keycreate(thread_key_t *, PFrV);
+extern	int	_thr_keycreate_once(thread_key_t *, PFrV);
 extern	int	_thr_key_delete(thread_key_t);
 extern	int	_thr_main(void);
 extern	thread_t _thr_self(void);
--- a/usr/src/lib/libc/port/gen/crypt.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/gen/crypt.c	Tue Mar 20 17:29:57 2007 -0700
@@ -18,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -46,6 +47,7 @@
 #include <fcntl.h>
 #include <syslog.h>
 #include <unistd.h>
+#include <atomic.h>
 
 #include <crypt.h>
 #include <libc.h>
@@ -903,8 +905,10 @@
 	int failed;
 	int assigned;
 
-	if (KS != NULL)		/* already allocated */
+	if (KS != NULL) {		/* already allocated */
+		membar_consumer();
 		return (0);
+	}
 
 	ks = calloc(16, 48 * sizeof (char));
 	failed = 0;
@@ -913,6 +917,7 @@
 		assigned = 0;
 	} else {
 		assigned = 1;
+		membar_producer();
 		if ((KS = ks) == NULL)	/* calloc() failed */
 			failed = 1;
 	}
--- a/usr/src/lib/libc/port/gen/getauxv.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/gen/getauxv.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -38,6 +37,7 @@
 #include <mtlib.h>
 #include <thread.h>
 #include <synch.h>
+#include <atomic.h>
 
 static mutex_t auxlock = DEFAULTMUTEX;
 
@@ -57,34 +57,37 @@
 	 * passed to the process at exec(2).  Only do this once.
 	 */
 	if (auxb == NULL) {
-		struct stat statb;
-		int fd;
+		lmutex_lock(&auxlock);
+		if (auxb == NULL) {
+			struct stat statb;
+			auxv_t *buf = NULL;
+			int fd;
 
-		lmutex_lock(&auxlock);
-
-		if (auxb == NULL) {
 			if ((fd = open("/proc/self/auxv", O_RDONLY)) != -1 &&
 			    fstat(fd, &statb) != -1)
-				auxb = libc_malloc(
+				buf = libc_malloc(
 				    statb.st_size + sizeof (auxv_t));
 
-			if (auxb != NULL) {
-				i = read(fd, auxb, statb.st_size);
+			if (buf != NULL) {
+				i = read(fd, buf, statb.st_size);
 				if (i != -1) {
 					nauxv = i / sizeof (auxv_t);
-					auxb[nauxv].a_type = AT_NULL;
+					buf[nauxv].a_type = AT_NULL;
 				} else {
-					libc_free(auxb);
-					auxb = NULL;
+					libc_free(buf);
+					buf = NULL;
 				}
 			}
 
 			if (fd != -1)
 				(void) close(fd);
+
+			membar_producer();
+			auxb = buf;
 		}
-
 		lmutex_unlock(&auxlock);
 	}
+	membar_consumer();
 
 	/*
 	 * Scan the auxiliary entries looking for the required type.
--- a/usr/src/lib/libc/port/gen/getenv.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/gen/getenv.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -131,26 +131,29 @@
 static void
 initenv()
 {
-	lmutex_lock(&update_lock);
 	if ((my_environ != environ) || !initenv_done) {
-		if (!initenv_done) {
-			/* Call the NLSPATH janitor in. */
-			clean_env();
+		lmutex_lock(&update_lock);
+		if ((my_environ != environ) || !initenv_done) {
+			if (!initenv_done) {
+				/* Call the NLSPATH janitor in. */
+				clean_env();
 
-			/* Pacify leak detectors in normal operation. */
-			orig_environ = environ;
+				/* Pacify leak detectors in normal operation. */
+				orig_environ = environ;
 #ifdef __lint
-			my_environ = orig_environ;
+				my_environ = orig_environ;
 #endif
+			}
 
+			my_environ = environ;
+			environ_base = my_environ;
+			environ_size = envsize(environ_base);
+			membar_producer();
 			initenv_done = 1;
 		}
-
-		my_environ = environ;
-		environ_base = my_environ;
-		environ_size = envsize(environ_base);
+		lmutex_unlock(&update_lock);
 	}
-	lmutex_unlock(&update_lock);
+	membar_consumer();
 }
 
 /*
@@ -220,8 +223,7 @@
 	int			new_size;
 	int			old_gen;
 
-	if ((my_environ != environ) || !initenv_done)
-		initenv();
+	initenv();
 
 	lmutex_lock(&update_lock);
 
@@ -419,8 +421,7 @@
 		return (-1);
 	}
 
-	if ((my_environ != environ) || !initenv_done)
-		initenv();
+	initenv();
 
 	lmutex_lock(&update_lock);
 
@@ -455,8 +456,7 @@
 {
 	char			*value;
 
-	if (!initenv_done)
-		initenv();
+	initenv();
 
 	if (findenv(environ, name, 1, &value) != NULL)
 		return (value);
--- a/usr/src/lib/libc/port/gen/nss_common.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/gen/nss_common.c	Tue Mar 20 17:29:57 2007 -0700
@@ -18,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -38,6 +39,7 @@
 #include "synonyms.h"
 #include <mtlib.h>
 #include <dlfcn.h>
+#include <atomic.h>
 
 #define	__NSS_PRIVATE_INTERFACE
 #include "nsswitch_priv.h"
@@ -252,7 +254,7 @@
 
 #define	NSS_CFG_INCR	16
 
-static nss_cfglist_t *nss_cfg = (nss_cfglist_t *)NULL;
+static nss_cfglist_t *nss_cfg = NULL;
 static int nss_cfgcount = 0;
 static int nss_cfgmax = 0;
 static mutex_t nss_cfglock = DEFAULTMUTEX;
@@ -303,39 +305,47 @@
 static int
 nss_cfg_init()
 {
+	nss_cfglist_t *cfg;
 	int i;
 
 	/* First time caller? */
-	if (nss_cfg != NULL)
+	if (nss_cfg != NULL) {
+		membar_consumer();
 		return (0);
+	}
 
 	/* Initialize internal tables */
 	lmutex_lock(&nss_cfglock);
 	if (nss_cfg != NULL) {
 		lmutex_unlock(&nss_cfglock);
+		membar_consumer();
 		return (0);
 	}
-	nss_cfg = (nss_cfglist_t *)libc_malloc(NSS_CFG_INCR *
-					    sizeof (nss_cfglist_t));
-	if (nss_cfg == (nss_cfglist_t *)NULL) {
+	cfg = libc_malloc(NSS_CFG_INCR * sizeof (nss_cfglist_t));
+	if (cfg == NULL) {
 		errno = ENOMEM;
 		lmutex_unlock(&nss_cfglock);
 		return (-1);
 	}
-	nss_cfgmax = NSS_CFG_INCR;
-	for (i = 0; i < nss_cfgmax; i++) {
-		nss_cfg[i].list = (nss_cfgparam_t *)libc_malloc(NSS_CFG_INCR *
-					sizeof (nss_cfgparam_t));
-		if (nss_cfg[i].list == (nss_cfgparam_t *)NULL) {
+	for (i = 0; i < NSS_CFG_INCR; i++) {
+		cfg[i].list = libc_malloc(
+		    NSS_CFG_INCR * sizeof (nss_cfgparam_t));
+		if (cfg[i].list == NULL) {
+			while (--i >= 0)
+				libc_free(cfg[i].list);
+			libc_free(cfg);
 			errno = ENOMEM;
 			lmutex_unlock(&nss_cfglock);
 			return (-1);
 		}
-		nss_cfg[i].max = NSS_CFG_INCR;
+		cfg[i].max = NSS_CFG_INCR;
 	}
+	nss_cfgmax = NSS_CFG_INCR;
+	membar_producer();
+	nss_cfg = cfg;
+	lmutex_unlock(&nss_cfglock);
 
 	/* Initialize Policy Engine values */
-	lmutex_unlock(&nss_cfglock);
 	if (nss_cfg_policy_init() < 0) {
 		return (-1);
 	}
@@ -352,7 +362,7 @@
 	size_t	nsize;
 
 	/* Make sure system is init'd */
-	if (nss_cfg == NULL && nss_cfg_init() < 0)
+	if (nss_cfg_init() < 0)
 		return ((nss_cfglist_t *)NULL);
 
 	/* and check component:name validity */
--- a/usr/src/lib/libc/port/gen/nss_dbdefs.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/gen/nss_dbdefs.c	Tue Mar 20 17:29:57 2007 -0700
@@ -18,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,6 +37,7 @@
 #include <dlfcn.h>
 #include <link.h>
 #include <thread.h>
+#include <atomic.h>
 /* headers for key2str/str2key routines */
 #include <sys/ethernet.h>
 #include <exec_attr.h>
@@ -319,10 +321,12 @@
 				}
 				getXbyYdbopHASH[hval] = i | DBOP_HASH_TAG;
 			}
+			membar_producer();
 			getXbyYdbop_hashed = 1;
 		}
 		lmutex_unlock(&getXbydbop_hash_lock);
 	}
+	membar_consumer();
 	cp = name;
 	hval = 0;
 	while (*cp) {
--- a/usr/src/lib/libc/port/gen/privlib.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/gen/privlib.c	Tue Mar 20 17:29:57 2007 -0700
@@ -18,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -62,6 +63,7 @@
 #include <strings.h>
 #include <synch.h>
 #include <alloca.h>
+#include <atomic.h>
 #include <sys/ucred.h>
 #include <sys/procfs.h>
 #include <sys/param.h>
@@ -233,7 +235,7 @@
 int
 lock_data(void)
 {
-	if (privdata == NULL && __priv_getdata() == NULL)
+	if (__priv_getdata() == NULL)
 		return (-1);
 
 	lmutex_lock(&pd_lock);
@@ -310,54 +312,59 @@
 priv_data_t *
 __priv_getdata(void)
 {
-	lmutex_lock(&pd_lock);
 	if (privdata == NULL) {
-		priv_data_t *tmp;
-		priv_impl_info_t *ip;
-		size_t size = sizeof (priv_impl_info_t) + 2048;
-		size_t realsize;
-		priv_impl_info_t *aip = alloca(size);
+		lmutex_lock(&pd_lock);
+		if (privdata == NULL) {
+			priv_data_t *tmp;
+			priv_impl_info_t *ip;
+			size_t size = sizeof (priv_impl_info_t) + 2048;
+			size_t realsize;
+			priv_impl_info_t *aip = alloca(size);
 
-		if (getprivinfo(aip, size) != 0)
-			goto out;
+			if (getprivinfo(aip, size) != 0)
+				goto out;
+
+			realsize = PRIV_IMPL_INFO_SIZE(aip);
+
+			ip = libc_malloc(realsize);
+
+			if (ip == NULL)
+				goto out;
 
-		realsize = PRIV_IMPL_INFO_SIZE(aip);
+			if (realsize <= size) {
+				(void) memcpy(ip, aip, realsize);
+			} else if (getprivinfo(ip, realsize) != 0) {
+				libc_free(ip);
+				goto out;
+			}
 
-		ip = libc_malloc(realsize);
+			if ((tmp = __priv_parse_info(ip)) == NULL) {
+				libc_free(ip);
+				goto out;
+			}
 
-		if (ip == NULL)
-			goto out;
+			/* Allocate the zoneset just once, here */
+			tmp->pd_zoneset = __priv_allocset(tmp);
+			if (tmp->pd_zoneset == NULL)
+				goto clean;
 
-		if (realsize <= size) {
-			(void) memcpy(ip, aip, realsize);
-		} else if (getprivinfo(ip, realsize) != 0) {
+			if (zone_getattr(getzoneid(), ZONE_ATTR_PRIVSET,
+			    tmp->pd_zoneset, tmp->pd_setsize)
+			    == tmp->pd_setsize) {
+				membar_producer();
+				privdata = tmp;
+				goto out;
+			}
+
+			priv_freeset(tmp->pd_zoneset);
+clean:
+			__priv_free_info(tmp);
 			libc_free(ip);
-			goto out;
 		}
-
-		if ((tmp = __priv_parse_info(ip)) == NULL) {
-			libc_free(ip);
-			goto out;
-		}
-
-		/* Allocate the zoneset just once, here */
-		tmp->pd_zoneset = __priv_allocset(tmp);
-		if (tmp->pd_zoneset == NULL)
-			goto clean;
-
-		if (zone_getattr(getzoneid(), ZONE_ATTR_PRIVSET,
-		    tmp->pd_zoneset, tmp->pd_setsize) == tmp->pd_setsize) {
-			privdata = tmp;
-			goto out;
-		}
-
-		priv_freeset(tmp->pd_zoneset);
-clean:
-		__priv_free_info(tmp);
-		libc_free(ip);
+out:
+		lmutex_unlock(&pd_lock);
 	}
-out:
-	lmutex_unlock(&pd_lock);
+	membar_consumer();
 	return (privdata);
 }
 
--- a/usr/src/lib/libc/port/gen/tsdalloc.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/gen/tsdalloc.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -65,9 +65,7 @@
 void *
 tsdalloc(__tsd_item_t n, size_t size, pfrv_t destructor)
 {
-	static int		once_key = 0;
-	static mutex_t		key_lock = DEFAULTMUTEX;
-	static thread_key_t	key;
+	static thread_key_t	key = THR_ONCE_KEY;
 	tsdent_t		*loc;
 	void			*p;
 	int			error;
@@ -77,17 +75,9 @@
 		return (NULL);
 	}
 
-	if (once_key == 0) {
-		lmutex_lock(&key_lock);
-		if (once_key == 0) {
-			if ((error = _thr_keycreate(&key, _free_tsdbuf)) != 0) {
-				lmutex_unlock(&key_lock);
-				errno = error;
-				return (NULL);
-			}
-			once_key = 1;
-		}
-		lmutex_unlock(&key_lock);
+	if ((error = _thr_keycreate_once(&key, _free_tsdbuf)) != 0) {
+		errno = error;
+		return (NULL);
 	}
 
 	if ((loc = _pthread_getspecific(key)) != NULL) {
--- a/usr/src/lib/libc/port/mapfile-vers	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/mapfile-vers	Tue Mar 20 17:29:57 2007 -0700
@@ -78,6 +78,7 @@
 	mq_unlink;
 	nanosleep;
 	posix_fallocate;
+	pthread_key_create_once_np;
 	_renameat;
 	sched_getparam;
 	sched_get_priority_max;
@@ -104,6 +105,7 @@
 	sigtimedwait;
 	sigwaitinfo;
 	strnlen;
+	thr_keycreate_once;
 	timer_create;
 	timer_delete;
 	timer_getoverrun;
@@ -1857,6 +1859,7 @@
 	_pthread_getspecific;
 	_pthread_join;
 	_pthread_key_create;
+	_pthread_key_create_once_np;
 	_pthread_key_delete;
 	_pthread_kill;
 	__pthread_min_stack;
@@ -2087,6 +2090,7 @@
 	_thr_getstate;
 	_thr_join;
 	_thr_keycreate;
+	_thr_keycreate_once;
 	_thr_key_delete;
 	_thr_kill;
 	_thr_main;
--- a/usr/src/lib/libc/port/threads/pthread.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/threads/pthread.c	Tue Mar 20 17:29:57 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -145,10 +145,12 @@
 			    &once->mlock);
 			(*init_routine)();
 			pthread_cleanup_pop(0);
+			_membar_producer();
 			once->once_flag = PTHREAD_ONCE_DONE;
 		}
 		(void) _private_mutex_unlock(&once->mlock);
 	}
+	_membar_consumer();
 
 	return (0);
 }
--- a/usr/src/lib/libc/port/threads/rtsched.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/threads/rtsched.c	Tue Mar 20 17:29:57 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -112,10 +112,12 @@
 		lmutex_lock(&prio_lock);
 		if (!initialized) {	/* do this only once */
 			_init_rt_prio_ranges();
+			_membar_producer();
 			initialized = 1;
 		}
 		lmutex_unlock(&prio_lock);
 	}
+	_membar_consumer();
 
 	switch (policy) {
 	case SCHED_FIFO:
--- a/usr/src/lib/libc/port/threads/tdb_agent.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/threads/tdb_agent.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -217,9 +217,10 @@
 	addr_hash[tdb_addr_hash(&udp->tdb_hash_lock)] =
 		(uintptr_t)&udp->tdb_hash_lock_stats;
 
+	tdbp->tdb_register_count = 1;
 	/* assign to tdb_sync_addr_hash only after fully initialized */
+	_membar_producer();
 	tdbp->tdb_sync_addr_hash = addr_hash;
-	tdbp->tdb_register_count = 1;
 	lmutex_unlock(&udp->tdb_hash_lock);
 }
 
@@ -269,6 +270,7 @@
 			goto out;
 		}
 	}
+	_membar_consumer();
 
 	sapp = &tdbp->tdb_sync_addr_hash[tdb_addr_hash(addr)];
 	if (udp->uberflags.uf_tdb_register_sync == REGISTER_SYNC_ON) {
--- a/usr/src/lib/libc/port/threads/tsd.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libc/port/threads/tsd.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -128,6 +128,47 @@
 	return (0);
 }
 
+/*
+ * Same as _thr_keycreate(), above, except that the key creation
+ * is performed only once.  This relies upon the fact that a key
+ * value of THR_ONCE_KEY is invalid, and requires that the key be
+ * allocated with a value of THR_ONCE_KEY before calling here.
+ * THR_ONCE_KEY and PTHREAD_ONCE_KEY_NP, defined in <thread.h>
+ * and <pthread.h> respectively, must have the same value.
+ * Example:
+ *
+ *	static pthread_key_t key = PTHREAD_ONCE_KEY_NP;
+ *	...
+ *	pthread_key_create_once_np(&key, destructor);
+ */
+#pragma weak pthread_key_create_once_np = _thr_keycreate_once
+#pragma weak _pthread_key_create_once_np = _thr_keycreate_once
+#pragma weak thr_keycreate_once = _thr_keycreate_once
+int
+_thr_keycreate_once(thread_key_t *keyp, void (*destructor)(void *))
+{
+	static mutex_t key_lock = DEFAULTMUTEX;
+	thread_key_t key;
+	int error;
+
+	if (*keyp == THR_ONCE_KEY) {
+		lmutex_lock(&key_lock);
+		if (*keyp == THR_ONCE_KEY) {
+			error = _thr_keycreate(&key, destructor);
+			if (error) {
+				lmutex_unlock(&key_lock);
+				return (error);
+			}
+			_membar_producer();
+			*keyp = key;
+		}
+		lmutex_unlock(&key_lock);
+	}
+	_membar_consumer();
+
+	return (0);
+}
+
 #pragma weak pthread_key_delete = _thr_key_delete
 #pragma weak _pthread_key_delete = _thr_key_delete
 int
--- a/usr/src/lib/libcrypt/common/des_crypt.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libcrypt/common/des_crypt.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,14 @@
  * CDDL HEADER END
  */
 
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
 /*	Copyright (c) 1988 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 /*LINTLIBRARY*/
 
@@ -42,7 +41,7 @@
 
 #include <stdlib.h>
 #include <thread.h>
-#include <synch.h>
+#include <pthread.h>
 #include <sys/types.h>
 
 /* EXPORT DELETE START */
@@ -330,22 +329,18 @@
 #define	IOBUF_SIZE	16
 
 static char *
-_get_iobuf(thread_key_t *key, unsigned size)
+_get_iobuf(thread_key_t *keyp, unsigned size)
 {
-	char *iobuf = NULL;
+	char *iobuf;
 
-	if (thr_getspecific(*key, (void **)&iobuf) != 0) {
-		if (thr_keycreate(key, free) != 0) {
-			return (NULL);
-		}
-	}
-
-	if (!iobuf) {
-		if (thr_setspecific(*key, (void *)(iobuf = malloc(size)))
-			!= 0) {
+	if (thr_keycreate_once(keyp, free) != 0)
+		return (NULL);
+	iobuf = pthread_getspecific(*keyp);
+	if (iobuf == NULL) {
+		if (thr_setspecific(*keyp, (iobuf = malloc(size))) != 0) {
 			if (iobuf)
 				(void) free(iobuf);
-			return (NULL);
+			iobuf = NULL;
 		}
 	}
 	return (iobuf);
@@ -357,8 +352,9 @@
 /* EXPORT DELETE START */
 	int	i, j;
 	char	c, temp;
-	static thread_key_t key = 0;
-	char block[66], *iobuf = _get_iobuf(&key, IOBUF_SIZE);
+	char block[66];
+	static thread_key_t key = THR_ONCE_KEY;
+	char *iobuf = _get_iobuf(&key, IOBUF_SIZE);
 
 	(void) mutex_lock(&lock);
 	for (i = 0; i < 66; i++)
--- a/usr/src/lib/libexacct/common/exacct_ops.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libexacct/common/exacct_ops.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -38,6 +38,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <thread.h>
+#include <pthread.h>
 
 #define	EXACCT_HDR_STR	"exacct"
 #define	EXACCT_HDR_LEN	7
@@ -45,9 +46,7 @@
 #define	DEFAULT_ENTRIES	4
 #define	SYSINFO_BUFSIZE	256
 
-static mutex_t		keylock;
-static thread_key_t	errkey;
-static int		keyonce = 0;
+static thread_key_t	errkey = THR_ONCE_KEY;
 static int		exacct_errval = 0;
 
 /*
@@ -298,29 +297,18 @@
 		exacct_errval = errval;
 		return;
 	}
-	if (keyonce == 0) {
-		(void) mutex_lock(&keylock);
-		if (keyonce == 0) {
-			(void) thr_keycreate(&errkey, 0);
-			keyonce++;
-		}
-		(void) mutex_unlock(&keylock);
-	}
+	(void) thr_keycreate_once(&errkey, 0);
 	(void) thr_setspecific(errkey, (void *)(intptr_t)errval);
 }
 
 int
 ea_error(void)
 {
-	intptr_t errvalp;
-
 	if (thr_main())
 		return (exacct_errval);
-	if (keyonce == 0)
+	if (errkey == THR_ONCE_KEY)
 		return (EXR_OK);
-
-	(void) thr_getspecific(errkey, (void**)&errvalp);
-	return ((int)errvalp);
+	return ((int)(uintptr_t)pthread_getspecific(errkey));
 }
 
 /*
--- a/usr/src/lib/libgen/common/bgets.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libgen/common/bgets.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,14 @@
  * CDDL HEADER END
  */
 
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
 /*	Copyright (c) 1988 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 /*
@@ -46,6 +45,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <thread.h>
+#include <pthread.h>
 
 #define	CHARS	256
 
@@ -57,21 +57,19 @@
 
 #ifdef _REENTRANT
 static char *
-_get_stop(thread_key_t *key)
+_get_stop(thread_key_t *keyp)
 {
-	char *str = NULL;
+	char *str;
 
-	if (thr_getspecific(*key, (void **)&str) != 0) {
-		if (thr_keycreate(key, free) != 0) {
-			return (NULL);
-		}
-	}
-	if (!str) {
-		if (thr_setspecific(*key, (void *)(str = calloc(CHARS,
-			sizeof (char)))) != 0) {
+	if (thr_keycreate_once(keyp, free) != 0)
+		return (NULL);
+	str = pthread_getspecific(*keyp);
+	if (str == NULL) {
+		str = calloc(CHARS, sizeof (char));
+		if (thr_setspecific(*keyp, str) != 0) {
 			if (str)
 				(void) free(str);
-			return (NULL);
+			str = NULL;
 		}
 	}
 	return (str);
@@ -85,7 +83,7 @@
 	int	c;
 	size_t	i;
 #ifdef _REENTRANT
-	static thread_key_t key = 0;
+	static thread_key_t key = THR_ONCE_KEY;
 	char  *stop  = _get_stop(&key);
 #else /* _REENTRANT */
 	if (! stop)
--- a/usr/src/lib/libgen/common/bufsplit.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libgen/common/bufsplit.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,14 @@
  * CDDL HEADER END
  */
 
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
 /*	Copyright (c) 1988 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 /*
@@ -48,6 +47,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <thread.h>
+#include <pthread.h>
 
 #ifndef _REENTRANT
 static char *bsplitchar = "\t\n";	/* characters that separate fields */
@@ -55,24 +55,23 @@
 
 #ifdef _REENTRANT
 static char **
-_get_bsplitchar(thread_key_t *key)
+_get_bsplitchar(thread_key_t *keyp)
 {
-	static char **strp = NULL;
 	static char *init_bsplitchar = "\t\n";
+	char **strp;
 
-	if (thr_getspecific(*key, (void **)&strp) != 0) {
-		if (thr_keycreate(key, free) != 0) {
-			return (NULL);
-		}
-	}
-	if (!strp) {
-		if (thr_setspecific(*key, (void *)(strp = malloc(
-			sizeof (char *)))) != 0) {
+	if (thr_keycreate_once(keyp, free) != 0)
+		return (NULL);
+	strp = pthread_getspecific(*keyp);
+	if (strp == NULL) {
+		strp = malloc(sizeof (char *));
+		if (thr_setspecific(*keyp, strp) != 0) {
 			if (strp)
 				(void) free(strp);
-			return (NULL);
+			strp = NULL;
 		}
-		*strp = init_bsplitchar;
+		if (strp != NULL)
+			*strp = init_bsplitchar;
 	}
 	return (strp);
 }
@@ -82,7 +81,7 @@
 bufsplit(char *buf, size_t dim, char **array)
 {
 #ifdef _REENTRANT
-	static thread_key_t key = 0;
+	static thread_key_t key = THR_ONCE_KEY;
 	char  **bsplitchar = _get_bsplitchar(&key);
 #define	bsplitchar (*bsplitchar)
 #endif /* _REENTRANT */
--- a/usr/src/lib/libgen/common/pathfind.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libgen/common/pathfind.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,14 @@
  * CDDL HEADER END
  */
 
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
 /*	Copyright (c) 1988 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #pragma weak pathfind = _pathfind
@@ -41,6 +40,7 @@
 #include "gen_synonyms.h"
 #ifdef _REENTRANT
 #include <thread.h>
+#include <pthread.h>
 #endif /* _REENTRANT */
 #include <sys/types.h>
 #include <libgen.h>
@@ -80,21 +80,19 @@
 
 #ifdef _REENTRANT
 static char *
-_get_cpath(thread_key_t *key)
+_get_cpath(thread_key_t *keyp)
 {
-	char *str = NULL;
+	char *str;
 
-	if (thr_getspecific(*key, (void **)&str) != 0) {
-		if (thr_keycreate(key, free) != 0) {
-			return (NULL);
-		}
-	}
-	if (!str) {
-		if (thr_setspecific(*key, (void *)(str = calloc(PATH_MAX,
-			sizeof (char)))) != 0) {
+	if (thr_keycreate_once(keyp, free) != 0)
+		return (NULL);
+	str = pthread_getspecific(*keyp);
+	if (str == NULL) {
+		str = calloc(PATH_MAX, sizeof (char));
+		if (thr_setspecific(*keyp, str) != 0) {
 			if (str)
 				(void) free(str);
-			return (NULL);
+			str = NULL;
 		}
 	}
 	return (str);
@@ -105,7 +103,7 @@
 pathfind(const char *path, const char *name, const char *mode)
 {
 #ifdef _REENTRANT
-	static thread_key_t key = 0;
+	static thread_key_t key = THR_ONCE_KEY;
 	char *cpath = _get_cpath(&key);
 #else /* _REENTRANT */
 	static char cpath[PATH_MAX];
--- a/usr/src/lib/libgen/common/reg_compile.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libgen/common/reg_compile.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,14 @@
  * CDDL HEADER END
  */
 
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
 /*	Copyright (c) 1988 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #pragma weak nbra = _nbra
@@ -42,6 +41,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <thread.h>
+#include <pthread.h>
 #include <widec.h> /* Defines multibyte and WCHAR_CSMASK for valid_range(). */
 #include "_range.h"
 #include "_regexp.h"
@@ -75,24 +75,22 @@
 	int	nbra, regerrno, reglength;
 } vars_storage;
 
-static thread_key_t key = 0;
+static thread_key_t key = THR_ONCE_KEY;
 
 static vars_storage *
-_get_vars_storage(thread_key_t *key)
+_get_vars_storage(thread_key_t *keyp)
 {
-	vars_storage *vars = NULL;
+	vars_storage *vars;
 
-	if (thr_getspecific(*key, (void **)&vars) != 0) {
-		if (thr_keycreate(key, free) != 0) {
-			return (NULL);
-		}
-	}
-	if (!vars) {
-		if (thr_setspecific(*key, (void *)(vars =
-			calloc(1, sizeof (vars_storage)))) != 0) {
+	if (thr_keycreate_once(keyp, free) != 0)
+		return (NULL);
+	vars = pthread_getspecific(*keyp);
+	if (vars == NULL) {
+		vars = calloc(1, sizeof (vars_storage));
+		if (thr_setspecific(*keyp, vars) != 0) {
 			if (vars)
 				(void) free(vars);
-			return (NULL);
+			vars = NULL;
 		}
 	}
 	return (vars);
--- a/usr/src/lib/libgen/common/reg_step.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libgen/common/reg_step.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,14 @@
  * CDDL HEADER END
  */
 
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
 /*	Copyright (c) 1988 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #pragma weak loc1 = _loc1
@@ -46,6 +45,7 @@
 #include <string.h>
 #include <synch.h>
 #include <thread.h>
+#include <pthread.h>
 #include <widec.h>
 #include "_regexp.h"
 
@@ -59,7 +59,7 @@
 char	*braelist[_NBRA] = { (char *)0};
 
 #ifdef  _REENTRANT
-static thread_key_t key = 0;
+static thread_key_t key = THR_ONCE_KEY;
 typedef struct _vars_storage {
 	char	*loc1, *loc2, *locs;
 	char    *braslist[_NBRA];
@@ -79,21 +79,19 @@
 static mutex_t lock = DEFAULTMUTEX;
 
 static vars_storage *
-_get_vars_storage(thread_key_t *key)
+_get_vars_storage(thread_key_t *keyp)
 {
-	vars_storage *vars = NULL;
+	vars_storage *vars;
 
-	if (thr_getspecific(*key, (void **)&vars) != 0) {
-		if (thr_keycreate(key, free) != 0) {
-			return (NULL);
-		}
-	}
-	if (!vars) {
-		if (thr_setspecific(*key, (void *)(vars =
-			calloc(1, sizeof (vars_storage)))) != 0) {
+	if (thr_keycreate_once(keyp, free) != 0)
+		return (NULL);
+	vars = pthread_getspecific(*keyp);
+	if (vars == NULL) {
+		vars = calloc(1, sizeof (vars_storage));
+		if (thr_setspecific(*keyp, vars) != 0) {
 			if (vars)
 				(void) free(vars);
-			return (NULL);
+			vars = NULL;
 		}
 	}
 	return (vars);
--- a/usr/src/lib/libnsl/common/common.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/common/common.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -33,26 +32,14 @@
 void *
 thr_get_storage(pthread_key_t *keyp, size_t size, void (*destructor)(void *))
 {
-	extern mutex_t tsd_lock;
-	pthread_key_t key;
 	void *addr;
 
-	if ((key = *keyp) == 0) {
-		(void) mutex_lock(&tsd_lock);
-		if ((key = *keyp) == 0) {
-			if (pthread_key_create(keyp, destructor) != 0) {
-				(void) mutex_unlock(&tsd_lock);
-				return (NULL);
-			}
-			key = *keyp;
-		}
-		(void) mutex_unlock(&tsd_lock);
-	}
-
-	addr = pthread_getspecific(key);
+	if (pthread_key_create_once_np(keyp, destructor) != 0)
+		return (NULL);
+	addr = pthread_getspecific(*keyp);
 	if (addr == NULL && size != 0) {
 		addr = calloc(1, size);
-		if (addr != NULL && pthread_setspecific(key, addr) != 0) {
+		if (addr != NULL && pthread_setspecific(*keyp, addr) != 0) {
 			free(addr);
 			return (NULL);
 		}
--- a/usr/src/lib/libnsl/netdir/netdir.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/netdir/netdir.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -102,7 +101,7 @@
 int *
 __nderror(void)
 {
-	static pthread_key_t nderror_key = 0;
+	static pthread_key_t nderror_key = PTHREAD_ONCE_KEY_NP;
 	int *ret;
 
 	if (thr_main())
@@ -746,7 +745,7 @@
 char *
 netdir_sperror(void)
 {
-	static pthread_key_t nderrbuf_key = 0;
+	static pthread_key_t nderrbuf_key = PTHREAD_ONCE_KEY_NP;
 	static char buf_main[NDERR_BUFSZ];
 	char	*str;
 	char *dlerrstr;
--- a/usr/src/lib/libnsl/netselect/netselect.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/netselect/netselect.c	Tue Mar 20 17:29:57 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -103,7 +103,7 @@
 static int *
 __nc_error(void)
 {
-	static pthread_key_t nc_error_key = 0;
+	static pthread_key_t nc_error_key = PTHREAD_ONCE_KEY_NP;
 	static int nc_error = NC_NOERROR;
 	int *ret;
 
@@ -815,7 +815,7 @@
 nc_sperror(void)
 {
 	static char buf_main[BUFSIZ];
-	static pthread_key_t perror_key;
+	static pthread_key_t perror_key = PTHREAD_ONCE_KEY_NP;
 	char *retstr = thr_main()?
 		buf_main :
 		thr_get_storage(&perror_key, BUFSIZ, free);
--- a/usr/src/lib/libnsl/nis/gen/nis_callback.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/nis/gen/nis_callback.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -133,7 +132,7 @@
 
 static void destroy_cbdata(void *);
 
-static pthread_key_t cbdata_key;
+static pthread_key_t cbdata_key = PTHREAD_ONCE_KEY_NP;
 static struct callback_data __cbdata_main;
 
 /*
--- a/usr/src/lib/libnsl/nis/gen/nis_groups.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/nis/gen/nis_groups.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -647,7 +646,7 @@
 	/* NOTREACHED */
 }
 
-static pthread_key_t visit_log_key;
+static pthread_key_t visit_log_key = PTHREAD_ONCE_KEY_NP;
 struct visit_log {
 	g_entry		 *ge_id;
 	struct visit_log *next;
--- a/usr/src/lib/libnsl/nis/gen/nis_perror.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/nis/gen/nis_perror.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,12 +18,9 @@
  *
  * CDDL HEADER END
  */
-/*
- *	nis_perror.c
- */
 
 /*
- * Copyright 1988-2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -256,7 +252,7 @@
 char *
 nis_sperror(nis_error stat, char *str)
 {
-	static 	pthread_key_t err_buf_key;
+	static 	pthread_key_t err_buf_key = PTHREAD_ONCE_KEY_NP;
 	char 	*err_buf;
 #define	ERR_BUF_SIZE 128
 	static	char	err_buf_main[ERR_BUF_SIZE];
--- a/usr/src/lib/libnsl/nis/gen/nis_subr.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/nis/gen/nis_subr.c	Tue Mar 20 17:29:57 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -468,7 +468,7 @@
 	return (buf);
 }
 
-static pthread_key_t buf_key;
+static pthread_key_t buf_key = PTHREAD_ONCE_KEY_NP;
 static char buf_main[LN_BUFSIZE];
 
 nis_name
@@ -840,7 +840,7 @@
 	nis_object	*obj,	/* The object to clone */
 	nis_object	*dest)	/* Use this pointer if non-null */
 {
-	static pthread_key_t clone_buf_key;
+	static pthread_key_t clone_buf_key = PTHREAD_ONCE_KEY_NP;
 	static struct nis_sdata clone_buf_main;
 	struct nis_sdata *clone_buf_ptr;
 
@@ -2107,7 +2107,7 @@
 char *
 nis_old_data(char *s)
 {
-	static pthread_key_t 	bs_key;
+	static pthread_key_t 	bs_key = PTHREAD_ONCE_KEY_NP;
 	static struct nis_sdata	bs_main;
 	struct nis_sdata	*bs_ptr;
 
@@ -2161,7 +2161,7 @@
 char *
 nis_data(char *s)
 {
-	static pthread_key_t 	bs_key;
+	static pthread_key_t 	bs_key = PTHREAD_ONCE_KEY_NP;
 	static struct nis_sdata	bs_main;
 	struct nis_sdata	*bs_ptr;
 
--- a/usr/src/lib/libnsl/nsl/_errlst.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/nsl/_errlst.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,14 @@
  * CDDL HEADER END
  */
 
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-/*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include "mt.h"
@@ -129,7 +128,7 @@
 int *
 __t_errno(void)
 {
-	static pthread_key_t t_errno_key = 0;
+	static pthread_key_t t_errno_key = PTHREAD_ONCE_KEY_NP;
 	int *ret;
 
 	if (thr_main())
--- a/usr/src/lib/libnsl/rpc/clnt_perror.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/rpc/clnt_perror.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,9 +20,10 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+
 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
 /* All Rights Reserved */
 /*
@@ -63,7 +63,7 @@
 {
 	char *buf;
 	static char buf_main[ERRBUFSZ];
-	static pthread_key_t perror_key;
+	static pthread_key_t perror_key = PTHREAD_ONCE_KEY_NP;
 
 	buf = thr_main()? buf_main :
 		thr_get_storage(&perror_key, ERRBUFSZ, free);
--- a/usr/src/lib/libnsl/rpc/clnt_simple.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/rpc/clnt_simple.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -94,7 +93,7 @@
 	struct rpc_call_private *rcp;
 	enum clnt_stat clnt_stat;
 	struct timeval timeout, tottimeout;
-	static pthread_key_t rpc_call_key;
+	static pthread_key_t rpc_call_key = PTHREAD_ONCE_KEY_NP;
 	char nettype_array[NETIDLEN];
 	char *nettype = &nettype_array[0];
 
--- a/usr/src/lib/libnsl/rpc/clnt_vc.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/rpc/clnt_vc.c	Tue Mar 20 17:29:57 2007 -0700
@@ -20,9 +20,10 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+
 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
 /* All Rights Reserved */
 /*
@@ -1117,7 +1118,7 @@
 static int
 read_vc(void *ct_tmp, caddr_t buf, int len)
 {
-	static pthread_key_t pfdp_key;
+	static pthread_key_t pfdp_key = PTHREAD_ONCE_KEY_NP;
 	struct pollfd *pfdp;
 	int npfd;		/* total number of pfdp allocated */
 	struct ct_data *ct = ct_tmp;
--- a/usr/src/lib/libnsl/rpc/inet_ntoa.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/rpc/inet_ntoa.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -74,7 +73,7 @@
 {
 	char *b;
 	static char b_main[18];
-	static pthread_key_t ntoa_key;
+	static pthread_key_t ntoa_key = PTHREAD_ONCE_KEY_NP;
 
 	if (thr_main())
 		b = b_main;
--- a/usr/src/lib/libnsl/rpc/key_call.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/rpc/key_call.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -786,15 +785,14 @@
 	}
 }
 
-static pthread_key_t key_call_key;
+static pthread_key_t key_call_key = PTHREAD_ONCE_KEY_NP;
 
 void
 _key_call_fini(void)
 {
-	struct key_call_private	*kcp = NULL;
+	struct key_call_private	*kcp;
 
-	if (key_call_key &&
-	    (kcp = pthread_getspecific(key_call_key)) != NULL) {
+	if ((kcp = pthread_getspecific(key_call_key)) != NULL) {
 		key_call_destroy(kcp);
 		(void) pthread_setspecific(key_call_key, NULL);
 	}
--- a/usr/src/lib/libnsl/rpc/mt_misc.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/rpc/mt_misc.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -69,7 +68,6 @@
 mutex_t	proglst_lock;		/* protects proglst list (svc_simple.c) */
 mutex_t	rpcsoc_lock;		/* serializes clnt_com_create() (rpc_soc.c) */
 mutex_t	svcraw_lock;		/* svc_raw.c serialization */
-mutex_t	tsd_lock;		/* protects TSD key creation */
 mutex_t	xprtlist_lock;		/* xprtlist (svc_generic.c) */
 mutex_t serialize_pkey;		/* serializes calls to public key routines */
 mutex_t	svc_thr_mutex;		/* protects thread related variables */
@@ -91,7 +89,6 @@
 	&proglst_lock,
 	&rpcsoc_lock,
 	&svcraw_lock,
-	&tsd_lock,
 	&xprtlist_lock,
 	&serialize_pkey,
 	&svc_thr_mutex,
@@ -162,7 +159,7 @@
 struct rpc_createerr *
 __rpc_createerr()
 {
-	static pthread_key_t rce_key = 0;
+	static pthread_key_t rce_key = PTHREAD_ONCE_KEY_NP;
 	struct rpc_createerr *rce_addr;
 
 	if (thr_main())
@@ -182,8 +179,8 @@
 struct rpc_err *
 __rpc_callerr(void)
 {
-	static pthread_key_t rpc_callerr_key = 0;
-	struct rpc_err *tsd = 0;
+	static pthread_key_t rpc_callerr_key = PTHREAD_ONCE_KEY_NP;
+	struct rpc_err *tsd;
 
 	if (thr_main())
 		return (&rpc_callerr);
--- a/usr/src/lib/libnsl/rpc/rpc_generic.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/rpc/rpc_generic.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -186,31 +185,21 @@
 __rpc_getconfip(char *nettype)
 {
 	char *netid;
-	char *netid_tcp = NULL;
-	char *netid_udp = NULL;
-	static char *netid_tcp_main;
-	static char *netid_udp_main;
-	static pthread_key_t tcp_key, udp_key;
+	char *netid_tcp;
+	char *netid_udp;
+	static char *netid_tcp_main = NULL;
+	static char *netid_udp_main = NULL;
+	static pthread_key_t tcp_key = PTHREAD_ONCE_KEY_NP;
+	static pthread_key_t udp_key = PTHREAD_ONCE_KEY_NP;
 	int main_thread;
-	extern mutex_t tsd_lock;
 
 	if ((main_thread = thr_main())) {
 		netid_udp = netid_udp_main;
 		netid_tcp = netid_tcp_main;
 	} else {
-		if (tcp_key == 0) {
-			(void) mutex_lock(&tsd_lock);
-			if (tcp_key == 0)
-				(void) pthread_key_create(&tcp_key, free);
-			(void) mutex_unlock(&tsd_lock);
-		}
+		(void) pthread_key_create_once_np(&tcp_key, free);
 		netid_tcp = pthread_getspecific(tcp_key);
-		if (udp_key == 0) {
-			(void) mutex_lock(&tsd_lock);
-			if (udp_key == 0)
-				(void) pthread_key_create(&udp_key, free);
-			(void) mutex_unlock(&tsd_lock);
-		}
+		(void) pthread_key_create_once_np(&udp_key, free);
 		netid_udp = pthread_getspecific(udp_key);
 	}
 	if (!netid_udp && !netid_tcp) {
--- a/usr/src/lib/libnsl/rpc/rpc_soc.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/rpc/rpc_soc.c	Tue Mar 20 17:29:57 2007 -0700
@@ -20,9 +20,10 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+
 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
 /* All Rights Reserved */
 /*
@@ -457,7 +458,7 @@
  * All the following clnt_broadcast stuff is convulated; it supports
  * the earlier calling style of the callback function
  */
-static pthread_key_t	clnt_broadcast_key;
+static pthread_key_t	clnt_broadcast_key = PTHREAD_ONCE_KEY_NP;
 static resultproc_t	clnt_broadcast_result_main;
 
 /*
@@ -485,18 +486,10 @@
 	caddr_t argsp, xdrproc_t xresults,
 	caddr_t resultsp, resultproc_t eachresult)
 {
-	extern mutex_t tsd_lock;
-
 	if (thr_main()) {
 		clnt_broadcast_result_main = eachresult;
 	} else {
-		if (clnt_broadcast_key == 0) {
-			(void) mutex_lock(&tsd_lock);
-			if (clnt_broadcast_key == 0)
-				(void) pthread_key_create(&clnt_broadcast_key,
-									NULL);
-			(void) mutex_unlock(&tsd_lock);
-		}
+		(void) pthread_key_create_once_np(&clnt_broadcast_key, NULL);
 		(void) pthread_setspecific(clnt_broadcast_key,
 							(void *)eachresult);
 	}
--- a/usr/src/lib/libnsl/rpc/rpcsec_gss_if.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libnsl/rpc/rpcsec_gss_if.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -30,6 +29,7 @@
 #include "mt.h"
 #include "rpc_mt.h"
 #include <stdio.h>
+#include <atomic.h>
 #include <sys/errno.h>
 #include <dlfcn.h>
 #include <rpc/rpc.h>
@@ -64,13 +64,18 @@
 static bool_t
 rpcgss_calls_init(void)
 {
-	void	*handle = NULL;
+	void	*handle;
 	bool_t	ret = FALSE;
 
+	if (initialized) {
+		membar_consumer();
+		return (TRUE);
+	}
 	(void) mutex_lock(&rpcgss_calls_mutex);
 	if (initialized) {
-		ret = TRUE;
-		goto done;
+		(void) mutex_unlock(&rpcgss_calls_mutex);
+		membar_consumer();
+		return (TRUE);
 	}
 
 	if ((handle = dlopen(RPCSEC, RTLD_LAZY)) == NULL)
@@ -137,6 +142,7 @@
 		if (handle != NULL)
 			(void) dlclose(handle);
 	}
+	membar_producer();
 	initialized = ret;
 	(void) mutex_unlock(&rpcgss_calls_mutex);
 	return (ret);
@@ -152,7 +158,7 @@
 	rpc_gss_options_req_t	*options_req,	/* requested options */
 	rpc_gss_options_ret_t	*options_ret)	/* returned options */
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (NULL);
 	return ((*calls.rpc_gss_seccreate)(clnt, principal, mechanism,
 				service_type, qop, options_req, options_ret));
@@ -161,7 +167,7 @@
 bool_t
 rpc_gss_set_defaults(AUTH *auth, rpc_gss_service_t service, char *qop)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.rpc_gss_set_defaults)(auth, service, qop));
 }
@@ -174,7 +180,7 @@
 	char			*node,
 	char			*secdomain)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.rpc_gss_get_principal_name)(principal, mechanism,
 					user_name, node, secdomain));
@@ -183,7 +189,7 @@
 char **
 rpc_gss_get_mechanisms(void)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (NULL);
 	return ((*calls.rpc_gss_get_mechanisms)());
 }
@@ -191,7 +197,7 @@
 char **
 rpc_gss_get_mech_info(char *mechanism, rpc_gss_service_t *service)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (NULL);
 	return ((*calls.rpc_gss_get_mech_info)(mechanism, service));
 }
@@ -199,7 +205,7 @@
 bool_t
 rpc_gss_get_versions(uint_t *vers_hi, uint_t *vers_lo)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.rpc_gss_get_versions)(vers_hi, vers_lo));
 }
@@ -207,7 +213,7 @@
 bool_t
 rpc_gss_is_installed(char *mechanism)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.rpc_gss_is_installed)(mechanism));
 }
@@ -220,7 +226,7 @@
 	uint_t			program,
 	uint_t			version)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.rpc_gss_set_svc_name)(principal, mechanism, req_time,
 						program, version));
@@ -229,7 +235,7 @@
 bool_t
 rpc_gss_set_callback(rpc_gss_callback_t *cb)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.rpc_gss_set_callback)(cb));
 }
@@ -238,7 +244,7 @@
 rpc_gss_getcred(struct svc_req *req, rpc_gss_rawcred_t **rcred,
 					rpc_gss_ucred_t **ucred, void **cookie)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.rpc_gss_getcred)(req, rcred, ucred, cookie));
 }
@@ -246,7 +252,7 @@
 bool_t
 rpc_gss_mech_to_oid(char *mech, rpc_gss_OID *oid)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.rpc_gss_mech_to_oid)(mech, oid));
 }
@@ -254,7 +260,7 @@
 bool_t
 rpc_gss_qop_to_num(char *qop, char *mech, uint_t *num)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.rpc_gss_qop_to_num)(qop, mech, num));
 }
@@ -262,7 +268,7 @@
 enum auth_stat
 __svcrpcsec_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (AUTH_FAILED);
 	return ((*calls.__svcrpcsec_gss)(rqst, msg, no_dispatch));
 }
@@ -271,7 +277,7 @@
 __rpc_gss_wrap(AUTH *auth, char *buf, uint_t buflen, XDR *out_xdrs,
 					bool_t (*xdr_func)(), caddr_t xdr_ptr)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.__rpc_gss_wrap)(auth, buf, buflen, out_xdrs,
 							xdr_func, xdr_ptr));
@@ -281,7 +287,7 @@
 __rpc_gss_unwrap(AUTH *auth, XDR *in_xdrs, bool_t (*xdr_func)(),
 								caddr_t xdr_ptr)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (FALSE);
 	return ((*calls.__rpc_gss_unwrap)(auth, in_xdrs, xdr_func, xdr_ptr));
 }
@@ -289,7 +295,7 @@
 int
 rpc_gss_max_data_length(AUTH *rpcgss_handle, int max_tp_unit_len)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (0);
 	return ((*calls.rpc_gss_max_data_length)(rpcgss_handle,
 					max_tp_unit_len));
@@ -298,7 +304,7 @@
 int
 rpc_gss_svc_max_data_length(struct svc_req *req, int max_tp_unit_len)
 {
-	if (!initialized && !rpcgss_calls_init())
+	if (!rpcgss_calls_init())
 		return (0);
 	return ((*calls.rpc_gss_svc_max_data_length)(req, max_tp_unit_len));
 }
@@ -306,7 +312,7 @@
 void
 rpc_gss_get_error(rpc_gss_error_t *error)
 {
-	if (!initialized && !rpcgss_calls_init()) {
+	if (!rpcgss_calls_init()) {
 		error->rpc_gss_error = RPC_GSS_ER_SYSTEMERROR;
 		error->system_error = ENOTSUP;
 		return;
--- a/usr/src/lib/libpool/common/pool.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libpool/common/pool.c	Tue Mar 20 17:29:57 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -31,6 +31,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <thread.h>
+#include <pthread.h>
 #include <synch.h>
 #include <unistd.h>
 #include <stropts.h>
@@ -112,9 +113,7 @@
  */
 static const char static_location[] = "/etc/pooladm.conf";
 static const char dynamic_location[] =  "/dev/poolctl";
-static mutex_t		keylock;
-static thread_key_t	errkey;
-static int		keyonce = 0;
+static thread_key_t	errkey = THR_ONCE_KEY;
 
 /*
  * libpool error code
@@ -611,14 +610,7 @@
 		pool_errval = errval;
 		return;
 	}
-	if (keyonce == 0) {
-		(void) mutex_lock(&keylock);
-		if (keyonce == 0) {
-			(void) thr_keycreate(&errkey, 0);
-			keyonce++;
-		}
-		(void) mutex_unlock(&keylock);
-	}
+	(void) thr_keycreate_once(&errkey, 0);
 	(void) thr_setspecific(errkey, (void *)(intptr_t)errval);
 }
 
@@ -629,14 +621,11 @@
 int
 pool_error(void)
 {
-	void *errval;
-
 	if (thr_main())
 		return (pool_errval);
-	if (keyonce == 0)
+	if (errkey == THR_ONCE_KEY)
 		return (POE_OK);
-	(void) thr_getspecific(errkey, &errval);
-	return ((intptr_t)errval);
+	return ((uintptr_t)pthread_getspecific(errkey));
 }
 
 /*
--- a/usr/src/lib/libproc/common/Pcontrol.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libproc/common/Pcontrol.c	Tue Mar 20 17:29:57 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -38,6 +38,7 @@
 #include <dirent.h>
 #include <limits.h>
 #include <signal.h>
+#include <atomic.h>
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/stat.h>
@@ -125,6 +126,7 @@
 				fd = 256;
 			else if ((fd = rlim.rlim_cur / 2) < 3)
 				fd = 3;
+			membar_producer();
 			minfd = fd;
 		}
 		(void) mutex_unlock(&minfd_lock);
--- a/usr/src/lib/libresolv2/common/irs/gai_strerror.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libresolv2/common/irs/gai_strerror.c	Tue Mar 20 17:29:57 2007 -0700
@@ -59,9 +59,7 @@
 #ifndef DO_PTHREADS
 	static char buf[EAI_BUFSIZE];
 #else	/* DO_PTHREADS */
-	static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-	static pthread_key_t key;
-	static int once = 0;
+	static pthread_key_t key = PTHREAD_ONCE_KEY_NP;
 	char *buf;
 #endif
 
@@ -69,20 +67,8 @@
 		return (gai_errlist[ecode]);
 
 #ifdef DO_PTHREADS
-	if (!once) {
-		if (pthread_mutex_lock(&lock) != 0)
-			goto unknown;
-		if (!once) {
-			if (pthread_key_create(&key, free) != 0) {
-				pthread_mutex_unlock(&lock);
-				goto unknown;
-			}
-			once = 1;
-		}
-		if (pthread_mutex_unlock(&lock) != 0)
-			goto unknown;
-	}
-
+	if (pthread_key_create_once_np(&key, free) != 0)
+		goto unknown;
 	buf = pthread_getspecific(key);
 	if (buf == NULL) {
 		buf = malloc(EAI_BUFSIZE);
--- a/usr/src/lib/libresolv2/common/irs/irs_data.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libresolv2/common/irs/irs_data.c	Tue Mar 20 17:29:57 2007 -0700
@@ -57,10 +57,9 @@
 extern int h_errno;
 
 #ifdef	DO_PTHREADS
-static pthread_key_t	key;
-static int		once = 0;
+static pthread_key_t	key = PTHREAD_ONCE_KEY_NP;
 #else
-static struct net_data	*net_data;
+static struct net_data	*net_data = NULL;
 #endif
 
 void
@@ -126,22 +125,10 @@
 struct net_data *
 net_data_init(const char *conf_file) {
 #ifdef	DO_PTHREADS
-	static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER;
 	struct net_data *net_data;
 
-	if (!once) {
-		if (pthread_mutex_lock(&keylock) != 0)
-			return (NULL);
-		if (!once) {
-			if (pthread_key_create(&key, net_data_destroy) != 0) {
-				pthread_mutex_unlock(&keylock);
-				return (NULL);
-			}
-			once = 1;
-		}
-		if (pthread_mutex_unlock(&keylock) != 0)
-			return (NULL);
-	}
+	if (pthread_key_create_once_np(&key, net_data_destroy) != 0)
+		return (NULL);
 	net_data = pthread_getspecific(key);
 #endif
 
--- a/usr/src/lib/libsasl/lib/common.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libsasl/lib/common.c	Tue Mar 20 17:29:57 2007 -0700
@@ -1,7 +1,8 @@
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 /* common.c - Functions that are common to server and clinet
@@ -92,8 +93,7 @@
 static int _sasl_getconf(void *context, const char **conf);
 
 #ifdef _INTEGRATED_SOLARIS_
-static int init_thread_set_specific = 0;
-static pthread_key_t errstring_key;
+static pthread_key_t errstring_key = PTHREAD_ONCE_KEY_NP;
 #endif /* _INTEGRATED_SOLARIS_ */
 #else
 static const char build_ident[] = "$Build: libsasl " PACKAGE "-" VERSION " $";
@@ -1110,8 +1110,6 @@
 static void free_err_tsd(void *key)
 {
     free(key);
-
-    pthread_setspecific(errstring_key, NULL);
 }
 #endif /* _INTEGRATED_SOLARIS_ */
 
@@ -1216,21 +1214,13 @@
   if (s_utf8 == NULL)
     return s;
 
-  if (!init_thread_set_specific) {
-    LOCK_MUTEX(&global_mutex);
-    if (!init_thread_set_specific) {
-      if (pthread_key_create(&errstring_key, free_err_tsd) == 0)
-	init_thread_set_specific = 1;
-    }
-    UNLOCK_MUTEX(&global_mutex);
-  }
-  if (!init_thread_set_specific) {
+  if (pthread_key_create_once_np(&errstring_key, free_err_tsd) != 0) {
     free(s_utf8);
     return s;
   }
 
   tsd = pthread_getspecific(errstring_key);
-  if (tsd == NULL)
+  if (tsd != NULL)
     free(tsd);
   pthread_setspecific(errstring_key, s_utf8);
 
--- a/usr/src/lib/libscf/common/error.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libscf/common/error.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -80,36 +80,56 @@
 	((e) >= scf_errors[0].ei_code && \
 	    (e) < scf_errors[SCF_NUM_ERRORS - 1].ei_code + 10)
 
-static pthread_mutex_t	scf_key_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_key_t	scf_error_key;
-static volatile int	scf_error_key_setup;
+static scf_error_t	_scf_fallback_error = SCF_ERROR_NONE;
 
-static scf_error_t	_scf_fallback_error = SCF_ERROR_NONE;
+#if defined(PTHREAD_ONCE_KEY_NP)
+
+static pthread_key_t	scf_error_key = PTHREAD_ONCE_KEY_NP;
 
 int
 scf_setup_error(void)
 {
-	(void) pthread_mutex_lock(&scf_key_lock);
+	return (pthread_key_create_once_np(&scf_error_key, NULL) == 0);
+}
+
+#else	/* PTHREAD_ONCE_KEY_NP */
+
+/*
+ * This old code is here to enable the building of a native version
+ * of libscf.so when the build machine has not yet been upgraded
+ * to a version of libc that provides pthread_key_create_once_np().
+ * It should be deleted when solaris_nevada ships.
+ * This code is not MT-safe in a relaxed memory model.
+ */
+
+static pthread_key_t	scf_error_key = 0;
+
+int
+scf_setup_error(void)
+{
+	static pthread_mutex_t scf_key_lock = PTHREAD_MUTEX_INITIALIZER;
+	static volatile int scf_error_key_setup = 0;
+
 	if (scf_error_key_setup == 0) {
-		if (pthread_key_create(&scf_error_key, NULL) != 0)
-			scf_error_key_setup = -1;
-		else
-			scf_error_key_setup = 1;
+		(void) pthread_mutex_lock(&scf_key_lock);
+		if (scf_error_key_setup == 0) {
+			if (pthread_key_create(&scf_error_key, NULL) == 0)
+				scf_error_key_setup = 1;
+		}
+		(void) pthread_mutex_unlock(&scf_key_lock);
 	}
-	(void) pthread_mutex_unlock(&scf_key_lock);
 
 	return (scf_error_key_setup == 1);
 }
 
+#endif	/* PTHREAD_ONCE_KEY_NP */
+
 int
 scf_set_error(scf_error_t code)
 {
 	assert(LOOKS_VALID(code));
 
-	if (scf_error_key_setup == 0)
-		(void) scf_setup_error();
-
-	if (scf_error_key_setup > 0)
+	if (scf_setup_error())
 		(void) pthread_setspecific(scf_error_key, (void *)code);
 	else
 		_scf_fallback_error = code;
@@ -121,15 +141,9 @@
 {
 	scf_error_t ret;
 
-	if (scf_error_key_setup < 0)
-		return (_scf_fallback_error);
-
-	if (scf_error_key_setup == 0)
-		return (SCF_ERROR_NONE);
-
 	ret = (scf_error_t)pthread_getspecific(scf_error_key);
 	if (ret == 0)
-		return (SCF_ERROR_NONE);
+		return (_scf_fallback_error);
 	assert(LOOKS_VALID(ret));
 	return (ret);
 }
--- a/usr/src/lib/libsocket/inet/ether_addr.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libsocket/inet/ether_addr.c	Tue Mar 20 17:29:57 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -54,6 +54,7 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <thread.h>
+#include <pthread.h>
 #include <sys/socket.h>
 #include <net/if.h>
 #include <netinet/in.h>
@@ -240,27 +241,16 @@
 static eabuf_t *
 ea_buf(void)
 {
-	static thread_key_t key;
-	static int key_once = 0;
-	static mutex_t tsd_lock = DEFAULTMUTEX;
+	static thread_key_t key = THR_ONCE_KEY;
 	static eabuf_t ea_main;
-	eabuf_t *eabuf = NULL;
+	eabuf_t *eabuf;
 
 	if (thr_main())
 		return (&ea_main);
 
-	if (key_once == 0) {
-		(void) mutex_lock(&tsd_lock);
-		if (key_once == 0) {
-			if (thr_keycreate(&key, free) != 0) {
-				(void) mutex_unlock(&tsd_lock);
-				return (NULL);
-			}
-			key_once = 1;
-		}
-		(void) mutex_unlock(&tsd_lock);
-	}
-	(void) thr_getspecific(key, (void **)&eabuf);
+	if (thr_keycreate_once(&key, free) != 0)
+		return (NULL);
+	eabuf = pthread_getspecific(key);
 	if (eabuf == NULL) {
 		eabuf = malloc(sizeof (eabuf_t));
 		(void) thr_setspecific(key, eabuf);
--- a/usr/src/lib/libtnfprobe/probe_cntl.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libtnfprobe/probe_cntl.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -601,8 +601,7 @@
 }   /* end probestart */
 
 
-static thread_key_t tpd_key;
-static int key_created = 0;
+static thread_key_t tpd_key = THR_ONCE_KEY;
 static tnf_ops_t *stashed_tpd = NULL;
 
 /*
@@ -612,21 +611,12 @@
 tnf_thread_disable(void)
 {
 	tnf_ops_t		*ops;
-	static mutex_t		keylock = DEFAULTMUTEX;
 
 	if (thr_probe_setup != 0) {
 		/* threaded client */
 
-		if (!key_created) {
-			(void) mutex_lock(&keylock);
-			if (!key_created) {
-				/* REMIND: destructor function ? */
-				(void) thr_keycreate(&tpd_key, NULL);
-				key_created++;
-			}
-			(void) mutex_unlock(&keylock);
-		}
-
+		/* REMIND: destructor function ? */
+		(void) thr_keycreate_once(&tpd_key, NULL);
 		/* get the tpd */
 		ops = thr_probe_getfunc_addr();
 		/* check ops to ensure function is idempotent */
@@ -663,19 +653,15 @@
 	if (thr_probe_setup != 0) {
 		/* threaded client */
 
-		if (key_created) {
-			(void) thr_getspecific(tpd_key, (void *)&ops);
-			if (ops) {
-				thr_probe_setup(ops);
-			}
-		}
+		ops = pthread_getspecific(tpd_key);
+		if (ops)
+			thr_probe_setup(ops);
 	} else {
 		/* non-threaded client */
 
 		ops = stashed_tpd;
-		if (ops) {
+		if (ops)
 			probe_setup(ops);
-		}
 	}
 }
 
@@ -711,10 +697,7 @@
 			 */
 			if (thr_probe_setup != 0) {
 				/* threaded client */
-				if (key_created) {
-					(void) thr_getspecific(tpd_key,
-							(void *)&ops);
-				}
+				ops = pthread_getspecific(tpd_key);
 			} else {
 				/* non-threaded client */
 				ops = stashed_tpd;
--- a/usr/src/lib/libuutil/common/uu_misc.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/libuutil/common/uu_misc.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -44,9 +44,23 @@
 #define	TEXT_DOMAIN "SYS_TEST"
 #endif
 
+/*
+ * All of the old code under !defined(PTHREAD_ONCE_KEY_NP)
+ * is here to enable the building of a native version of
+ * libuutil.so when the build machine has not yet been upgraded
+ * to a version of libc that provides pthread_key_create_once_np().
+ * It should all be deleted when solaris_nevada ships.
+ * The code is not MT-safe in a relaxed memory model.
+ */
+
+#if defined(PTHREAD_ONCE_KEY_NP)
+static pthread_key_t	uu_error_key = PTHREAD_ONCE_KEY_NP;
+#else	/* PTHREAD_ONCE_KEY_NP */
+static pthread_key_t	uu_error_key = 0;
 static pthread_mutex_t	uu_key_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_key_t	uu_error_key;
-static int		uu_error_key_setup;
+#endif	/* PTHREAD_ONCE_KEY_NP */
+
+static int		uu_error_key_setup = 0;
 
 static pthread_mutex_t	uu_panic_lock = PTHREAD_MUTEX_INITIALIZER;
 /* LINTED static unused */
@@ -60,22 +74,27 @@
 void
 uu_set_error(uint_t code)
 {
-	int error;
 	if (thr_main() != 0) {
 		_uu_main_error = code;
 		return;
 	}
+#if defined(PTHREAD_ONCE_KEY_NP)
+	if (pthread_key_create_once_np(&uu_error_key, NULL) != 0)
+		uu_error_key_setup = -1;
+	else
+		uu_error_key_setup = 1;
+#else	/* PTHREAD_ONCE_KEY_NP */
 	if (uu_error_key_setup == 0) {
 		(void) pthread_mutex_lock(&uu_key_lock);
 		if (uu_error_key_setup == 0) {
-			error = pthread_key_create(&uu_error_key, NULL);
-			if (error != 0)
+			if (pthread_key_create(&uu_error_key, NULL) != 0)
 				uu_error_key_setup = -1;
 			else
 				uu_error_key_setup = 1;
 		}
 		(void) pthread_mutex_unlock(&uu_key_lock);
 	}
+#endif	/* PTHREAD_ONCE_KEY_NP */
 	if (uu_error_key_setup > 0)
 		(void) pthread_setspecific(uu_error_key,
 		    (void *)(uintptr_t)code);
@@ -87,12 +106,14 @@
 	if (thr_main() != 0)
 		return (_uu_main_error);
 
-	if (uu_error_key_setup < 0)
+	if (uu_error_key_setup < 0)	/* can't happen? */
 		return (UU_ERROR_UNKNOWN);
-	else if (uu_error_key_setup == 0)
-		return (UU_ERROR_NONE);
-	else
-		return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key));
+
+	/*
+	 * Because UU_ERROR_NONE == 0, if uu_set_error() was
+	 * never called, then this will return UU_ERROR_NONE:
+	 */
+	return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key));
 }
 
 const char *
@@ -199,7 +220,9 @@
 uu_lockup(void)
 {
 	(void) pthread_mutex_lock(&uu_panic_lock);
+#if !defined(PTHREAD_ONCE_KEY_NP)
 	(void) pthread_mutex_lock(&uu_key_lock);
+#endif
 	uu_avl_lockup();
 	uu_list_lockup();
 }
@@ -208,7 +231,9 @@
 uu_release(void)
 {
 	(void) pthread_mutex_unlock(&uu_panic_lock);
+#if !defined(PTHREAD_ONCE_KEY_NP)
 	(void) pthread_mutex_unlock(&uu_key_lock);
+#endif
 	uu_avl_release();
 	uu_list_release();
 }
--- a/usr/src/lib/rpcsec_gss/rpcsec_gss.c	Tue Mar 20 13:38:31 2007 -0700
+++ b/usr/src/lib/rpcsec_gss/rpcsec_gss.c	Tue Mar 20 17:29:57 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -19,9 +18,10 @@
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright (c) 1986-1995, 1997, 2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -60,9 +60,9 @@
  */
 extern bool_t	xdr_opaque_auth(XDR *, struct opaque_auth *);
 extern int	_thr_main(void);
-extern int	_thr_getspecific(thread_key_t key, void **valuep);
+extern void	*_pthread_getspecific(pthread_key_t key);
 typedef void	(*PFrV) (void *);
-extern int	_thr_keycreate(thread_key_t *pkey, PFrV destructor);
+extern int	_thr_keycreate_once(thread_key_t *pkey, PFrV destructor);
 extern int	_thr_setspecific(unsigned int key, void *value);
 
 
@@ -124,19 +124,15 @@
 	AUTH			*auth = NULL;
 	rpc_gss_data		*ap = NULL;
 	OM_uint32		qop_num;
-	rpc_gss_error_t		error;
-	void			__rpc_gss_get_error();
 
 	/*
 	 * convert ascii strings to GSS values
 	 */
 	if (!__rpc_gss_qop_to_num(qop, mech, &qop_num)) {
-		__rpc_gss_get_error(&error);
 		return (NULL);
 	}
 
 	if (!__rpc_gss_mech_to_oid(mech, &mech_type)) {
-		__rpc_gss_get_error(&error);
 		return (NULL);
 	}
 
@@ -900,46 +896,34 @@
 			max_tp_unit_len));
 }
 
+void
+__rpc_gss_get_error(rpc_gss_error_t *error)
+{
+	*error = rpc_gss_err;
+}
+
 #undef  rpc_gss_err
 
 rpc_gss_error_t	rpc_gss_err;
-static mutex_t	rge_lock;		/* protects TSD key creation */
 
 rpc_gss_error_t *
 __rpc_gss_err()
 {
-	static thread_key_t rpc_gss_err_key = 0;
-	rpc_gss_error_t *tsd = 0;
+	static thread_key_t rpc_gss_err_key = THR_ONCE_KEY;
+	rpc_gss_error_t *tsd;
 
 	if (_thr_main())
 		return (&rpc_gss_err);
-	if (_thr_getspecific(rpc_gss_err_key, (void **) &tsd) != 0) {
-		mutex_lock(&rge_lock);
-		if (_thr_keycreate(&rpc_gss_err_key, free) != 0) {
-			mutex_unlock(&rge_lock);
-			return (&rpc_gss_err);
-		}
-		mutex_unlock(&rge_lock);
-	}
-	if (!tsd) {
-		tsd = (rpc_gss_error_t *)
-			calloc(1, sizeof (rpc_gss_error_t));
-		if (_thr_setspecific(rpc_gss_err_key, (void *) tsd) != 0) {
+	if (_thr_keycreate_once(&rpc_gss_err_key, free) != 0)
+		return (&rpc_gss_err);
+	tsd = _pthread_getspecific(rpc_gss_err_key);
+	if (tsd == NULL) {
+		tsd = (rpc_gss_error_t *)calloc(1, sizeof (rpc_gss_error_t));
+		if (_thr_setspecific(rpc_gss_err_key, tsd) != 0) {
 			if (tsd)
 				free(tsd);
 			return (&rpc_gss_err);
 		}
-		memset(tsd, 0, sizeof (rpc_gss_error_t));
-		return (tsd);
 	}
 	return (tsd);
 }
-
-void
-__rpc_gss_get_error(error)
-	rpc_gss_error_t	*error;
-{
-
-	error->rpc_gss_error = rpc_gss_err.rpc_gss_error;
-	error->system_error = rpc_gss_err.system_error;
-}