#include "lint.h"
#include "thr_uberdata.h"
#include <pthread.h>
#pragma weak _pthread_mutexattr_init = pthread_mutexattr_init
int
pthread_mutexattr_init(pthread_mutexattr_t *attr)
{
mattr_t *ap;
if ((ap = lmalloc(sizeof (mattr_t))) == NULL)
return (ENOMEM);
ap->pshared = PTHREAD_PROCESS_PRIVATE;
ap->type = PTHREAD_MUTEX_DEFAULT;
ap->protocol = PTHREAD_PRIO_NONE;
ap->robustness = PTHREAD_MUTEX_STALLED;
attr->__pthread_mutexattrp = ap;
return (0);
}
int
pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
{
if (attr == NULL || attr->__pthread_mutexattrp == NULL)
return (EINVAL);
lfree(attr->__pthread_mutexattrp, sizeof (mattr_t));
attr->__pthread_mutexattrp = NULL;
return (0);
}
int
pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
{
mattr_t *ap;
if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
(pshared != PTHREAD_PROCESS_PRIVATE &&
pshared != PTHREAD_PROCESS_SHARED))
return (EINVAL);
ap->pshared = pshared;
return (0);
}
#pragma weak _pthread_mutexattr_getpshared = pthread_mutexattr_getpshared
int
pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared)
{
mattr_t *ap;
if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
pshared == NULL)
return (EINVAL);
*pshared = ap->pshared;
return (0);
}
int
pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling)
{
const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO);
mattr_t *ap;
if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
prioceiling < pccp->pcc_primin || prioceiling > pccp->pcc_primax)
return (EINVAL);
ap->prioceiling = prioceiling;
return (0);
}
#pragma weak _pthread_mutexattr_getprioceiling = \
pthread_mutexattr_getprioceiling
int
pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *ceiling)
{
mattr_t *ap;
if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
ceiling == NULL)
return (EINVAL);
*ceiling = ap->prioceiling;
return (0);
}
int
pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol)
{
mattr_t *ap;
if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL)
return (EINVAL);
if (protocol != PTHREAD_PRIO_NONE &&
protocol != PTHREAD_PRIO_INHERIT &&
protocol != PTHREAD_PRIO_PROTECT)
return (ENOTSUP);
ap->protocol = protocol;
return (0);
}
#pragma weak _pthread_mutexattr_getprotocol = pthread_mutexattr_getprotocol
int
pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol)
{
mattr_t *ap;
if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
protocol == NULL)
return (EINVAL);
*protocol = ap->protocol;
return (0);
}
#pragma weak pthread_mutexattr_setrobust_np = pthread_mutexattr_setrobust
int
pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust)
{
mattr_t *ap;
if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
(robust != PTHREAD_MUTEX_ROBUST && robust != PTHREAD_MUTEX_STALLED))
return (EINVAL);
ap->robustness = robust;
return (0);
}
#pragma weak pthread_mutexattr_getrobust_np = pthread_mutexattr_getrobust
int
pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, int *robust)
{
mattr_t *ap;
if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
robust == NULL)
return (EINVAL);
*robust = ap->robustness;
return (0);
}
#pragma weak _pthread_mutex_init = pthread_mutex_init
int
pthread_mutex_init(pthread_mutex_t *_RESTRICT_KYWD mutex,
const pthread_mutexattr_t *_RESTRICT_KYWD attr)
{
mattr_t *ap;
int type, ret;
int prioceiling = 0;
uint16_t flags = 0;
if (attr != NULL) {
if ((ap = attr->__pthread_mutexattrp) == NULL)
return (EINVAL);
switch (ap->type) {
case PTHREAD_MUTEX_NORMAL:
type = LOCK_NORMAL;
flags = LOCK_DEADLOCK;
break;
case PTHREAD_MUTEX_ERRORCHECK:
type = LOCK_ERRORCHECK;
break;
case PTHREAD_MUTEX_RECURSIVE:
type = LOCK_RECURSIVE | LOCK_ERRORCHECK;
break;
default:
type = LOCK_NORMAL;
break;
}
type |= ap->pshared | ap->protocol | ap->robustness;
if (ap->protocol == PTHREAD_PRIO_PROTECT)
prioceiling = ap->prioceiling;
} else {
type = PTHREAD_PROCESS_PRIVATE | LOCK_NORMAL |
PTHREAD_PRIO_NONE | PTHREAD_MUTEX_STALLED;
}
if (((type & PTHREAD_MUTEX_ROBUST) != 0) &&
(((mutex_t *)mutex)->mutex_magic != MUTEX_MAGIC)) {
(void) memset(mutex, 0, sizeof (*mutex));
}
ret = mutex_init((mutex_t *)mutex, type, &prioceiling);
if (ret == 0 && flags != 0) {
mutex_t *mp = (mutex_t *)mutex;
mp->mutex_flag |= flags;
}
return (ret);
}
int
pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int ceil, int *oceil)
{
mutex_t *mp = (mutex_t *)mutex;
const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO);
int error;
if (!(mp->mutex_type & PTHREAD_PRIO_PROTECT) ||
ceil < pccp->pcc_primin || ceil > pccp->pcc_primax)
return (EINVAL);
error = mutex_lock_internal(mp, NULL, MUTEX_LOCK | MUTEX_NOCEIL);
if (error == 0 || error == EOWNERDEAD || error == ELOCKUNMAPPED) {
if (oceil)
*oceil = mp->mutex_ceiling;
mp->mutex_ceiling = ceil;
error = mutex_unlock_internal(mp, 1);
}
return (error);
}
#pragma weak _pthread_mutex_getprioceiling = pthread_mutex_getprioceiling
int
pthread_mutex_getprioceiling(const pthread_mutex_t *mp, int *ceiling)
{
*ceiling = ((mutex_t *)mp)->mutex_ceiling;
return (0);
}
int
pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
{
mattr_t *ap;
if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL)
return (EINVAL);
switch (type) {
case PTHREAD_MUTEX_NORMAL:
case PTHREAD_MUTEX_ERRORCHECK:
case PTHREAD_MUTEX_RECURSIVE:
case PTHREAD_MUTEX_DEFAULT:
break;
default:
return (EINVAL);
}
ap->type = type;
return (0);
}
int
pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep)
{
mattr_t *ap;
if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
typep == NULL)
return (EINVAL);
*typep = ap->type;
return (0);
}