1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
/* $OpenBSD: thread_private.h,v 1.7 2001/08/12 12:03:01 heko Exp $ */
#ifndef _THREAD_PRIVATE_H_
#define _THREAD_PRIVATE_H_
#include <pthread.h>
/*
* This variable is initially 0 when there is exactly one thread.
* It should never decrease.
*/
extern int __isthreaded;
/*
* Weak symbols are used in libc so that the thread library can
* efficiently wrap libc functions.
*
* Use WEAK_NAME(n) to get a libc-private name for n (_weak_n),
* 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).
*
* If the symbol _NO_WEAK_ALIASES is defined, then symbols will be
*/
#ifdef _NO_WEAK_ALIASES
#ifdef _THREAD_SAFE
#define WEAK_NAME(name) __CONCAT(_weak,name)
#else
#define WEAK_NAME(name) name
#endif
#define WEAK_ALIAS(name) /* unavailable */
#define WEAK_PROTOTYPE(name) /* unnecessary */
#else /* !_NO_WEAK_ALIASES */
#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)
#else
#define WEAK_PROTOTYPE(name) /* typeof() only in gcc */
#endif
#endif /* !_NO_WEAK_ALIASES */
/*
* 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.
*/
#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)__P((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 \
}
/*
* 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.
*/
#define _THREAD_PRIVATE(keyname, storage, error) \
_libc_private_storage(&__THREAD_KEY_NAME(keyname), \
&(storage), sizeof (storage), error)
/*
* Macros for locking and unlocking FILEs. These test if the
* process is threaded to avoid locking when not required.
*/
#ifdef _FLOCK_DEBUG
#define FLOCKFILE(fp) _flockfile_debug(fp, __FILE__, __LINE__)
#else
#define FLOCKFILE(fp) flockfile(fp)
#endif
#define FUNLOCKFILE(fp) funlockfile(fp)
/*
* File descriptor locking definitions.
*/
#define FD_READ 0x1
#define FD_WRITE 0x2
#define FD_RDWR (FD_READ | FD_WRITE)
#ifdef _LOCK_DEBUG
#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock_debug(_fd, _type, \
_ts, __FILE__, __LINE__)
#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock_debug(_fd, _type, \
__FILE__, __LINE__)
#else
#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts)
#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type)
#endif
int _thread_fd_lock(int, int, struct timespec *);
int _thread_fd_lock_debug(int, int, struct timespec *, const char *, int);
void _thread_fd_unlock(int, int);
void _thread_fd_unlock_debug(int, int, const char *, int);
#endif /* _THREAD_PRIVATE_H_ */
|