minix/lib/libmthread/attribute.c
Lionel Sambuc d3d33afe9f Experimental pthread compatibility library
This patch adds pthread compatibility by using libmthread.

To use this with a program using pthreads, you have to replace
  #include <pthread>
with
  #define _MTHREADIFY_PTHREADS
  #include <minix/mthreads>

This also changes the initialization function to be a constructor, which
is implicitly called before the call to main. This allows for
conformance with pthreads, while not paying a high price by checking on
each mthread_* call whether the library has been initialized or not.

As mthread_init is now a constructor, it also has been set as static, and
relevent calls removed from programs using it.

Change-Id: I2aa375db557958d2bee9a70d285aabb990c88f00
2014-07-28 17:05:08 +02:00

312 lines
7.9 KiB
C

#include <minix/mthread.h>
#include "global.h"
#include "proto.h"
static struct __mthread_attr *va_front, *va_rear;
static void mthread_attr_add(mthread_attr_t *a);
static void mthread_attr_remove(mthread_attr_t *a);
static int mthread_attr_valid(mthread_attr_t *a);
/*===========================================================================*
* mthread_init_valid_attributes *
*===========================================================================*/
void mthread_init_valid_attributes(void)
{
/* Initialize list of valid attributs */
va_front = va_rear = NULL;
}
/*===========================================================================*
* mthread_attr_add *
*===========================================================================*/
static 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 *
*===========================================================================*/
int mthread_attr_destroy(attr)
mthread_attr_t *attr;
{
/* Invalidate attribute and deallocate resources. */
if (attr == NULL)
return(EINVAL);
if (!mthread_attr_valid(attr))
return(EINVAL);
/* Valide attribute; invalidate it */
mthread_attr_remove(attr);
free(*attr);
*attr = NULL;
return(0);
}
/*===========================================================================*
* mthread_attr_init *
*===========================================================================*/
int mthread_attr_init(attr)
mthread_attr_t *attr; /* Attribute */
{
/* Initialize the attribute to a known state. */
struct __mthread_attr *a;
if (attr == NULL)
return(EAGAIN);
else if (mthread_attr_valid(attr))
return(EBUSY);
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 *
*===========================================================================*/
int mthread_attr_getdetachstate(attr, detachstate)
mthread_attr_t *attr;
int *detachstate;
{
/* Get detachstate of a thread attribute */
struct __mthread_attr *a;
if (attr == NULL)
return(EINVAL);
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr))
return(EINVAL);
*detachstate = a->ma_detachstate;
return(0);
}
/*===========================================================================*
* mthread_attr_setdetachstate *
*===========================================================================*/
int mthread_attr_setdetachstate(attr, detachstate)
mthread_attr_t *attr;
int detachstate;
{
/* Set detachstate of a thread attribute */
struct __mthread_attr *a;
if (attr == NULL)
return(EINVAL);
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr))
return(EINVAL);
else if(detachstate != MTHREAD_CREATE_JOINABLE &&
detachstate != MTHREAD_CREATE_DETACHED)
return(EINVAL);
a->ma_detachstate = detachstate;
return(0);
}
/*===========================================================================*
* mthread_attr_getstack *
*===========================================================================*/
int mthread_attr_getstack(attr, stackaddr, stacksize)
mthread_attr_t *attr;
void **stackaddr;
size_t *stacksize;
{
/* Get stack attribute */
struct __mthread_attr *a;
if (attr == NULL)
return(EINVAL);
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr))
return(EINVAL);
*stackaddr = a->ma_stackaddr;
*stacksize = a->ma_stacksize;
return(0);
}
/*===========================================================================*
* mthread_attr_getstacksize *
*===========================================================================*/
int mthread_attr_getstacksize(attr, stacksize)
mthread_attr_t *attr;
size_t *stacksize;
{
/* Get stack size attribute */
struct __mthread_attr *a;
if (attr == NULL)
return(EINVAL);
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr))
return(EINVAL);
*stacksize = a->ma_stacksize;
return(0);
}
/*===========================================================================*
* mthread_attr_setstack *
*===========================================================================*/
int mthread_attr_setstack(attr, stackaddr, stacksize)
mthread_attr_t *attr;
void *stackaddr;
size_t stacksize;
{
/* Set stack attribute */
struct __mthread_attr *a;
if (attr == NULL)
return(EINVAL);
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr) || stacksize < MTHREAD_STACK_MIN)
return(EINVAL);
/* 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 *
*===========================================================================*/
int mthread_attr_setstacksize(attr, stacksize)
mthread_attr_t *attr;
size_t stacksize;
{
/* Set stack size attribute */
struct __mthread_attr *a;
if (attr == NULL)
return(EINVAL);
a = (struct __mthread_attr *) *attr;
if (!mthread_attr_valid(attr) || stacksize < MTHREAD_STACK_MIN)
return(EINVAL);
a->ma_stacksize = stacksize;
return(0);
}
/*===========================================================================*
* mthread_attr_remove *
*===========================================================================*/
static 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 *
*===========================================================================*/
static 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;
loopitem = va_front;
while (loopitem != NULL) {
if (loopitem == *a)
return(1);
loopitem = loopitem->ma_next;
}
return(0);
}
/*===========================================================================*
* mthread_attr_verify *
*===========================================================================*/
#ifdef MDEBUG
int mthread_attr_verify(void)
{
/* Return true when no attributes are in use */
struct __mthread_attr *loopitem;
loopitem = va_front;
while (loopitem != NULL) {
loopitem = loopitem->ma_next;
return(0);
}
return(1);
}
#endif
/* pthread compatibility layer. */
__weak_alias(pthread_attr_destroy, mthread_attr_destroy)
__weak_alias(pthread_attr_getdetachstate, mthread_attr_getdetachstate)
__weak_alias(pthread_attr_getstack, mthread_attr_getstack)
__weak_alias(pthread_attr_getstacksize, mthread_attr_getstacksize)
__weak_alias(pthread_attr_init, mthread_attr_init)
__weak_alias(pthread_attr_setdetachstate, mthread_attr_setdetachstate)
__weak_alias(pthread_attr_setstack, mthread_attr_setstack)
__weak_alias(pthread_attr_setstacksize, mthread_attr_setstacksize)