minix/lib/libmthread/attribute.c
Thomas Veerman c8d0edc06a - Refactor mthread structure fields to prevent name clashes
- Remove sanity checks for initialized mutexes and condition variables. This
  significantly boosts performance. The checks can be turned back on by
  compiling libmthread with MTHREAD_STRICT. According to POSIX operations on
  uninitialized variables are a MAY fail if, therefore allowing this
  optimization.
- Test59 has to be accommodated to the lack of sanity checks on uninitialized
  variables in the library. It specifically tests for them and will run into
  segfaults when the checks are absent in the library.
- Fix a few bugs related to the scheduler
- Do some general code cleanups
2011-03-18 10:29:54 +00:00

355 lines
8.4 KiB
C

#include <minix/mthread.h>
#include "global.h"
#include "proto.h"
PRIVATE struct __mthread_attr *va_front, *va_rear;
FORWARD _PROTOTYPE( void mthread_attr_add, (mthread_attr_t *a) );
FORWARD _PROTOTYPE( void mthread_attr_remove, (mthread_attr_t *a) );
FORWARD _PROTOTYPE( int mthread_attr_valid, (mthread_attr_t *a) );
/*===========================================================================*
* mthread_init_valid_attributes *
*===========================================================================*/
PUBLIC void mthread_init_valid_attributes(void)
{
/* Initialize list of valid attributs */
va_front = va_rear = NULL;
}
/*===========================================================================*
* mthread_attr_add *
*===========================================================================*/
PRIVATE void mthread_attr_add(a)
mthread_attr_t *a;
{
/* Add attribute to list of valid, initialized attributes */
if (va_front == NULL) { /* Empty list */
va_front = *a;
(*a)->ma_prev = NULL;
} else {
va_rear->ma_next = *a;
(*a)->ma_prev = va_rear;
}
(*a)->ma_next = NULL;
va_rear = *a;
}
/*===========================================================================*
* mthread_attr_destroy *
*===========================================================================*/
PUBLIC int mthread_attr_destroy(attr)
mthread_attr_t *attr;
{
/* Invalidate attribute and deallocate resources. */
mthread_init(); /* Make sure mthreads is initialized */
if (attr == NULL) {
errno = EINVAL;
return(-1);
}
if (!mthread_attr_valid(attr)) {
errno = EINVAL;
return(-1);
}
/* Valide attribute; invalidate it */
mthread_attr_remove(attr);
free(*attr);
*attr = NULL;
return(0);
}
/*===========================================================================*
* mthread_attr_init *
*===========================================================================*/
PUBLIC int mthread_attr_init(attr)
mthread_attr_t *attr; /* Attribute */
{
/* Initialize the attribute to a known state. */
struct __mthread_attr *a;
mthread_init(); /* Make sure mthreads is initialized */
if (attr == NULL) {
errno = EAGAIN;
return(-1);
} else if (mthread_attr_valid(attr)) {
errno = EBUSY;
return(-1);
}
if ((a = malloc(sizeof(struct __mthread_attr))) == NULL)
return(-1);
a->ma_detachstate = MTHREAD_CREATE_JOINABLE;
a->ma_stackaddr = NULL;
a->ma_stacksize = (size_t) 0;
*attr = (mthread_attr_t) a;
mthread_attr_add(attr); /* Validate attribute: attribute now in use */
return(0);
}
/*===========================================================================*
* mthread_attr_getdetachstate *
*===========================================================================*/
PUBLIC int mthread_attr_getdetachstate(attr, detachstate)
mthread_attr_t *attr;
int *detachstate;
{
/* Get detachstate of a thread attribute */
struct __mthread_attr *a;
mthread_init(); /* Make sure mthreads is initialized */
if (attr == NULL) {
errno = EINVAL;
return(-1);
}
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr)) {
errno = EINVAL;
return(-1);
}
*detachstate = a->ma_detachstate;
return(0);
}
/*===========================================================================*
* mthread_attr_setdetachstate *
*===========================================================================*/
PUBLIC int mthread_attr_setdetachstate(attr, detachstate)
mthread_attr_t *attr;
int detachstate;
{
/* Set detachstate of a thread attribute */
struct __mthread_attr *a;
mthread_init(); /* Make sure mthreads is initialized */
if (attr == NULL) {
errno = EINVAL;
return(-1);
}
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr)) {
errno = EINVAL;
return(-1);
} else if(detachstate != MTHREAD_CREATE_JOINABLE &&
detachstate != MTHREAD_CREATE_DETACHED) {
errno = EINVAL;
return(-1);
}
a->ma_detachstate = detachstate;
return(0);
}
/*===========================================================================*
* mthread_attr_getstack *
*===========================================================================*/
PUBLIC int mthread_attr_getstack(attr, stackaddr, stacksize)
mthread_attr_t *attr;
void **stackaddr;
size_t *stacksize;
{
/* Get stack attribute */
struct __mthread_attr *a;
mthread_init(); /* Make sure mthreads is initialized */
if (attr == NULL) {
errno = EINVAL;
return(-1);
}
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr)) {
errno = EINVAL;
return(-1);
}
*stackaddr = a->ma_stackaddr;
*stacksize = a->ma_stacksize;
return(0);
}
/*===========================================================================*
* mthread_attr_getstacksize *
*===========================================================================*/
PUBLIC int mthread_attr_getstacksize(attr, stacksize)
mthread_attr_t *attr;
size_t *stacksize;
{
/* Get stack size attribute */
struct __mthread_attr *a;
mthread_init(); /* Make sure mthreads is initialized */
if (attr == NULL) {
errno = EINVAL;
return(-1);
}
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr)) {
errno = EINVAL;
return(-1);
}
*stacksize = a->ma_stacksize;
return(0);
}
/*===========================================================================*
* mthread_attr_setstack *
*===========================================================================*/
PUBLIC int mthread_attr_setstack(attr, stackaddr, stacksize)
mthread_attr_t *attr;
void *stackaddr;
size_t stacksize;
{
/* Set stack attribute */
struct __mthread_attr *a;
mthread_init(); /* Make sure mthreads is initialized */
if (attr == NULL) {
errno = EINVAL;
return(-1);
}
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr) || stacksize < MTHREAD_STACK_MIN) {
errno = EINVAL;
return(-1);
}
/* We don't care about address alignment (POSIX standard). The ucontext
* system calls will make sure that the provided stack will be aligned (at
* the cost of some memory if needed).
*/
a->ma_stackaddr = stackaddr;
a->ma_stacksize = stacksize;
return(0);
}
/*===========================================================================*
* mthread_attr_setstacksize *
*===========================================================================*/
PUBLIC int mthread_attr_setstacksize(attr, stacksize)
mthread_attr_t *attr;
size_t stacksize;
{
/* Set stack size attribute */
struct __mthread_attr *a;
mthread_init(); /* Make sure mthreads is initialized */
if (attr == NULL) {
errno = EINVAL;
return(-1);
}
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr) || stacksize < MTHREAD_STACK_MIN) {
errno = EINVAL;
return(-1);
}
a->ma_stacksize = stacksize;
return(0);
}
/*===========================================================================*
* mthread_attr_remove *
*===========================================================================*/
PRIVATE void mthread_attr_remove(a)
mthread_attr_t *a;
{
/* Remove attribute from list of valid, initialized attributes */
if ((*a)->ma_prev == NULL)
va_front = (*a)->ma_next;
else
(*a)->ma_prev->ma_next = (*a)->ma_next;
if ((*a)->ma_next == NULL)
va_rear = (*a)->ma_prev;
else
(*a)->ma_next->ma_prev = (*a)->ma_prev;
}
/*===========================================================================*
* mthread_attr_valid *
*===========================================================================*/
PRIVATE int mthread_attr_valid(a)
mthread_attr_t *a;
{
/* Check to see if attribute is on the list of valid attributes */
struct __mthread_attr *loopitem;
mthread_init(); /* Make sure mthreads is initialized */
loopitem = va_front;
while (loopitem != NULL) {
if (loopitem == *a)
return(1);
loopitem = loopitem->ma_next;
}
return(0);
}
/*===========================================================================*
* mthread_attr_verify *
*===========================================================================*/
#ifdef MDEBUG
PUBLIC int mthread_attr_verify(void)
{
/* Return true when no attributes are in use */
struct __mthread_attr *loopitem;
mthread_init(); /* Make sure mthreads is initialized */
loopitem = va_front;
while (loopitem != NULL) {
loopitem = loopitem->ma_next;
return(0);
}
return(1);
}
#endif