Deleted Added
sdiff udiff text old ( 113942 ) new ( 114187 )
full compact
1/*
2 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * Private thread definitions for the uthread kernel.
33 *
34 * $FreeBSD: head/lib/libkse/thread/thr_private.h 113942 2003-04-23 21:46:50Z deischen $
35 */
36
37#ifndef _THR_PRIVATE_H
38#define _THR_PRIVATE_H
39
40/*
41 * Include files.
42 */
43#include <setjmp.h>
44#include <signal.h>
45#include <stdio.h>
46#include <sys/queue.h>
47#include <sys/types.h>
48#include <sys/time.h>
49#include <sys/cdefs.h>
50#include <sys/kse.h>
51#include <sched.h>
52#include <ucontext.h>
53#include <unistd.h>
54#include <pthread.h>
55#include <pthread_np.h>
56
57#include "ksd.h"
58#include "lock.h"
59#include "pthread_md.h"
60
61/*
62 * Evaluate the storage class specifier.
63 */
64#ifdef GLOBAL_PTHREAD_PRIVATE
65#define SCLASS
66#define SCLASS_PRESET(x...) = x
67#else
68#define SCLASS extern
69#define SCLASS_PRESET(x...)
70#endif
71
72/*
73 * Kernel fatal error handler macro.
74 */
75#define PANIC(string) _thr_exit(__FILE__,__LINE__,string)
76
77
78/* Output debug messages like this: */
79#define stdout_debug(args...) _thread_printf(STDOUT_FILENO, ##args)
80#define stderr_debug(args...) _thread_printf(STDOUT_FILENO, ##args)
81
82#define DBG_MUTEX 0x0001
83#define DBG_SIG 0x0002
84
85
86#define THR_ASSERT(cond, msg) do { \
87 if (!(cond)) \
88 PANIC(msg); \
89} while (0)
90
91
92/*
93 * State change macro without scheduling queue change:
94 */
95#define THR_SET_STATE(thrd, newstate) do { \
96 (thrd)->state = newstate; \
97 (thrd)->fname = __FILE__; \
98 (thrd)->lineno = __LINE__; \
99} while (0)
100
101
102/*
103 * Define the signals to be used for scheduling.
104 */
105#define _ITIMER_SCHED_TIMER ITIMER_PROF
106#define _SCHED_SIGNAL SIGPROF
107
108#define TIMESPEC_ADD(dst, src, val) \
109 do { \
110 (dst)->tv_sec = (src)->tv_sec + (val)->tv_sec; \
111 (dst)->tv_nsec = (src)->tv_nsec + (val)->tv_nsec; \
112 if ((dst)->tv_nsec > 1000000000) { \
113 (dst)->tv_sec++; \
114 (dst)->tv_nsec -= 1000000000; \
115 } \
116 } while (0)
117
118#define TIMESPEC_SUB(dst, src, val) \
119 do { \
120 (dst)->tv_sec = (src)->tv_sec - (val)->tv_sec; \
121 (dst)->tv_nsec = (src)->tv_nsec - (val)->tv_nsec; \
122 if ((dst)->tv_nsec < 0) { \
123 (dst)->tv_sec--; \
124 (dst)->tv_nsec += 1000000000; \
125 } \
126 } while (0)
127
128/*
129 * Priority queues.
130 *
131 * XXX It'd be nice if these were contained in uthread_priority_queue.[ch].
132 */
133typedef struct pq_list {
134 TAILQ_HEAD(, pthread) pl_head; /* list of threads at this priority */
135 TAILQ_ENTRY(pq_list) pl_link; /* link for queue of priority lists */
136 int pl_prio; /* the priority of this list */
137 int pl_queued; /* is this in the priority queue */
138} pq_list_t;
139
140typedef struct pq_queue {
141 TAILQ_HEAD(, pq_list) pq_queue; /* queue of priority lists */
142 pq_list_t *pq_lists; /* array of all priority lists */
143 int pq_size; /* number of priority lists */
144#define PQF_ACTIVE 0x0001
145 int pq_flags;
146} pq_queue_t;
147
148/*
149 * Each KSEG has a scheduling queue. For now, threads that exist in their
150 * own KSEG (system scope) will get a full priority queue. In the future
151 * this can be optimized for the single thread per KSEG case.
152 */
153struct sched_queue {
154 pq_queue_t sq_runq;
155 TAILQ_HEAD(, pthread) sq_waitq; /* waiting in userland */
156};
157
158/* Used to maintain pending and active signals: */
159struct sigstatus {
160 siginfo_t *info; /* arg 2 to signal handler */
161 int pending; /* Is this a pending signal? */
162 int blocked; /*
163 * This signal has occured and hasn't
164 * yet been handled; ignore subsequent
165 * signals until the handler is done.
166 */
167 int signo;
168};
169
170typedef struct kse_thr_mailbox *kse_critical_t;
171
172struct kse_group;
173
174#define MAX_KSE_LOCKLEVEL 3
175struct kse {
176 struct kse_mailbox k_mbx; /* kernel kse mailbox */
177 /* -- location and order specific items for gdb -- */
178 struct pthread *k_curthread; /* current thread */
179 struct kse_group *k_kseg; /* parent KSEG */
180 struct sched_queue *k_schedq; /* scheduling queue */
181 /* -- end of location and order specific items -- */
182 TAILQ_ENTRY(kse) k_qe; /* KSE list link entry */
183 TAILQ_ENTRY(kse) k_kgqe; /* KSEG's KSE list entry */
184 struct ksd k_ksd; /* KSE specific data */
185 /*
186 * Items that are only modified by the kse, or that otherwise
187 * don't need to be locked when accessed
188 */
189 struct lock k_lock;
190 struct lockuser k_lockusers[MAX_KSE_LOCKLEVEL];
191 int k_locklevel;
192 sigset_t k_sigmask;
193 struct sigstatus k_sigq[NSIG];
194 stack_t k_stack;
195 int k_check_sigq;
196 int k_flags;
197#define KF_STARTED 0x0001 /* kernel kse created */
198#define KF_INITIALIZED 0x0002 /* initialized on 1st upcall */
199 int k_waiting;
200 int k_error; /* syscall errno in critical */
201 int k_cpu; /* CPU ID when bound */
202 int k_done; /* this KSE is done */
203};
204
205/*
206 * Each KSE group contains one or more KSEs in which threads can run.
207 * At least for now, there is one scheduling queue per KSE group; KSEs
208 * within the same KSE group compete for threads from the same scheduling
209 * queue. A scope system thread has one KSE in one KSE group; the group
210 * does not use its scheduling queue.
211 */
212struct kse_group {
213 TAILQ_HEAD(, kse) kg_kseq; /* list of KSEs in group */
214 TAILQ_HEAD(, pthread) kg_threadq; /* list of threads in group */
215 TAILQ_ENTRY(kse_group) kg_qe; /* link entry */
216 struct sched_queue kg_schedq; /* scheduling queue */
217 struct lock kg_lock;
218 int kg_threadcount; /* # of assigned threads */
219 int kg_ksecount; /* # of assigned KSEs */
220 int kg_idle_kses;
221 int kg_flags;
222#define KGF_SINGLE_THREAD 0x0001 /* scope system kse group */
223#define KGF_SCHEDQ_INITED 0x0002 /* has an initialized schedq */
224};
225
226/*
227 * Add/remove threads from a KSE's scheduling queue.
228 * For now the scheduling queue is hung off the KSEG.
229 */
230#define KSEG_THRQ_ADD(kseg, thr) \
231do { \
232 TAILQ_INSERT_TAIL(&(kseg)->kg_threadq, thr, kle);\
233 (kseg)->kg_threadcount++; \
234} while (0)
235
236#define KSEG_THRQ_REMOVE(kseg, thr) \
237do { \
238 TAILQ_REMOVE(&(kseg)->kg_threadq, thr, kle); \
239 (kseg)->kg_threadcount--; \
240} while (0)
241
242
243/*
244 * Lock acquire and release for KSEs.
245 */
246#define KSE_LOCK_ACQUIRE(kse, lck) \
247do { \
248 if ((kse)->k_locklevel >= MAX_KSE_LOCKLEVEL) \
249 PANIC("Exceeded maximum lock level"); \
250 else { \
251 (kse)->k_locklevel++; \
252 _lock_acquire((lck), \
253 &(kse)->k_lockusers[(kse)->k_locklevel - 1], 0); \
254 } \
255} while (0)
256
257#define KSE_LOCK_RELEASE(kse, lck) \
258do { \
259 if ((kse)->k_locklevel > 0) { \
260 _lock_release((lck), \
261 &(kse)->k_lockusers[(kse)->k_locklevel - 1]); \
262 (kse)->k_locklevel--; \
263 } \
264} while (0)
265
266/*
267 * Lock our own KSEG.
268 */
269#define KSE_LOCK(curkse) \
270 KSE_LOCK_ACQUIRE(curkse, &(curkse)->k_kseg->kg_lock)
271#define KSE_UNLOCK(curkse) \
272 KSE_LOCK_RELEASE(curkse, &(curkse)->k_kseg->kg_lock)
273
274/*
275 * Lock a potentially different KSEG.
276 */
277#define KSE_SCHED_LOCK(curkse, kseg) \
278 KSE_LOCK_ACQUIRE(curkse, &(kseg)->kg_lock)
279#define KSE_SCHED_UNLOCK(curkse, kseg) \
280 KSE_LOCK_RELEASE(curkse, &(kseg)->kg_lock)
281
282/*
283 * Waiting queue manipulation macros (using pqe link):
284 */
285#define KSE_WAITQ_REMOVE(kse, thrd) \
286do { \
287 if (((thrd)->flags & THR_FLAGS_IN_WAITQ) != 0) { \
288 TAILQ_REMOVE(&(kse)->k_schedq->sq_waitq, thrd, pqe); \
289 (thrd)->flags &= ~THR_FLAGS_IN_WAITQ; \
290 } \
291} while (0)
292#define KSE_WAITQ_INSERT(kse, thrd) kse_waitq_insert(thrd)
293#define KSE_WAITQ_FIRST(kse) TAILQ_FIRST(&(kse)->k_schedq->sq_waitq)
294
295#define KSE_SET_WAIT(kse) atomic_store_rel_int(&(kse)->k_waiting, 1)
296
297#define KSE_CLEAR_WAIT(kse) atomic_set_acq_int(&(kse)->k_waiting, 0)
298
299#define KSE_WAITING(kse) (kse)->k_waiting != 0
300#define KSE_WAKEUP(kse) kse_wakeup(&(kse)->k_mbx)
301
302/*
303 * TailQ initialization values.
304 */
305#define TAILQ_INITIALIZER { NULL, NULL }
306
307/*
308 * lock initialization values.
309 */
310#define LCK_INITIALIZER { NULL, NULL, LCK_DEFAULT }
311
312struct pthread_mutex {
313 /*
314 * Lock for accesses to this structure.
315 */
316 struct lock m_lock;
317 enum pthread_mutextype m_type;
318 int m_protocol;
319 TAILQ_HEAD(mutex_head, pthread) m_queue;
320 struct pthread *m_owner;
321 long m_flags;
322 int m_count;
323 int m_refcount;
324
325 /*
326 * Used for priority inheritence and protection.
327 *
328 * m_prio - For priority inheritence, the highest active
329 * priority (threads locking the mutex inherit
330 * this priority). For priority protection, the
331 * ceiling priority of this mutex.
332 * m_saved_prio - mutex owners inherited priority before
333 * taking the mutex, restored when the owner
334 * unlocks the mutex.
335 */
336 int m_prio;
337 int m_saved_prio;
338
339 /*
340 * Link for list of all mutexes a thread currently owns.
341 */
342 TAILQ_ENTRY(pthread_mutex) m_qe;
343};
344
345/*
346 * Flags for mutexes.
347 */
348#define MUTEX_FLAGS_PRIVATE 0x01
349#define MUTEX_FLAGS_INITED 0x02
350#define MUTEX_FLAGS_BUSY 0x04
351
352/*
353 * Static mutex initialization values.
354 */
355#define PTHREAD_MUTEX_STATIC_INITIALIZER \
356 { LCK_INITIALIZER, PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, \
357 TAILQ_INITIALIZER, NULL, MUTEX_FLAGS_PRIVATE, 0, 0, 0, 0, \
358 TAILQ_INITIALIZER }
359
360struct pthread_mutex_attr {
361 enum pthread_mutextype m_type;
362 int m_protocol;
363 int m_ceiling;
364 long m_flags;
365};
366
367#define PTHREAD_MUTEXATTR_STATIC_INITIALIZER \
368 { PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, MUTEX_FLAGS_PRIVATE }
369
370/*
371 * Condition variable definitions.
372 */
373enum pthread_cond_type {
374 COND_TYPE_FAST,
375 COND_TYPE_MAX
376};
377
378struct pthread_cond {
379 /*
380 * Lock for accesses to this structure.
381 */
382 struct lock c_lock;
383 enum pthread_cond_type c_type;
384 TAILQ_HEAD(cond_head, pthread) c_queue;
385 struct pthread_mutex *c_mutex;
386 long c_flags;
387 long c_seqno;
388};
389
390struct pthread_cond_attr {
391 enum pthread_cond_type c_type;
392 long c_flags;
393};
394
395/*
396 * Flags for condition variables.
397 */
398#define COND_FLAGS_PRIVATE 0x01
399#define COND_FLAGS_INITED 0x02
400#define COND_FLAGS_BUSY 0x04
401
402/*
403 * Static cond initialization values.
404 */
405#define PTHREAD_COND_STATIC_INITIALIZER \
406 { LCK_INITIALIZER, COND_TYPE_FAST, TAILQ_INITIALIZER, \
407 NULL, NULL, 0, 0 }
408
409/*
410 * Semaphore definitions.
411 */
412struct sem {
413#define SEM_MAGIC ((u_int32_t) 0x09fa4012)
414 u_int32_t magic;
415 pthread_mutex_t lock;
416 pthread_cond_t gtzero;
417 u_int32_t count;
418 u_int32_t nwaiters;
419};
420
421/*
422 * Cleanup definitions.
423 */
424struct pthread_cleanup {
425 struct pthread_cleanup *next;
426 void (*routine) ();
427 void *routine_arg;
428};
429
430struct pthread_attr {
431 int sched_policy;
432 int sched_inherit;
433 int sched_interval;
434 int prio;
435 int suspend;
436#define THR_STACK_USER 0x100 /* 0xFF reserved for <pthread.h> */
437 int flags;
438 void *arg_attr;
439 void (*cleanup_attr) ();
440 void *stackaddr_attr;
441 size_t stacksize_attr;
442 size_t guardsize_attr;
443};
444
445/*
446 * Thread creation state attributes.
447 */
448#define THR_CREATE_RUNNING 0
449#define THR_CREATE_SUSPENDED 1
450
451/*
452 * Miscellaneous definitions.
453 */
454#define THR_STACK_DEFAULT 65536
455
456/*
457 * Maximum size of initial thread's stack. This perhaps deserves to be larger
458 * than the stacks of other threads, since many applications are likely to run
459 * almost entirely on this stack.
460 */
461#define THR_STACK_INITIAL 0x100000
462
463/*
464 * Define the different priority ranges. All applications have thread
465 * priorities constrained within 0-31. The threads library raises the
466 * priority when delivering signals in order to ensure that signal
467 * delivery happens (from the POSIX spec) "as soon as possible".
468 * In the future, the threads library will also be able to map specific
469 * threads into real-time (cooperating) processes or kernel threads.
470 * The RT and SIGNAL priorities will be used internally and added to
471 * thread base priorities so that the scheduling queue can handle both
472 * normal and RT priority threads with and without signal handling.
473 *
474 * The approach taken is that, within each class, signal delivery
475 * always has priority over thread execution.
476 */
477#define THR_DEFAULT_PRIORITY 15
478#define THR_MIN_PRIORITY 0
479#define THR_MAX_PRIORITY 31 /* 0x1F */
480#define THR_SIGNAL_PRIORITY 32 /* 0x20 */
481#define THR_RT_PRIORITY 64 /* 0x40 */
482#define THR_FIRST_PRIORITY THR_MIN_PRIORITY
483#define THR_LAST_PRIORITY \
484 (THR_MAX_PRIORITY + THR_SIGNAL_PRIORITY + THR_RT_PRIORITY)
485#define THR_BASE_PRIORITY(prio) ((prio) & THR_MAX_PRIORITY)
486
487/*
488 * Clock resolution in microseconds.
489 */
490#define CLOCK_RES_USEC 10000
491
492/*
493 * Time slice period in microseconds.
494 */
495#define TIMESLICE_USEC 20000
496
497/*
498 * XXX - Define a thread-safe macro to get the current time of day
499 * which is updated at regular intervals by something.
500 *
501 * For now, we just make the system call to get the time.
502 */
503#define KSE_GET_TOD(curkse, tsp) \
504do { \
505 *tsp = (curkse)->k_mbx.km_timeofday; \
506 if ((tsp)->tv_sec == 0) \
507 clock_gettime(CLOCK_REALTIME, tsp); \
508} while (0)
509
510struct pthread_rwlockattr {
511 int pshared;
512};
513
514struct pthread_rwlock {
515 pthread_mutex_t lock; /* monitor lock */
516 int state; /* 0 = idle >0 = # of readers -1 = writer */
517 pthread_cond_t read_signal;
518 pthread_cond_t write_signal;
519 int blocked_writers;
520};
521
522/*
523 * Thread states.
524 */
525enum pthread_state {
526 PS_RUNNING,
527 PS_LOCKWAIT,
528 PS_MUTEX_WAIT,
529 PS_COND_WAIT,
530 PS_SLEEP_WAIT,
531 PS_SIGSUSPEND,
532 PS_SIGWAIT,
533 PS_JOIN,
534 PS_SUSPENDED,
535 PS_DEAD,
536 PS_DEADLOCK,
537 PS_STATE_MAX
538};
539
540
541union pthread_wait_data {
542 pthread_mutex_t mutex;
543 pthread_cond_t cond;
544 const sigset_t *sigwait; /* Waiting on a signal in sigwait */
545 struct lock *lock;
546};
547
548/*
549 * Define a continuation routine that can be used to perform a
550 * transfer of control:
551 */
552typedef void (*thread_continuation_t) (void *);
553
554/*
555 * This stores a thread's state prior to running a signal handler.
556 * It is used when a signal is delivered to a thread blocked in
557 * userland. If the signal handler returns normally, the thread's
558 * state is restored from here.
559 */
560struct pthread_sigframe {
561 int psf_flags;
562 int psf_interrupted;
563 int psf_signo;
564 enum pthread_state psf_state;
565 union pthread_wait_data psf_wait_data;
566 struct timespec psf_wakeup_time;
567 sigset_t psf_sigset;
568 sigset_t psf_sigmask;
569 int psf_seqno;
570};
571
572struct join_status {
573 struct pthread *thread;
574 void *ret;
575 int error;
576};
577
578struct pthread_specific_elem {
579 const void *data;
580 int seqno;
581};
582
583
584#define MAX_THR_LOCKLEVEL 3
585/*
586 * Thread structure.
587 */
588struct pthread {
589 /*
590 * Magic value to help recognize a valid thread structure
591 * from an invalid one:
592 */
593#define THR_MAGIC ((u_int32_t) 0xd09ba115)
594 u_int32_t magic;
595 char *name;
596 u_int64_t uniqueid; /* for gdb */
597
598 /* Queue entry for list of all threads: */
599 TAILQ_ENTRY(pthread) tle; /* link for all threads in process */
600 TAILQ_ENTRY(pthread) kle; /* link for all threads in KSE/KSEG */
601
602 /* Queue entry for GC lists: */
603 TAILQ_ENTRY(pthread) gcle;
604
605 /*
606 * Lock for accesses to this thread structure.
607 */
608 struct lock lock;
609 struct lockuser lockusers[MAX_THR_LOCKLEVEL];
610 int locklevel;
611 kse_critical_t critical[MAX_KSE_LOCKLEVEL];
612 struct kse *kse;
613 struct kse_group *kseg;
614
615 /*
616 * Thread start routine, argument, stack pointer and thread
617 * attributes.
618 */
619 void *(*start_routine)(void *);
620 void *arg;
621 struct pthread_attr attr;
622
623 /*
624 * Thread mailbox.
625 */
626 struct kse_thr_mailbox tmbx;
627 int active; /* thread running */
628 int blocked; /* thread blocked in kernel */
629 int need_switchout;
630 int need_wakeup;
631
632 /*
633 * Used for tracking delivery of signal handlers.
634 */
635 struct pthread_sigframe *curframe;
636 siginfo_t siginfo[NSIG];
637
638 /*
639 * Cancelability flags - the lower 2 bits are used by cancel
640 * definitions in pthread.h
641 */
642#define THR_AT_CANCEL_POINT 0x0004
643#define THR_CANCELLING 0x0008
644#define THR_CANCEL_NEEDED 0x0010
645 int cancelflags;
646
647 thread_continuation_t continuation;
648
649 /*
650 * The thread's base and pending signal masks. The active
651 * signal mask is stored in the thread's context (in mailbox).
652 */
653 sigset_t sigmask;
654 sigset_t sigpend;
655 int sigmask_seqno;
656 int check_pending;
657 int refcount;
658
659 /* Thread state: */
660 enum pthread_state state;
661
662 /*
663 * Number of microseconds accumulated by this thread when
664 * time slicing is active.
665 */
666 long slice_usec;
667
668 /*
669 * Time to wake up thread. This is used for sleeping threads and
670 * for any operation which may time out (such as select).
671 */
672 struct timespec wakeup_time;
673
674 /* TRUE if operation has timed out. */
675 int timeout;
676
677 /*
678 * Error variable used instead of errno. The function __error()
679 * returns a pointer to this.
680 */
681 int error;
682
683 /*
684 * The joiner is the thread that is joining to this thread. The
685 * join status keeps track of a join operation to another thread.
686 */
687 struct pthread *joiner;
688 struct join_status join_status;
689
690 /*
691 * The current thread can belong to only one scheduling queue at
692 * a time (ready or waiting queue). It can also belong to:
693 *
694 * o A queue of threads waiting for a mutex
695 * o A queue of threads waiting for a condition variable
696 *
697 * It is possible for a thread to belong to more than one of the
698 * above queues if it is handling a signal. A thread may only
699 * enter a mutex or condition variable queue when it is not
700 * being called from a signal handler. If a thread is a member
701 * of one of these queues when a signal handler is invoked, it
702 * must be removed from the queue before invoking the handler
703 * and then added back to the queue after return from the handler.
704 *
705 * Use pqe for the scheduling queue link (both ready and waiting),
706 * sqe for synchronization (mutex, condition variable, and join)
707 * queue links, and qe for all other links.
708 */
709 TAILQ_ENTRY(pthread) pqe; /* priority, wait queues link */
710 TAILQ_ENTRY(pthread) sqe; /* synchronization queue link */
711
712 /* Wait data. */
713 union pthread_wait_data data;
714
715 /*
716 * Set to TRUE if a blocking operation was
717 * interrupted by a signal:
718 */
719 int interrupted;
720
721 /* Signal number when in state PS_SIGWAIT: */
722 int signo;
723
724 /*
725 * Set to non-zero when this thread has entered a critical
726 * region. We allow for recursive entries into critical regions.
727 */
728 int critical_count;
729
730 /*
731 * Set to TRUE if this thread should yield after leaving a
732 * critical region to check for signals, messages, etc.
733 */
734 int critical_yield;
735
736 int sflags;
737#define THR_FLAGS_IN_SYNCQ 0x0001
738
739 /* Miscellaneous flags; only set with scheduling lock held. */
740 int flags;
741#define THR_FLAGS_PRIVATE 0x0001
742#define THR_FLAGS_IN_WAITQ 0x0002 /* in waiting queue using pqe link */
743#define THR_FLAGS_IN_RUNQ 0x0004 /* in run queue using pqe link */
744#define THR_FLAGS_EXITING 0x0008 /* thread is exiting */
745#define THR_FLAGS_SUSPENDED 0x0010 /* thread is suspended */
746#define THR_FLAGS_GC_SAFE 0x0020 /* thread safe for cleaning */
747#define THR_FLAGS_IN_TDLIST 0x0040 /* thread in all thread list */
748#define THR_FLAGS_IN_GCLIST 0x0080 /* thread in gc list */
749 /*
750 * Base priority is the user setable and retrievable priority
751 * of the thread. It is only affected by explicit calls to
752 * set thread priority and upon thread creation via a thread
753 * attribute or default priority.
754 */
755 char base_priority;
756
757 /*
758 * Inherited priority is the priority a thread inherits by
759 * taking a priority inheritence or protection mutex. It
760 * is not affected by base priority changes. Inherited
761 * priority defaults to and remains 0 until a mutex is taken
762 * that is being waited on by any other thread whose priority
763 * is non-zero.
764 */
765 char inherited_priority;
766
767 /*
768 * Active priority is always the maximum of the threads base
769 * priority and inherited priority. When there is a change
770 * in either the base or inherited priority, the active
771 * priority must be recalculated.
772 */
773 char active_priority;
774
775 /* Number of priority ceiling or protection mutexes owned. */
776 int priority_mutex_count;
777
778 /*
779 * Queue of currently owned mutexes.
780 */
781 TAILQ_HEAD(, pthread_mutex) mutexq;
782
783 void *ret;
784 struct pthread_specific_elem *specific;
785 int specific_data_count;
786
787 /* Cleanup handlers Link List */
788 struct pthread_cleanup *cleanup;
789 char *fname; /* Ptr to source file name */
790 int lineno; /* Source line number. */
791};
792
793/*
794 * Critical regions can also be detected by looking at the threads
795 * current lock level. Ensure these macros increment and decrement
796 * the lock levels such that locks can not be held with a lock level
797 * of 0.
798 */
799#define THR_IN_CRITICAL(thrd) \
800 (((thrd)->locklevel > 0) || \
801 ((thrd)->critical_count > 0))
802
803#define THR_YIELD_CHECK(thrd) \
804do { \
805 if (((thrd)->critical_yield != 0) && \
806 !(THR_IN_CRITICAL(thrd))) \
807 _thr_sched_switch(thrd); \
808 else if (((thrd)->check_pending != 0) && \
809 !(THR_IN_CRITICAL(thrd))) \
810 _thr_sig_check_pending(thrd); \
811} while (0)
812
813#define THR_LOCK_ACQUIRE(thrd, lck) \
814do { \
815 if ((thrd)->locklevel >= MAX_THR_LOCKLEVEL) \
816 PANIC("Exceeded maximum lock level"); \
817 else { \
818 (thrd)->locklevel++; \
819 _lock_acquire((lck), \
820 &(thrd)->lockusers[(thrd)->locklevel - 1], \
821 (thrd)->active_priority); \
822 } \
823} while (0)
824
825#define THR_LOCK_RELEASE(thrd, lck) \
826do { \
827 if ((thrd)->locklevel > 0) { \
828 _lock_release((lck), \
829 &(thrd)->lockusers[(thrd)->locklevel - 1]); \
830 (thrd)->locklevel--; \
831 if ((thrd)->locklevel != 0) \
832 ; \
833 else if ((thrd)->critical_yield != 0) \
834 _thr_sched_switch(thrd); \
835 else if ((thrd)->check_pending != 0) \
836 _thr_sig_check_pending(thrd); \
837 } \
838} while (0)
839
840/*
841 * For now, threads will have their own lock separate from their
842 * KSE scheduling lock.
843 */
844#define THR_LOCK(thr) THR_LOCK_ACQUIRE(thr, &(thr)->lock)
845#define THR_UNLOCK(thr) THR_LOCK_RELEASE(thr, &(thr)->lock)
846#define THR_THREAD_LOCK(curthrd, thr) THR_LOCK_ACQUIRE(curthrd, &(thr)->lock)
847#define THR_THREAD_UNLOCK(curthrd, thr) THR_LOCK_RELEASE(curthrd, &(thr)->lock)
848
849/*
850 * Priority queue manipulation macros (using pqe link). We use
851 * the thread's kseg link instead of the kse link because a thread
852 * does not (currently) have a statically assigned kse.
853 */
854#define THR_RUNQ_INSERT_HEAD(thrd) \
855 _pq_insert_head(&(thrd)->kseg->kg_schedq.sq_runq, thrd)
856#define THR_RUNQ_INSERT_TAIL(thrd) \
857 _pq_insert_tail(&(thrd)->kseg->kg_schedq.sq_runq, thrd)
858#define THR_RUNQ_REMOVE(thrd) \
859 _pq_remove(&(thrd)->kseg->kg_schedq.sq_runq, thrd)
860#define THR_RUNQ_FIRST() \
861 _pq_first(&(thrd)->kseg->kg_schedq.sq_runq)
862
863/*
864 * Macros to insert/remove threads to the all thread list and
865 * the gc list.
866 */
867#define THR_LIST_ADD(thrd) do { \
868 if (((thrd)->flags & THR_FLAGS_IN_TDLIST) == 0) { \
869 TAILQ_INSERT_HEAD(&_thread_list, thrd, tle); \
870 (thrd)->flags |= THR_FLAGS_IN_TDLIST; \
871 } \
872} while (0)
873#define THR_LIST_REMOVE(thrd) do { \
874 if (((thrd)->flags & THR_FLAGS_IN_TDLIST) != 0) { \
875 TAILQ_REMOVE(&_thread_list, thrd, tle); \
876 (thrd)->flags &= ~THR_FLAGS_IN_TDLIST; \
877 } \
878} while (0)
879#define THR_GCLIST_ADD(thrd) do { \
880 if (((thrd)->flags & THR_FLAGS_IN_GCLIST) == 0) { \
881 TAILQ_INSERT_HEAD(&_thread_gc_list, thrd, gcle);\
882 (thrd)->flags |= THR_FLAGS_IN_GCLIST; \
883 _gc_count++; \
884 } \
885} while (0)
886#define THR_GCLIST_REMOVE(thrd) do { \
887 if (((thrd)->flags & THR_FLAGS_IN_GCLIST) != 0) { \
888 TAILQ_REMOVE(&_thread_gc_list, thrd, gcle); \
889 (thrd)->flags &= ~THR_FLAGS_IN_GCLIST; \
890 _gc_count--; \
891 } \
892} while (0)
893
894#define GC_NEEDED() (atomic_load_acq_int(&_gc_count) >= 5)
895
896/*
897 * Locking the scheduling queue for another thread uses that thread's
898 * KSEG lock.
899 */
900#define THR_SCHED_LOCK(curthr, thr) do { \
901 (curthr)->critical[(curthr)->locklevel] = _kse_critical_enter(); \
902 (curthr)->locklevel++; \
903 KSE_SCHED_LOCK((curthr)->kse, (thr)->kseg); \
904} while (0)
905
906#define THR_SCHED_UNLOCK(curthr, thr) do { \
907 KSE_SCHED_UNLOCK((curthr)->kse, (thr)->kseg); \
908 (curthr)->locklevel--; \
909 _kse_critical_leave((curthr)->critical[(curthr)->locklevel]); \
910 if ((curthr)->locklevel == 0) \
911 THR_YIELD_CHECK(curthr); \
912} while (0)
913
914#define THR_CRITICAL_ENTER(thr) (thr)->critical_count++
915#define THR_CRITICAL_LEAVE(thr) do { \
916 (thr)->critical_count--; \
917 if (((thr)->critical_yield != 0) && \
918 ((thr)->critical_count == 0)) { \
919 (thr)->critical_yield = 0; \
920 _thr_sched_switch(thr); \
921 } \
922} while (0)
923
924#define THR_IS_ACTIVE(thrd) \
925 ((thrd)->kse != NULL) && ((thrd)->kse->k_curthread == (thrd))
926
927#define THR_IN_SYNCQ(thrd) (((thrd)->sflags & THR_FLAGS_IN_SYNCQ) != 0)
928
929/*
930 * Global variables for the pthread kernel.
931 */
932
933SCLASS void *_usrstack SCLASS_PRESET(NULL);
934SCLASS struct kse *_kse_initial SCLASS_PRESET(NULL);
935SCLASS struct pthread *_thr_initial SCLASS_PRESET(NULL);
936
937/* List of all threads: */
938SCLASS TAILQ_HEAD(, pthread) _thread_list
939 SCLASS_PRESET(TAILQ_HEAD_INITIALIZER(_thread_list));
940
941/* List of threads needing GC: */
942SCLASS TAILQ_HEAD(, pthread) _thread_gc_list
943 SCLASS_PRESET(TAILQ_HEAD_INITIALIZER(_thread_gc_list));
944
945/* Default thread attributes: */
946SCLASS struct pthread_attr _pthread_attr_default
947 SCLASS_PRESET({
948 SCHED_RR, 0, TIMESLICE_USEC, THR_DEFAULT_PRIORITY,
949 THR_CREATE_RUNNING, PTHREAD_CREATE_JOINABLE, NULL,
950 NULL, NULL, THR_STACK_DEFAULT
951 });
952
953/* Default mutex attributes: */
954SCLASS struct pthread_mutex_attr _pthread_mutexattr_default
955 SCLASS_PRESET({PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, 0 });
956
957/* Default condition variable attributes: */
958SCLASS struct pthread_cond_attr _pthread_condattr_default
959 SCLASS_PRESET({COND_TYPE_FAST, 0});
960
961/* Clock resolution in usec. */
962SCLASS int _clock_res_usec SCLASS_PRESET(CLOCK_RES_USEC);
963
964/* Array of signal actions for this process: */
965SCLASS struct sigaction _thread_sigact[NSIG];
966
967/*
968 * Array of counts of dummy handlers for SIG_DFL signals. This is used to
969 * assure that there is always a dummy signal handler installed while there
970 * is a thread sigwait()ing on the corresponding signal.
971 */
972SCLASS int _thread_dfl_count[NSIG];
973
974/*
975 * Lock for above count of dummy handlers and for the process signal
976 * mask and pending signal sets.
977 */
978SCLASS struct lock _thread_signal_lock;
979
980/* Pending signals and mask for this process: */
981SCLASS sigset_t _thr_proc_sigpending;
982SCLASS sigset_t _thr_proc_sigmask SCLASS_PRESET({{0, 0, 0, 0}});
983SCLASS siginfo_t _thr_proc_siginfo[NSIG];
984
985SCLASS pid_t _thr_pid SCLASS_PRESET(0);
986
987/* Garbage collector lock. */
988SCLASS struct lock _gc_lock;
989SCLASS int _gc_check SCLASS_PRESET(0);
990SCLASS int _gc_count SCLASS_PRESET(0);
991
992SCLASS struct lock _mutex_static_lock;
993SCLASS struct lock _rwlock_static_lock;
994SCLASS struct lock _keytable_lock;
995SCLASS struct lock _thread_list_lock;
996SCLASS int _thr_guard_default;
997SCLASS int _thr_page_size;
998
999SCLASS int _thr_debug_flags SCLASS_PRESET(0);
1000
1001/* Undefine the storage class and preset specifiers: */
1002#undef SCLASS
1003#undef SCLASS_PRESET
1004
1005
1006/*
1007 * Function prototype definitions.
1008 */
1009__BEGIN_DECLS
1010int _cond_reinit(pthread_cond_t *);
1011void _cond_wait_backout(struct pthread *);
1012struct pthread *_get_curthread(void);
1013struct kse *_get_curkse(void);
1014void _set_curkse(struct kse *);
1015struct kse *_kse_alloc(struct pthread *);
1016kse_critical_t _kse_critical_enter(void);
1017void _kse_critical_leave(kse_critical_t);
1018int _kse_in_critical(void);
1019void _kse_free(struct pthread *, struct kse *);
1020void _kse_init();
1021struct kse_group *_kseg_alloc(struct pthread *);
1022void _kse_lock_wait(struct lock *, struct lockuser *lu);
1023void _kse_lock_wakeup(struct lock *, struct lockuser *lu);
1024void _kse_sig_check_pending(struct kse *);
1025void _kse_single_thread(struct pthread *);
1026void _kse_start(struct kse *);
1027int _kse_setthreaded(int);
1028int _kse_isthreaded(void);
1029void _kseg_free(struct kse_group *);
1030int _mutex_cv_lock(pthread_mutex_t *);
1031int _mutex_cv_unlock(pthread_mutex_t *);
1032void _mutex_lock_backout(struct pthread *);
1033void _mutex_notify_priochange(struct pthread *, struct pthread *, int);
1034int _mutex_reinit(struct pthread_mutex *);
1035void _mutex_unlock_private(struct pthread *);
1036void _libpthread_init(struct pthread *);
1037int _pq_alloc(struct pq_queue *, int, int);
1038void _pq_free(struct pq_queue *);
1039int _pq_init(struct pq_queue *);
1040void _pq_remove(struct pq_queue *pq, struct pthread *);
1041void _pq_insert_head(struct pq_queue *pq, struct pthread *);
1042void _pq_insert_tail(struct pq_queue *pq, struct pthread *);
1043struct pthread *_pq_first(struct pq_queue *pq);
1044void *_pthread_getspecific(pthread_key_t);
1045int _pthread_key_create(pthread_key_t *, void (*) (void *));
1046int _pthread_key_delete(pthread_key_t);
1047int _pthread_mutex_destroy(pthread_mutex_t *);
1048int _pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
1049int _pthread_mutex_lock(pthread_mutex_t *);
1050int _pthread_mutex_trylock(pthread_mutex_t *);
1051int _pthread_mutex_unlock(pthread_mutex_t *);
1052int _pthread_mutexattr_init(pthread_mutexattr_t *);
1053int _pthread_mutexattr_destroy(pthread_mutexattr_t *);
1054int _pthread_mutexattr_settype(pthread_mutexattr_t *, int);
1055int _pthread_once(pthread_once_t *, void (*) (void));
1056struct pthread *_pthread_self(void);
1057int _pthread_setspecific(pthread_key_t, const void *);
1058struct pthread *_thr_alloc(struct pthread *);
1059int _thread_enter_uts(struct kse_thr_mailbox *, struct kse_mailbox *);
1060int _thread_switch(struct kse_thr_mailbox *, struct kse_thr_mailbox **);
1061void _thr_exit(char *, int, char *);
1062void _thr_exit_cleanup(void);
1063void _thr_lock_wait(struct lock *lock, struct lockuser *lu);
1064void _thr_lock_wakeup(struct lock *lock, struct lockuser *lu);
1065int _thr_ref_add(struct pthread *, struct pthread *, int);
1066void _thr_ref_delete(struct pthread *, struct pthread *);
1067int _thr_schedule_add(struct pthread *, struct pthread *);
1068void _thr_schedule_remove(struct pthread *, struct pthread *);
1069void _thr_setrunnable(struct pthread *curthread, struct pthread *thread);
1070void _thr_setrunnable_unlocked(struct pthread *thread);
1071void _thr_sig_add(struct pthread *, int, siginfo_t *, ucontext_t *);
1072void _thr_sig_dispatch(struct kse *, int, siginfo_t *);
1073int _thr_stack_alloc(struct pthread_attr *);
1074void _thr_stack_free(struct pthread_attr *);
1075void _thr_exit_cleanup(void);
1076void _thr_free(struct pthread *, struct pthread *);
1077void _thr_gc(struct pthread *);
1078void _thr_panic_exit(char *, int, char *);
1079void _thread_cleanupspecific(void);
1080void _thread_dump_info(void);
1081void _thread_printf(int, const char *, ...);
1082void _thr_sched_frame(struct pthread_sigframe *);
1083void _thr_sched_switch(struct pthread *);
1084void _thr_set_timeout(const struct timespec *);
1085void _thr_sig_handler(int, siginfo_t *, ucontext_t *);
1086void _thr_sig_check_pending(struct pthread *);
1087void _thr_sig_rundown(struct pthread *, ucontext_t *,
1088 struct pthread_sigframe *);
1089void _thr_sig_send(struct pthread *pthread, int sig);
1090void _thr_sig_wrapper(void);
1091void _thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf);
1092void _thr_seterrno(struct pthread *, int);
1093void _thr_enter_cancellation_point(struct pthread *);
1094void _thr_leave_cancellation_point(struct pthread *);
1095
1096/* XXX - Stuff that goes away when my sources get more up to date. */
1097/* #include <sys/kse.h> */
1098#ifdef SYS_KSE_H
1099int __sys_kse_create(struct kse_mailbox *, int);
1100int __sys_kse_thr_wakeup(struct kse_mailbox *);
1101int __sys_kse_exit(struct kse_mailbox *);
1102int __sys_kse_release(struct kse_mailbox *);
1103#endif
1104
1105/* #include <sys/aio.h> */
1106#ifdef _SYS_AIO_H_
1107int __sys_aio_suspend(const struct aiocb * const[], int, const struct timespec *);
1108#endif
1109
1110/* #include <fcntl.h> */
1111#ifdef _SYS_FCNTL_H_
1112int __sys_fcntl(int, int, ...);
1113int __sys_open(const char *, int, ...);
1114#endif
1115
1116/* #include <sys/ioctl.h> */
1117#ifdef _SYS_IOCTL_H_
1118int __sys_ioctl(int, unsigned long, ...);
1119#endif
1120
1121/* #inclde <sched.h> */
1122#ifdef _SCHED_H_
1123int __sys_sched_yield(void);
1124#endif
1125
1126/* #include <signal.h> */
1127#ifdef _SIGNAL_H_
1128int __sys_kill(pid_t, int);
1129int __sys_sigaction(int, const struct sigaction *, struct sigaction *);
1130int __sys_sigpending(sigset_t *);
1131int __sys_sigprocmask(int, const sigset_t *, sigset_t *);
1132int __sys_sigsuspend(const sigset_t *);
1133int __sys_sigreturn(ucontext_t *);
1134int __sys_sigaltstack(const struct sigaltstack *, struct sigaltstack *);
1135#endif
1136
1137/* #include <sys/socket.h> */
1138#ifdef _SYS_SOCKET_H_
1139int __sys_sendfile(int, int, off_t, size_t, struct sf_hdtr *,
1140 off_t *, int);
1141#endif
1142
1143/* #include <sys/uio.h> */
1144#ifdef _SYS_UIO_H_
1145ssize_t __sys_readv(int, const struct iovec *, int);
1146ssize_t __sys_writev(int, const struct iovec *, int);
1147#endif
1148
1149/* #include <time.h> */
1150#ifdef _TIME_H_
1151int __sys_nanosleep(const struct timespec *, struct timespec *);
1152#endif
1153
1154/* #include <unistd.h> */
1155#ifdef _UNISTD_H_
1156int __sys_close(int);
1157int __sys_execve(const char *, char * const *, char * const *);
1158int __sys_fork(void);
1159int __sys_fsync(int);
1160pid_t __sys_getpid(void);
1161int __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
1162ssize_t __sys_read(int, void *, size_t);
1163ssize_t __sys_write(int, const void *, size_t);
1164void __sys_exit(int);
1165#endif
1166
1167/* #include <poll.h> */
1168#ifdef _SYS_POLL_H_
1169int __sys_poll(struct pollfd *, unsigned, int);
1170#endif
1171
1172/* #include <sys/mman.h> */
1173#ifdef _SYS_MMAN_H_
1174int __sys_msync(void *, size_t, int);
1175#endif
1176
1177#endif /* !_THR_PRIVATE_H */