Quote Originally Posted by adeyblue View Post
The Linux/posix equivalent of TLSAlloc and friends are pthread_key_create and pthread_get/setspecific
Thanks, having look at it I think I'll still go with a custom solution, was just about to post an improved version of my existing solution, realised I was taking the long route with buffers when linked lists would be faster, so now I'm using that:
Code:
typedef struct _pawtls_ent pawtls_ent;
typedef struct _pawtls_buf pawtls_buf;
struct _pawtls_ent { pawtls_ent *prv, *nxt; pawexe tid; void *data; };
struct _pawtls_buf { pawtls_buf *prv, *nxt; pawvu size; pawvu *addr; pawtls_ent *top; };
PAWTLS pawtls_buf *pawtls = NULL;
#			ifdef PAWTLS_IS_GLOBAL
static pawsyn pawtls_syn = BAD_pawsyn;
pawd  pawtls_init(void)
	{ return pawsyn_init(&pawtls_syn,(void*)&pawtls,pawtls_class,1); }
PAWAPP_QCK pawtls_buf* pawtls_wait(void)
	{ return *((pawtls_buf**)pawsyn_wait(&pawtls_syn)); }
PAWAPP_QCK void  pawtls_free(void) { pawsyn_free(&pawtls_syn); }
void  pawtls_term(void) { pawsyn_term(&pawtls_syn); }
#			else
pawd  pawtls_init(void) { return 0; }
PAWAPP_QCK pawtls_buf* pawtls_wait(void) { return pawtls; }
PAWAPP_QCK void  pawtls_free(void) {}
void  pawtls_term(void) { pawbuf_expire(&pawtls); }
#			endif
static pawtls_ent* pawtls_newmem( pawtls_buf *buff )
{
	pawexe tid = pawgetexe();
	pawtls_ent *prv = buff->top, *ent = prv;
	for ( ; ent; prv = ent, ent = ent->nxt )
	{
		if ( ent->tid == tid )
			return ent;
	}
	ent = pawnew(sizeof(pawtls_ent));
	if ( !ent )
		return PAWERR_OUT_OF_SPACE;
	ent->tid = pawgetexe();
	ent->nxt = buff->top;
	ent->data = pawnew( buff->size );
	if ( !pawmem_gettop(ent->data) )
	{
		pawdel( ent, sizeof(pawtls_ent) );
		return NULL;
	}
	if ( buff->top )
		buff->top->prv = ent;
	buff->top = ent;
	return ent;
}
PAWAPP_API pawd pawtls_getloc( void **dest, pawvu *addr, pawvu size )
{
	pawd err = 0;
	pawtls_ent *entry = NULL;
	pawtls_buf *buffs = pawtls_wait(), *buff = (void*)(*addr);
	*dest = NULL;
	if ( !size )
	{
		pawtls_free();
		return PAWERR_INVALID_DATA;
	}
	if ( buff )
	{
		if ( buff->size != size )
		{
			pawtls_free();
			return PAWERR_INVALID_DATA;
		}
		entry = pawtls_newmem(buff);
		if ( !entry )
			err = PAWERR_OUT_OF_SPACE;
		else
			*dest = entry->data;
		pawtls_free();
		return err;
	}
	buff = pawnew(sizeof(pawtls_buf));
	if ( !buff )
	{
		pawtls_free(buff);
		return PAWERR_OUT_OF_SPACE;
	}
	buff->addr = addr;
	buff->size = size;
	buff->nxt = buffs;
	entry = pawtls_newmem(buff);
	if ( !entry )
	{
		pawtls_free();
		pawdel( buff, sizeof(pawtls_buf) );
		return PAWERR_OUT_OF_SPACE;
	}
	*dest = entry->data;
	if ( buffs )
		buffs->prv = buff;
	pawtls = buff;
	pawtls_free();
	return 0;
}
PAWAPP_API void   pawtls_remloc( pawvu *addr )
{
	pawexe tid = pawgetexe();
	pawtls_ent *prv = NULL, *ent = NULL;
	pawtls_buf *tls = pawtls_wait(), *buff = (void*)(*addr);
	pawvu i = 0, len = 0;
	if ( !buff || buff->addr != addr )
	{
		pawtls_free();
		return;
	}
	prv = ent = buff->top;
	for ( ; ent; prv = ent->nxt )
	{
		if ( ent->tid == tid )
		{
			prv->nxt = ent->nxt;
			if ( ent->nxt )
				ent->nxt->prv = ent->prv;
			if ( buff->top == ent )
				buff->top = ent->nxt;
			break;
		}
	}
	if ( !(buff->top) )
	{
		if ( buff->prv )
			buff->prv->nxt = buff->nxt;
		if ( buff->nxt )
			buff->nxt->prv = buff->prv;
		pawdel(buff);
		*addr = 0;
	}
	pawtls_free();
}
PAWAPP_API void   pawtls_remall(void)
{
	pawtls_buf *buff = pawtls_wait(), temp = {NULL};
	for ( ; buff; buff = temp.nxt )
	{
		temp = *buff;
		pawtls_remloc( buff->addr );
	}
	pawtls_free();
}