summaryrefslogtreecommitdiffstats
path: root/lib/libkse/thread/thr_private.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libkse/thread/thr_private.h')
-rw-r--r--lib/libkse/thread/thr_private.h1294
1 files changed, 0 insertions, 1294 deletions
diff --git a/lib/libkse/thread/thr_private.h b/lib/libkse/thread/thr_private.h
deleted file mode 100644
index 46f6e80..0000000
--- a/lib/libkse/thread/thr_private.h
+++ /dev/null
@@ -1,1294 +0,0 @@
-/*
- * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
- * 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. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
- *
- * Private thread definitions for the uthread kernel.
- *
- * $FreeBSD$
- */
-
-#ifndef _THR_PRIVATE_H
-#define _THR_PRIVATE_H
-
-/*
- * Include files.
- */
-#include <setjmp.h>
-#include <signal.h>
-#include <stdio.h>
-#include <sys/queue.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/cdefs.h>
-#include <sys/kse.h>
-#include <sched.h>
-#include <ucontext.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <pthread_np.h>
-
-#ifndef LIBTHREAD_DB
-#include "lock.h"
-#include "pthread_md.h"
-#endif
-
-
-/*
- * Evaluate the storage class specifier.
- */
-#ifdef GLOBAL_PTHREAD_PRIVATE
-#define SCLASS
-#define SCLASS_PRESET(x...) = x
-#else
-#define SCLASS extern
-#define SCLASS_PRESET(x...)
-#endif
-
-/*
- * Kernel fatal error handler macro.
- */
-#define PANIC(string) _thr_exit(__FILE__, __LINE__, string)
-
-
-/* Output debug messages like this: */
-#ifdef STDOUT_FILENO
-#define stdout_debug(...) _thread_printf(STDOUT_FILENO, __VA_ARGS__)
-#endif
-#ifdef STDERR_FILENO
-#define stderr_debug(...) _thread_printf(STDERR_FILENO, __VA_ARGS__)
-#endif
-
-#define DBG_MUTEX 0x0001
-#define DBG_SIG 0x0002
-#define DBG_INFO_DUMP 0x0004
-
-#ifdef _PTHREADS_INVARIANTS
-#define THR_ASSERT(cond, msg) do { \
- if (!(cond)) \
- PANIC(msg); \
-} while (0)
-#else
-#define THR_ASSERT(cond, msg)
-#endif
-
-/*
- * State change macro without scheduling queue change:
- */
-#define THR_SET_STATE(thrd, newstate) do { \
- (thrd)->state = newstate; \
- (thrd)->fname = __FILE__; \
- (thrd)->lineno = __LINE__; \
-} while (0)
-
-
-#define TIMESPEC_ADD(dst, src, val) \
- do { \
- (dst)->tv_sec = (src)->tv_sec + (val)->tv_sec; \
- (dst)->tv_nsec = (src)->tv_nsec + (val)->tv_nsec; \
- if ((dst)->tv_nsec >= 1000000000) { \
- (dst)->tv_sec++; \
- (dst)->tv_nsec -= 1000000000; \
- } \
- } while (0)
-
-#define TIMESPEC_SUB(dst, src, val) \
- do { \
- (dst)->tv_sec = (src)->tv_sec - (val)->tv_sec; \
- (dst)->tv_nsec = (src)->tv_nsec - (val)->tv_nsec; \
- if ((dst)->tv_nsec < 0) { \
- (dst)->tv_sec--; \
- (dst)->tv_nsec += 1000000000; \
- } \
- } 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.
- */
- struct lock m_lock;
- enum pthread_mutextype m_type;
- int m_protocol;
- TAILQ_HEAD(mutex_head, pthread) m_queue;
- struct pthread *m_owner;
- long m_flags;
- int m_count;
- int m_refcount;
-
- /*
- * Used for priority inheritence and protection.
- *
- * m_prio - For priority inheritence, the highest active
- * priority (threads locking the mutex inherit
- * this priority). For priority protection, the
- * ceiling priority of this mutex.
- * m_saved_prio - mutex owners inherited priority before
- * taking the mutex, restored when the owner
- * unlocks the mutex.
- */
- int m_prio;
- int m_saved_prio;
-
- /*
- * Link for list of all mutexes a thread currently owns.
- */
- TAILQ_ENTRY(pthread_mutex) m_qe;
-};
-
-/*
- * Flags for mutexes.
- */
-#define MUTEX_FLAGS_PRIVATE 0x01
-#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;
- int m_ceiling;
- long m_flags;
-};
-
-#define PTHREAD_MUTEXATTR_STATIC_INITIALIZER \
- { PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, MUTEX_FLAGS_PRIVATE }
-
-/*
- * Condition variable definitions.
- */
-enum pthread_cond_type {
- COND_TYPE_FAST,
- COND_TYPE_MAX
-};
-
-struct pthread_cond {
- /*
- * Lock for accesses to this structure.
- */
- struct lock c_lock;
- enum pthread_cond_type c_type;
- TAILQ_HEAD(cond_head, pthread) c_queue;
- struct pthread_mutex *c_mutex;
- long c_flags;
- long c_seqno;
-};
-
-struct pthread_cond_attr {
- enum pthread_cond_type c_type;
- long c_flags;
-};
-
-struct pthread_barrier {
- pthread_mutex_t b_lock;
- pthread_cond_t b_cond;
- int b_count;
- int b_waiters;
- int b_generation;
-};
-
-struct pthread_barrierattr {
- int pshared;
-};
-
-struct pthread_spinlock {
- volatile int s_lock;
- pthread_t s_owner;
-};
-
-/*
- * Flags for condition variables.
- */
-#define COND_FLAGS_PRIVATE 0x01
-#define COND_FLAGS_INITED 0x02
-#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 *);
- void *routine_arg;
- int onstack;
-};
-
-#define THR_CLEANUP_PUSH(td, func, arg) { \
- struct pthread_cleanup __cup; \
- \
- __cup.routine = func; \
- __cup.routine_arg = arg; \
- __cup.onstack = 1; \
- __cup.next = (td)->cleanup; \
- (td)->cleanup = &__cup;
-
-#define THR_CLEANUP_POP(td, exec) \
- (td)->cleanup = __cup.next; \
- if ((exec) != 0) \
- __cup.routine(__cup.routine_arg); \
-}
-
-struct pthread_atfork {
- TAILQ_ENTRY(pthread_atfork) qe;
- void (*prepare)(void);
- void (*parent)(void);
- void (*child)(void);
-};
-
-struct pthread_attr {
- int sched_policy;
- int sched_inherit;
- int sched_interval;
- int prio;
- int suspend;
-#define THR_STACK_USER 0x100 /* 0xFF reserved for <pthread.h> */
-#define THR_SIGNAL_THREAD 0x200 /* This is a signal thread */
- int flags;
- void *arg_attr;
- void (*cleanup_attr) (void *);
- void *stackaddr_attr;
- size_t stacksize_attr;
- size_t guardsize_attr;
-};
-
-/*
- * Thread creation state attributes.
- */
-#define THR_CREATE_RUNNING 0
-#define THR_CREATE_SUSPENDED 1
-
-/*
- * Miscellaneous definitions.
- */
-#define THR_STACK32_DEFAULT (1 * 1024 * 1024)
-#define THR_STACK64_DEFAULT (2 * 1024 * 1024)
-
-/*
- * Maximum size of initial thread's stack. This perhaps deserves to be larger
- * than the stacks of other threads, since many applications are likely to run
- * almost entirely on this stack.
- */
-#define THR_STACK32_INITIAL (2 * 1024 * 1024)
-#define THR_STACK64_INITIAL (4 * 1024 * 1024)
-
-/*
- * Define the different priority ranges. All applications have thread
- * priorities constrained within 0-31. The threads library raises the
- * priority when delivering signals in order to ensure that signal
- * delivery happens (from the POSIX spec) "as soon as possible".
- * In the future, the threads library will also be able to map specific
- * threads into real-time (cooperating) processes or kernel threads.
- * The RT and SIGNAL priorities will be used internally and added to
- * thread base priorities so that the scheduling queue can handle both
- * normal and RT priority threads with and without signal handling.
- *
- * The approach taken is that, within each class, signal delivery
- * always has priority over thread execution.
- */
-#define THR_DEFAULT_PRIORITY 15
-#define THR_MIN_PRIORITY 0
-#define THR_MAX_PRIORITY 31 /* 0x1F */
-#define THR_SIGNAL_PRIORITY 32 /* 0x20 */
-#define THR_RT_PRIORITY 64 /* 0x40 */
-#define THR_FIRST_PRIORITY THR_MIN_PRIORITY
-#define THR_LAST_PRIORITY \
- (THR_MAX_PRIORITY + THR_SIGNAL_PRIORITY + THR_RT_PRIORITY)
-#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;
-};
-
-struct pthread_rwlock {
- pthread_mutex_t lock; /* monitor lock */
- pthread_cond_t read_signal;
- pthread_cond_t write_signal;
- int state; /* 0 = idle >0 = # of readers -1 = writer */
- int blocked_writers;
-};
-
-/*
- * Thread states.
- */
-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,
- PS_DEADLOCK,
- 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 *);
-
-/*
- * This stores a thread's state prior to running a signal handler.
- * It is used when a signal is delivered to a thread blocked in
- * userland. If the signal handler returns normally, the thread's
- * 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 {
- struct pthread *thread;
- void *ret;
- int error;
-};
-
-struct pthread_specific_elem {
- void *data;
- int seqno;
-};
-
-typedef void (*const_key_destructor_t)(const void *);
-typedef void (*key_destructor_t)(void *);
-
-struct pthread_key {
- volatile int allocated;
- volatile int count;
- int seqno;
- key_destructor_t destructor;
-};
-
-#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:
- */
-#define THR_MAGIC ((u_int32_t) 0xd09ba115)
- u_int32_t magic;
- char *name;
- u_int64_t uniqueid; /* for gdb */
-
- /* 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: */
- TAILQ_ENTRY(pthread) gcle;
-
- /* 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;
-
- /*
- * Thread start routine, argument, stack pointer and thread
- * attributes.
- */
- void *(*start_routine)(void *);
- 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.
- */
- siginfo_t *siginfo;
- thread_continuation_t sigbackout;
-
- /*
- * Cancelability flags - the lower 2 bits are used by cancel
- * definitions in pthread.h
- */
-#define THR_AT_CANCEL_POINT 0x0004
-#define THR_CANCELLING 0x0008
-#define THR_CANCEL_NEEDED 0x0010
- int cancelflags;
-
- 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).
- */
- sigset_t sigmask;
- sigset_t sigpend;
- sigset_t *oldsigmask;
- 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).
- */
- struct timespec wakeup_time;
-
- /* TRUE if operation has timed out. */
- int timeout;
-
- /*
- * Error variable used instead of errno. The function __error()
- * returns a pointer to this.
- */
- int error;
-
- /*
- * The joiner is the thread that is joining to this thread. The
- * join status keeps track of a join operation to another thread.
- */
- struct pthread *joiner;
- 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:
- *
- * o A queue of threads waiting for a mutex
- * o A queue of threads waiting for a condition variable
- *
- * It is possible for a thread to belong to more than one of the
- * above queues if it is handling a signal. A thread may only
- * enter a mutex or condition variable queue when it is not
- * being called from a signal handler. If a thread is a member
- * of one of these queues when a signal handler is invoked, it
- * must be removed from the queue before invoking the handler
- * and then added back to the queue after return from the handler.
- *
- * Use pqe for the scheduling queue link (both ready and waiting),
- * 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. */
- union pthread_wait_data data;
-
- /*
- * Set to TRUE if a blocking operation was
- * interrupted by a signal:
- */
- int interrupted;
-
- /*
- * Set to non-zero when this thread has entered a critical
- * region. We allow for recursive entries into critical regions.
- */
- 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 */
-
- /* Thread list flags; only set with thread list lock held. */
-#define TLFLAGS_GC_SAFE 0x0001 /* thread safe for cleaning */
-#define TLFLAGS_IN_TDLIST 0x0002 /* thread in all thread list */
-#define TLFLAGS_IN_GCLIST 0x0004 /* thread in gc list */
- int tlflags;
-
- /*
- * Base priority is the user setable and retrievable priority
- * of the thread. It is only affected by explicit calls to
- * set thread priority and upon thread creation via a thread
- * attribute or default priority.
- */
- char base_priority;
-
- /*
- * Inherited priority is the priority a thread inherits by
- * taking a priority inheritence or protection mutex. It
- * is not affected by base priority changes. Inherited
- * priority defaults to and remains 0 until a mutex is taken
- * that is being waited on by any other thread whose priority
- * is non-zero.
- */
- char inherited_priority;
-
- /*
- * Active priority is always the maximum of the threads base
- * priority and inherited priority. When there is a change
- * in either the base or inherited priority, the active
- * priority must be recalculated.
- */
- char active_priority;
-
- /* Number of priority ceiling or protection mutexes owned. */
- int priority_mutex_count;
-
- /* Number rwlocks rdlocks held. */
- int rdlock_count;
-
- /*
- * Queue of currently owned mutexes.
- */
- TAILQ_HEAD(, pthread_mutex) mutexq;
-
- void *ret;
- struct pthread_specific_elem *specific;
- int specific_data_count;
-
- /* Alternative stack for sigaltstack() */
- stack_t sigstk;
-
- /*
- * Current locks bitmap for rtld.
- */
- int rtld_bits;
-
- /* Cleanup handlers Link List */
- struct pthread_cleanup *cleanup;
- const char *fname; /* Ptr to source file name */
- int lineno; /* Source line number. */
-};
-
-/*
- * Critical regions can also be detected by looking at the threads
- * current lock level. Ensure these macros increment and decrement
- * the lock levels such that locks can not be held with a lock level
- * of 0.
- */
-#define THR_IN_CRITICAL(thrd) \
- (((thrd)->locklevel > 0) || \
- ((thrd)->critical_count > 0))
-
-#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); \
- } \
-} while (0)
-
-#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"); \
-} while (0)
-
-#define THR_LOCK_RELEASE(thrd, lck) \
-do { \
- if ((thrd)->locklevel > 0) { \
- _lock_release((lck), \
- &(thrd)->lockusers[(thrd)->locklevel - 1]); \
- (thrd)->locklevel--; \
- THR_ACTIVATE_LAST_LOCK(thrd); \
- if ((thrd)->locklevel == 0) \
- THR_YIELD_CHECK(thrd); \
- } \
-} 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.
- */
-#define THR_LIST_ADD(thrd) do { \
- if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) == 0) { \
- TAILQ_INSERT_HEAD(&_thread_list, thrd, tle); \
- _thr_hash_add(thrd); \
- (thrd)->tlflags |= TLFLAGS_IN_TDLIST; \
- } \
-} while (0)
-#define THR_LIST_REMOVE(thrd) do { \
- if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) != 0) { \
- TAILQ_REMOVE(&_thread_list, thrd, tle); \
- _thr_hash_remove(thrd); \
- (thrd)->tlflags &= ~TLFLAGS_IN_TDLIST; \
- } \
-} while (0)
-#define THR_GCLIST_ADD(thrd) do { \
- if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) == 0) { \
- TAILQ_INSERT_HEAD(&_thread_gc_list, thrd, gcle);\
- (thrd)->tlflags |= TLFLAGS_IN_GCLIST; \
- _gc_count++; \
- } \
-} while (0)
-#define THR_GCLIST_REMOVE(thrd) do { \
- if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) != 0) { \
- TAILQ_REMOVE(&_thread_gc_list, thrd, gcle); \
- (thrd)->tlflags &= ~TLFLAGS_IN_GCLIST; \
- _gc_count--; \
- } \
-} while (0)
-
-#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); \
-} while (0)
-#define THR_UNLOCK_SWITCH(curthr) do { \
- KSE_SCHED_UNLOCK((curthr)->kse, (curthr)->kseg);\
-} 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); \
- } \
-} 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 _thread_scope_system SCLASS_PRESET(0);
-
-/* List of all threads: */
-SCLASS TAILQ_HEAD(, pthread) _thread_list
- SCLASS_PRESET(TAILQ_HEAD_INITIALIZER(_thread_list));
-
-/* List of threads needing GC: */
-SCLASS TAILQ_HEAD(, pthread) _thread_gc_list
- SCLASS_PRESET(TAILQ_HEAD_INITIALIZER(_thread_gc_list));
-
-SCLASS int _thread_active_threads SCLASS_PRESET(1);
-
-SCLASS TAILQ_HEAD(atfork_head, pthread_atfork) _thr_atfork_list;
-SCLASS pthread_mutex_t _thr_atfork_mutex;
-
-/* Default thread attributes: */
-SCLASS struct pthread_attr _pthread_attr_default
- SCLASS_PRESET({
- SCHED_RR, 0, TIMESLICE_USEC, THR_DEFAULT_PRIORITY,
- THR_CREATE_RUNNING, PTHREAD_CREATE_JOINABLE, NULL,
- NULL, NULL, /* stacksize */0, /* guardsize */0
- });
-
-/* Default mutex attributes: */
-SCLASS struct pthread_mutex_attr _pthread_mutexattr_default
- SCLASS_PRESET({PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, 0 });
-
-/* Default condition variable attributes: */
-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);
-
-/* 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 _rwlock_static_lock;
-SCLASS struct lock _keytable_lock;
-SCLASS struct lock _thread_list_lock;
-SCLASS size_t _thr_guard_default;
-SCLASS size_t _thr_stack_default;
-SCLASS size_t _thr_stack_initial;
-SCLASS int _thr_page_size;
-SCLASS pthread_t _thr_sig_daemon;
-SCLASS int _thr_debug_flags SCLASS_PRESET(0);
-
-/* Undefine the storage class and preset specifiers: */
-#undef SCLASS
-#undef SCLASS_PRESET
-
-
-/*
- * Function prototype definitions.
- */
-__BEGIN_DECLS
-int _cond_reinit(pthread_cond_t *);
-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(void);
-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 *);
-int _mutex_cv_lock(pthread_mutex_t *);
-int _mutex_cv_unlock(pthread_mutex_t *);
-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);
-int _pthread_mutex_destroy(pthread_mutex_t *);
-int _pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
-int _pthread_mutex_lock(pthread_mutex_t *);
-int _pthread_mutex_trylock(pthread_mutex_t *);
-int _pthread_mutex_unlock(pthread_mutex_t *);
-int _pthread_mutexattr_init(pthread_mutexattr_t *);
-int _pthread_mutexattr_destroy(pthread_mutexattr_t *);
-int _pthread_mutexattr_settype(pthread_mutexattr_t *, int);
-int _pthread_once(pthread_once_t *, void (*) (void));
-int _pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
-int _pthread_rwlock_destroy (pthread_rwlock_t *);
-struct pthread *_pthread_self(void);
-int _pthread_setspecific(pthread_key_t, const void *);
-void _pthread_yield(void);
-void _pthread_cleanup_push(void (*routine) (void *), void *routine_arg);
-void _pthread_cleanup_pop(int execute);
-struct pthread *_thr_alloc(struct pthread *);
-void _thr_exit(const char *, int, const char *) __dead2;
-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 *);
-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 *);
-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 *, void *);
-void _thr_sig_check_pending(struct pthread *);
-void _thr_sig_rundown(struct pthread *, ucontext_t *);
-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 *);
-
-/*
- * Aliases for _pthread functions. Should be called instead of
- * originals if PLT replocation is unwanted at runtme.
- */
-int _thr_cond_broadcast(pthread_cond_t *);
-int _thr_cond_signal(pthread_cond_t *);
-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 *);
-
-/* #include <sys/aio.h> */
-#ifdef _SYS_AIO_H_
-int __sys_aio_suspend(const struct aiocb * const[], int, const struct timespec *);
-#endif
-
-/* #include <fcntl.h> */
-#ifdef _SYS_FCNTL_H_
-int __sys_fcntl(int, int, ...);
-int __sys_open(const char *, int, ...);
-#endif
-
-/* #include <sys/ioctl.h> */
-#ifdef _SYS_IOCTL_H_
-int __sys_ioctl(int, unsigned long, ...);
-#endif
-
-/* #inclde <sched.h> */
-#ifdef _SCHED_H_
-int __sys_sched_yield(void);
-#endif
-
-/* #include <signal.h> */
-#ifdef _SIGNAL_H_
-int __sys_kill(pid_t, int);
-int __sys_sigaction(int, const struct sigaction *, struct sigaction *);
-int __sys_sigpending(sigset_t *);
-int __sys_sigprocmask(int, const sigset_t *, sigset_t *);
-int __sys_sigsuspend(const sigset_t *);
-int __sys_sigreturn(ucontext_t *);
-int __sys_sigaltstack(const struct sigaltstack *, struct sigaltstack *);
-#endif
-
-/* #include <sys/socket.h> */
-#ifdef _SYS_SOCKET_H_
-int __sys_accept(int, struct sockaddr *, socklen_t *);
-int __sys_connect(int, const struct sockaddr *, socklen_t);
-int __sys_sendfile(int, int, off_t, size_t, struct sf_hdtr *,
- off_t *, int);
-#endif
-
-/* #include <sys/uio.h> */
-#ifdef _SYS_UIO_H_
-ssize_t __sys_readv(int, const struct iovec *, int);
-ssize_t __sys_writev(int, const struct iovec *, int);
-#endif
-
-/* #include <time.h> */
-#ifdef _TIME_H_
-int __sys_nanosleep(const struct timespec *, struct timespec *);
-#endif
-
-/* #include <unistd.h> */
-#ifdef _UNISTD_H_
-int __sys_close(int);
-int __sys_execve(const char *, char * const *, char * const *);
-int __sys_fork(void);
-int __sys_fsync(int);
-pid_t __sys_getpid(void);
-int __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
-ssize_t __sys_read(int, void *, size_t);
-ssize_t __sys_write(int, const void *, size_t);
-void __sys_exit(int);
-int __sys_sigwait(const sigset_t *, int *);
-int __sys_sigtimedwait(const sigset_t *, siginfo_t *, const struct timespec *);
-#endif
-
-/* #include <poll.h> */
-#ifdef _SYS_POLL_H_
-int __sys_poll(struct pollfd *, unsigned, int);
-#endif
-
-/* #include <sys/mman.h> */
-#ifdef _SYS_MMAN_H_
-int __sys_msync(void *, size_t, int);
-#endif
-
-static __inline int
-_thr_dump_enabled(void)
-{
-
- return ((_thr_debug_flags & DBG_INFO_DUMP) != 0);
-}
-
-#endif /* !_THR_PRIVATE_H */
OpenPOWER on IntegriCloud