add thread local storage feature.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1049 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
bernard.xiong@gmail.com 2010-11-15 15:36:54 +00:00
parent aca1628a31
commit 1c67fc851a
4 changed files with 193 additions and 60 deletions

View File

@ -1,41 +1,18 @@
#include "pthread.h"
#define PTHREAD_MAGIC 0x70746873
struct _pthread_data
{
rt_uint32_t magic;
pthread_attr_t attr;
rt_thread_t tid;
void* (*thread_entry)(void* parameter);
void* thread_parameter;
/* return value */
void* return_value;
/* semaphore for joinable thread */
rt_sem_t joinable_sem;
void** tls; /* thread-local storage area */
};
typedef struct _pthread_data _pthread_data_t;
rt_inline _pthread_data_t* get_pthread_data(pthread_t thread)
{
RT_ASSERT(thread != RT_NULL);
return (_pthread_data_t*)thread->user_data;
}
#include <pthread.h>
#include "pthread_internal.h"
int pthread_system_init(void)
{
/* initialize key area */
pthread_key_system_init();
return 0;
}
static void _pthread_cleanup(rt_thread_t tid)
{
_pthread_data_t *ptd;
ptd = get_pthread_data(tid);
ptd = _pthread_get_data(tid);
/* clear cleanup function */
tid->cleanup = RT_NULL;
@ -75,10 +52,10 @@ int pthread_create (pthread_t *tid, const pthread_attr_t *attr,
/* tid shall be provided */
RT_ASSERT(tid != RT_NULL);
/* allocate pthread data */
/* allocate posix thread data */
ptd = (_pthread_data_t*)rt_malloc(sizeof(_pthread_data_t));
if (ptd == RT_NULL) return ENOMEM;
/* clean memory */
/* clean posix thread data memory */
rt_memset(ptd, 0, sizeof(_pthread_data_t));
if (attr != RT_NULL) ptd->attr = *attr;
@ -161,7 +138,7 @@ int pthread_detach(pthread_t thread)
{
_pthread_data_t* ptd;
ptd = get_pthread_data(thread);
ptd = _pthread_get_data(thread);
if (thread->stat == RT_THREAD_CLOSE)
{
@ -177,6 +154,12 @@ int pthread_detach(pthread_t thread)
/* release thread allocated stack */
rt_free(ptd->tid->stack_addr);
}
/*
* if this thread create the local thread data,
* delete it
*/
if (ptd->tls != RT_NULL) rt_free(ptd->tls);
rt_free(ptd->tid);
rt_free(ptd);
}
@ -205,7 +188,7 @@ int pthread_join (pthread_t thread, void **value_ptr)
return EDEADLK;
}
ptd = get_pthread_data(thread);
ptd = _pthread_get_data(thread);
if (ptd->attr.detachstate == PTHREAD_CREATE_DETACHED)
return EINVAL; /* join on a detached pthread */
@ -225,7 +208,7 @@ int pthread_cancel (pthread_t thread)
{
_pthread_data_t* ptd;
ptd = get_pthread_data(thread);
ptd = _pthread_get_data(thread);
/* check cancel point */
}
@ -234,7 +217,7 @@ void pthread_exit (void* value)
{
_pthread_data_t* ptd;
ptd = get_pthread_data(rt_thread_self());
ptd = _pthread_get_data(rt_thread_self());
/* set return value */
ptd->return_value = value;
@ -281,10 +264,50 @@ int pthread_kill(pthread_t thread, int sig)
void pthread_cleanup_pop(int execute)
{
_pthread_data_t* ptd;
_pthread_cleanup_t* cleanup;
/* get posix thread data */
ptd = _pthread_get_data(rt_thread_self());
RT_ASSERT(ptd != RT_NULL);
if (execute)
{
rt_enter_critical();
cleanup = ptd->cleanup;
if (cleanup)
ptd->cleanup = cleanup->next;
rt_exit_critical();
if (cleanup)
{
cleanup->cleanup_func(cleanup->parameter);
rt_free(cleanup);
}
}
}
void pthread_cleanup_push(void (*routine)(void*), void *arg)
{
_pthread_data_t* ptd;
_pthread_cleanup_t* cleanup;
/* get posix thread data */
ptd = _pthread_get_data(rt_thread_self());
RT_ASSERT(ptd != RT_NULL);
cleanup = (_pthread_cleanup_t*)rt_malloc(sizeof(_pthread_cleanup_t));
if (cleanup != RT_NULL)
{
cleanup->cleanup_func = routine;
cleanup->parameter = arg;
rt_enter_critical();
cleanup->next = ptd->cleanup;
ptd->cleanup = cleanup;
rt_exit_critical();
}
}
int pthread_setcancelstate(int state, int *oldstate)

View File

@ -18,22 +18,7 @@
#include <errno.h>
#include <sys/types.h>
typedef rt_thread_t pthread_t;
typedef long pthread_condattr_t;
typedef long pthread_rwlockattr_t;
typedef long pthread_mutexattr_t;
typedef long pthread_barrierattr_t;
typedef int pthread_key_t;
typedef int pthread_once_t;
enum {
PTHREAD_CANCEL_ASYNCHRONOUS = 0,
PTHREAD_CANCEL_ENABLE,
PTHREAD_CANCEL_DEFERRED,
PTHREAD_CANCEL_DISABLE,
PTHREAD_CANCELED
};
#define PTHREAD_KEY_MAX 8
#define PTHREAD_COND_INITIALIZER {-1, 0}
#define PTHREAD_RWLOCK_INITIALIZER {-1, 0}
@ -45,6 +30,30 @@ enum {
#define PTHREAD_EXPLICIT_SCHED 0
#define PTHREAD_INHERIT_SCHED 1
typedef rt_thread_t pthread_t;
typedef long pthread_condattr_t;
typedef long pthread_rwlockattr_t;
typedef long pthread_mutexattr_t;
typedef long pthread_barrierattr_t;
typedef int pthread_key_t;
typedef int pthread_once_t;
/*
* Scheduling policies required by IEEE Std 1003.1-2001
*/
#define SCHED_OTHER 0 /* Behavior can be FIFO or RR, or not */
#define SCHED_FIFO 1
#define SCHED_RR 2
enum {
PTHREAD_CANCEL_ASYNCHRONOUS = 0,
PTHREAD_CANCEL_ENABLE,
PTHREAD_CANCEL_DEFERRED,
PTHREAD_CANCEL_DISABLE,
PTHREAD_CANCELED
};
enum {
PTHREAD_MUTEX_NORMAL = 0,
PTHREAD_MUTEX_RECURSIVE = 1,
@ -66,7 +75,6 @@ enum {
#define PTHREAD_PROCESS_PRIVATE 0
#define PTHREAD_PROCESS_SHARED 1
#define PTHREAD_SCOPE_PROCESS 0
#define PTHREAD_SCOPE_SYSTEM 1
@ -129,13 +137,6 @@ struct pthread_barrier
};
typedef struct pthread_barrier pthread_barrier_t;
/*
* Scheduling policies required by IEEE Std 1003.1-2001
*/
#define SCHED_OTHER 0 /* Behavior can be FIFO or RR, or not */
#define SCHED_FIFO 1
#define SCHED_RR 2
/* pthread thread interface */
int pthread_attr_destroy(pthread_attr_t *attr);
int pthread_attr_init(pthread_attr_t *attr);

View File

@ -0,0 +1,44 @@
#ifndef __PTHREAD_INTERNAL_H__
#define __PTHREAD_INTERNAL_H__
#include <rtthread.h>
#include <pthread.h>
struct _pthread_cleanup
{
void (*cleanup_func)(void* parameter);
void* parameter;
struct _pthread_cleanup* next;
};
typedef struct _pthread_cleanup _pthread_cleanup_t;
#define PTHREAD_MAGIC 0x70746873
struct _pthread_data
{
rt_uint32_t magic;
pthread_attr_t attr;
rt_thread_t tid;
void* (*thread_entry)(void* parameter);
void* thread_parameter;
/* return value */
void* return_value;
/* semaphore for joinable thread */
rt_sem_t joinable_sem;
_pthread_cleanup_t* cleanup;
void** tls; /* thread-local storage area */
};
typedef struct _pthread_data _pthread_data_t;
rt_inline _pthread_data_t* _pthread_get_data(pthread_t thread)
{
RT_ASSERT(thread != RT_NULL);
return (_pthread_data_t*)thread->user_data;
}
#endif

View File

@ -1,19 +1,84 @@
#include <pthread.h>
#include "pthread_internal.h"
struct _pthread_key_data
{
int is_used;
void* (*destructor)(void* parameter);
};
typedef struct _pthread_key_data _pthread_key_data_t;
static _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX];
void pthread_key_system_init()
{
rt_memset(&_thread_keys[0], 0, sizeof(_thread_keys));
}
void *pthread_getspecific(pthread_key_t key)
{
struct _pthread_data* ptd;
ptd = _pthread_get_data(rt_thread_self());
RT_ASSERT(ptd != NULL);
if (ptd->tls == NULL) return NULL;
if ((key < PTHREAD_KEY_MAX) && (_thread_keys[key].is_used))
return ptd->tls[key];
return NULL;
}
int pthread_setspecific(pthread_key_t key, const void *value)
{
struct _pthread_data* ptd;
ptd = _pthread_get_data(rt_thread_self());
RT_ASSERT(ptd != NULL);
/* check tls area */
if (ptd->tls == NULL) ptd->tls = rt_malloc(sizeof(void*) * PTHREAD_KEY_MAX);
if ((key < PTHREAD_KEY_MAX) && _thread_keys[key].is_used)
{
ptd->tls[key] = (void *)value;
return 0;
}
return EINVAL;
}
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*))
{
return 0;
rt_uint32_t index;
rt_enter_critical();
for (index = 0; index < PTHREAD_KEY_MAX; index ++)
{
if (_thread_keys[index].is_used == 0)
{
_thread_keys[index].is_used = 1;
_thread_keys[index].destructor = destructor;
*key = index;
rt_exit_critical();
return 0;
}
}
rt_exit_critical();
return EAGAIN;
}
int pthread_key_delete(pthread_key_t key)
{
if (key >= PTHREAD_KEY_MAX) return EINVAL;
rt_enter_critical();
_thread_keys[key].is_used = 0;
_thread_keys[key].destructor = 0;
rt_exit_critical();
return 0;
}