summaryrefslogtreecommitdiff
path: root/lib/libpthread/thread/thr_private.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpthread/thread/thr_private.h')
-rw-r--r--lib/libpthread/thread/thr_private.h257
1 files changed, 169 insertions, 88 deletions
diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h
index 6cacb2752e41b..036ea80db1ebe 100644
--- a/lib/libpthread/thread/thr_private.h
+++ b/lib/libpthread/thread/thr_private.h
@@ -31,6 +31,7 @@
*
* Private thread definitions for the uthread kernel.
*
+ * $Id$
*/
#ifndef _PTHREAD_PRIVATE_H
@@ -68,33 +69,88 @@
/*
- * Priority queue manipulation macros:
+ * Priority queue manipulation macros (using pqe link):
*/
#define PTHREAD_PRIOQ_INSERT_HEAD(thrd) _pq_insert_head(&_readyq,thrd)
#define PTHREAD_PRIOQ_INSERT_TAIL(thrd) _pq_insert_tail(&_readyq,thrd)
#define PTHREAD_PRIOQ_REMOVE(thrd) _pq_remove(&_readyq,thrd)
-#define PTHREAD_PRIOQ_FIRST _pq_first(&_readyq)
+#define PTHREAD_PRIOQ_FIRST() _pq_first(&_readyq)
/*
- * Waiting queue manipulation macros:
+ * Waiting queue manipulation macros (using pqe link):
*/
-#define PTHREAD_WAITQ_INSERT(thrd) TAILQ_INSERT_TAIL(&_waitingq,thrd,pqe)
+#if defined(_PTHREADS_INVARIANTS)
+#define PTHREAD_WAITQ_REMOVE(thrd) _waitq_remove(thrd)
+#define PTHREAD_WAITQ_INSERT(thrd) _waitq_insert(thrd)
+#define PTHREAD_WAITQ_CLEARACTIVE() _waitq_clearactive()
+#define PTHREAD_WAITQ_SETACTIVE() _waitq_setactive()
+#else
#define PTHREAD_WAITQ_REMOVE(thrd) TAILQ_REMOVE(&_waitingq,thrd,pqe)
+#define PTHREAD_WAITQ_INSERT(thrd) do { \
+ if ((thrd)->wakeup_time.tv_sec == -1) \
+ TAILQ_INSERT_TAIL(&_waitingq,thrd,pqe); \
+ else { \
+ pthread_t tid = TAILQ_FIRST(&_waitingq); \
+ while ((tid != NULL) && (tid->wakeup_time.tv_sec != -1) && \
+ ((tid->wakeup_time.tv_sec < (thrd)->wakeup_time.tv_sec) || \
+ ((tid->wakeup_time.tv_sec == (thrd)->wakeup_time.tv_sec) && \
+ (tid->wakeup_time.tv_nsec <= (thrd)->wakeup_time.tv_nsec)))) \
+ tid = TAILQ_NEXT(tid, pqe); \
+ if (tid == NULL) \
+ TAILQ_INSERT_TAIL(&_waitingq,thrd,pqe); \
+ else \
+ TAILQ_INSERT_BEFORE(tid,thrd,pqe); \
+ } \
+} while (0)
+#define PTHREAD_WAITQ_CLEARACTIVE()
+#define PTHREAD_WAITQ_SETACTIVE()
+#endif
+
+/*
+ * Work queue manipulation macros (using qe link):
+ */
+#define PTHREAD_WORKQ_INSERT(thrd) do { \
+ TAILQ_INSERT_TAIL(&_workq,thrd,qe); \
+ (thrd)->flags |= PTHREAD_FLAGS_IN_WORKQ; \
+} while (0)
+#define PTHREAD_WORKQ_REMOVE(thrd) do { \
+ TAILQ_REMOVE(&_workq,thrd,qe); \
+ (thrd)->flags &= ~PTHREAD_FLAGS_IN_WORKQ; \
+} while (0)
+
/*
* State change macro without scheduling queue change:
*/
-#define PTHREAD_SET_STATE(thrd, newstate) { \
+#define PTHREAD_SET_STATE(thrd, newstate) do { \
(thrd)->state = newstate; \
(thrd)->fname = __FILE__; \
(thrd)->lineno = __LINE__; \
-}
+} while (0)
/*
* State change macro with scheduling queue change - This must be
* called with preemption deferred (see thread_kern_sched_[un]defer).
*/
-#define PTHREAD_NEW_STATE(thrd, newstate) { \
+#if defined(_PTHREADS_INVARIANTS)
+#define PTHREAD_NEW_STATE(thrd, newstate) do { \
+ if (_thread_kern_new_state != 0) \
+ PANIC("Recursive PTHREAD_NEW_STATE"); \
+ _thread_kern_new_state = 1; \
+ if ((thrd)->state != newstate) { \
+ if ((thrd)->state == PS_RUNNING) { \
+ PTHREAD_PRIOQ_REMOVE(thrd); \
+ PTHREAD_WAITQ_INSERT(thrd); \
+ } else if (newstate == PS_RUNNING) { \
+ PTHREAD_WAITQ_REMOVE(thrd); \
+ PTHREAD_PRIOQ_INSERT_TAIL(thrd); \
+ } \
+ } \
+ _thread_kern_new_state = 0; \
+ PTHREAD_SET_STATE(thrd, newstate); \
+} while (0)
+#else
+#define PTHREAD_NEW_STATE(thrd, newstate) do { \
if ((thrd)->state != newstate) { \
if ((thrd)->state == PS_RUNNING) { \
PTHREAD_PRIOQ_REMOVE(thrd); \
@@ -105,7 +161,8 @@
} \
} \
PTHREAD_SET_STATE(thrd, newstate); \
-}
+} while (0)
+#endif
/*
* Define the signals to be used for scheduling.
@@ -119,15 +176,6 @@
#endif
/*
- * Queue definitions.
- */
-struct pthread_queue {
- struct pthread *q_next;
- struct pthread *q_last;
- void *q_data;
-};
-
-/*
* Priority queues.
*
* XXX It'd be nice if these were contained in uthread_priority_queue.[ch].
@@ -147,14 +195,9 @@ typedef struct pq_queue {
/*
- * Static queue initialization values.
- */
-#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL }
-
-/*
* TailQ initialization values.
*/
-#define TAILQ_INITIALIZER { NULL, NULL }
+#define TAILQ_INITIALIZER { NULL, NULL }
/*
* Mutex definitions.
@@ -257,7 +300,7 @@ struct pthread_cond_attr {
* Static cond initialization values.
*/
#define PTHREAD_COND_STATIC_INITIALIZER \
- { COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, NULL, \
+ { COND_TYPE_FAST, TAILQ_INITIALIZER, NULL, NULL, \
0, _SPINLOCK_INITIALIZER }
/*
@@ -303,12 +346,6 @@ struct pthread_attr {
#define CLOCK_RES_NSEC 10000000
/*
- * Number of microseconds between incremental priority updates for
- * threads that are ready to run, but denied being run.
- */
-#define INC_PRIO_USEC 500000
-
-/*
* Time slice period in microseconds.
*/
#define TIMESLICE_USEC 100000
@@ -345,6 +382,7 @@ enum pthread_state {
PS_FDR_WAIT,
PS_FDW_WAIT,
PS_FILE_WAIT,
+ PS_POLL_WAIT,
PS_SELECT_WAIT,
PS_SLEEP_WAIT,
PS_WAIT_WAIT,
@@ -377,8 +415,8 @@ struct fd_table_entry {
* state of the lock on the file descriptor.
*/
spinlock_t lock;
- struct pthread_queue r_queue; /* Read queue. */
- struct pthread_queue w_queue; /* Write queue. */
+ TAILQ_HEAD(, pthread) r_queue; /* Read queue. */
+ TAILQ_HEAD(, pthread) w_queue; /* Write queue. */
struct pthread *r_owner; /* Ptr to thread owning read lock. */
struct pthread *w_owner; /* Ptr to thread owning write lock. */
char *r_fname; /* Ptr to read lock source file name */
@@ -390,11 +428,9 @@ struct fd_table_entry {
int flags; /* Flags used in open. */
};
-struct pthread_select_data {
+struct pthread_poll_data {
int nfds;
- fd_set readfds;
- fd_set writefds;
- fd_set exceptfds;
+ struct pollfd *fds;
};
union pthread_wait_data {
@@ -406,7 +442,7 @@ union pthread_wait_data {
short branch; /* Line number, for debugging. */
char *fname; /* Source file name for debugging.*/
} fd;
- struct pthread_select_data * select_data;
+ struct pthread_poll_data * poll_data;
spinlock_t *spinlock;
};
@@ -427,15 +463,11 @@ struct pthread {
*/
spinlock_t lock;
- /*
- * Pointer to the next thread in the thread linked list.
- */
- struct pthread *nxt;
+ /* Queue entry for list of all threads: */
+ TAILQ_ENTRY(pthread) tle;
- /*
- * Pointer to the next thread in the dead thread linked list.
- */
- struct pthread *nxt_dead;
+ /* Queue entry for list of dead threads: */
+ TAILQ_ENTRY(pthread) dle;
/*
* Thread start routine, argument, stack pointer and thread
@@ -514,25 +546,25 @@ struct pthread {
*/
int error;
- /* Join queue for waiting threads: */
- struct pthread_queue join_queue;
+ /* Join queue head and link for waiting threads: */
+ TAILQ_HEAD(join_head, pthread) join_queue;
/*
- * The current thread can belong to only one scheduling queue
- * at a time (ready or waiting queue). It can also belong to
- * a queue of threads waiting on mutexes or condition variables.
- * Use pqe for the scheduling queue link (both ready and waiting),
- * and qe for other links (mutexes and condition variables).
+ * The current thread can belong to only one scheduling queue at
+ * a time (ready or waiting queue). It can also belong to (only)
+ * one of:
*
- * Pointer to queue (if any) on which the current thread is waiting.
+ * o A queue of threads waiting for a mutex
+ * o A queue of threads waiting for a condition variable
+ * o A queue of threads waiting for another thread to terminate
+ * (the join queue above)
+ * o A queue of threads waiting for a file descriptor lock
+ * o A queue of threads needing work done by the kernel thread
+ * (waiting for a spinlock or file I/O)
*
- * XXX The queuing should be changed to use the TAILQ entry below.
- * XXX For the time being, it's hybrid.
+ * Use pqe for the scheduling queue link (both ready and waiting),
+ * and qe for other links.
*/
- struct pthread_queue *queue;
-
- /* Pointer to next element in queue. */
- struct pthread *qnxt;
/* Priority queue entry for this thread: */
TAILQ_ENTRY(pthread) pqe;
@@ -544,6 +576,11 @@ struct pthread {
union pthread_wait_data data;
/*
+ * Allocated for converting select into poll.
+ */
+ struct pthread_poll_data poll_data;
+
+ /*
* Set to TRUE if a blocking operation was
* interrupted by a signal:
*/
@@ -553,23 +590,26 @@ struct pthread {
int signo;
/*
- * Set to non-zero when this thread has deferred thread
- * scheduling. We allow for recursive deferral.
+ * Set to non-zero when this thread has deferred signals.
+ * We allow for recursive deferral.
*/
- int sched_defer_count;
+ int sig_defer_count;
/*
* Set to TRUE if this thread should yield after undeferring
- * thread scheduling.
+ * signals.
*/
- int yield_on_sched_undefer;
+ int yield_on_sig_undefer;
/* Miscellaneous data. */
int flags;
#define PTHREAD_FLAGS_PRIVATE 0x0001
#define PTHREAD_EXITING 0x0002
-#define PTHREAD_FLAGS_QUEUED 0x0004 /* in queue (qe is used) */
-#define PTHREAD_FLAGS_TRACE 0x0008
+#define PTHREAD_FLAGS_IN_CONDQ 0x0004 /* in condition queue using qe link*/
+#define PTHREAD_FLAGS_IN_WORKQ 0x0008 /* in work queue using qe link */
+#define PTHREAD_FLAGS_IN_WAITQ 0x0010 /* in waiting queue using pqe link*/
+#define PTHREAD_FLAGS_IN_PRIOQ 0x0020 /* in priority queue using pqe link*/
+#define PTHREAD_FLAGS_TRACE 0x0040 /* for debugging purposes */
/*
* Base priority is the user setable and retrievable priority
@@ -592,7 +632,7 @@ struct pthread {
/*
* Active priority is always the maximum of the threads base
* priority and inherited priority. When there is a change
- * in either the real or inherited priority, the active
+ * in either the base or inherited priority, the active
* priority must be recalculated.
*/
char active_priority;
@@ -649,10 +689,10 @@ SCLASS struct pthread * volatile _thread_single
;
#endif
-/* Ptr to the first thread in the thread linked list: */
-SCLASS struct pthread * volatile _thread_link_list
+/* List of all threads: */
+SCLASS TAILQ_HEAD(, pthread) _thread_list
#ifdef GLOBAL_PTHREAD_PRIVATE
-= NULL;
+= TAILQ_HEAD_INITIALIZER(_thread_list);
#else
;
#endif
@@ -661,7 +701,7 @@ SCLASS struct pthread * volatile _thread_link_list
* Array of kernel pipe file descriptors that are used to ensure that
* no signals are missed in calls to _select.
*/
-SCLASS int _thread_kern_pipe[2]
+SCLASS int _thread_kern_pipe[2]
#ifdef GLOBAL_PTHREAD_PRIVATE
= {
-1,
@@ -670,7 +710,7 @@ SCLASS int _thread_kern_pipe[2]
#else
;
#endif
-SCLASS int _thread_kern_in_select
+SCLASS int volatile _queue_signals
#ifdef GLOBAL_PTHREAD_PRIVATE
= 0;
#else
@@ -692,9 +732,9 @@ SCLASS struct timeval kern_inc_prio_time
#endif
/* Dead threads: */
-SCLASS struct pthread * volatile _thread_dead
+SCLASS TAILQ_HEAD(, pthread) _dead_list
#ifdef GLOBAL_PTHREAD_PRIVATE
-= NULL;
+= TAILQ_HEAD_INITIALIZER(_dead_list);
#else
;
#endif
@@ -747,6 +787,14 @@ SCLASS struct fd_table_entry **_thread_fd_table
;
#endif
+/* Table for polling file descriptors: */
+SCLASS struct pollfd *_thread_pfd_table
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
SCLASS const int dtablecount
#ifdef GLOBAL_PTHREAD_PRIVATE
= 4096/sizeof(struct fd_table_entry);
@@ -760,6 +808,13 @@ SCLASS int _thread_dtablesize /* Descriptor table size. */
;
#endif
+SCLASS int _clock_res_nsec /* Clock resolution in nsec. */
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= CLOCK_RES_NSEC;
+#else
+;
+#endif
+
/* Garbage collector mutex and condition variable. */
SCLASS pthread_mutex_t _gc_mutex
#ifdef GLOBAL_PTHREAD_PRIVATE
@@ -783,8 +838,20 @@ struct sigaction _thread_sigact[NSIG];
SCLASS pq_queue_t _readyq;
SCLASS TAILQ_HEAD(, pthread) _waitingq;
-/* Indicates that the waitingq now has threads ready to run. */
-SCLASS volatile int _waitingq_check_reqd
+/*
+ * Work queue:
+ */
+SCLASS TAILQ_HEAD(, pthread) _workq;
+
+/* Tracks the number of threads blocked while waiting for a spinlock. */
+SCLASS volatile int _spinblock_count
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 0
+#endif
+;
+
+/* Indicates that the signal queue needs to be checked. */
+SCLASS volatile int _sigq_check_reqd
#ifdef GLOBAL_PTHREAD_PRIVATE
= 0
#endif
@@ -797,6 +864,13 @@ SCLASS pthread_switch_routine_t _sched_switch_hook
#endif
;
+/* Used for _PTHREADS_INVARIANTS checking. */
+SCLASS int _thread_kern_new_state
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 0
+#endif
+;
+
/* Undefine the storage class specifier: */
#undef SCLASS
@@ -825,18 +899,23 @@ int _thread_fd_lock(int, int, struct timespec *);
int _thread_fd_lock_debug(int, int, struct timespec *,char *fname,int lineno);
void _dispatch_signals(void);
void _thread_signal(pthread_t, int);
-void _lock_thread(void);
-void _lock_thread_list(void);
-void _unlock_thread(void);
-void _unlock_thread_list(void);
int _mutex_cv_lock(pthread_mutex_t *);
int _mutex_cv_unlock(pthread_mutex_t *);
+int _mutex_reinit(pthread_mutex_t *);
void _mutex_notify_priochange(struct pthread *);
-int _pq_init(struct pq_queue *pq, int, int);
+int _cond_reinit(pthread_cond_t *);
+int _pq_alloc(struct pq_queue *, int, int);
+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);
+#if defined(_PTHREADS_INVARIANTS)
+void _waitq_insert(pthread_t pthread);
+void _waitq_remove(pthread_t pthread);
+void _waitq_setactive(void);
+void _waitq_clearactive(void);
+#endif
void _thread_exit(char *, int, char *);
void _thread_fd_unlock(int, int);
void _thread_fd_unlock_debug(int, int, char *, int);
@@ -849,18 +928,15 @@ void _thread_kern_sched_state(enum pthread_state,char *fname,int lineno);
void _thread_kern_sched_state_unlock(enum pthread_state state,
spinlock_t *lock, char *fname, int lineno);
void _thread_kern_set_timeout(struct timespec *);
-void _thread_kern_sched_defer(void);
-void _thread_kern_sched_undefer(void);
+void _thread_kern_sig_defer(void);
+void _thread_kern_sig_undefer(void);
void _thread_sig_handler(int, int, struct sigcontext *);
+void _thread_sig_handle(int, struct sigcontext *);
+void _thread_sig_init(void);
void _thread_start(void);
void _thread_start_sig_handler(void);
void _thread_seterrno(pthread_t,int);
-void _thread_queue_init(struct pthread_queue *);
-void _thread_queue_enq(struct pthread_queue *, struct pthread *);
-int _thread_queue_remove(struct pthread_queue *, struct pthread *);
int _thread_fd_table_init(int fd);
-struct pthread *_thread_queue_get(struct pthread_queue *);
-struct pthread *_thread_queue_deq(struct pthread_queue *);
pthread_addr_t _thread_gc(pthread_addr_t);
/* #include <signal.h> */
@@ -1036,6 +1112,11 @@ pid_t _thread_sys_waitpid(pid_t, int *, int);
pid_t _thread_sys_wait3(int *, int, struct rusage *);
pid_t _thread_sys_wait4(pid_t, int *, int, struct rusage *);
#endif
+
+/* #include <poll.h> */
+#ifdef _SYS_POLL_H_
+int _thread_sys_poll(struct pollfd *, unsigned, int);
+#endif
__END_DECLS
#endif /* !_PTHREAD_PRIVATE_H */