#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include <inttypes.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <execinfo.h>
#include <sched.h>
#include <rte_atomic_64.h>
#include "lthread_tls.h"
#include "lthread_queue.h"
#include "lthread_objcache.h"
#include "lthread_sched.h"
static uint64_t key_pool_init;
RTE_DEFINE_PER_LTHREAD(void *, dummy);
static struct lthread_key key_table[LTHREAD_MAX_KEYS];
void lthread_tls_ctor(void) __attribute__((constructor));
void lthread_tls_ctor(void)
{
key_pool = NULL;
key_pool_init = 0;
}
void _lthread_key_pool_init(void)
{
struct lthread_key *new_key;
char name[MAX_LTHREAD_NAME_SIZE];
bzero(key_table, sizeof(key_table));
snprintf(name,
MAX_LTHREAD_NAME_SIZE,
"lthread_key_pool_%d",
getpid());
LTHREAD_MAX_KEYS, 0, 0);
LTHREAD_ASSERT(pool);
int i;
for (i = 1; i < LTHREAD_MAX_KEYS; i++) {
new_key = &key_table[i];
(void *)new_key);
}
key_pool = pool;
}
while (key_pool == NULL) {
sched_yield();
};
}
int lthread_key_create(unsigned int *key, tls_destructor_func destructor)
{
if (key == NULL)
return POSIX_ERRNO(EINVAL);
struct lthread_key *new_key;
== 0) {
new_key->destructor = destructor;
*key = (new_key - key_table);
return 0;
}
return POSIX_ERRNO(EAGAIN);
}
int lthread_key_delete(unsigned int k)
{
struct lthread_key *key;
key = (struct lthread_key *) &key_table[k];
if (k > LTHREAD_MAX_KEYS)
return POSIX_ERRNO(EINVAL);
key->destructor = NULL;
(void *)key);
return 0;
}
void _lthread_tls_destroy(struct lthread *lt)
{
int i, k;
int nb_keys;
void *data;
for (i = 0; i < LTHREAD_DESTRUCTOR_ITERATIONS; i++) {
for (k = 1; k < LTHREAD_MAX_KEYS; k++) {
nb_keys = lt->tls->nb_keys_inuse;
if (nb_keys == 0)
return;
if (lt->tls->data[k] == NULL)
continue;
data = lt->tls->data[k];
lt->tls->data[k] = NULL;
lt->tls->nb_keys_inuse = nb_keys-1;
if (key_table[k].destructor != NULL)
key_table[k].destructor(data);
}
}
}
void
*lthread_getspecific(unsigned int k)
{
if (k > LTHREAD_MAX_KEYS)
return NULL;
return THIS_LTHREAD->tls->data[k];
}
int lthread_setspecific(unsigned int k, const void *data)
{
if (k > LTHREAD_MAX_KEYS)
return POSIX_ERRNO(EINVAL);
int n = THIS_LTHREAD->tls->nb_keys_inuse;
char *p = (char *) (uintptr_t) data;
if (data != NULL) {
if (THIS_LTHREAD->tls->data[k] == NULL)
THIS_LTHREAD->tls->nb_keys_inuse = n+1;
}
THIS_LTHREAD->tls->data[k] = (void *) p;
return 0;
}
void _lthread_tls_alloc(struct lthread *lt)
{
struct lthread_tls *tls;
tls = _lthread_objcache_alloc((THIS_SCHED)->tls_cache);
LTHREAD_ASSERT(tls != NULL);
tls->root_sched = (THIS_SCHED);
lt->tls = tls;
if (sizeof(void *) < (uint64_t)RTE_PER_LTHREAD_SECTION_SIZE) {
lt->per_lthread_data =
_lthread_objcache_alloc((THIS_SCHED)->per_lthread_cache);
}
}