/* * pthread_attr_equal: compare two pthread_attr_t's, return 1 if equal. * A NULL pthread_attr_t pointer implies default attributes. * This is a consolidation-private interface, for librt. */ int pthread_attr_equal(const pthread_attr_t *attr1, const pthread_attr_t *attr2) { const thrattr_t *ap1 = attr1? attr1->__pthread_attrp : def_thrattr(); const thrattr_t *ap2 = attr2? attr2->__pthread_attrp : def_thrattr(); if (ap1 == NULL || ap2 == NULL) return (0); return (ap1 == ap2 || memcmp(ap1, ap2, sizeof (thrattr_t)) == 0); }
int pthread_attr_init(pthread_attr_t *attr) { thrattr_t *ap; if ((ap = lmalloc(sizeof (thrattr_t))) != NULL) { *ap = *def_thrattr(); attr->__pthread_attrp = ap; return (0); } return (ENOMEM); }
/* * pthread_attr_clone: make a copy of a pthread_attr_t. */ int pthread_attr_clone(pthread_attr_t *attr, const pthread_attr_t *old_attr) { thrattr_t *ap; const thrattr_t *old_ap = old_attr? old_attr->__pthread_attrp : def_thrattr(); if (old_ap == NULL) return (EINVAL); if ((ap = lmalloc(sizeof (thrattr_t))) == NULL) return (ENOMEM); *ap = *old_ap; attr->__pthread_attrp = ap; return (0); }
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * (*start_routine)(void *), void *arg) { ulwp_t *self = curthread; const thrattr_t *ap = attr? attr->__pthread_attrp : def_thrattr(); const pcclass_t *pccp; long flag; pthread_t tid; int error; update_sched(self); if (ap == NULL) return (EINVAL); /* validate explicit scheduling attributes */ if (ap->inherit == PTHREAD_EXPLICIT_SCHED && (ap->policy == SCHED_SYS || (pccp = get_info_by_policy(ap->policy)) == NULL || ap->prio < pccp->pcc_primin || ap->prio > pccp->pcc_primax)) return (EINVAL); flag = ap->scope | ap->detachstate | ap->daemonstate | THR_SUSPENDED; error = _thrp_create(ap->stkaddr, ap->stksize, start_routine, arg, flag, &tid, ap->guardsize, ap->name); if (error == 0) { /* * Record the original inheritence value for * pthread_getattr_np(). We should always be able to find the * thread. */ (void) _thr_setinherit(tid, ap->inherit); if (ap->inherit == PTHREAD_EXPLICIT_SCHED && (ap->policy != self->ul_policy || ap->prio != (self->ul_epri ? self->ul_epri : self->ul_pri))) { /* * The SUSv3 specification requires pthread_create() * to fail with EPERM if it cannot set the scheduling * policy and parameters on the new thread. */ error = _thr_setparam(tid, ap->policy, ap->prio); } if (error) { /* * We couldn't determine this error before * actually creating the thread. To recover, * mark the thread detached and cancel it. * It is as though it was never created. */ ulwp_t *ulwp = find_lwp(tid); if (ulwp->ul_detached == 0) { ulwp->ul_detached = 1; ulwp->ul_usropts |= THR_DETACHED; (void) __lwp_detach(tid); } ulwp->ul_cancel_pending = 2; /* cancelled on creation */ ulwp->ul_cancel_disabled = 0; ulwp_unlock(ulwp, self->ul_uberdata); } else if (thread) { *thread = tid; } (void) thr_continue(tid); } /* posix version expects EAGAIN for lack of memory */ if (error == ENOMEM) error = EAGAIN; return (error); }