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:
parent
aca1628a31
commit
1c67fc851a
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue