From owner-p4-projects@FreeBSD.ORG Sat Nov 20 02:58:52 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 5776016A4D0; Sat, 20 Nov 2004 02:58:52 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2F1A216A4CE for ; Sat, 20 Nov 2004 02:58:52 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id EB05243D1F for ; Sat, 20 Nov 2004 02:58:51 +0000 (GMT) (envelope-from davidxu@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.11/8.12.11) with ESMTP id iAK2wpTS002608 for ; Sat, 20 Nov 2004 02:58:51 GMT (envelope-from davidxu@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.11/8.12.11/Submit) id iAK2wp4p002605 for perforce@freebsd.org; Sat, 20 Nov 2004 02:58:51 GMT (envelope-from davidxu@freebsd.org) Date: Sat, 20 Nov 2004 02:58:51 GMT Message-Id: <200411200258.iAK2wp4p002605@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to davidxu@freebsd.org using -f From: David Xu To: Perforce Change Reviews Subject: PERFORCE change 65496 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 20 Nov 2004 02:58:53 -0000 http://perforce.freebsd.org/chv.cgi?CH=65496 Change 65496 by davidxu@davidxu_alona on 2004/11/20 02:58:04 remove sched queue. Affected files ... .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_private.h#2 edit Differences ... ==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_private.h#2 (text+ko) ==== @@ -43,21 +43,19 @@ #include #include #include -#include +#include +#include +#include #include #include #include -#include -#include -#include -#include +#include +#include #include #include -#ifndef LIBTHREAD_DB #include "lock.h" #include "pthread_md.h" -#endif /* * Evaluate the storage class specifier. @@ -75,14 +73,10 @@ */ #define PANIC(string) _thr_exit(__FILE__,__LINE__,string) - /* Output debug messages like this: */ #define stdout_debug(args...) _thread_printf(STDOUT_FILENO, ##args) #define stderr_debug(args...) _thread_printf(STDOUT_FILENO, ##args) -#define DBG_MUTEX 0x0001 -#define DBG_SIG 0x0002 - #ifdef _PTHREADS_INVARIANTS #define THR_ASSERT(cond, msg) do { \ if (!(cond)) \ @@ -122,179 +116,6 @@ } \ } while (0) -/* - * Priority queues. - * - * XXX It'd be nice if these were contained in uthread_priority_queue.[ch]. - */ -typedef struct pq_list { - TAILQ_HEAD(, pthread) pl_head; /* list of threads at this priority */ - TAILQ_ENTRY(pq_list) pl_link; /* link for queue of priority lists */ - int pl_prio; /* the priority of this list */ - int pl_queued; /* is this in the priority queue */ -} pq_list_t; - -typedef struct pq_queue { - TAILQ_HEAD(, pq_list) pq_queue; /* queue of priority lists */ - pq_list_t *pq_lists; /* array of all priority lists */ - int pq_size; /* number of priority lists */ -#define PQF_ACTIVE 0x0001 - int pq_flags; - int pq_threads; -} pq_queue_t; - -/* - * Each KSEG has a scheduling queue. For now, threads that exist in their - * own KSEG (system scope) will get a full priority queue. In the future - * this can be optimized for the single thread per KSEG case. - */ -struct sched_queue { - pq_queue_t sq_runq; - TAILQ_HEAD(, pthread) sq_waitq; /* waiting in userland */ -}; - -typedef struct kse_thr_mailbox *kse_critical_t; - -struct kse_group; - -#define MAX_KSE_LOCKLEVEL 5 -struct kse { - /* -- location and order specific items for gdb -- */ - struct kcb *k_kcb; - struct pthread *k_curthread; /* current thread */ - struct kse_group *k_kseg; /* parent KSEG */ - struct sched_queue *k_schedq; /* scheduling queue */ - /* -- end of location and order specific items -- */ - TAILQ_ENTRY(kse) k_qe; /* KSE list link entry */ - TAILQ_ENTRY(kse) k_kgqe; /* KSEG's KSE list entry */ - /* - * Items that are only modified by the kse, or that otherwise - * don't need to be locked when accessed - */ - struct lock k_lock; - struct lockuser k_lockusers[MAX_KSE_LOCKLEVEL]; - int k_locklevel; - stack_t k_stack; - int k_flags; -#define KF_STARTED 0x0001 /* kernel kse created */ -#define KF_INITIALIZED 0x0002 /* initialized on 1st upcall */ -#define KF_TERMINATED 0x0004 /* kse is terminated */ -#define KF_IDLE 0x0008 /* kse is idle */ -#define KF_SWITCH 0x0010 /* thread switch in UTS */ - int k_error; /* syscall errno in critical */ - int k_cpu; /* CPU ID when bound */ - int k_sigseqno; /* signal buffered count */ -}; - -#define KSE_SET_IDLE(kse) ((kse)->k_flags |= KF_IDLE) -#define KSE_CLEAR_IDLE(kse) ((kse)->k_flags &= ~KF_IDLE) -#define KSE_IS_IDLE(kse) (((kse)->k_flags & KF_IDLE) != 0) -#define KSE_SET_SWITCH(kse) ((kse)->k_flags |= KF_SWITCH) -#define KSE_CLEAR_SWITCH(kse) ((kse)->k_flags &= ~KF_SWITCH) -#define KSE_IS_SWITCH(kse) (((kse)->k_flags & KF_SWITCH) != 0) - -/* - * Each KSE group contains one or more KSEs in which threads can run. - * At least for now, there is one scheduling queue per KSE group; KSEs - * within the same KSE group compete for threads from the same scheduling - * queue. A scope system thread has one KSE in one KSE group; the group - * does not use its scheduling queue. - */ -struct kse_group { - TAILQ_HEAD(, kse) kg_kseq; /* list of KSEs in group */ - TAILQ_HEAD(, pthread) kg_threadq; /* list of threads in group */ - TAILQ_ENTRY(kse_group) kg_qe; /* link entry */ - struct sched_queue kg_schedq; /* scheduling queue */ - struct lock kg_lock; - int kg_threadcount; /* # of assigned threads */ - int kg_ksecount; /* # of assigned KSEs */ - int kg_idle_kses; - int kg_flags; -#define KGF_SINGLE_THREAD 0x0001 /* scope system kse group */ -#define KGF_SCHEDQ_INITED 0x0002 /* has an initialized schedq */ -}; - -/* - * Add/remove threads from a KSE's scheduling queue. - * For now the scheduling queue is hung off the KSEG. - */ -#define KSEG_THRQ_ADD(kseg, thr) \ -do { \ - TAILQ_INSERT_TAIL(&(kseg)->kg_threadq, thr, kle);\ - (kseg)->kg_threadcount++; \ -} while (0) - -#define KSEG_THRQ_REMOVE(kseg, thr) \ -do { \ - TAILQ_REMOVE(&(kseg)->kg_threadq, thr, kle); \ - (kseg)->kg_threadcount--; \ -} while (0) - - -/* - * Lock acquire and release for KSEs. - */ -#define KSE_LOCK_ACQUIRE(kse, lck) \ -do { \ - if ((kse)->k_locklevel < MAX_KSE_LOCKLEVEL) { \ - (kse)->k_locklevel++; \ - _lock_acquire((lck), \ - &(kse)->k_lockusers[(kse)->k_locklevel - 1], 0); \ - } \ - else \ - PANIC("Exceeded maximum lock level"); \ -} while (0) - -#define KSE_LOCK_RELEASE(kse, lck) \ -do { \ - if ((kse)->k_locklevel > 0) { \ - _lock_release((lck), \ - &(kse)->k_lockusers[(kse)->k_locklevel - 1]); \ - (kse)->k_locklevel--; \ - } \ -} while (0) - -/* - * Lock our own KSEG. - */ -#define KSE_LOCK(curkse) \ - KSE_LOCK_ACQUIRE(curkse, &(curkse)->k_kseg->kg_lock) -#define KSE_UNLOCK(curkse) \ - KSE_LOCK_RELEASE(curkse, &(curkse)->k_kseg->kg_lock) - -/* - * Lock a potentially different KSEG. - */ -#define KSE_SCHED_LOCK(curkse, kseg) \ - KSE_LOCK_ACQUIRE(curkse, &(kseg)->kg_lock) -#define KSE_SCHED_UNLOCK(curkse, kseg) \ - KSE_LOCK_RELEASE(curkse, &(kseg)->kg_lock) - -/* - * Waiting queue manipulation macros (using pqe link): - */ -#define KSE_WAITQ_REMOVE(kse, thrd) \ -do { \ - if (((thrd)->flags & THR_FLAGS_IN_WAITQ) != 0) { \ - TAILQ_REMOVE(&(kse)->k_schedq->sq_waitq, thrd, pqe); \ - (thrd)->flags &= ~THR_FLAGS_IN_WAITQ; \ - } \ -} while (0) -#define KSE_WAITQ_INSERT(kse, thrd) kse_waitq_insert(thrd) -#define KSE_WAITQ_FIRST(kse) TAILQ_FIRST(&(kse)->k_schedq->sq_waitq) - -#define KSE_WAKEUP(kse) kse_wakeup(&(kse)->k_kcb->kcb_kmbx) - -/* - * TailQ initialization values. - */ -#define TAILQ_INITIALIZER { NULL, NULL } - -/* - * lock initialization values. - */ -#define LCK_INITIALIZER { NULL, NULL, LCK_DEFAULT } - struct pthread_mutex { /* * Lock for accesses to this structure. @@ -335,14 +156,6 @@ #define MUTEX_FLAGS_INITED 0x02 #define MUTEX_FLAGS_BUSY 0x04 -/* - * Static mutex initialization values. - */ -#define PTHREAD_MUTEX_STATIC_INITIALIZER \ - { LCK_INITIALIZER, PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, \ - TAILQ_INITIALIZER, NULL, MUTEX_FLAGS_PRIVATE, 0, 0, 0, 0, \ - TAILQ_INITIALIZER } - struct pthread_mutex_attr { enum pthread_mutextype m_type; int m_protocol; @@ -391,8 +204,7 @@ }; struct pthread_spinlock { - volatile int s_lock; - pthread_t s_owner; + struct lock s_lock; }; /* @@ -403,18 +215,11 @@ #define COND_FLAGS_BUSY 0x04 /* - * Static cond initialization values. - */ -#define PTHREAD_COND_STATIC_INITIALIZER \ - { LCK_INITIALIZER, COND_TYPE_FAST, TAILQ_INITIALIZER, \ - NULL, NULL, 0, 0 } - -/* * Cleanup definitions. */ struct pthread_cleanup { struct pthread_cleanup *next; - void (*routine) (); + void (*routine)(); void *routine_arg; }; @@ -435,7 +240,7 @@ #define THR_SIGNAL_THREAD 0x200 /* This is a signal thread */ int flags; void *arg_attr; - void (*cleanup_attr) (); + void (*cleanup_attr)(); void *stackaddr_attr; size_t stacksize_attr; size_t guardsize_attr; @@ -484,28 +289,10 @@ #define THR_BASE_PRIORITY(prio) ((prio) & THR_MAX_PRIORITY) /* - * Clock resolution in microseconds. - */ -#define CLOCK_RES_USEC 10000 - -/* * Time slice period in microseconds. */ #define TIMESLICE_USEC 20000 -/* - * XXX - Define a thread-safe macro to get the current time of day - * which is updated at regular intervals by something. - * - * For now, we just make the system call to get the time. - */ -#define KSE_GET_TOD(curkse, tsp) \ -do { \ - *tsp = (curkse)->k_kcb->kcb_kmbx.km_timeofday; \ - if ((tsp)->tv_sec == 0) \ - clock_gettime(CLOCK_REALTIME, tsp); \ -} while (0) - struct pthread_rwlockattr { int pshared; }; @@ -523,12 +310,8 @@ */ enum pthread_state { PS_RUNNING, - PS_LOCKWAIT, PS_MUTEX_WAIT, PS_COND_WAIT, - PS_SLEEP_WAIT, - PS_SIGSUSPEND, - PS_SIGWAIT, PS_JOIN, PS_SUSPENDED, PS_DEAD, @@ -536,23 +319,16 @@ PS_STATE_MAX }; -struct sigwait_data { - sigset_t *waitset; - siginfo_t *siginfo; /* used to save siginfo for sigwaitinfo() */ -}; - union pthread_wait_data { pthread_mutex_t mutex; pthread_cond_t cond; - struct lock *lock; - struct sigwait_data *sigwait; }; /* * Define a continuation routine that can be used to perform a * transfer of control: */ -typedef void (*thread_continuation_t) (void *); +typedef void (*thread_continuation_t)(void *); /* * This stores a thread's state prior to running a signal handler. @@ -561,18 +337,14 @@ * state is restored from here. */ struct pthread_sigframe { - int psf_valid; int psf_flags; int psf_cancelflags; int psf_interrupted; int psf_timeout; - int psf_signo; enum pthread_state psf_state; union pthread_wait_data psf_wait_data; struct timespec psf_wakeup_time; - sigset_t psf_sigset; - sigset_t psf_sigmask; - int psf_seqno; + thread_continuation_t psf_continuation; }; struct join_status { @@ -590,17 +362,13 @@ volatile int allocated; volatile int count; int seqno; - void (*destructor) (void *); + void (*destructor)(void *); }; -#define MAX_THR_LOCKLEVEL 5 /* * Thread structure. */ struct pthread { - /* Thread control block */ - struct tcb *tcb; - /* * Magic value to help recognize a valid thread structure * from an invalid one: @@ -610,25 +378,40 @@ char *name; u_int64_t uniqueid; /* for gdb */ - /* Queue entry for list of all threads: */ + /* How many low level locks the thread held. */ + int locklevel; + + /* + * Lock for accesses to this thread structure. + */ + struct lock lock; + + /* Kernel thread id. */ + long tid; + + /* Thread exits in kernel, written by kernel. */ + long isdead; + + /* How many signals were received. */ + int sigseqno; + + /* Thread lock held and switching state. */ + int lock_switch; + + /* Thread is waiting. */ + int idle; + + /* Queue entry for list of all threads. */ TAILQ_ENTRY(pthread) tle; /* link for all threads in process */ - TAILQ_ENTRY(pthread) kle; /* link for all threads in KSE/KSEG */ - /* Queue entry for GC lists: */ + /* Queue entry for GC lists. */ TAILQ_ENTRY(pthread) gcle; - /* Hash queue entry */ + /* Hash queue entry. */ LIST_ENTRY(pthread) hle; - /* - * Lock for accesses to this thread structure. - */ - struct lock lock; - struct lockuser lockusers[MAX_THR_LOCKLEVEL]; - int locklevel; - kse_critical_t critical[MAX_KSE_LOCKLEVEL]; - struct kse *kse; - struct kse_group *kseg; + /* Threads reference count. */ + int refcount; /* * Thread start routine, argument, stack pointer and thread @@ -638,15 +421,8 @@ void *arg; struct pthread_attr attr; - int active; /* thread running */ - int blocked; /* thread blocked in kernel */ - int need_switchout; - - /* - * Used for tracking delivery of signal handlers. - */ - struct pthread_sigframe *curframe; - siginfo_t *siginfo; + /* backout routine must be invoke before handling signal. */ + thread_continuation_t sigbackout; /* * Cancelability flags - the lower 2 bits are used by cancel @@ -659,27 +435,18 @@ thread_continuation_t continuation; - /* - * The thread's base and pending signal masks. The active - * signal mask is stored in the thread's context (in mailbox). - */ + /* Thread's temporary signal masks. */ sigset_t sigmask; + + /* Used for tracking delivery of signal handlers. */ sigset_t sigpend; - sigset_t *oldsigmask; + siginfo_t siginfo[_SIG_MAXSIG]; volatile int check_pending; - int refcount; /* Thread state: */ enum pthread_state state; - volatile int lock_switch; /* - * Number of microseconds accumulated by this thread when - * time slicing is active. - */ - long slice_usec; - - /* * Time to wake up thread. This is used for sleeping threads and * for any operation which may time out (such as select). */ @@ -702,8 +469,7 @@ struct join_status join_status; /* - * The current thread can belong to only one scheduling queue at - * a time (ready or waiting queue). It can also belong to: + * The current thread can belong to: * * o A queue of threads waiting for a mutex * o A queue of threads waiting for a condition variable @@ -720,7 +486,6 @@ * sqe for synchronization (mutex, condition variable, and join) * queue links, and qe for all other links. */ - TAILQ_ENTRY(pthread) pqe; /* priority, wait queues link */ TAILQ_ENTRY(pthread) sqe; /* synchronization queue link */ /* Wait data. */ @@ -738,20 +503,12 @@ */ int critical_count; - /* - * Set to TRUE if this thread should yield after leaving a - * critical region to check for signals, messages, etc. - */ - int critical_yield; - int sflags; #define THR_FLAGS_IN_SYNCQ 0x0001 /* Miscellaneous flags; only set with scheduling lock held. */ int flags; #define THR_FLAGS_PRIVATE 0x0001 -#define THR_FLAGS_IN_WAITQ 0x0002 /* in waiting queue using pqe link */ -#define THR_FLAGS_IN_RUNQ 0x0004 /* in run queue using pqe link */ #define THR_FLAGS_EXITING 0x0008 /* thread is exiting */ #define THR_FLAGS_SUSPENDED 0x0010 /* thread is suspended */ @@ -790,9 +547,6 @@ /* Number of priority ceiling or protection mutexes owned. */ int priority_mutex_count; - /* Number rwlocks rdlocks held. */ - int rdlock_count; - /* * Queue of currently owned mutexes. */ @@ -802,18 +556,24 @@ struct pthread_specific_elem *specific; int specific_data_count; - /* Alternative stack for sigaltstack() */ - stack_t sigstk; + /* Number rwlocks rdlocks held. */ + int rdlock_count; /* - * Current locks bitmap for rtld. - */ - int rtld_bits; + * Current locks bitmap for rtld. */ + int rtld_bits; + + /* Thread control block */ + struct tcb *tcb; /* Cleanup handlers Link List */ struct pthread_cleanup *cleanup; - char *fname; /* Ptr to source file name */ - int lineno; /* Source line number. */ + + /* Ptr to source file name*/ + char *fname; + + /* Source line number. */ + int lineno; }; /* @@ -829,10 +589,6 @@ #define THR_YIELD_CHECK(thrd) \ do { \ if (!THR_IN_CRITICAL(thrd)) { \ - if (__predict_false(_libkse_debug)) \ - _thr_debug_check_yield(thrd); \ - if ((thrd)->critical_yield != 0) \ - _thr_sched_switch(thrd); \ if ((thrd)->check_pending != 0) \ _thr_sig_check_pending(thrd); \ } \ @@ -840,64 +596,28 @@ #define THR_LOCK_ACQUIRE(thrd, lck) \ do { \ - if ((thrd)->locklevel < MAX_THR_LOCKLEVEL) { \ - THR_DEACTIVATE_LAST_LOCK(thrd); \ - (thrd)->locklevel++; \ - _lock_acquire((lck), \ - &(thrd)->lockusers[(thrd)->locklevel - 1], \ - (thrd)->active_priority); \ - } else \ - PANIC("Exceeded maximum lock level"); \ + (thrd)->locklevel++; \ + _lock_acquire((lck), (thrd)->tid); \ } while (0) #define THR_LOCK_RELEASE(thrd, lck) \ do { \ if ((thrd)->locklevel > 0) { \ - _lock_release((lck), \ - &(thrd)->lockusers[(thrd)->locklevel - 1]); \ + _lock_release((lck), (thrd)->tid); \ (thrd)->locklevel--; \ - THR_ACTIVATE_LAST_LOCK(thrd); \ if ((thrd)->locklevel == 0) \ THR_YIELD_CHECK(thrd); \ + } else { \ + PANIC("locklevel <= 0"); \ } \ } while (0) -#define THR_ACTIVATE_LAST_LOCK(thrd) \ -do { \ - if ((thrd)->locklevel > 0) \ - _lockuser_setactive( \ - &(thrd)->lockusers[(thrd)->locklevel - 1], 1); \ -} while (0) - -#define THR_DEACTIVATE_LAST_LOCK(thrd) \ -do { \ - if ((thrd)->locklevel > 0) \ - _lockuser_setactive( \ - &(thrd)->lockusers[(thrd)->locklevel - 1], 0); \ -} while (0) - -/* - * For now, threads will have their own lock separate from their - * KSE scheduling lock. - */ #define THR_LOCK(thr) THR_LOCK_ACQUIRE(thr, &(thr)->lock) #define THR_UNLOCK(thr) THR_LOCK_RELEASE(thr, &(thr)->lock) #define THR_THREAD_LOCK(curthrd, thr) THR_LOCK_ACQUIRE(curthrd, &(thr)->lock) #define THR_THREAD_UNLOCK(curthrd, thr) THR_LOCK_RELEASE(curthrd, &(thr)->lock) /* - * Priority queue manipulation macros (using pqe link). We use - * the thread's kseg link instead of the kse link because a thread - * does not (currently) have a statically assigned kse. - */ -#define THR_RUNQ_INSERT_HEAD(thrd) \ - _pq_insert_head(&(thrd)->kseg->kg_schedq.sq_runq, thrd) -#define THR_RUNQ_INSERT_TAIL(thrd) \ - _pq_insert_tail(&(thrd)->kseg->kg_schedq.sq_runq, thrd) -#define THR_RUNQ_REMOVE(thrd) \ - _pq_remove(&(thrd)->kseg->kg_schedq.sq_runq, thrd) - -/* * Macros to insert/remove threads to the all thread list and * the gc list. */ @@ -932,71 +652,43 @@ #define GC_NEEDED() (atomic_load_acq_int(&_gc_count) >= 5) -/* - * Locking the scheduling queue for another thread uses that thread's - * KSEG lock. - */ -#define THR_SCHED_LOCK(curthr, thr) do { \ - (curthr)->critical[(curthr)->locklevel] = _kse_critical_enter(); \ - (curthr)->locklevel++; \ - KSE_SCHED_LOCK((curthr)->kse, (thr)->kseg); \ -} while (0) - -#define THR_SCHED_UNLOCK(curthr, thr) do { \ - KSE_SCHED_UNLOCK((curthr)->kse, (thr)->kseg); \ - (curthr)->locklevel--; \ - _kse_critical_leave((curthr)->critical[(curthr)->locklevel]); \ -} while (0) - /* Take the scheduling lock with the intent to call the scheduler. */ #define THR_LOCK_SWITCH(curthr) do { \ - (void)_kse_critical_enter(); \ - KSE_SCHED_LOCK((curthr)->kse, (curthr)->kseg); \ + curthread->lock_switch++; \ + _lock_acquire(&(curthr->lock), (curthr)->tid); \ } while (0) #define THR_UNLOCK_SWITCH(curthr) do { \ - KSE_SCHED_UNLOCK((curthr)->kse, (curthr)->kseg);\ + _lock_release(&(curthr->lock), (curthr)->tid); \ + curthread->lock_switch--; \ + THR_YIELD_CHECK(curthr); \ } while (0) #define THR_CRITICAL_ENTER(thr) (thr)->critical_count++ #define THR_CRITICAL_LEAVE(thr) do { \ (thr)->critical_count--; \ - if (((thr)->critical_yield != 0) && \ - ((thr)->critical_count == 0)) { \ - (thr)->critical_yield = 0; \ - _thr_sched_switch(thr); \ + if ((thr)->critical_count == 0) { \ + THR_YIELD_CHECK(thr); \ } \ } while (0) -#define THR_IS_ACTIVE(thrd) \ - ((thrd)->kse != NULL) && ((thrd)->kse->k_curthread == (thrd)) - #define THR_IN_SYNCQ(thrd) (((thrd)->sflags & THR_FLAGS_IN_SYNCQ) != 0) #define THR_IS_SUSPENDED(thrd) \ (((thrd)->state == PS_SUSPENDED) || \ (((thrd)->flags & THR_FLAGS_SUSPENDED) != 0)) #define THR_IS_EXITING(thrd) (((thrd)->flags & THR_FLAGS_EXITING) != 0) -#define DBG_CAN_RUN(thrd) (((thrd)->tcb->tcb_tmbx.tm_dflags & \ - TMDF_SUSPEND) == 0) extern int __isthreaded; -static inline int -_kse_isthreaded(void) -{ - return (__isthreaded != 0); -} - /* * Global variables for the pthread kernel. */ SCLASS void *_usrstack SCLASS_PRESET(NULL); -SCLASS struct kse *_kse_initial SCLASS_PRESET(NULL); SCLASS struct pthread *_thr_initial SCLASS_PRESET(NULL); /* For debugger */ -SCLASS int _libkse_debug SCLASS_PRESET(0); -SCLASS int _thread_activated SCLASS_PRESET(0); +SCLASS int _libkse2_debug SCLASS_PRESET(0); +SCLASS int _thread_inited SCLASS_PRESET(0); SCLASS int _thread_scope_system SCLASS_PRESET(0); /* List of all threads: */ @@ -1016,7 +708,7 @@ SCLASS struct pthread_attr _pthread_attr_default SCLASS_PRESET({ SCHED_RR, 0, TIMESLICE_USEC, THR_DEFAULT_PRIORITY, - THR_CREATE_RUNNING, PTHREAD_CREATE_JOINABLE, NULL, + THR_CREATE_RUNNING, 0, NULL, NULL, NULL, THR_STACK_DEFAULT, /* guardsize */0 }); @@ -1028,76 +720,40 @@ SCLASS struct pthread_cond_attr _pthread_condattr_default SCLASS_PRESET({COND_TYPE_FAST, 0}); -/* Clock resolution in usec. */ -SCLASS int _clock_res_usec SCLASS_PRESET(CLOCK_RES_USEC); - /* Array of signal actions for this process: */ SCLASS struct sigaction _thread_sigact[_SIG_MAXSIG]; -/* - * Lock for above count of dummy handlers and for the process signal - * mask and pending signal sets. - */ -SCLASS struct lock _thread_signal_lock; - -/* Pending signals and mask for this process: */ -SCLASS sigset_t _thr_proc_sigpending; -SCLASS siginfo_t _thr_proc_siginfo[_SIG_MAXSIG]; - SCLASS pid_t _thr_pid SCLASS_PRESET(0); +SCLASS int _thr_guard_default; +SCLASS int _thr_page_size; +/* Garbage thread count. */ +SCLASS int _gc_count SCLASS_PRESET(0); -/* Garbage collector lock. */ -SCLASS struct lock _gc_lock; -SCLASS int _gc_check SCLASS_PRESET(0); -SCLASS int _gc_count SCLASS_PRESET(0); - SCLASS struct lock _mutex_static_lock; +SCLASS struct lock _cond_static_lock; SCLASS struct lock _rwlock_static_lock; SCLASS struct lock _keytable_lock; SCLASS struct lock _thread_list_lock; -SCLASS int _thr_guard_default; -SCLASS int _thr_page_size; -SCLASS pthread_t _thr_sig_daemon; -SCLASS int _thr_debug_flags SCLASS_PRESET(0); +SCLASS struct lock _thread_signal_lock; /* Undefine the storage class and preset specifiers: */ #undef SCLASS #undef SCLASS_PRESET - /* * Function prototype definitions. */ __BEGIN_DECLS int _cond_reinit(pthread_cond_t *); -void _cond_wait_backout(struct pthread *); -struct kse *_kse_alloc(struct pthread *, int sys_scope); -kse_critical_t _kse_critical_enter(void); -void _kse_critical_leave(kse_critical_t); -int _kse_in_critical(void); -void _kse_free(struct pthread *, struct kse *); -void _kse_init(); -struct kse_group *_kseg_alloc(struct pthread *); -void _kse_lock_wait(struct lock *, struct lockuser *lu); -void _kse_lock_wakeup(struct lock *, struct lockuser *lu); -void _kse_single_thread(struct pthread *); -int _kse_setthreaded(int); -void _kseg_free(struct kse_group *); +void _thr_kern_init(); +void _thr_single_thread(struct pthread *); +int _thr_setthreaded(int); int _mutex_cv_lock(pthread_mutex_t *); int _mutex_cv_unlock(pthread_mutex_t *); -void _mutex_lock_backout(struct pthread *); void _mutex_notify_priochange(struct pthread *, struct pthread *, int); int _mutex_reinit(struct pthread_mutex *); void _mutex_unlock_private(struct pthread *); void _libpthread_init(struct pthread *); -int _pq_alloc(struct pq_queue *, int, int); -void _pq_free(struct pq_queue *); -int _pq_init(struct pq_queue *); -void _pq_remove(struct pq_queue *pq, struct pthread *); -void _pq_insert_head(struct pq_queue *pq, struct pthread *); -void _pq_insert_tail(struct pq_queue *pq, struct pthread *); -struct pthread *_pq_first(struct pq_queue *pq); -struct pthread *_pq_first_debug(struct pq_queue *pq); void *_pthread_getspecific(pthread_key_t); int _pthread_key_create(pthread_key_t *, void (*) (void *)); int _pthread_key_delete(pthread_key_t); @@ -1120,56 +776,43 @@ struct pthread *_thr_alloc(struct pthread *); void _thr_exit(char *, int, char *); void _thr_exit_cleanup(void); -void _thr_lock_wait(struct lock *lock, struct lockuser *lu); -void _thr_lock_wakeup(struct lock *lock, struct lockuser *lu); -void _thr_mutex_reinit(pthread_mutex_t *); +void _thr_mutex_reinit(struct pthread *, pthread_mutex_t *); int _thr_ref_add(struct pthread *, struct pthread *, int); void _thr_ref_delete(struct pthread *, struct pthread *); void _thr_rtld_init(void); void _thr_rtld_fini(void); -int _thr_schedule_add(struct pthread *, struct pthread *); -void _thr_schedule_remove(struct pthread *, struct pthread *); void _thr_setrunnable(struct pthread *curthread, struct pthread *thread); -struct kse_mailbox *_thr_setrunnable_unlocked(struct pthread *thread); -struct kse_mailbox *_thr_sig_add(struct pthread *, int, siginfo_t *); -void _thr_sig_dispatch(struct kse *, int, siginfo_t *); +long _thr_setrunnable_unlocked(struct pthread *thread); +long _thr_sig_add(struct pthread *, int, siginfo_t *); int _thr_stack_alloc(struct pthread_attr *); void _thr_stack_free(struct pthread_attr *); void _thr_exit_cleanup(void); void _thr_free(struct pthread *, struct pthread *); void _thr_gc(struct pthread *); -void _thr_panic_exit(char *, int, char *); void _thread_cleanupspecific(void); void _thread_dump_info(void); void _thread_printf(int, const char *, ...); void _thr_sched_switch(struct pthread *); void _thr_sched_switch_unlocked(struct pthread *); void _thr_set_timeout(const struct timespec *); -void _thr_seterrno(struct pthread *, int); void _thr_sig_handler(int, siginfo_t *, ucontext_t *); void _thr_sig_check_pending(struct pthread *); -void _thr_sig_rundown(struct pthread *, ucontext_t *, - struct pthread_sigframe *); +void _thr_sig_rundown(struct pthread *); void _thr_sig_send(struct pthread *pthread, int sig); void _thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf); void _thr_spinlock_init(void); void _thr_cancel_enter(struct pthread *); void _thr_cancel_leave(struct pthread *, int); -int _thr_setconcurrency(int new_level); -int _thr_setmaxconcurrency(void); void _thr_critical_enter(struct pthread *); void _thr_critical_leave(struct pthread *); -int _thr_start_sig_daemon(void); -int _thr_getprocsig(int sig, siginfo_t *siginfo); -int _thr_getprocsig_unlocked(int sig, siginfo_t *siginfo); void _thr_signal_init(void); void _thr_signal_deinit(void); void _thr_hash_add(struct pthread *); void _thr_hash_remove(struct pthread *); struct pthread *_thr_hash_find(struct pthread *); void _thr_finish_cancellation(void *arg); -int _thr_sigonstack(void *sp); -void _thr_debug_check_yield(struct pthread *); +void _thr_link(struct pthread *curthread, struct pthread *thread); +void _thr_unlink(struct pthread *curthread, struct pthread *thread); /* * Aliases for _pthread functions. Should be called instead of @@ -1180,9 +823,9 @@ int _thr_cond_wait(pthread_cond_t *, pthread_mutex_t *); int _thr_mutex_lock(pthread_mutex_t *); int _thr_mutex_unlock(pthread_mutex_t *); -int _thr_rwlock_rdlock (pthread_rwlock_t *); -int _thr_rwlock_wrlock (pthread_rwlock_t *); -int _thr_rwlock_unlock (pthread_rwlock_t *); +int _thr_rwlock_rdlock(pthread_rwlock_t *); +int _thr_rwlock_wrlock(pthread_rwlock_t *); +int _thr_rwlock_unlock(pthread_rwlock_t *); /* #include */ #ifdef _SYS_AIO_H_ @@ -1247,7 +890,9 @@ ssize_t __sys_write(int, const void *, size_t); void __sys_exit(int); int __sys_sigwait(const sigset_t *, int *); -int __sys_sigtimedwait(sigset_t *, siginfo_t *, struct timespec *); +int __sys_sigtimedwait(const sigset_t *, siginfo_t *, + const struct timespec *); +int __sys_sigwaitinfo(const sigset_t *set, siginfo_t *info); #endif /* #include */ @@ -1260,4 +905,25 @@ int __sys_msync(void *, size_t, int); #endif +__END_DECLS + +static inline int +_thr_isthreaded(void) +{ + return (__isthreaded != 0); +} + +static inline int +_thr_is_inited(void) +{ + return _thread_inited; +} + +static inline void +_thr_check_init(void) +{ + if (_thread_inited == 0) + _libpthread_init(0); +} + #endif /* !_THR_PRIVATE_H */