svn commit: r202201 - stable/8/lib/libc/stdtime

John Baldwin jhb at FreeBSD.org
Wed Jan 13 18:12:22 UTC 2010


Author: jhb
Date: Wed Jan 13 18:12:21 2010
New Revision: 202201
URL: http://svn.freebsd.org/changeset/base/202201

Log:
  MFC 199607, 200797, 201270, 201669:
  Use pthread_once() to initialize the thread-local storage for localtime()
  and gmtime() and _once() to initialize gmt state rather than home-rolled
  versions using pthread mutex locks.

Modified:
  stable/8/lib/libc/stdtime/localtime.c
Directory Properties:
  stable/8/lib/libc/   (props changed)
  stable/8/lib/libc/stdtime/   (props changed)

Modified: stable/8/lib/libc/stdtime/localtime.c
==============================================================================
--- stable/8/lib/libc/stdtime/localtime.c	Wed Jan 13 18:09:54 2010	(r202200)
+++ stable/8/lib/libc/stdtime/localtime.c	Wed Jan 13 18:12:21 2010	(r202201)
@@ -235,9 +235,14 @@ static struct state	gmtmem;
 
 static char		lcl_TZname[TZ_STRLEN_MAX + 1];
 static int		lcl_is_set;
-static int		gmt_is_set;
+static pthread_once_t	gmt_once = PTHREAD_ONCE_INIT;
 static pthread_rwlock_t	lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER;
-static pthread_mutex_t	gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_once_t	gmtime_once = PTHREAD_ONCE_INIT;
+static pthread_key_t	gmtime_key;
+static int		gmtime_key_error;
+static pthread_once_t	localtime_once = PTHREAD_ONCE_INIT;
+static pthread_key_t	localtime_key;
+static int		localtime_key_error;
 
 char *			tzname[2] = {
 	wildabbr,
@@ -1407,27 +1412,24 @@ struct tm * const	tmp;
 	return result;
 }
 
+static void
+localtime_key_init(void)
+{
+
+	localtime_key_error = _pthread_key_create(&localtime_key, free);
+}
+
 struct tm *
 localtime(timep)
 const time_t * const	timep;
 {
-	static pthread_mutex_t localtime_mutex = PTHREAD_MUTEX_INITIALIZER;
-	static pthread_key_t localtime_key = -1;
 	struct tm *p_tm;
-	int r;
 
 	if (__isthreaded != 0) {
-		if (localtime_key < 0) {
-			_pthread_mutex_lock(&localtime_mutex);
-			if (localtime_key < 0) {
-				if ((r = _pthread_key_create(&localtime_key,
-				    free)) != 0) {
-					_pthread_mutex_unlock(&localtime_mutex);
-					errno = r;
-					return(NULL);
-				}
-			}
-			_pthread_mutex_unlock(&localtime_mutex);
+		_pthread_once(&localtime_once, localtime_key_init);
+		if (localtime_key_error != 0) {
+			errno = localtime_key_error;
+			return(NULL);
 		}
 		p_tm = _pthread_getspecific(localtime_key);
 		if (p_tm == NULL) {
@@ -1464,6 +1466,17 @@ struct tm *		tmp;
 	return tmp;
 }
 
+static void
+gmt_init(void)
+{
+
+#ifdef ALL_STATE
+	gmtptr = (struct state *) malloc(sizeof *gmtptr);
+	if (gmtptr != NULL)
+#endif /* defined ALL_STATE */
+		gmtload(gmtptr);
+}
+
 /*
 ** gmtsub is to gmtime as localsub is to localtime.
 */
@@ -1476,16 +1489,7 @@ struct tm * const	tmp;
 {
 	register struct tm *	result;
 
-	_MUTEX_LOCK(&gmt_mutex);
-	if (!gmt_is_set) {
-#ifdef ALL_STATE
-		gmtptr = (struct state *) malloc(sizeof *gmtptr);
-		if (gmtptr != NULL)
-#endif /* defined ALL_STATE */
-			gmtload(gmtptr);
-		gmt_is_set = TRUE;
-	}
-	_MUTEX_UNLOCK(&gmt_mutex);
+	_once(&gmt_once, gmt_init);
 	result = timesub(timep, offset, gmtptr, tmp);
 #ifdef TM_ZONE
 	/*
@@ -1509,27 +1513,24 @@ struct tm * const	tmp;
 	return result;
 }
 
+static void
+gmtime_key_init(void)
+{
+
+	gmtime_key_error = _pthread_key_create(&gmtime_key, free);
+}
+
 struct tm *
 gmtime(timep)
 const time_t * const	timep;
 {
-	static pthread_mutex_t gmtime_mutex = PTHREAD_MUTEX_INITIALIZER;
-	static pthread_key_t gmtime_key = -1;
 	struct tm *p_tm;
-	int r;
 
 	if (__isthreaded != 0) {
-		if (gmtime_key < 0) {
-			_pthread_mutex_lock(&gmtime_mutex);
-			if (gmtime_key < 0) {
-				if ((r = _pthread_key_create(&gmtime_key,
-				    free)) != 0) {
-					_pthread_mutex_unlock(&gmtime_mutex);
-					errno = r;
-					return(NULL);
-				}
-			}
-			_pthread_mutex_unlock(&gmtime_mutex);
+		_pthread_once(&gmtime_once, gmtime_key_init);
+		if (gmtime_key_error != 0) {
+			errno = gmtime_key_error;
+			return(NULL);
 		}
 		/*
 		 * Changed to follow POSIX.1 threads standard, which


More information about the svn-src-stable-8 mailing list