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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
|
/* Internal defenitions for pthreads library.
Copyright (C) 2000, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _PT_INTERNAL_H
#define _PT_INTERNAL_H 1
#include <pthread.h>
#include <stddef.h>
#include <sched.h>
#include <signal.h>
#include <assert.h>
#include <atomic.h>
#include <pt-key.h>
#include <pt-sysdep.h>
#include <pt-machdep.h>
#include <sig-internal.h>
/* Thread state. */
enum pthread_state
{
PTHREAD_JOINABLE = 0,
PTHREAD_DETACHED,
PTHREAD_EXITED,
PTHREAD_TERMINATED
};
#ifndef PTHREAD_KEY_MEMBERS
# define PTHREAD_KEY_MEMBERS
#endif
#ifndef PTHREAD_SYSDEP_MEMBERS
# define PTHREAD_SYSDEP_MEMBERS
#endif
#ifndef PTHREAD_SIGNAL_MEMBERS
# define PTHREAD_SIGNAL_MEMBERS
#endif
/* This structure describes a POSIX thread. */
struct __pthread
{
/* Thread ID. */
pthread_t thread;
/* Cancellation. */
int cancel_state;
int cancel_type;
int cancel_pending;
struct __pthread_cancelation_handler *cancelation_handlers;
/* Thread stack. */
void *stackaddr;
size_t stacksize;
size_t guardsize; /* Included in STACKSIZE (i.e. total
stack memory is STACKSIZE, not
STACKSIZE + GUARDSIZE). */
int stack; /* Nonzero if the stack was allocated. */
/* Exit status. */
void *status;
/* Thread state. */
enum pthread_state state;
pthread_mutex_t state_lock; /* Locks the state. */
pthread_cond_t state_cond; /* Signalled when the state changes. */
/* Thread context. */
struct pthread_mcontext mcontext;
PTHREAD_KEY_MEMBERS
PTHREAD_SYSDEP_MEMBERS
PTHREAD_SIGNAL_MEMBERS
struct __pthread *next, **prevp;
};
/* Enqueue an element THREAD on the queue *HEAD. */
static inline void
__pthread_enqueue (struct __pthread **head, struct __pthread *thread)
{
assert (thread->prevp == 0);
thread->next = *head;
thread->prevp = head;
if (*head)
(*head)->prevp = &thread->next;
*head = thread;
}
/* Dequeue the element THREAD from the queue it is connected to. */
static inline void
__pthread_dequeue (struct __pthread *thread)
{
assert (thread);
if (thread->next)
thread->next->prevp = thread->prevp;
*thread->prevp = thread->next;
thread->prevp = 0;
}
/* Iterate over QUEUE storing each element in ELEMENT. */
#define __pthread_queue_iterate(queue, element) \
for (element = queue; element; element = element->next)
/* Iterate over QUEUE dequeuing each element, storing it in
ELEMENT. */
#define __pthread_dequeuing_iterate(queue, element) \
for (element = queue; \
element && ((element->prevp = 0), 1); \
element = element->next)
/* The total number of threads currently active. */
extern atomic_fast32_t __pthread_total;
/* The total number of thread IDs currently in use, or on the list of
available thread IDs. */
extern int __pthread_num_threads;
/* Concurrency hint. */
extern int __pthread_concurrency;
/* Array of __pthread structures and its lock. Indexed by the pthread
id minus one. (Why not just use the pthread id? Because some
brain-dead users of the pthread interface incorrectly assume that 0
is an invalid pthread id.) */
extern struct __pthread **__pthread_threads;
extern pthread_rwlock_t __pthread_threads_lock;
#define __pthread_getid(thread) \
({ struct __pthread *__t; \
pthread_rwlock_rdlock (&__pthread_threads_lock); \
__t = __pthread_threads[thread - 1]; \
pthread_rwlock_unlock (&__pthread_threads_lock); \
__t; })
#define __pthread_setid(thread, pthread) \
pthread_rwlock_wrlock (&__pthread_threads_lock); \
__pthread_threads[thread - 1] = pthread; \
pthread_rwlock_unlock (&__pthread_threads_lock);
/* Similar to pthread_self, but returns the thread descriptor instead
of the thread ID. */
#ifndef _pthread_self
extern struct __pthread *_pthread_self (void);
#endif
/* Initialize the pthreads library. */
extern void __pthread_initialize (void);
/* Internal version of pthread_create. Rather than return the new
tid, we return the whole __pthread structure in *PTHREAD. */
extern int __pthread_create_internal (struct __pthread **__restrict pthread,
const pthread_attr_t *__restrict attr,
void *(*start_routine)(void *),
void *__restrict arg);
/* Allocate a new thread structure and a pthread thread ID (but not a
kernel thread or a stack). */
extern int __pthread_alloc (struct __pthread **thread);
/* Deallocate the thread structure. This is the dual of
__pthread_alloc (N.B. it does not call __pthread_stack_alloc nor
__pthread_thread_halt). */
extern void __pthread_dealloc (struct __pthread *thread);
/* Allocate a stack of size STACKSIZE. The stack base shall be
returned in *STACKADDR. */
extern int __pthread_stack_alloc (void **stackaddr, size_t stacksize);
/* Deallocate the stack STACKADDR of size STACKSIZE. */
extern void __pthread_stack_dealloc (void *stackaddr, size_t stacksize);
/* Setup thread THREAD's context. */
extern int __pthread_setup (struct __pthread *__restrict thread,
void (*entry_point)(void *(*)(void *),
void *),
void *(*start_routine)(void *),
void *__restrict arg);
/* Allocate a kernel thread (and any miscellaneous system dependent
resources) for THREAD; it must not be placed on the run queue. */
extern int __pthread_thread_alloc (struct __pthread *thread);
/* Deallocate any kernel resources associated with THREAD except don't
halt the thread itself. On return, the thread will be marked as
dead and __pthread_halt will be called. */
extern void __pthread_thread_dealloc (struct __pthread *thread);
/* Start THREAD making it eligible to run. */
extern int __pthread_thread_start (struct __pthread *thread);
/* Stop the kernel thread associated with THREAD. If NEED_DEALLOC is
true, the function must call __pthread_dealloc on THREAD.
NB: The thread executing this function may be the thread which is
being halted, thus the last action should be halting the thread
itself. */
extern void __pthread_thread_halt (struct __pthread *thread,
int need_dealloc);
/* Called by a thread just before it calls the provided start
routine. */
extern void __pthread_startup (void);
/* Block THREAD. */
extern void __pthread_block (struct __pthread *thread);
/* Block THREAD until *ABSTIME is reached. */
extern error_t __pthread_timedblock (struct __pthread *__restrict thread,
const struct timespec *__restrict abstime);
/* Wakeup THREAD. */
extern void __pthread_wakeup (struct __pthread *thread);
/* Perform a cancelation. */
extern int __pthread_do_cancel (struct __pthread *thread);
/* Initialize the thread specific data structures. THREAD must be the
calling thread. */
extern error_t __pthread_init_specific (struct __pthread *thread);
/* Call the destructors on all of the thread specific data in THREAD.
THREAD must be the calling thread. */
extern void __pthread_destroy_specific (struct __pthread *thread);
/* Initialize newly create thread *THREAD's signal state data
structures. */
extern error_t __pthread_sigstate_init (struct __pthread *thread);
/* Destroy the signal state data structures associcated with thread
*THREAD. */
extern void __pthread_sigstate_destroy (struct __pthread *thread);
/* Modify thread *THREAD's signal state. */
extern error_t __pthread_sigstate (struct __pthread *__restrict thread, int how,
const sigset_t *__restrict set,
sigset_t *__restrict oset,
int clear_pending);
/* Default thread attributes. */
extern const struct __pthread_attr __pthread_default_attr;
/* Default barrier attributes. */
extern const struct __pthread_barrierattr __pthread_default_barrierattr;
/* Default mutex attributes. */
extern const struct __pthread_mutexattr __pthread_default_mutexattr;
/* Default rdlock attributes. */
const struct __pthread_rwlockattr __pthread_default_rwlockattr;
/* Default condition attributes. */
const struct __pthread_condattr __pthread_default_condattr;
#endif /* pt-internal.h */
|