blob: c03f0abe8a20cd2cdddab5b3df8a716b123780f7 [file] [log] [blame]
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -07001/* $OpenBSD: thread_private.h,v 1.18 2006/02/22 07:16:31 otto Exp $ */
2
3/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */
4
5#ifndef _THREAD_PRIVATE_H_
6#define _THREAD_PRIVATE_H_
7
8#include <pthread.h>
9
10/*
11 * This file defines the thread library interface to libc. Thread
12 * libraries must implement the functions described here for proper
13 * inter-operation with libc. libc contains weak versions of the
14 * described functions for operation in a non-threaded environment.
15 */
16
17/*
18 * This variable is 0 until a second thread is created.
19 */
20extern int __isthreaded;
21
22/*
23 * Weak symbols are used in libc so that the thread library can
24 * efficiently wrap libc functions.
25 *
26 * Use WEAK_NAME(n) to get a libc-private name for n (_weak_n),
27 * WEAK_ALIAS(n) to generate the weak symbol n pointing to _weak_n,
28 * WEAK_PROTOTYPE(n) to generate a prototype for _weak_n (based on n).
29 */
30#define WEAK_NAME(name) __CONCAT(_weak_,name)
31#define WEAK_ALIAS(name) __weak_alias(name, WEAK_NAME(name))
32#ifdef __GNUC__
33#define WEAK_PROTOTYPE(name) __typeof__(name) WEAK_NAME(name)
34#else
35#define WEAK_PROTOTYPE(name) /* typeof() only in gcc */
36#endif
37
38/*
39 * helper macro to make unique names in the thread namespace
40 */
41#define __THREAD_NAME(name) __CONCAT(_thread_tagname_,name)
42
43struct __thread_private_tag_t {
44 pthread_mutex_t _private_lock;
45 pthread_key_t _private_key;
46};
47
48#define _THREAD_PRIVATE_MUTEX(name) \
49 static struct __thread_private_tag_t __THREAD_NAME(name) = { PTHREAD_MUTEX_INITIALIZER, -1 }
50#define _THREAD_PRIVATE_MUTEX_LOCK(name) \
51 pthread_mutex_lock( &__THREAD_NAME(name)._private_lock )
52#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
53 pthread_mutex_unlock( &__THREAD_NAME(name)._private_lock )
54
55#define _THREAD_PRIVATE_KEY(name) \
56 static struct __thread_private_tag_t __THREAD_NAME(name) = { PTHREAD_MUTEX_INITIALIZER, -1 }
57
58extern void* __bionic_thread_private_storage( struct __thread_private_tag_t* ptag, void* storage, size_t objsize, void* error );
59
60#define _THREAD_PRIVATE(name, storage, error) \
61 __bionic_thread_private_storage( &__THREAD_NAME(name), &(storage),sizeof(storage), error)
62
63#if 0
64/*
65 * helper functions that exist as (weak) null functions in libc and
66 * (strong) functions in the thread library. These functions:
67 *
68 * _thread_tag_lock:
69 * lock the mutex associated with the given tag. If the given
70 * tag is NULL a tag is first allocated.
71 *
72 * _thread_tag_unlock:
73 * unlock the mutex associated with the given tag. If the given
74 * tag is NULL a tag is first allocated.
75 *
76 * _thread_tag_storage:
77 * return a pointer to per thread instance of data associated
78 * with the given tag. If the given tag is NULL a tag is first
79 * allocated.
80 */
81void _thread_tag_lock(void **);
82void _thread_tag_unlock(void **);
83void *_thread_tag_storage(void **, void *, size_t, void *);
84
85/*
86 * Macros used in libc to access thread mutex, keys, and per thread storage.
87 * _THREAD_PRIVATE_KEY and _THREAD_PRIVATE_MUTEX are different macros for
88 * historical reasons. They do the same thing, define a static variable
89 * keyed by 'name' that identifies a mutex and a key to identify per thread
90 * data.
91 */
92#define _THREAD_PRIVATE_KEY(name) \
93 static void *__THREAD_NAME(name)
94#define _THREAD_PRIVATE_MUTEX(name) \
95 static void *__THREAD_NAME(name)
96#define _THREAD_PRIVATE_MUTEX_LOCK(name) \
97 _thread_tag_lock(&(__THREAD_NAME(name)))
98#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
99 _thread_tag_unlock(&(__THREAD_NAME(name)))
100#define _THREAD_PRIVATE(keyname, storage, error) \
101 _thread_tag_storage(&(__THREAD_NAME(keyname)), &(storage), \
102 sizeof (storage), error)
103/*
104 * Resolver code is special cased in that it uses global keys.
105 */
106extern void *__THREAD_NAME(_res);
107extern void *__THREAD_NAME(_res_ext);
108extern void *__THREAD_NAME(serv_mutex);
109#endif
110
111/*
112 * File descriptor locking definitions.
113 */
114#define FD_READ 0x1
115#define FD_WRITE 0x2
116#define FD_RDWR (FD_READ | FD_WRITE)
117
118struct timespec;
119int _thread_fd_lock(int, int, struct timespec *);
120void _thread_fd_unlock(int, int);
121
122/*
123 * Macros are used in libc code for historical (debug) reasons.
124 * Define them here.
125 */
126#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts)
127#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type)
128
129
130/*
131 * malloc lock/unlock prototypes and definitions
132 */
133void _thread_malloc_init(void);
134void _thread_malloc_lock(void);
135void _thread_malloc_unlock(void);
136
137#define _MALLOC_LOCK() do { \
138 if (__isthreaded) \
139 _thread_malloc_lock(); \
140 } while (0)
141#define _MALLOC_UNLOCK() do { \
142 if (__isthreaded) \
143 _thread_malloc_unlock();\
144 } while (0)
145#define _MALLOC_LOCK_INIT() do { \
146 if (__isthreaded) \
147 _thread_malloc_init();\
148 } while (0)
149
150void _thread_atexit_lock(void);
151void _thread_atexit_unlock(void);
152
153#define _ATEXIT_LOCK() do { \
154 if (__isthreaded) \
155 _thread_atexit_lock(); \
156 } while (0)
157#define _ATEXIT_UNLOCK() do { \
158 if (__isthreaded) \
159 _thread_atexit_unlock();\
160 } while (0)
161
162#endif /* _THREAD_PRIVATE_H_ */