summaryrefslogtreecommitdiff
path: root/mit-pthreads/include/pthread.h
blob: e8a44050215f02b74a0b59cded434975727dcda5 (plain)
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
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/* ==== pthread.h ============================================================
 * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *  This product includes software developed by Chris Provenzano.
 * 4. The name of Chris Provenzano may not be used to endorse or promote 
 *	  products derived from this software without specific prior written
 *	  permission.
 *
 * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY 
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE.
 *
 * $Id$
 *
 * Description : Basic pthread header.
 *
 *  1.00 93/07/20 proven
 *      -Started coding this file.
 *
 *  93/9/28 streepy - Added support for pthread cancel
 *	
 */
 
#ifndef _PTHREAD_H_
#define	_PTHREAD_H_

#include <pthread/types.h>

#include <pthread/version.h>
#include <pthread/machdep.h>
#include <pthread/cleanup.h>
#include <pthread/kernel.h>
#include <pthread/prio_queue.h>
#include <pthread/queue.h>
#include <pthread/sleep.h>
#include <pthread/mutex.h>
#include <pthread/cond.h>
#include <pthread/fd.h>
#include <pthread/debug_out.h>

/* Requires mutex.h */
#include <pthread/specific.h>

#include <pthread/util.h>

/* More includes */
#include <pthread/pthread_once.h>

/* More includes, that need size_t */
#include <pthread/pthread_attr.h>

#include <signal.h> /* for sigset_t */	/* Moved by monty */

/* Constants for use with pthread_setcancelstate and pthread_setcanceltype */
#define PTHREAD_CANCEL_DISABLE		0
#define PTHREAD_CANCEL_ENABLE		1
#define PTHREAD_CANCEL_DEFERRED		0
#define PTHREAD_CANCEL_ASYNCHRONOUS	1

#define PTHREAD_CANCELLED (void *)1		/* Exit status of a cancelled thread */


#ifdef PTHREAD_KERNEL

enum pthread_state {
#define __pthread_defstate(S,NAME) S,
#include "pthread/state.def"
#undef __pthread_defstate

  /* enum lists aren't supposed to end with a comma, sigh */
  PS_STATE_MAX
};

/* Put PANIC inside an expression that evaluates to non-void type, to
   make it easier to combine it in expressions.  */
#define DO_PANIC()	(PANIC (), 0)
#define PANICIF(x)	((x) ? DO_PANIC () : 0)

/* In the thread flag field, we use a series of bit flags. Flags can
 * organized into "groups" of mutually exclusive flags.  Other flags
 * are unrelated and can be set and cleared with a single bit operation.
 */

#define PF_WAIT_EVENT		0x01
#define PF_DONE_EVENT		0x02
#define PF_EVENT_GROUP		0x03		/* All event bits */

#define PF_CANCEL_STATE			0x04	/* cancellability state */
#define PF_CANCEL_TYPE			0x08	/* cancellability type */
#define PF_THREAD_CANCELLED		0x10	/* thread has been cancelled */
#define PF_RUNNING_TO_CANCEL	0x20	/* Thread is running so it can cancel*/
#define PF_AT_CANCEL_POINT		0x40	/* Thread is at a cancel point */

/* Flag operations */

#define SET_PF_FLAG(x,f)				( (x)->flags |= (f) )
#define TEST_PF_FLAG(x,f)				( (x)->flags & (f) )
#define CLEAR_PF_FLAG(x,f)				( (x)->flags &= ~(f) )
#define CLEAR_PF_GROUP(x,g)				( (x)->flags &= ~(g) )
#define SET_PF_FLAG_IN_GROUP(x,g,f)		( CLEAR_PF_GROUP(x,g),SET_PF_FLAG(x,f))
#define TEST_PF_GROUP(x,g)				( (x)->flags & (g) )

#define SET_PF_DONE_EVENT(x)			\
( !TEST_PF_FLAG(x,PF_DONE_EVENT)		\
  ? ( TEST_PF_FLAG(x,PF_WAIT_EVENT)		\
	  ? (SET_PF_FLAG_IN_GROUP(x,PF_EVENT_GROUP,PF_DONE_EVENT), OK)	\
	  : DO_PANIC ())					\
  : NOTOK )

#define SET_PF_WAIT_EVENT(x)			\
( PANICIF (TEST_PF_GROUP(x,PF_EVENT_GROUP) ),	\
  SET_PF_FLAG_IN_GROUP(x,PF_EVENT_GROUP,PF_WAIT_EVENT), 0)

