d3d33afe9f
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
312 lines
7.9 KiB
C
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)
|
|
|