+ kern_return_t kern_result;
+ mach_timespec_t then;
+ struct timespec now;
+
+ if(uap->timeout) {
+
+ if (uap->relative) {
+ then.tv_sec = uap->tv_sec;
+ then.tv_nsec = uap->tv_nsec;
+ } else {
+ nanotime(&now);
+ then.tv_sec = uap->tv_sec - now.tv_sec;
+ then.tv_nsec = uap->tv_nsec - now.tv_nsec;
+ if (then.tv_nsec < 0) {
+ then.tv_nsec += NSEC_PER_SEC;
+ then.tv_sec--;
+ }
+ }
+
+ if (uap->mutex_sem == (void *)NULL)
+ kern_result = semaphore_timedwait_trap_internal(uap->cond_sem, then.tv_sec, then.tv_nsec, __posix_sem_syscall_return);
+ else
+ kern_result = semaphore_timedwait_signal_trap_internal(uap->cond_sem, uap->mutex_sem, then.tv_sec, then.tv_nsec, __posix_sem_syscall_return);
+
+ } else {
+
+ if (uap->mutex_sem == (void *)NULL)
+ kern_result = semaphore_wait_trap_internal(uap->cond_sem, __posix_sem_syscall_return);
+ else
+
+ kern_result = semaphore_wait_signal_trap_internal(uap->cond_sem, uap->mutex_sem, __posix_sem_syscall_return);
+ }
+
+out:
+ if (kern_result == KERN_SUCCESS)
+ return(0);
+ else if (kern_result == KERN_ABORTED)
+ return(EINTR);
+ else if (kern_result == KERN_OPERATION_TIMED_OUT)
+ return(ETIMEDOUT);
+ else
+ return(EINVAL);
+}
+
+
+int
+__pthread_kill(__unused struct proc *p,
+ register struct __pthread_kill_args *uap,
+ __unused register_t *retval)
+{
+ thread_t target_act;
+ int error = 0;
+ int signum = uap->sig;
+ struct uthread *uth;
+
+ target_act = (thread_t)port_name_to_thread(uap->thread_port);
+
+ if (target_act == THREAD_NULL)
+ return (ESRCH);
+ if ((u_int)signum >= NSIG) {
+ error = EINVAL;
+ goto out;
+ }
+
+ uth = (struct uthread *)get_bsdthread_info(target_act);
+
+ if (uth->uu_flag & UT_NO_SIGMASK) {
+ error = ESRCH;
+ goto out;
+ }
+
+ if (signum)
+ psignal_uthread(target_act, signum);
+out:
+ thread_deallocate(target_act);
+ return (error);
+}
+
+
+int
+pthread_sigmask(__unused register struct proc *p,
+ register struct pthread_sigmask_args *uap,
+ __unused register_t *retval)
+{
+ user_addr_t set = uap->set;
+ user_addr_t oset = uap->oset;
+ sigset_t nset;
+ int error = 0;
+ struct uthread *ut;
+ sigset_t oldset;
+
+ ut = (struct uthread *)get_bsdthread_info(current_thread());
+ oldset = ut->uu_sigmask;
+
+ if (set == USER_ADDR_NULL) {
+ /* need only old mask */
+ goto out;
+ }
+
+ error = copyin(set, &nset, sizeof(sigset_t));
+ if (error)
+ goto out;
+
+ switch (uap->how) {
+ case SIG_BLOCK:
+ ut->uu_sigmask |= (nset & ~sigcantmask);
+ break;
+
+ case SIG_UNBLOCK:
+ ut->uu_sigmask &= ~(nset);
+ signal_setast(current_thread());
+ break;
+
+ case SIG_SETMASK:
+ ut->uu_sigmask = (nset & ~sigcantmask);
+ signal_setast(current_thread());
+ break;
+
+ default:
+ error = EINVAL;
+
+ }
+out:
+ if (!error && oset != USER_ADDR_NULL)
+ copyout(&oldset, oset, sizeof(sigset_t));
+
+ return(error);
+}
+
+
+int
+sigwait(register struct proc *p, register struct sigwait_args *uap, __unused register_t *retval)
+{
+ struct uthread *ut;
+ struct uthread *uth;
+ int error = 0;
+ sigset_t mask;
+ sigset_t siglist;
+ sigset_t sigw=0;
+ int signum;
+
+ ut = (struct uthread *)get_bsdthread_info(current_thread());
+
+ if (uap->set == USER_ADDR_NULL)
+ return(EINVAL);
+
+ error = copyin(uap->set, &mask, sizeof(sigset_t));
+ if (error)
+ return(error);
+
+ siglist = (mask & ~sigcantmask);
+
+ if (siglist == 0)
+ return(EINVAL);
+
+ signal_lock(p);
+ if ((p->p_flag & P_INVFORK) && p->p_vforkact) {
+ signal_unlock(p);
+ return(EINVAL);
+ } else {
+ TAILQ_FOREACH(uth, &p->p_uthlist, uu_list) {
+ if ( (sigw = uth->uu_siglist & siglist) ) {
+ break;
+ }
+ }
+ }
+ signal_unlock(p);
+ if (sigw) {
+ /* The signal was pending on a thread */
+ goto sigwait1;
+ }
+ /*
+ * When returning from sigwait, we want
+ * the old mask to be restored after the
+ * signal handler has finished. Thus, we
+ * save it here and mark the sigacts structure
+ * to indicate this.
+ */
+ ut->uu_oldmask = ut->uu_sigmask;
+ ut->uu_flag |= UT_SAS_OLDMASK;
+ if (siglist == (sigset_t)0)
+ return(EINVAL);
+ /* SIGKILL and SIGSTOP are not maskable as well */
+ ut->uu_sigmask = ~(siglist|sigcantmask);
+ ut->uu_sigwait = siglist;
+ /* No Continuations for now */
+ error = tsleep((caddr_t)&ut->uu_sigwait, PPAUSE|PCATCH, "pause", 0);
+
+ if ((error == EINTR) || (error == ERESTART))
+ error = 0;
+
+ sigw = (ut->uu_sigwait & siglist);
+ ut->uu_sigmask = ut->uu_oldmask;
+ ut->uu_oldmask = 0;
+ ut->uu_flag &= ~UT_SAS_OLDMASK;
+sigwait1:
+ ut->uu_sigwait = 0;
+ if (!error) {
+ signum = ffs((unsigned int)sigw);
+ if (!signum)
+ panic("sigwait with no signal wakeup");
+ ut->uu_siglist &= ~(sigmask(signum));
+ if (uap->sig != USER_ADDR_NULL)
+ error = copyout(&signum, uap->sig, sizeof(int));
+ }
+
+ return(error);
+
+}
+
+
+int
+sigaltstack(struct proc *p, register struct sigaltstack_args *uap, __unused register_t *retval)
+{
+ struct sigacts *psp;
+ struct user_sigaltstack ss;
+ int error;
+
+ psp = p->p_sigacts;
+ if ((psp->ps_flags & SAS_ALTSTACK) == 0)
+ psp->ps_sigstk.ss_flags |= SA_DISABLE;
+ if (uap->oss) {
+ if (IS_64BIT_PROCESS(p)) {
+ error = copyout(&psp->ps_sigstk, uap->oss, sizeof(struct user_sigaltstack));
+ } else {
+ struct sigaltstack ss32;
+ sigaltstack_64to32(&psp->ps_sigstk, &ss32);
+ error = copyout(&ss32, uap->oss, sizeof(struct sigaltstack));
+ }
+ if (error)
+ return (error);
+ }
+ if (uap->nss == USER_ADDR_NULL)
+ return (0);
+ if (IS_64BIT_PROCESS(p)) {
+ error = copyin(uap->nss, &ss, sizeof(struct user_sigaltstack));
+ } else {
+ struct sigaltstack ss32;
+ error = copyin(uap->nss, &ss32, sizeof(struct sigaltstack));
+ sigaltstack_32to64(&ss32,&ss);
+ }
+ if (error)
+ return (error);
+ if ((ss.ss_flags & ~SA_DISABLE) != 0) {
+ return(EINVAL);
+ }
+
+ if (ss.ss_flags & SA_DISABLE) {
+ if (psp->ps_sigstk.ss_flags & SA_ONSTACK)
+ return (EINVAL);
+ psp->ps_flags &= ~SAS_ALTSTACK;
+ psp->ps_sigstk.ss_flags = ss.ss_flags;
+ return (0);
+ }
+/* The older stacksize was 8K, enforce that one so no compat problems */
+#define OLDMINSIGSTKSZ 8*1024
+ if (ss.ss_size < OLDMINSIGSTKSZ)
+ return (ENOMEM);
+ psp->ps_flags |= SAS_ALTSTACK;
+ psp->ps_sigstk= ss;
+ return (0);
+}
+
+int
+kill(struct proc *cp, struct kill_args *uap, __unused register_t *retval)
+{
+ register struct proc *p;
+ kauth_cred_t uc = kauth_cred_get();
+
+ AUDIT_ARG(pid, uap->pid);
+ AUDIT_ARG(signum, uap->signum);
+
+ if ((u_int)uap->signum >= NSIG)
+ return (EINVAL);
+ if (uap->pid > 0) {
+ /* kill single process */
+ if ((p = proc_findref(uap->pid)) == NULL) {
+ if ((p = pzfind(uap->pid)) != NULL) {
+ /*
+ * IEEE Std 1003.1-2001: return success
+ * when killing a zombie.
+ */
+ return (0);
+ }
+ return (ESRCH);
+ }
+ AUDIT_ARG(process, p);
+ if (!cansignal(cp, uc, p, uap->signum)) {
+ proc_dropref(p);
+ return(EPERM);
+ }
+ if (uap->signum)