#define CLEAR_PF_DONE_EVENT(x)			\
( PANICIF (!TEST_PF_FLAG(x,PF_DONE_EVENT)),	\
  CLEAR_PF_GROUP(x,PF_EVENT_GROUP) )

#define SET_PF_CANCELLED(x)			( SET_PF_FLAG(x,PF_THREAD_CANCELLED) )
#define TEST_PF_CANCELLED(x)		( TEST_PF_FLAG(x,PF_THREAD_CANCELLED) )

#define SET_PF_RUNNING_TO_CANCEL(x)	( SET_PF_FLAG(x,PF_RUNNING_TO_CANCEL) )
#define CLEAR_PF_RUNNING_TO_CANCEL(x)( CLEAR_PF_FLAG(x,PF_RUNNING_TO_CANCEL) )
#define TEST_PF_RUNNING_TO_CANCEL(x)( TEST_PF_FLAG(x,PF_RUNNING_TO_CANCEL) )

#define SET_PF_AT_CANCEL_POINT(x)	( SET_PF_FLAG(x,PF_AT_CANCEL_POINT) )
#define CLEAR_PF_AT_CANCEL_POINT(x)	( CLEAR_PF_FLAG(x,PF_AT_CANCEL_POINT) )
#define TEST_PF_AT_CANCEL_POINT(x)	( TEST_PF_FLAG(x,PF_AT_CANCEL_POINT) )

#define SET_PF_CANCEL_STATE(x,f) \
	( (f) ? SET_PF_FLAG(x,PF_CANCEL_STATE) : CLEAR_PF_FLAG(x,PF_CANCEL_STATE) )
#define TEST_PF_CANCEL_STATE(x) \
	( (TEST_PF_FLAG(x,PF_CANCEL_STATE)) ? PTHREAD_CANCEL_ENABLE \
										: PTHREAD_CANCEL_DISABLE )

#define SET_PF_CANCEL_TYPE(x,f) \
	( (f) ? SET_PF_FLAG(x,PF_CANCEL_TYPE) : CLEAR_PF_FLAG(x,PF_CANCEL_TYPE) )
#define TEST_PF_CANCEL_TYPE(x) \
	( (TEST_PF_FLAG(x,PF_CANCEL_TYPE)) ? PTHREAD_CANCEL_ASYNCHRONOUS \
									   : PTHREAD_CANCEL_DEFERRED )

/* See if a thread is in a state that it can be cancelled */
#define TEST_PTHREAD_IS_CANCELLABLE(x) \
( (TEST_PF_CANCEL_STATE(x) == PTHREAD_CANCEL_ENABLE && TEST_PF_CANCELLED(x)) \
    ? ((TEST_PF_CANCEL_TYPE(x) == PTHREAD_CANCEL_ASYNCHRONOUS) \
        ? 1 \
        : TEST_PF_AT_CANCEL_POINT(x)) \
	: 0 )


struct pthread_select_data {
	int		nfds;
	fd_set	readfds;
	fd_set	writefds;
	fd_set	exceptfds;
};

union pthread_wait_data {
	pthread_mutex_t   * mutex;
	pthread_cond_t 	  * cond;
	const sigset_t	  * sigwait;		/* Waiting on a signal in sigwait */
	struct {
		short	fd;						/* Used when thread waiting on fd */
		short	branch;					/* line number, for debugging */
	} fd;
	struct pthread_select_data * select_data;
};

#define PTT_USER_THREAD		0x0001

struct pthread {
	int			thread_type;
	struct machdep_pthread	machdep_data;
	pthread_attr_t		attr;

	/* Signal interface */
	sigset_t		sigmask;
	sigset_t		sigpending;
	int			sigcount; /* Number of signals pending */
	int			sighandled; /* Set when signal has been handled */
	/* Timeout time */
	struct timespec		wakeup_time;

	/* Join queue for waiting threads */
	struct pthread_queue	join_queue;

	/*
	 * Thread implementations are just multiple queue type implemenations,
	 * Below are the various link lists currently necessary
	 * It is possible for a thread to be on multiple, or even all the
	 * queues at once, much care must be taken during queue manipulation.
	 *
	 * The pthread structure must be locked before you can even look at
	 * the link lists.
	 */ 

	/*
	 * ALL threads, in any state. 
	 * Must lock kernel lock before manipulating.
	 */
	struct pthread		* pll;		

