minix/lib/libmthread/attribute.c
Thomas Veerman a7072a5e1c Revamp the mthread library and update test59
Before, the 'main thread' of a process was never taken into account anywhere in
the library, causing mutexes not to work properly (and consequently, neither
did the condition variables). For example, if the 'main thread' (that is, the
thread which is started at the beginning of a process; not a spawned thread by
the library) would lock a mutex, it wasn't actually locked.
2010-09-30 13:44:13 +00:00

354 lines
8.3 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)->prev = NULL;
} else {
va_rear->next = *a;
(*a)->prev = va_rear;
}
(*a)->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->a_detachstate = MTHREAD_CREATE_JOINABLE;
a->a_stackaddr = NULL;
a->a_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->a_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->a_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->a_stackaddr;
*stacksize = a->a_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->a_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->a_stackaddr = stackaddr;
a->a_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->a_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)->prev == NULL)
va_front = (*a)->next;
else
(*a)->prev->next = (*a)->next;
if ((*a)->next == NULL)
va_rear = (*a)->prev;
else
(*a)->next->prev = (*a)->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->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->next;
return(0);
}
return(1);
}
#endif