summaryrefslogtreecommitdiff
path: root/lib/libc/include/thread_private.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/include/thread_private.h')
-rw-r--r--lib/libc/include/thread_private.h160
1 files changed, 76 insertions, 84 deletions
diff --git a/lib/libc/include/thread_private.h b/lib/libc/include/thread_private.h
index 4212e7dcb2e..edac6b008d0 100644
--- a/lib/libc/include/thread_private.h
+++ b/lib/libc/include/thread_private.h
@@ -1,13 +1,19 @@
-/* $OpenBSD: thread_private.h,v 1.15 2003/01/28 04:58:00 marc Exp $ */
+/* $OpenBSD: thread_private.h,v 1.16 2004/06/07 21:11:23 marc Exp $ */
+
+/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */
#ifndef _THREAD_PRIVATE_H_
#define _THREAD_PRIVATE_H_
-#include <pthread.h>
+/*
+ * This file defines the thread library interface to libc. Thread
+ * libraries must implement the functions described here for proper
+ * inter-operation with libc. libc contains weak versions of the
+ * described functions for operation in a non-threaded environment.
+ */
/*
- * This variable is initially 0 when there is exactly one thread.
- * It should never decrease.
+ * This variable is 0 until a second thread is created.
*/
extern int __isthreaded;
@@ -19,116 +25,102 @@ extern int __isthreaded;
* WEAK_ALIAS(n) to generate the weak symbol n pointing to _weak_n,
* WEAK_PROTOTYPE(n) to generate a prototype for _weak_n (based on n).
*/
-#define WEAK_NAME(name) __CONCAT(_weak_,name)
-#define WEAK_ALIAS(name) __weak_alias(name, WEAK_NAME(name))
+#define WEAK_NAME(name) __CONCAT(_weak_,name)
+#define WEAK_ALIAS(name) __weak_alias(name, WEAK_NAME(name))
#ifdef __GNUC__
-#define WEAK_PROTOTYPE(name) __typeof__(name) WEAK_NAME(name)
+#define WEAK_PROTOTYPE(name) __typeof__(name) WEAK_NAME(name)
#else
-#define WEAK_PROTOTYPE(name) /* typeof() only in gcc */
+#define WEAK_PROTOTYPE(name) /* typeof() only in gcc */
#endif
/*
- * These macros help in making persistent storage thread-specific.
- * Libc makes extensive use of private static data structures
- * that hold state across function invocation, and these macros
- * are no-ops when running single-threaded.
- *
- * Linking against the user-thread library causes these macros to
- * allocate storage on a per-thread basis.
+ * helper macro to make unique names in the thread namespace
*/
-
-#define __THREAD_MUTEX_NAME(name) __CONCAT(_libc_storage_mutex_,name)
-#define __THREAD_KEY_NAME(name) __CONCAT(_libc_storage_key_,name)
-
-struct _thread_private_key_struct {
- pthread_once_t once;
- void (*cleanfn)(void *);
- pthread_key_t key;
-};
-
-void _libc_private_storage_lock(pthread_mutex_t *);
-void _libc_private_storage_unlock(pthread_mutex_t *);
-void * _libc_private_storage(volatile struct _thread_private_key_struct *,
- void *, size_t, void *);
-
-/* Declare a module mutex. */
-#define _THREAD_PRIVATE_MUTEX(name) \
- static pthread_mutex_t __THREAD_MUTEX_NAME(name) = \
- PTHREAD_MUTEX_INITIALIZER
-
-/* Lock a module mutex against use by any other threads. */
-#define _THREAD_PRIVATE_MUTEX_LOCK(name) \
- _libc_private_storage_lock(&__THREAD_MUTEX_NAME(name))
-
-/* Unlock a module mutex. */
-#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
- _libc_private_storage_unlock(&__THREAD_MUTEX_NAME(name))
-
-/* Declare a thread-private storage key. */
-#define _THREAD_PRIVATE_KEY(name) \
- static volatile struct _thread_private_key_struct \
- __THREAD_KEY_NAME(name) = { \
- PTHREAD_ONCE_INIT, \
- 0 \
- }
+#define __THREAD_NAME(name) __CONCAT(_thread_tagname_,name)
/*
- * In threaded mode, return a pointer to thread-private memory of
- * the same size as, and (initially) with the same contents as 'storage'. If
- * an error occurs, the 'error' parameter is returned.
- * In single-threaded mode, no storage is allocated. Instead, a pointer
- * to storage is always returned.
- * The 'cleanfn' function of the key structure is called to free the storage.
- * If 'cleanfn' is NULL, then free() is used. This hook can be useful for
- * getting rid of memory leaks.
+ * helper functions that exist as (weak) null functions in libc and
+ * (strong) functions in the thread library. These functions:
+ *
+ * _thread_tag_lock:
+ * lock the mutex associated with the given tag. If the given
+ * tag is NULL a tag is first allocated.
+ *
+ * _thread_tag_unlock:
+ * unlock the mutex associated with the given tag. If the given
+ * tag is NULL a tag is first allocated.
+ *
+ * _thread_tag_storage:
+ * return a pointer to per thread instance of data associated
+ * with the given tag. If the given tag is NULL a tag is first
+ * allocated.
*/
-#define _THREAD_PRIVATE(keyname, storage, error) \
- _libc_private_storage(&__THREAD_KEY_NAME(keyname), \
- &(storage), sizeof (storage), error)
+void _thread_tag_lock(void **);
+void _thread_tag_unlock(void **);
+void *_thread_tag_storage(void **, void *, size_t, void *);
/*
- * Keys used to access the per thread instances of resolver global data.
- * These are not static as they are referenced in several places.
+ * Macros used in libc to access thread mutex, keys, and per thread storage.
+ * _THREAD_PRIVATE_KEY and _THREAD_PRIVATE_MUTEX are different macros for
+ * historical reasons. They do the same thing, define a static variable
+ * keyed by 'name' that identifies a mutex and a key to identify per thread
+ * data.
*/
-extern volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res);
-#ifdef INET6
-extern volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res_ext);
-#endif
+#define _THREAD_PRIVATE_KEY(name) \
+ static void *__THREAD_NAME(name)
+#define _THREAD_PRIVATE_MUTEX(name) \
+ static void *__THREAD_NAME(name)
+#define _THREAD_PRIVATE_MUTEX_LOCK(name) \
+ _thread_tag_lock(&(__THREAD_NAME(name)))
+#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
+ _thread_tag_unlock(&(__THREAD_NAME(name)))
+#define _THREAD_PRIVATE(keyname, storage, error) \
+ _thread_tag_storage(&(__THREAD_NAME(keyname)), &(storage), \
+ sizeof (storage), error)
+/*
+ * Resolver code is special cased in that it uses global keys.
+ */
+extern void *__THREAD_NAME(_res);
+extern void *__THREAD_NAME(_res_ext);
+extern void *__THREAD_NAME(serv_mutex);
/*
* File descriptor locking definitions.
*/
-#define FD_READ 0x1
-#define FD_WRITE 0x2
-#define FD_RDWR (FD_READ | FD_WRITE)
+#define FD_READ 0x1
+#define FD_WRITE 0x2
+#define FD_RDWR (FD_READ | FD_WRITE)
+
+int _thread_fd_lock(int, int, struct timespec *);
+void _thread_fd_unlock(int, int);
-#define _FD_LOCK(_fd,_type,_ts) \
- _thread_fd_lock(_fd, _type, _ts, __FILE__, __LINE__)
-#define _FD_UNLOCK(_fd,_type) \
- _thread_fd_unlock(_fd, _type, __FILE__, __LINE__)
+/*
+ * Macros are used in libc code for historical (debug) reasons.
+ * Define them here.
+ */
+#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts)
+#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type)
-int _thread_fd_lock(int, int, struct timespec *, const char *, int);
-void _thread_fd_unlock(int, int, const char *, int);
/*
- * malloc lock/unlock definitions
+ * malloc lock/unlock prototypes and definitions
*/
-# define _MALLOC_LOCK() do { \
+void _thread_malloc_init(void);
+void _thread_malloc_lock(void);
+void _thread_malloc_unlock(void);
+
+#define _MALLOC_LOCK() do { \
if (__isthreaded) \
_thread_malloc_lock(); \
} while (0)
-# define _MALLOC_UNLOCK() do { \
+#define _MALLOC_UNLOCK() do { \
if (__isthreaded) \
_thread_malloc_unlock();\
} while (0)
-# define _MALLOC_LOCK_INIT()do { \
+#define _MALLOC_LOCK_INIT() do { \
if (__isthreaded) \
_thread_malloc_init();\
} while (0)
-void _thread_malloc_init(void);
-void _thread_malloc_lock(void);
-void _thread_malloc_unlock(void);
-
#endif /* _THREAD_PRIVATE_H_ */