Refactor _pthread_mutex_init
o Simplify the logic by removing a lot of unnecesary nesting o Reduce the amount of local variables o Zero-out the allocated structure and get rid of all the unnecessary setting to 0 and NULL; Refactor _pthread_mutex_destroy o Simplify the logic by removing a lot of unnecesary nesting o No need to check pointer that the mutex attributes points to. Checking passed in pointer is enough.
This commit is contained in:
parent
2d3f49ebd3
commit
b6945f083e
@ -60,6 +60,7 @@
|
|||||||
#define _MUTEX_ASSERT_NOT_OWNED(m)
|
#define _MUTEX_ASSERT_NOT_OWNED(m)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
@ -131,144 +132,82 @@ int
|
|||||||
_pthread_mutex_init(pthread_mutex_t * mutex,
|
_pthread_mutex_init(pthread_mutex_t * mutex,
|
||||||
const pthread_mutexattr_t * mutex_attr)
|
const pthread_mutexattr_t * mutex_attr)
|
||||||
{
|
{
|
||||||
enum pthread_mutextype type;
|
struct pthread_mutex_attr default_attr = {PTHREAD_MUTEX_ERRORCHECK,
|
||||||
int protocol;
|
PTHREAD_PRIO_NONE, PTHREAD_MAX_PRIORITY, 0 };
|
||||||
int ceiling;
|
struct pthread_mutex_attr *attr;
|
||||||
int flags;
|
|
||||||
pthread_mutex_t pmutex;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (mutex == NULL)
|
if (mutex_attr == NULL) {
|
||||||
ret = EINVAL;
|
attr = &default_attr;
|
||||||
|
} else {
|
||||||
/* Check if default mutex attributes: */
|
/*
|
||||||
if (mutex_attr == NULL || *mutex_attr == NULL) {
|
* Check that the given mutex attribute is valid.
|
||||||
/* Default to a (error checking) POSIX mutex: */
|
*/
|
||||||
type = PTHREAD_MUTEX_ERRORCHECK;
|
if (((*mutex_attr)->m_type < PTHREAD_MUTEX_ERRORCHECK) ||
|
||||||
protocol = PTHREAD_PRIO_NONE;
|
((*mutex_attr)->m_type >= MUTEX_TYPE_MAX))
|
||||||
ceiling = PTHREAD_MAX_PRIORITY;
|
return (EINVAL);
|
||||||
flags = 0;
|
else if (((*mutex_attr)->m_protocol < PTHREAD_PRIO_NONE) ||
|
||||||
|
((*mutex_attr)->m_protocol > PTHREAD_MUTEX_RECURSIVE))
|
||||||
|
return (EINVAL);
|
||||||
|
attr = *mutex_attr;
|
||||||
}
|
}
|
||||||
|
if ((*mutex =
|
||||||
|
(pthread_mutex_t)malloc(sizeof(struct pthread_mutex))) == NULL)
|
||||||
|
return (ENOMEM);
|
||||||
|
memset((void *)(*mutex), 0, sizeof(struct pthread_mutex));
|
||||||
|
|
||||||
/* Check mutex type: */
|
/* Initialise the rest of the mutex: */
|
||||||
else if (((*mutex_attr)->m_type < PTHREAD_MUTEX_ERRORCHECK) ||
|
TAILQ_INIT(&(*mutex)->m_queue);
|
||||||
((*mutex_attr)->m_type >= MUTEX_TYPE_MAX))
|
_MUTEX_INIT_LINK(*mutex);
|
||||||
/* Return an invalid argument error: */
|
(*mutex)->m_protocol = attr->m_protocol;
|
||||||
ret = EINVAL;
|
(*mutex)->m_flags = (attr->m_flags | MUTEX_FLAGS_INITED);
|
||||||
|
(*mutex)->m_type = attr->m_type;
|
||||||
/* Check mutex protocol: */
|
if ((*mutex)->m_protocol == PTHREAD_PRIO_PROTECT)
|
||||||
else if (((*mutex_attr)->m_protocol < PTHREAD_PRIO_NONE) ||
|
(*mutex)->m_prio = attr->m_ceiling;
|
||||||
((*mutex_attr)->m_protocol > PTHREAD_MUTEX_RECURSIVE))
|
return (0);
|
||||||
/* Return an invalid argument error: */
|
|
||||||
ret = EINVAL;
|
|
||||||
|
|
||||||
else {
|
|
||||||
/* Use the requested mutex type and protocol: */
|
|
||||||
type = (*mutex_attr)->m_type;
|
|
||||||
protocol = (*mutex_attr)->m_protocol;
|
|
||||||
ceiling = (*mutex_attr)->m_ceiling;
|
|
||||||
flags = (*mutex_attr)->m_flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check no errors so far: */
|
|
||||||
if (ret == 0) {
|
|
||||||
if ((pmutex = (pthread_mutex_t)
|
|
||||||
malloc(sizeof(struct pthread_mutex))) == NULL)
|
|
||||||
ret = ENOMEM;
|
|
||||||
else {
|
|
||||||
/* Set the mutex flags: */
|
|
||||||
pmutex->m_flags = flags;
|
|
||||||
|
|
||||||
/* Process according to mutex type: */
|
|
||||||
switch (type) {
|
|
||||||
/* case PTHREAD_MUTEX_DEFAULT: */
|
|
||||||
case PTHREAD_MUTEX_ERRORCHECK:
|
|
||||||
case PTHREAD_MUTEX_NORMAL:
|
|
||||||
/* Nothing to do here. */
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Single UNIX Spec 2 recursive mutex: */
|
|
||||||
case PTHREAD_MUTEX_RECURSIVE:
|
|
||||||
/* Reset the mutex count: */
|
|
||||||
pmutex->m_data.m_count = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Trap invalid mutex types: */
|
|
||||||
default:
|
|
||||||
/* Return an invalid argument error: */
|
|
||||||
ret = EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ret == 0) {
|
|
||||||
/* Initialise the rest of the mutex: */
|
|
||||||
TAILQ_INIT(&pmutex->m_queue);
|
|
||||||
pmutex->m_flags |= MUTEX_FLAGS_INITED;
|
|
||||||
pmutex->m_owner = NULL;
|
|
||||||
pmutex->m_type = type;
|
|
||||||
pmutex->m_protocol = protocol;
|
|
||||||
pmutex->m_refcount = 0;
|
|
||||||
if (protocol == PTHREAD_PRIO_PROTECT)
|
|
||||||
pmutex->m_prio = ceiling;
|
|
||||||
else
|
|
||||||
pmutex->m_prio = 0;
|
|
||||||
pmutex->m_saved_prio = 0;
|
|
||||||
_MUTEX_INIT_LINK(pmutex);
|
|
||||||
memset(&pmutex->lock, 0, sizeof(pmutex->lock));
|
|
||||||
*mutex = pmutex;
|
|
||||||
} else {
|
|
||||||
free(pmutex);
|
|
||||||
*mutex = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Return the completion status: */
|
|
||||||
return (ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_pthread_mutex_destroy(pthread_mutex_t * mutex)
|
_pthread_mutex_destroy(pthread_mutex_t * mutex)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
if (mutex == NULL)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
if (mutex == NULL || *mutex == NULL)
|
/*
|
||||||
ret = EINVAL;
|
* If this mutex was statically initialized, don't bother
|
||||||
else {
|
* initializing it in order to destroy it immediately.
|
||||||
/* Lock the mutex structure: */
|
*/
|
||||||
_SPINLOCK(&(*mutex)->lock);
|
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
|
||||||
|
return (0);
|
||||||
|
|
||||||
/*
|
/* Lock the mutex structure: */
|
||||||
* Check to see if this mutex is in use:
|
_SPINLOCK(&(*mutex)->lock);
|
||||||
*/
|
|
||||||
if (((*mutex)->m_owner != NULL) ||
|
|
||||||
(TAILQ_FIRST(&(*mutex)->m_queue) != NULL) ||
|
|
||||||
((*mutex)->m_refcount != 0)) {
|
|
||||||
ret = EBUSY;
|
|
||||||
|
|
||||||
/* Unlock the mutex structure: */
|
/*
|
||||||
_SPINUNLOCK(&(*mutex)->lock);
|
* Check to see if this mutex is in use:
|
||||||
}
|
*/
|
||||||
else {
|
if (((*mutex)->m_owner != NULL) ||
|
||||||
/*
|
(TAILQ_FIRST(&(*mutex)->m_queue) != NULL) ||
|
||||||
* Free the memory allocated for the mutex
|
((*mutex)->m_refcount != 0)) {
|
||||||
* structure:
|
/* Unlock the mutex structure: */
|
||||||
*/
|
_SPINUNLOCK(&(*mutex)->lock);
|
||||||
_MUTEX_ASSERT_NOT_OWNED(*mutex);
|
return (EBUSY);
|
||||||
|
|
||||||
/* Unlock the mutex structure: */
|
|
||||||
_SPINUNLOCK(&(*mutex)->lock);
|
|
||||||
|
|
||||||
free(*mutex);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Leave the caller's pointer NULL now that
|
|
||||||
* the mutex has been destroyed:
|
|
||||||
*/
|
|
||||||
*mutex = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the completion status: */
|
/*
|
||||||
return (ret);
|
* Free the memory allocated for the mutex
|
||||||
|
* structure:
|
||||||
|
*/
|
||||||
|
_MUTEX_ASSERT_NOT_OWNED(*mutex);
|
||||||
|
_SPINUNLOCK(&(*mutex)->lock);
|
||||||
|
free(*mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Leave the caller's pointer NULL now that
|
||||||
|
* the mutex has been destroyed:
|
||||||
|
*/
|
||||||
|
*mutex = NULL;
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
Loading…
x
Reference in New Issue
Block a user