diff options
| author | bernard.xiong <[email protected]> | 2010-11-16 09:54:26 +0000 |
|---|---|---|
| committer | bernard.xiong <[email protected]> | 2010-11-16 09:54:26 +0000 |
| commit | ecfc8e76a9a14b470000c0f9bbfd1ee03ecc71bd (patch) | |
| tree | 8cc78728c14742c2ece4f23e4107b49bbf1f966c /components | |
| parent | 1c67fc851a0773dda7363065d13aa4ddf1330d38 (diff) | |
add more pthreads cancel operation.
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1050 bbd45198-f89e-11dd-88c7-29a3b14d5316
Diffstat (limited to 'components')
| -rw-r--r-- | components/pthreads/pthread.c | 109 | ||||
| -rw-r--r-- | components/pthreads/pthread_internal.h | 12 | ||||
| -rw-r--r-- | components/pthreads/pthread_tls.c | 9 |
3 files changed, 114 insertions, 16 deletions
diff --git a/components/pthreads/pthread.c b/components/pthreads/pthread.c index e02a174f4e..646727f854 100644 --- a/components/pthreads/pthread.c +++ b/components/pthreads/pthread.c @@ -57,6 +57,9 @@ int pthread_create (pthread_t *tid, const pthread_attr_t *attr, if (ptd == RT_NULL) return ENOMEM;
/* clean posix thread data memory */
rt_memset(ptd, 0, sizeof(_pthread_data_t));
+ ptd->canceled = 0;
+ ptd->cancelstate = PTHREAD_CANCEL_DISABLE;
+ ptd->canceltype = PTHREAD_CANCEL_DEFERRED;
if (attr != RT_NULL) ptd->attr = *attr;
else
@@ -204,23 +207,54 @@ int pthread_join (pthread_t thread, void **value_ptr) else return ESRCH;
}
-int pthread_cancel (pthread_t thread)
-{
- _pthread_data_t* ptd;
-
- ptd = _pthread_get_data(thread);
-
- /* check cancel point */
-}
-
void pthread_exit (void* value)
{
_pthread_data_t* ptd;
+ _pthread_cleanup_t* cleanup;
+ _pthread_key_data_t* key;
+ extern _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX];
ptd = _pthread_get_data(rt_thread_self());
+ rt_enter_critical();
+ /* disable cancel */
+ ptd->cancelstate = PTHREAD_CANCEL_DISABLE;
/* set return value */
ptd->return_value = value;
+ rt_exit_critical();
+
+ /* invoke pushed cleanup */
+ while (ptd->cleanup != RT_NULL)
+ {
+ cleanup = ptd->cleanup;
+ ptd->cleanup = cleanup->next;
+
+ cleanup->cleanup_func(cleanup->parameter);
+ /* release this cleanup function */
+ rt_free(cleanup);
+ }
+
+ /* destruct thread local key */
+ if (ptd->tls != RT_NULL)
+ {
+ void* data;
+ rt_uint32_t index;
+
+ for (index = 0; index < PTHREAD_KEY_MAX; index ++)
+ {
+ if (_thread_keys[index].is_used)
+ {
+ data = ptd->tls[index];
+ if (data)
+ _thread_keys[index].destructor(data);
+ }
+ }
+
+ /* release tls area */
+ rt_free(ptd->tls);
+ ptd->tls = RT_NULL;
+ }
+
if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE)
{
/* release the joinable pthread */
@@ -312,14 +346,71 @@ void pthread_cleanup_push(void (*routine)(void*), void *arg) int pthread_setcancelstate(int state, int *oldstate)
{
+ _pthread_data_t* ptd;
+
+ /* get posix thread data */
+ ptd = _pthread_get_data(rt_thread_self());
+ RT_ASSERT(ptd != RT_NULL);
+
+ if ((state == PTHREAD_CANCEL_ENABLE) || (state == PTHREAD_CANCEL_DISABLE))
+ {
+ if (oldstate) *oldstate = ptd->cancelstate;
+ ptd->cancelstate = state;
+
+ return 0;
+ }
+
+ return EINVAL;
}
int pthread_setcanceltype(int type, int *oldtype)
{
+ _pthread_data_t* ptd;
+
+ /* get posix thread data */
+ ptd = _pthread_get_data(rt_thread_self());
+ RT_ASSERT(ptd != RT_NULL);
+
+ if ((type != PTHREAD_CANCEL_DEFERRED) && (type != PTHREAD_CANCEL_ASYNCHRONOUS))
+ return EINVAL;
+
+ if (oldtype) *oldtype = ptd->canceltype;
+ ptd->canceltype = type;
+
return 0;
}
void pthread_testcancel(void)
{
+ int cancel=0;
+ _pthread_data_t* ptd;
+
+ /* get posix thread data */
+ ptd = _pthread_get_data(rt_thread_self());
+ RT_ASSERT(ptd != RT_NULL);
+
+ if (ptd->cancelstate == PTHREAD_CANCEL_ENABLE) cancel = ptd->canceled;
+ if (cancel) pthread_exit((void*)PTHREAD_CANCELED);
+}
+
+int pthread_cancel(pthread_t thread)
+{
+ _pthread_data_t* ptd;
+
+ /* get posix thread data */
+ ptd = _pthread_get_data(thread);
+ RT_ASSERT(ptd != RT_NULL);
+
+ /* set canceled */
+ if (ptd->cancelstate == PTHREAD_CANCEL_ENABLE)
+ {
+ ptd->canceled = 1;
+ if (ptd->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
+ {
+ /* TODO: need cancel thread */
+ }
+ }
+
+ return 0;
}
diff --git a/components/pthreads/pthread_internal.h b/components/pthreads/pthread_internal.h index 33ecfb8d0d..9f32105694 100644 --- a/components/pthreads/pthread_internal.h +++ b/components/pthreads/pthread_internal.h @@ -13,6 +13,13 @@ struct _pthread_cleanup };
typedef struct _pthread_cleanup _pthread_cleanup_t;
+struct _pthread_key_data
+{
+ int is_used;
+ void (*destructor)(void* parameter);
+};
+typedef struct _pthread_key_data _pthread_key_data_t;
+
#define PTHREAD_MAGIC 0x70746873
struct _pthread_data
{
@@ -29,6 +36,11 @@ struct _pthread_data /* semaphore for joinable thread */
rt_sem_t joinable_sem;
+ /* cancel state and type */
+ rt_uint8_t cancelstate;
+ volatile rt_uint8_t canceltype;
+ volatile rt_uint8_t canceled;
+
_pthread_cleanup_t* cleanup;
void** tls; /* thread-local storage area */
};
diff --git a/components/pthreads/pthread_tls.c b/components/pthreads/pthread_tls.c index 5dacc1e1f2..0fda158a39 100644 --- a/components/pthreads/pthread_tls.c +++ b/components/pthreads/pthread_tls.c @@ -1,13 +1,7 @@ #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];
+_pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX];
void pthread_key_system_init()
{
@@ -82,3 +76,4 @@ int pthread_key_delete(pthread_key_t key) return 0;
}
+
|