	/*
	 * Standard link list for running threads, mutexes, etc ...
	 * It can't be on both a running link list and a wait queue.
	 * Must lock kernel lock before manipulating.
	 */
	struct pthread		* next;	
	union pthread_wait_data data;

	/*
	 * Actual queue state and priority of thread.
	 * (Note: "priority" is a reserved word in Concurrent C, please
	 * don't use it.  --KR)
	 */
	struct pthread_queue	* queue;
	enum pthread_state		  state;
	enum pthread_state		  old_state; /* Used when cancelled */
	char					  flags;
	char 					  pthread_priority;

	/*
	 * Sleep queue, this is different from the standard link list
	 * because it is possible to be on both (pthread_cond_timedwait();
	 * Must lock sleep mutex before manipulating
	 */
	struct pthread		*sll;	/* For sleeping threads */

	/*
	 * Data that doesn't need to be locked
	 * Mostly because only the thread owning the data can manipulate it
	 */
	void 			* ret;
	int				  error;
	int 			* error_p;
	const void		** specific_data;
	int			specific_data_count;

	/* Cleanup handlers Link List */
	struct pthread_cleanup *cleanup;
};

#else /* not PTHREAD_KERNEL */

struct pthread;

#endif

typedef struct pthread *pthread_t;

/*
 * Globals
 */
#ifdef PTHREAD_KERNEL

extern	struct pthread 		* pthread_run;
extern	struct pthread 		* pthread_initial;
extern	struct pthread 		* pthread_link_list;
extern	struct pthread_queue	pthread_dead_queue;
extern	struct pthread_queue	pthread_alloc_queue;

extern	pthread_attr_t		pthread_attr_default;
extern	volatile int		fork_lock;
extern	pthread_size_t		pthread_pagesize;

extern	sigset_t		* uthread_sigmask;

/* Kernel global functions */
extern void pthread_sched_prevent(void);
extern void pthread_sched_resume(void);
extern int __pthread_is_valid( pthread_t );
extern void pthread_cancel_internal( int freelocks );

#endif

/*
 * New functions
 */

__BEGIN_DECLS

#if defined(DCE_COMPAT)

typedef	void * (*pthread_startroutine_t)(void *);
typedef void * pthread_addr_t;

int	pthread_create __P_((pthread_t *, pthread_attr_t,
			    pthread_startroutine_t,
			    pthread_addr_t));
void	pthread_exit __P_((pthread_addr_t));
int	pthread_join __P_((pthread_t, pthread_addr_t *));

#else

void	pthread_init __P_((void));
int	pthread_create __P_((pthread_t *,
			    const pthread_attr_t *,
			    void * (*start_routine)(void *),
			    void *));
void	pthread_exit __P_((void *));
pthread_t pthread_self __P_((void));
int	pthread_equal __P_((pthread_t, pthread_t));
int	pthread_join __P_((pthread_t, void **));
int	pthread_detach __P_((pthread_t));
void	pthread_yield __P_((void));
int	pthread_setschedparam __P_((pthread_t pthread, int policy,
				   struct sched_param * param));
int	pthread_getschedparam __P_((pthread_t pthread, int * policy,
				   struct sched_param * param));
int	pthread_kill __P_((struct pthread *, int));
void	(*pthread_signal __P_((int, void (*)(int))))();
int	pthread_cancel __P_(( pthread_t pthread ));
int	pthread_setcancelstate __P_(( int state, int *oldstate ));
int	pthread_setcanceltype __P_(( int type, int *oldtype ));
void	pthread_testcancel __P_(( void ));

int 	pthread_sigmask __P_((int how, const sigset_t *set,
			     sigset_t * oset)); /* added by Monty */
int	sigwait __P_((const sigset_t * set, int * sig));
int	sigsetwait __P_((const sigset_t * set, int * sig));
#endif

#if defined(PTHREAD_KERNEL)

/* Not valid, but I can't spell so this will be caught at compile time */
#define		pthread_yeild(notvalid)

#endif

__END_DECLS

/*
 * Static constructors
 */
#ifdef __cplusplus

extern	struct pthread 		  * pthread_initial;

class __pthread_init_t {
/* struct __pthread_init_t { */
	public:
	__pthread_init_t() {
		if (pthread_initial == NULL) {
			pthread_init();
		}
	}
};

static __pthread_init_t __pthread_init_this_file;

#endif /* __cplusplus */

#endif