📄 pthread.c
字号:
pthread_q_all_enq(&all, t); pthread_q_primary_enq(&ready, t); CLEAR_KERNEL_FLAG; return(0);}/*------------------------------------------------------------*//* * pthread_suspend_internal() - suspend thread indefinitely, * assumes SET_KERNEL_FLAG */void pthread_suspend_internal(t) pthread_t t;{ PTRACEIN; t->suspend.state = t->state & (T_RUNNING | T_BLOCKED); t->suspend.queue = t->queue; t->suspend.cond = t->cond; if (t->state & (T_RUNNING | T_BLOCKED)) pthread_q_deq(t->queue, t, PRIMARY_QUEUE); if (t->cond) { if (!--t->cond->waiters) t->cond->mutex = NO_MUTEX; t->cond = NO_COND; } t->state |= T_SUSPEND; t->state &= ~(T_RUNNING | T_BLOCKED); pthread_q_primary_enq(&suspend_q, t);}/*------------------------------------------------------------*//* * pthread_suspend_np() - suspend thread indefinitely */int pthread_suspend_np(t) pthread_t t;{ if (is_in_kernel) return(EINVAL); PTRACEIN; SET_KERNEL_FLAG; if (!t || t->state & (T_SUSPEND | T_EXITING | T_RETURNED)) { CLEAR_KERNEL_FLAG; return(EINVAL); } if (t->state & T_RUNNING) { pthread_pending_sigaction.func = pthread_suspend_internal; pthread_pending_sigaction.arg = t; /* issue a SIGALRM to force a suspend on the current thread, if requested */#ifdef TDI_SUPPORT __pthread_debug_TDI_ignored_signals |= 0x1 << (SIGALRM-1);#endif } else pthread_suspend_internal(t); CLEAR_KERNEL_FLAG; return(0);}/*------------------------------------------------------------*//* * pthread_resume_np() - resume suspended thread in saved state */int pthread_resume_np(t) pthread_t t;{ int was_in_kernel = is_in_kernel; PTRACEIN; if (was_in_kernel && mac_pthread_self() != NULL) return(EINVAL); if (!was_in_kernel) SET_KERNEL_FLAG; if (!t || !(t->state & T_SUSPEND)) { if (!was_in_kernel) CLEAR_KERNEL_FLAG; return(EINVAL); } /* * assumption: Q ist 1st component in pthread_mutex_t structure !!! * check that cond is still associated with mutex */ if (t->suspend.cond) { pthread_mutex_t *mutex = (pthread_mutex_t *) t->queue; if (t->suspend.cond->mutex != mutex) { CLEAR_KERNEL_FLAG; return(EINVAL); } t->suspend.cond->waiters++; } pthread_q_deq(t->queue, t, PRIMARY_QUEUE); t->state = t->suspend.state; t->queue = t->suspend.queue; t->cond = t->suspend.cond; pthread_q_primary_enq(t->queue, t); if (!was_in_kernel) CLEAR_KERNEL_FLAG; if (!TAILQ_HASTWO(&ready, pt_qelem[PRIMARY_QUEUE])) kill(getpid(), SIGALRM); /* ignore signal but re-check ready queue */ return(0);}/*------------------------------------------------------------*//* * pthread_equal() - Cmpares two threads. Returns * 0 if t1 <> t2 * 1 if t1 == t2 */int pthread_equal(t1, t2) pthread_t t1, t2;{ PTRACEIN; return(t1 == t2);}/*------------------------------------------------------------*//* * pthread_detach - Detaching a running thread simply consists of * marking it as such. If the thread has returned then the resources * are also freed. */int pthread_detach(thread) pthread_t thread;{ PTRACEIN; if (thread == NO_PTHREAD) return(EINVAL); SET_KERNEL_FLAG; if (thread->state & T_DETACHED) { CLEAR_KERNEL_FLAG; return(ESRCH); } thread->state |= T_DETACHED; if (thread->state & T_RETURNED) { free(thread->stack_base); free(thread); SIM_SYSCALL(TRUE); } CLEAR_KERNEL_FLAG; return(0);}/*------------------------------------------------------------*//* * pthread_join - Wait for a thread to exit. If the status parameter is * non-NULL then that threads exit status is stored in it. */int pthread_join(thread, status) pthread_t thread; any_t *status;{ register pthread_t p = mac_pthread_self(); PTRACEIN; if (thread == NO_PTHREAD) return(EINVAL); if (thread == p) return(EDEADLK); SET_KERNEL_FLAG; if (thread->state & T_RETURNED) { if (thread->state & T_DETACHED) { CLEAR_KERNEL_FLAG; return(ESRCH); } if (status) *status = thread->result; thread->state |= T_DETACHED; free(thread->stack_base); free(thread); CLEAR_KERNEL_FLAG; return(0); } /* * clear error number before suspending */ set_errno(0); pthread_q_sleep(&thread->joinq, PRIMARY_QUEUE); p->state |= T_INTR_POINT; if (sigismember(&p->pending, SIGCANCEL) && !sigismember(&p->mask, SIGCANCEL)) SIG_CLEAR_KERNEL_FLAG(TRUE); else { SIM_SYSCALL(TRUE); CLEAR_KERNEL_FLAG; } PDEBUG(PDBG_RUN,"<-join returned"); if (get_errno() == EINTR) return(EINTR); /* * status was copied into result field of current TCB by other thread */ if (status) *status = p->result; return(0);}/*------------------------------------------------------------*//* Function: * sched_yield - Yield the processor to another thread. * The current process is taken off the queue and another executes * Simply put oneself at the tail of the queue. */int sched_yield(void){ PTRACEIN; SET_KERNEL_FLAG; if (TAILQ_HASTWO(&ready,pt_qelem[PRIMARY_QUEUE])) { /* * Place ourself at the end of the ready queue. * This allows the other ready processes to execute thus * in effect yielding the processor. */ pthread_q_primary_enq(&ready, pthread_q_deq_head(&ready, PRIMARY_QUEUE)); SIM_SYSCALL(TRUE); } CLEAR_KERNEL_FLAG; return(0);}/*------------------------------------------------------------*//* * pthread_exit - Save the exit status of the thread so that other * threads joining with this thread can find it. */void pthread_exit(status) any_t status;{ register pthread_t t = mac_pthread_self(); PTRACEIN; t->result = status; pthread_terminate();}/*------------------------------------------------------------*//* * pthread_attr_init - Initializes the attr (thread attribute object) * with the default values. */int pthread_attr_init(attr) pthread_attr_t *attr;{ PTRACEIN; if (!attr) return(EINVAL); attr->flags = TRUE; attr->contentionscope = PTHREAD_SCOPE_PROCESS; attr->inheritsched = PTHREAD_EXPLICIT_SCHED; attr->detachstate = PTHREAD_CREATE_JOINABLE;#ifdef DEF_RR attr->sched = SCHED_RR;#else attr->sched = SCHED_FIFO;#endif attr->stacksize = DEFAULT_STACKSIZE; attr->stack = 0; attr->name = 0; attr->param.sched_priority = DEFAULT_PRIORITY;#ifdef REAL_TIME NTIMERCLEAR(attr->starttime); NTIMERCLEAR(attr->deadline); NTIMERCLEAR(attr->period);#endif /* REAL_TIME */ return(0);}/*------------------------------------------------------------*//* * pthread_attr_destroy - Destroys the thread attribute object. */int pthread_attr_destroy(attr) pthread_attr_t *attr;{ PTRACEIN; if (!attr || !attr->flags) { return(EINVAL); } attr->flags = FALSE; return(0);}/*------------------------------------------------------------*//* * pthread_getschedparam - get the thread scheduling policy and params */int pthread_getschedparam(thread, policy, param) pthread_t thread; int *policy; struct sched_param *param;{ PTRACEIN; if (thread == NO_PTHREAD) { return(ESRCH); } if (!policy || !param) return(EINVAL); *policy = thread->attr.sched;#ifdef _POSIX_THREADS_PRIO_PROTECT param->sched_priority = thread->base_prio;#else param->sched_priority = thread->attr.param.sched_priority;#endif return(0);}/*------------------------------------------------------------*//* * pthread_setschedparam - Set the thread specific scheduling policy and params */int pthread_setschedparam(thread, policy, param) pthread_t thread; int policy; struct sched_param *param;{ pthread_t p = mac_pthread_self(); pthread_queue_t q; int oldsched, run_prio; PTRACEIN; if (thread == NO_PTHREAD) return(ESRCH); if (!param) return(EINVAL); #ifdef DEF_RR if (policy != SCHED_FIFO && policy != SCHED_RR) {#else if (policy != SCHED_FIFO) {#endif return(ENOTSUP); } if (param->sched_priority < MIN_PRIORITY || param->sched_priority > MAX_PRIORITY) return(EINVAL);#ifdef REAL_TIME if (ISNTIMERSET(thread->attr.starttime) || ISNTIMERSET(thread->attr.deadline) || ISNTIMERSET(thread->attr.period)) return(EINVAL);#endif /* REAL_TIME */ SET_KERNEL_FLAG; if (thread->state & T_RETURNED) { CLEAR_KERNEL_FLAG; return(EINVAL); } oldsched = thread->attr.sched; thread->attr.sched = policy;#ifdef DEF_RR if (policy != oldsched && p == thread) switch (oldsched) { case SCHED_FIFO: pthread_timed_sigwait(thread, NULL, RR_TIME, NULL, thread); break; case SCHED_RR: pthread_cancel_timed_sigwait(thread, FALSE, RR_TIME, thread->queue != &ready); break; default: ; }#endif#ifdef _POSIX_THREADS_PRIO_PROTECT#ifdef SRP if (thread->new_prio == MUTEX_WAIT) { thread->new_prio = param->sched_priority; CLEAR_KERNEL_FLAG; return (0); }#endif run_prio = thread->attr.param.sched_priority; thread->base_prio = param->sched_priority; if (thread->max_ceiling_prio != NO_PRIO) thread->attr.param.sched_priority = MAX(param->sched_priority, thread->max_ceiling_prio); else thread->attr.param.sched_priority = param->sched_priority;#else run_prio = thread->attr.param.sched_priority; thread->attr.param.sched_priority = param->sched_priority;#endif q = thread->queue; if (TAILQ_FIRST(q) != thread || (TAILQ_HASTWO(q,pt_qelem[PRIMARY_QUEUE]) && thread->attr.param.sched_priority < run_prio && TAILQ_NEXT(thread,pt_qelem[PRIMARY_QUEUE]) && thread->attr.param.sched_priority < TAILQ_NEXT(thread,pt_qelem[PRIMARY_QUEUE])->attr.param.sched_priority)) { pthread_q_deq(q, thread, PRIMARY_QUEUE); pthread_q_primary_enq_first(q, thread); } SIM_SYSCALL(TRUE); CLEAR_KERNEL_FLAG; return(0);}/*------------------------------------------------------------*//* * pthread_attr_setstacksize - Aligns the "stacksize" to double * word boundary and then sets the size of the stack to "stacksize" * in thread attribute object "attr". */int pthread_attr_setstacksize(attr, stacksize) pthread_attr_t *attr; size_t stacksize;{ PTRACEIN; if (!attr || !attr->flags) return(EINVAL); attr->stacksize = SA(stacksize); /* stack align, see asm_linkage.h */ return(0); }/*------------------------------------------------------------*//* * pthread_attr_getstacksize - gets the stacksize from an pthread * attribute object. */int pthread_attr_getstacksize(attr, stacksize) pthread_attr_t *attr; size_t *stacksize;{ PTRACEIN; if (!attr || !attr->flags) return(EINVAL); *stacksize = attr->stacksize; return(0);}/*------------------------------------------------------------*//* * pthread_attr_setscope - Set the contentionscope attribute in a * thread attribute object. */int pthread_attr_setscope(attr,contentionscope) pthread_attr_t *attr; int contentionscope;{ PTRACEIN; if (!attr || !attr->flags) { return(EINVAL); } if (contentionscope == PTHREAD_SCOPE_PROCESS) { attr->contentionscope=contentionscope; return(0); } else return(EINVAL);}/*------------------------------------------------------------*//* * pthread_attr_setinheritsched - Set the inheritsched attribute. */int pthread_attr_setinheritsched(attr, inheritsched) pthread_attr_t *attr; int inheritsched;{ PTRACEIN; if (!attr || !attr->flags) return(EINVAL); if (inheritsched == PTHREAD_INHERIT_SCHED || inheritsched == PTHREAD_EXPLICIT_SCHED) { attr->inheritsched = inheritsched; return(0); } else return(EINVAL);}/*------------------------------------------------------------*//* * pthread_attr_setschedpolicy - set the sched attribute */int pthread_attr_setschedpolicy(attr, policy) pthread_attr_t *attr; int policy;{ PTRACEIN; if (!attr || !attr->flags) return(EINVAL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -