From 8ab2b287b813edc1cdbe8bba430a2593e5fc3e8a Mon Sep 17 00:00:00 2001 From: "yiyue.fang" Date: Wed, 26 Jun 2013 23:18:30 +0800 Subject: [PATCH] Embedded GPLv2 license in pthreads --- components/pthreads/clock_time.c | 147 +++--- components/pthreads/mqueue.c | 400 ++++++++------- components/pthreads/mqueue.h | 78 ++- components/pthreads/posix_types.h | 327 ++++++------ components/pthreads/pthread.c | 672 +++++++++++++------------ components/pthreads/pthread.h | 159 +++--- components/pthreads/pthread_attr.c | 178 ++++--- components/pthreads/pthread_barrier.c | 117 +++-- components/pthreads/pthread_cond.c | 250 +++++---- components/pthreads/pthread_internal.h | 80 +-- components/pthreads/pthread_mutex.c | 239 +++++---- components/pthreads/pthread_rwlock.c | 443 +++++++++------- components/pthreads/pthread_spin.c | 76 ++- components/pthreads/pthread_tls.c | 115 +++-- components/pthreads/sched.c | 42 +- components/pthreads/sched.h | 35 +- components/pthreads/semaphore.c | 458 +++++++++-------- components/pthreads/semaphore.h | 40 +- 18 files changed, 2239 insertions(+), 1617 deletions(-) diff --git a/components/pthreads/clock_time.c b/components/pthreads/clock_time.c index 52034936ec..06227e17e7 100644 --- a/components/pthreads/clock_time.c +++ b/components/pthreads/clock_time.c @@ -3,15 +3,26 @@ * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2012, RT-Thread Development Team * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Change Logs: * Date Author Notes * 2012-12-08 Bernard fix the issue of _timevalue.tv_usec initialization, * which found by Rob */ + #include #include @@ -26,11 +37,11 @@ void clock_time_system_init() device = rt_device_find("rtc"); if (device != RT_NULL) { - /* get realtime seconds */ + /* get realtime seconds */ rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time); } - /* get tick */ + /* get tick */ tick = rt_tick_get(); _timevalue.tv_usec = (tick%RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK; @@ -39,102 +50,106 @@ void clock_time_system_init() int clock_time_to_tick(const struct timespec *time) { - int tick; - int nsecond, second; - struct timespec tp; + int tick; + int nsecond, second; + struct timespec tp; - RT_ASSERT(time != RT_NULL); + RT_ASSERT(time != RT_NULL); - tick = RT_WAITING_FOREVER; - if (time != NULL) - { - /* get current tp */ - clock_gettime(CLOCK_REALTIME, &tp); + tick = RT_WAITING_FOREVER; + if (time != NULL) + { + /* get current tp */ + clock_gettime(CLOCK_REALTIME, &tp); - if ((time->tv_nsec - tp.tv_nsec) < 0) - { - nsecond = NANOSECOND_PER_SECOND - (tp.tv_nsec - time->tv_nsec); - second = time->tv_sec - tp.tv_sec - 1; - } - else - { - nsecond = time->tv_nsec - tp.tv_nsec; - second = time->tv_sec - tp.tv_sec; - } + if ((time->tv_nsec - tp.tv_nsec) < 0) + { + nsecond = NANOSECOND_PER_SECOND - (tp.tv_nsec - time->tv_nsec); + second = time->tv_sec - tp.tv_sec - 1; + } + else + { + nsecond = time->tv_nsec - tp.tv_nsec; + second = time->tv_sec - tp.tv_sec; + } - tick = second * RT_TICK_PER_SECOND + nsecond * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND; - if (tick < 0) tick = 0; - } + tick = second * RT_TICK_PER_SECOND + nsecond * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND; + if (tick < 0) tick = 0; + } - return tick; + return tick; } RTM_EXPORT(clock_time_to_tick); -int clock_getres (clockid_t clockid, struct timespec *res) +int clock_getres(clockid_t clockid, struct timespec *res) { - if ((clockid != CLOCK_REALTIME) || (res == RT_NULL)) - { - rt_set_errno(EINVAL); - return -1; - } + if ((clockid != CLOCK_REALTIME) || (res == RT_NULL)) + { + rt_set_errno(EINVAL); - res->tv_sec = 0; - res->tv_nsec = NANOSECOND_PER_SECOND/RT_TICK_PER_SECOND; + return -1; + } - return 0; + res->tv_sec = 0; + res->tv_nsec = NANOSECOND_PER_SECOND/RT_TICK_PER_SECOND; + + return 0; } RTM_EXPORT(clock_getres); -int clock_gettime (clockid_t clockid, struct timespec *tp) +int clock_gettime(clockid_t clockid, struct timespec *tp) { - rt_tick_t tick; + rt_tick_t tick; - if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL)) - { - rt_set_errno(EINVAL); - return -1; - } + if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL)) + { + rt_set_errno(EINVAL); - /* get tick */ - tick = rt_tick_get(); + return -1; + } - tp->tv_sec = _timevalue.tv_sec + tick / RT_TICK_PER_SECOND; - tp->tv_nsec = (_timevalue.tv_usec + (tick % RT_TICK_PER_SECOND) * NANOSECOND_PER_TICK) * 1000; - - return 0; + /* get tick */ + tick = rt_tick_get(); + + tp->tv_sec = _timevalue.tv_sec + tick / RT_TICK_PER_SECOND; + tp->tv_nsec = (_timevalue.tv_usec + (tick % RT_TICK_PER_SECOND) * NANOSECOND_PER_TICK) * 1000; + + return 0; } RTM_EXPORT(clock_gettime); -int clock_settime (clockid_t clockid, const struct timespec *tp) +int clock_settime(clockid_t clockid, const struct timespec *tp) { - int second; - rt_tick_t tick; + int second; + rt_tick_t tick; rt_device_t device; - if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL)) - { - rt_set_errno(EINVAL); - return -1; - } + if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL)) + { + rt_set_errno(EINVAL); - /* get second */ - second = tp->tv_sec; - /* get tick */ + return -1; + } + + /* get second */ + second = tp->tv_sec; + /* get tick */ tick = rt_tick_get(); - /* update timevalue */ + /* update timevalue */ _timevalue.tv_usec = MICROSECOND_PER_SECOND - (tick % RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK; _timevalue.tv_sec = second - tick/RT_TICK_PER_SECOND - 1; - /* update for RTC device */ + /* update for RTC device */ device = rt_device_find("rtc"); if (device != RT_NULL) { - /* set realtime seconds */ + /* set realtime seconds */ rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &second); } - else return -1; + else + return -1; - return 0; + return 0; } RTM_EXPORT(clock_settime); diff --git a/components/pthreads/mqueue.c b/components/pthreads/mqueue.c index f441011e1c..8886988a1f 100644 --- a/components/pthreads/mqueue.c +++ b/components/pthreads/mqueue.c @@ -1,3 +1,26 @@ +/* + * File : mqueue.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + #include "mqueue.h" #include "pthread_internal.h" @@ -5,266 +28,285 @@ static mqd_t posix_mq_list = RT_NULL; static struct rt_semaphore posix_mq_lock; void posix_mq_system_init() { - rt_sem_init(&posix_mq_lock, "pmq", 1, RT_IPC_FLAG_FIFO); + rt_sem_init(&posix_mq_lock, "pmq", 1, RT_IPC_FLAG_FIFO); } rt_inline void posix_mq_insert(mqd_t pmq) { - pmq->next = posix_mq_list; - posix_mq_list = pmq; + pmq->next = posix_mq_list; + posix_mq_list = pmq; } static void posix_mq_delete(mqd_t pmq) { - mqd_t iter; - if (posix_mq_list == pmq) - { - posix_mq_list = pmq->next; + mqd_t iter; + if (posix_mq_list == pmq) + { + posix_mq_list = pmq->next; - rt_mq_delete(pmq->mq); - rt_free(pmq); + rt_mq_delete(pmq->mq); + rt_free(pmq); - return; - } - for (iter = posix_mq_list; iter->next != RT_NULL; iter = iter->next) - { - if (iter->next == pmq) - { - /* delete this mq */ - if (pmq->next != RT_NULL) - iter->next = pmq->next; - else - iter->next = RT_NULL; + return; + } + for (iter = posix_mq_list; iter->next != RT_NULL; iter = iter->next) + { + if (iter->next == pmq) + { + /* delete this mq */ + if (pmq->next != RT_NULL) + iter->next = pmq->next; + else + iter->next = RT_NULL; - /* delete RT-Thread mqueue */ - rt_mq_delete(pmq->mq); - rt_free(pmq); - return ; - } - } + /* delete RT-Thread mqueue */ + rt_mq_delete(pmq->mq); + rt_free(pmq); + + return ; + } + } } static mqd_t posix_mq_find(const char* name) { - mqd_t iter; - rt_object_t object; + mqd_t iter; + rt_object_t object; - for (iter = posix_mq_list; iter != RT_NULL; iter = iter->next) - { - object = (rt_object_t)(iter->mq); + for (iter = posix_mq_list; iter != RT_NULL; iter = iter->next) + { + object = (rt_object_t)(iter->mq); - if (strncmp(object->name, name, RT_NAME_MAX) == 0) - { - return iter; - } - } + if (strncmp(object->name, name, RT_NAME_MAX) == 0) + { + return iter; + } + } - return RT_NULL; + return RT_NULL; } -int mq_setattr(mqd_t mqdes, const struct mq_attr *mqstat, - struct mq_attr *omqstat) +int mq_setattr(mqd_t mqdes, + const struct mq_attr *mqstat, + struct mq_attr *omqstat) { - rt_set_errno(-RT_ERROR); - return -1; + rt_set_errno(-RT_ERROR); + + return -1; } RTM_EXPORT(mq_setattr); int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat) { - if ((mqdes == RT_NULL) || mqstat == RT_NULL) - { - rt_set_errno(EBADF); - return -1; - } + if ((mqdes == RT_NULL) || mqstat == RT_NULL) + { + rt_set_errno(EBADF); - mqstat->mq_maxmsg = mqdes->mq->max_msgs; - mqstat->mq_msgsize = mqdes->mq->msg_size; - mqstat->mq_curmsgs = 0; - mqstat->mq_flags = 0; + return -1; + } - return 0; + mqstat->mq_maxmsg = mqdes->mq->max_msgs; + mqstat->mq_msgsize = mqdes->mq->msg_size; + mqstat->mq_curmsgs = 0; + mqstat->mq_flags = 0; + + return 0; } RTM_EXPORT(mq_getattr); mqd_t mq_open(const char *name, int oflag, ...) { - mqd_t mqdes; - va_list arg; - mode_t mode; - struct mq_attr *attr = RT_NULL; + mqd_t mqdes; + va_list arg; + mode_t mode; + struct mq_attr *attr = RT_NULL; /* lock posix mqueue list */ rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); mqdes = RT_NULL; - if (oflag & O_CREAT) - { - va_start(arg, oflag); - mode = (mode_t) va_arg(arg, unsigned int); mode = mode; - attr = (struct mq_attr *) va_arg(arg, struct mq_attr *); - va_end(arg); + if (oflag & O_CREAT) + { + va_start(arg, oflag); + mode = (mode_t)va_arg(arg, unsigned int); + mode = mode; + attr = (struct mq_attr *)va_arg(arg, struct mq_attr *); + va_end(arg); - if (oflag & O_EXCL) - { - if (posix_mq_find(name) != RT_NULL) - { - rt_set_errno(EEXIST); - goto __return; - } - } - mqdes = (mqd_t) rt_malloc (sizeof(struct mqdes)); - if (mqdes == RT_NULL) - { - rt_set_errno(ENFILE); - goto __return; - } + if (oflag & O_EXCL) + { + if (posix_mq_find(name) != RT_NULL) + { + rt_set_errno(EEXIST); + goto __return; + } + } + mqdes = (mqd_t) rt_malloc (sizeof(struct mqdes)); + if (mqdes == RT_NULL) + { + rt_set_errno(ENFILE); + goto __return; + } - /* create RT-Thread message queue */ - mqdes->mq = rt_mq_create(name, attr->mq_msgsize, attr->mq_maxmsg, RT_IPC_FLAG_FIFO); - if (mqdes->mq == RT_NULL) /* create failed */ - { - rt_set_errno(ENFILE); - goto __return; - } - /* initialize reference count */ - mqdes->refcount = 1; - mqdes->unlinked = 0; + /* create RT-Thread message queue */ + mqdes->mq = rt_mq_create(name, attr->mq_msgsize, attr->mq_maxmsg, RT_IPC_FLAG_FIFO); + if (mqdes->mq == RT_NULL) /* create failed */ + { + rt_set_errno(ENFILE); + goto __return; + } + /* initialize reference count */ + mqdes->refcount = 1; + mqdes->unlinked = 0; - /* insert mq to posix mq list */ - posix_mq_insert(mqdes); - } - else - { - /* find mqueue */ - mqdes = posix_mq_find(name); - if (mqdes != RT_NULL) - { - mqdes->refcount ++; /* increase reference count */ - } - else - { - rt_set_errno(ENOENT); - goto __return; - } - } - rt_sem_release(&posix_mq_lock); - return mqdes; + /* insert mq to posix mq list */ + posix_mq_insert(mqdes); + } + else + { + /* find mqueue */ + mqdes = posix_mq_find(name); + if (mqdes != RT_NULL) + { + mqdes->refcount ++; /* increase reference count */ + } + else + { + rt_set_errno(ENOENT); + goto __return; + } + } + rt_sem_release(&posix_mq_lock); + + return mqdes; __return: - /* release lock */ - rt_sem_release(&posix_mq_lock); + /* release lock */ + rt_sem_release(&posix_mq_lock); - /* release allocated memory */ - if (mqdes != RT_NULL) - { - if (mqdes->mq != RT_NULL) - { - /* delete RT-Thread message queue */ - rt_mq_delete(mqdes->mq); - } - rt_free(mqdes); - } - return RT_NULL; + /* release allocated memory */ + if (mqdes != RT_NULL) + { + if (mqdes->mq != RT_NULL) + { + /* delete RT-Thread message queue */ + rt_mq_delete(mqdes->mq); + } + rt_free(mqdes); + } + return RT_NULL; } RTM_EXPORT(mq_open); ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio) { - rt_err_t result; + rt_err_t result; - if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) - { - rt_set_errno(EINVAL); - return -1; - } + if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) + { + rt_set_errno(EINVAL); - result = rt_mq_recv(mqdes->mq, msg_ptr, msg_len, RT_WAITING_FOREVER); - if (result == RT_EOK) - return msg_len; + return -1; + } - rt_set_errno(EBADF); - return -1; + result = rt_mq_recv(mqdes->mq, msg_ptr, msg_len, RT_WAITING_FOREVER); + if (result == RT_EOK) + return msg_len; + + rt_set_errno(EBADF); + return -1; } RTM_EXPORT(mq_receive); int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio) { - rt_err_t result; + rt_err_t result; - if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) - { - rt_set_errno(EINVAL); - return -1; - } + if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) + { + rt_set_errno(EINVAL); - result = rt_mq_send(mqdes->mq, (void*)msg_ptr, msg_len); - if (result == RT_EOK) - return 0; + return -1; + } - rt_set_errno(EBADF); - return -1; + result = rt_mq_send(mqdes->mq, (void*)msg_ptr, msg_len); + if (result == RT_EOK) + return 0; + + rt_set_errno(EBADF); + + return -1; } RTM_EXPORT(mq_send); -ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, - unsigned *msg_prio, const struct timespec *abs_timeout) +ssize_t mq_timedreceive(mqd_t mqdes, + char *msg_ptr, + size_t msg_len, + unsigned *msg_prio, + const struct timespec *abs_timeout) { - int tick; - rt_err_t result; + int tick; + rt_err_t result; - /* parameters check */ - if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) - { - rt_set_errno(EINVAL); - return -1; - } + /* parameters check */ + if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) + { + rt_set_errno(EINVAL); - tick = clock_time_to_tick(abs_timeout); + return -1; + } - result = rt_mq_recv(mqdes->mq, msg_ptr, msg_len, tick); - if (result == RT_EOK) return msg_len; + tick = clock_time_to_tick(abs_timeout); - if (result == -RT_ETIMEOUT) - rt_set_errno(ETIMEDOUT); - else - rt_set_errno(EBADMSG); + result = rt_mq_recv(mqdes->mq, msg_ptr, msg_len, tick); + if (result == RT_EOK) + return msg_len; - return -1; + if (result == -RT_ETIMEOUT) + rt_set_errno(ETIMEDOUT); + else + rt_set_errno(EBADMSG); + + return -1; } RTM_EXPORT(mq_timedreceive); -int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio, - const struct timespec *abs_timeout) +int mq_timedsend(mqd_t mqdes, + const char *msg_ptr, + size_t msg_len, + unsigned msg_prio, + const struct timespec *abs_timeout) { - /* RT-Thread does not support timed send */ - return mq_send(mqdes, msg_ptr, msg_len, msg_prio); + /* RT-Thread does not support timed send */ + return mq_send(mqdes, msg_ptr, msg_len, msg_prio); } RTM_EXPORT(mq_timedsend); int mq_notify(mqd_t mqdes, const struct sigevent *notification) { - rt_set_errno(-RT_ERROR); - return -1; + rt_set_errno(-RT_ERROR); + + return -1; } RTM_EXPORT(mq_notify); int mq_close(mqd_t mqdes) { - if (mqdes == RT_NULL) - { - rt_set_errno(EINVAL); - return -1; - } + if (mqdes == RT_NULL) + { + rt_set_errno(EINVAL); + + return -1; + } /* lock posix mqueue list */ rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); mqdes->refcount --; if (mqdes->refcount == 0) { - /* delete from posix mqueue list */ - if (mqdes->unlinked) - posix_mq_delete(mqdes); + /* delete from posix mqueue list */ + if (mqdes->unlinked) + posix_mq_delete(mqdes); } rt_sem_release(&posix_mq_lock); @@ -274,26 +316,28 @@ RTM_EXPORT(mq_close); int mq_unlink(const char *name) { - mqd_t pmq; + mqd_t pmq; /* lock posix mqueue list */ rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); pmq = posix_mq_find(name); if (pmq != RT_NULL) { - pmq->unlinked = 1; - if (pmq->refcount == 0) - { - /* remove this mqueue */ - posix_mq_delete(pmq); - } + pmq->unlinked = 1; + if (pmq->refcount == 0) + { + /* remove this mqueue */ + posix_mq_delete(pmq); + } rt_sem_release(&posix_mq_lock); + return 0; } rt_sem_release(&posix_mq_lock); /* no this entry */ rt_set_errno(ENOENT); + return -1; } RTM_EXPORT(mq_unlink); diff --git a/components/pthreads/mqueue.h b/components/pthreads/mqueue.h index 5c17884721..de2925837f 100644 --- a/components/pthreads/mqueue.h +++ b/components/pthreads/mqueue.h @@ -1,3 +1,26 @@ +/* + * File : mqueue.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + #ifndef __MQUEUE_H__ #define __MQUEUE_H__ @@ -6,38 +29,45 @@ struct mqdes { - /* reference count and unlinked */ - rt_uint16_t refcount; - rt_uint16_t unlinked; + /* reference count and unlinked */ + rt_uint16_t refcount; + rt_uint16_t unlinked; - /* RT-Thread message queue */ - rt_mq_t mq; - /* next posix mqueue */ - struct mqdes* next; + /* RT-Thread message queue */ + rt_mq_t mq; + /* next posix mqueue */ + struct mqdes* next; }; typedef struct mqdes* mqd_t; struct mq_attr { - long mq_flags; /* Message queue flags. */ - long mq_maxmsg; /* Maximum number of messages. */ - long mq_msgsize; /* Maximum message size. */ - long mq_curmsgs; /* Number of messages currently queued. */ + long mq_flags; /* Message queue flags. */ + long mq_maxmsg; /* Maximum number of messages. */ + long mq_msgsize; /* Maximum message size. */ + long mq_curmsgs; /* Number of messages currently queued. */ }; -int mq_close(mqd_t mqdes); -int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat); -int mq_notify(mqd_t mqdes, const struct sigevent *notification); -mqd_t mq_open(const char *name, int oflag, ...); -ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio); -int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio); -int mq_setattr(mqd_t mqdes, const struct mq_attr *mqstat, - struct mq_attr *omqstat); -ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, - unsigned *msg_prio, const struct timespec *abs_timeout); -int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio, - const struct timespec *abs_timeout); +int mq_close(mqd_t mqdes); +int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat); +int mq_notify(mqd_t mqdes, const struct sigevent *notification); +mqd_t mq_open(const char *name, int oflag, ...); +ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio); +int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio); +int mq_setattr(mqd_t mqdes, + const struct mq_attr *mqstat, + struct mq_attr *omqstat); +ssize_t mq_timedreceive(mqd_t mqdes, + char *msg_ptr, + size_t msg_len, + unsigned *msg_prio, + const struct timespec *abs_timeout); +int mq_timedsend(mqd_t mqdes, + const char *msg_ptr, + size_t msg_len, + unsigned msg_prio, + const struct timespec *abs_timeout); -int mq_unlink(const char *name); +int mq_unlink(const char *name); #endif diff --git a/components/pthreads/posix_types.h b/components/pthreads/posix_types.h index 2fcbb71045..cbc2515884 100644 --- a/components/pthreads/posix_types.h +++ b/components/pthreads/posix_types.h @@ -1,3 +1,26 @@ +/* + * File : posix_types.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + #ifndef __POSIX_TYPES_H__ #define __POSIX_TYPES_H__ @@ -19,177 +42,179 @@ #else /* ARM compiler and IAR compiler */ -#if defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) +#if defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) #include #include #include typedef rt_int32_t clockid_t; -typedef rt_int32_t key_t; /* Used for interprocess communication. */ -typedef rt_int32_t pid_t; /* Used for process IDs and process group IDs. */ -typedef signed long ssize_t; /* Used for a count of bytes or an error indication. */ -typedef signed long time_t; /* Used for time in seconds. */ +typedef rt_int32_t key_t; /* Used for interprocess communication. */ +typedef rt_int32_t pid_t; /* Used for process IDs and process group IDs. */ +typedef signed long ssize_t; /* Used for a count of bytes or an error indication. */ +typedef signed long time_t; /* Used for time in seconds. */ -struct timespec { - time_t tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ +struct timespec +{ + time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ }; -struct timeval { +struct timeval +{ long tv_sec; /* seconds */ long tv_usec; /* microseconds */ }; /* errno definitions */ -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Arg list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ -#define ENOMSG 35 /* No message of desired type */ -#define EIDRM 36 /* Identifier removed */ -#define ECHRNG 37 /* Channel number out of range */ -#define EL2NSYNC 38 /* Level 2 not synchronized */ -#define EL3HLT 39 /* Level 3 halted */ -#define EL3RST 40 /* Level 3 reset */ -#define ELNRNG 41 /* Link number out of range */ -#define EUNATCH 42 /* Protocol driver not attached */ -#define ENOCSI 43 /* No CSI structure available */ -#define EL2HLT 44 /* Level 2 halted */ -#define EDEADLK 45 /* Resource deadlock would occur */ -#define ENOLCK 46 /* No record locks available */ -#define EBADE 50 /* Invalid exchange */ -#define EBADR 51 /* Invalid request descriptor */ -#define EXFULL 52 /* Exchange full */ -#define ENOANO 53 /* No anode */ -#define EBADRQC 54 /* Invalid request code */ -#define EBADSLT 55 /* Invalid slot */ -#define EDEADLOCK 56 /* File locking deadlock error */ -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EDOTDOT 73 /* RFS specific error */ -#define EMULTIHOP 74 /* Multihop attempted */ -#define EBADMSG 77 /* Not a data message */ -#define ENAMETOOLONG 78 /* File name too long */ -#define EOVERFLOW 79 /* Value too large for defined data type */ -#define ENOTUNIQ 80 /* Name not unique on network */ -#define EBADFD 81 /* File descriptor in bad state */ -#define EREMCHG 82 /* Remote address changed */ -#define ELIBACC 83 /* Can not access a needed shared library */ -#define ELIBBAD 84 /* Accessing a corrupted shared library */ -#define ELIBSCN 85 /* .lib section in a.out corrupted */ -#define ELIBMAX 86 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 87 /* Cannot exec a shared library directly */ -#define EILSEQ 88 /* Illegal byte sequence */ -#define ENOSYS 89 /* Function not implemented */ -#define ELOOP 90 /* Too many symbolic links encountered */ -#define ERESTART 91 /* Interrupted system call should be restarted */ -#define ESTRPIPE 92 /* Streams pipe error */ -#define ENOTEMPTY 93 /* Directory not empty */ -#define EUSERS 94 /* Too many users */ -#define ENOTSOCK 95 /* Socket operation on non-socket */ -#define EDESTADDRREQ 96 /* Destination address required */ -#define EMSGSIZE 97 /* Message too long */ -#define EPROTOTYPE 98 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 99 /* Protocol not available */ -#define EPROTONOSUPPORT 120 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 121 /* Socket type not supported */ -#define EOPNOTSUPP 122 /* Operation not supported on transport endpoint */ -#define ENOTSUP EOPNOTSUPP/* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 123 /* Protocol family not supported */ -#define EAFNOSUPPORT 124 /* Address family not supported by protocol */ -#define EADDRINUSE 125 /* Address already in use */ -#define EADDRNOTAVAIL 126 /* Cannot assign requested address */ -#define ENETDOWN 127 /* Network is down */ -#define ENETUNREACH 128 /* Network is unreachable */ -#define ENETRESET 129 /* Network dropped connection because of reset */ -#define ECONNABORTED 130 /* Software caused connection abort */ -#define ECONNRESET 131 /* Connection reset by peer */ -#define ENOBUFS 132 /* No buffer space available */ -#define EISCONN 133 /* Transport endpoint is already connected */ -#define ENOTCONN 134 /* Transport endpoint is not connected */ -#define EUCLEAN 135 /* Structure needs cleaning */ -#define ENOTNAM 137 /* Not a XENIX named type file */ -#define ENAVAIL 138 /* No XENIX semaphores available */ -#define EISNAM 139 /* Is a named type file */ -#define EREMOTEIO 140 /* Remote I/O error */ -#define EINIT 141 /* Reserved */ -#define EREMDEV 142 /* Error 142 */ -#define ESHUTDOWN 143 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 144 /* Too many references: cannot splice */ -#define ETIMEDOUT 145 /* Connection timed out */ -#define ECONNREFUSED 146 /* Connection refused */ -#define EHOSTDOWN 147 /* Host is down */ -#define EHOSTUNREACH 148 /* No route to host */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define EALREADY 149 /* Operation already in progress */ -#define EINPROGRESS 150 /* Operation now in progress */ -#define ESTALE 151 /* Stale NFS file handle */ -#define ECANCELED 158 /* AIO operation canceled */ -#define ENOMEDIUM 159 /* No medium found */ -#define EMEDIUMTYPE 160 /* Wrong medium type */ -#define ENOKEY 161 /* Required key not available */ -#define EKEYEXPIRED 162 /* Key has expired */ -#define EKEYREVOKED 163 /* Key has been revoked */ -#define EKEYREJECTED 164 /* Key was rejected by service */ -#define EDQUOT 1133 /* Quota exceeded */ +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define ENOMSG 35 /* No message of desired type */ +#define EIDRM 36 /* Identifier removed */ +#define ECHRNG 37 /* Channel number out of range */ +#define EL2NSYNC 38 /* Level 2 not synchronized */ +#define EL3HLT 39 /* Level 3 halted */ +#define EL3RST 40 /* Level 3 reset */ +#define ELNRNG 41 /* Link number out of range */ +#define EUNATCH 42 /* Protocol driver not attached */ +#define ENOCSI 43 /* No CSI structure available */ +#define EL2HLT 44 /* Level 2 halted */ +#define EDEADLK 45 /* Resource deadlock would occur */ +#define ENOLCK 46 /* No record locks available */ +#define EBADE 50 /* Invalid exchange */ +#define EBADR 51 /* Invalid request descriptor */ +#define EXFULL 52 /* Exchange full */ +#define ENOANO 53 /* No anode */ +#define EBADRQC 54 /* Invalid request code */ +#define EBADSLT 55 /* Invalid slot */ +#define EDEADLOCK 56 /* File locking deadlock error */ +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EDOTDOT 73 /* RFS specific error */ +#define EMULTIHOP 74 /* Multihop attempted */ +#define EBADMSG 77 /* Not a data message */ +#define ENAMETOOLONG 78 /* File name too long */ +#define EOVERFLOW 79 /* Value too large for defined data type */ +#define ENOTUNIQ 80 /* Name not unique on network */ +#define EBADFD 81 /* File descriptor in bad state */ +#define EREMCHG 82 /* Remote address changed */ +#define ELIBACC 83 /* Can not access a needed shared library */ +#define ELIBBAD 84 /* Accessing a corrupted shared library */ +#define ELIBSCN 85 /* .lib section in a.out corrupted */ +#define ELIBMAX 86 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 87 /* Cannot exec a shared library directly */ +#define EILSEQ 88 /* Illegal byte sequence */ +#define ENOSYS 89 /* Function not implemented */ +#define ELOOP 90 /* Too many symbolic links encountered */ +#define ERESTART 91 /* Interrupted system call should be restarted */ +#define ESTRPIPE 92 /* Streams pipe error */ +#define ENOTEMPTY 93 /* Directory not empty */ +#define EUSERS 94 /* Too many users */ +#define ENOTSOCK 95 /* Socket operation on non-socket */ +#define EDESTADDRREQ 96 /* Destination address required */ +#define EMSGSIZE 97 /* Message too long */ +#define EPROTOTYPE 98 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 99 /* Protocol not available */ +#define EPROTONOSUPPORT 120 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 121 /* Socket type not supported */ +#define EOPNOTSUPP 122 /* Operation not supported on transport endpoint */ +#define ENOTSUP EOPNOTSUPP/* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 123 /* Protocol family not supported */ +#define EAFNOSUPPORT 124 /* Address family not supported by protocol */ +#define EADDRINUSE 125 /* Address already in use */ +#define EADDRNOTAVAIL 126 /* Cannot assign requested address */ +#define ENETDOWN 127 /* Network is down */ +#define ENETUNREACH 128 /* Network is unreachable */ +#define ENETRESET 129 /* Network dropped connection because of reset */ +#define ECONNABORTED 130 /* Software caused connection abort */ +#define ECONNRESET 131 /* Connection reset by peer */ +#define ENOBUFS 132 /* No buffer space available */ +#define EISCONN 133 /* Transport endpoint is already connected */ +#define ENOTCONN 134 /* Transport endpoint is not connected */ +#define EUCLEAN 135 /* Structure needs cleaning */ +#define ENOTNAM 137 /* Not a XENIX named type file */ +#define ENAVAIL 138 /* No XENIX semaphores available */ +#define EISNAM 139 /* Is a named type file */ +#define EREMOTEIO 140 /* Remote I/O error */ +#define EINIT 141 /* Reserved */ +#define EREMDEV 142 /* Error 142 */ +#define ESHUTDOWN 143 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 144 /* Too many references: cannot splice */ +#define ETIMEDOUT 145 /* Connection timed out */ +#define ECONNREFUSED 146 /* Connection refused */ +#define EHOSTDOWN 147 /* Host is down */ +#define EHOSTUNREACH 148 /* No route to host */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EALREADY 149 /* Operation already in progress */ +#define EINPROGRESS 150 /* Operation now in progress */ +#define ESTALE 151 /* Stale NFS file handle */ +#define ECANCELED 158 /* AIO operation canceled */ +#define ENOMEDIUM 159 /* No medium found */ +#define EMEDIUMTYPE 160 /* Wrong medium type */ +#define ENOKEY 161 /* Required key not available */ +#define EKEYEXPIRED 162 /* Key has expired */ +#define EKEYREVOKED 163 /* Key has been revoked */ +#define EKEYREJECTED 164 /* Key was rejected by service */ +#define EDQUOT 1133 /* Quota exceeded */ #ifdef RT_USING_DFS #include #else typedef rt_uint16_t mode_t; -#define O_RDONLY 0x0000000 -#define O_WRONLY 0x0000001 -#define O_RDWR 0x0000002 -#define O_ACCMODE 0x0000003 -#define O_CREAT 0x0000100 -#define O_EXCL 0x0000200 -#define O_TRUNC 0x0001000 -#define O_APPEND 0x0002000 -#define O_DIRECTORY 0x0200000 +#define O_RDONLY 0x0000000 +#define O_WRONLY 0x0000001 +#define O_RDWR 0x0000002 +#define O_ACCMODE 0x0000003 +#define O_CREAT 0x0000100 +#define O_EXCL 0x0000200 +#define O_TRUNC 0x0001000 +#define O_APPEND 0x0002000 +#define O_DIRECTORY 0x0200000 #endif -#elif defined (__GNUC__) /* GNU GCC Compiler, with minilibc */ +#elif defined (__GNUC__) /* GNU GCC Compiler, with minilibc */ #include #include #include diff --git a/components/pthreads/pthread.c b/components/pthreads/pthread.c index 4455885652..a823253d48 100644 --- a/components/pthreads/pthread.c +++ b/components/pthreads/pthread.c @@ -1,366 +1,409 @@ +/* + * File : pthread.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + #include #include #include "pthread_internal.h" int pthread_system_init(void) { - /* initialize clock and time */ - clock_time_system_init(); + /* initialize clock and time */ + clock_time_system_init(); - /* initialize key area */ - pthread_key_system_init(); - /* initialize posix mqueue */ - posix_mq_system_init(); - /* initialize posix semaphore */ - posix_sem_system_init(); + /* initialize key area */ + pthread_key_system_init(); + /* initialize posix mqueue */ + posix_mq_system_init(); + /* initialize posix semaphore */ + posix_sem_system_init(); - return 0; + return 0; } static void _pthread_cleanup(rt_thread_t tid) { - _pthread_data_t *ptd; - ptd = _pthread_get_data(tid); + _pthread_data_t *ptd; + ptd = _pthread_get_data(tid); - /* clear cleanup function */ - tid->cleanup = RT_NULL; - if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE) - { - rt_sem_release(ptd->joinable_sem); - } - else - { - /* release pthread resource */ - pthread_detach(tid); - } + /* clear cleanup function */ + tid->cleanup = RT_NULL; + if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE) + { + rt_sem_release(ptd->joinable_sem); + } + else + { + /* release pthread resource */ + pthread_detach(tid); + } } -static void pthread_entry_stub(void* parameter) +static void pthread_entry_stub(void *parameter) { - _pthread_data_t *ptd; - void* value; + _pthread_data_t *ptd; + void *value; - ptd = (_pthread_data_t*)parameter; + ptd = (_pthread_data_t*)parameter; - /* execute pthread entry */ - value = ptd->thread_entry(ptd->thread_parameter); - /* set value */ - ptd->return_value = value; + /* execute pthread entry */ + value = ptd->thread_entry(ptd->thread_parameter); + /* set value */ + ptd->return_value = value; } -int pthread_create (pthread_t *tid, const pthread_attr_t *attr, - void *(*start) (void *), void *parameter) +int pthread_create(pthread_t *tid, + const pthread_attr_t *attr, + void *(*start) (void *), void *parameter) { - int result; - void* stack; - char name[RT_NAME_MAX]; - static rt_uint16_t pthread_number = 0; - _pthread_data_t *ptd; + int result; + void *stack; + char name[RT_NAME_MAX]; + static rt_uint16_t pthread_number = 0; + _pthread_data_t *ptd; - /* tid shall be provided */ - RT_ASSERT(tid != RT_NULL); + /* tid shall be provided */ + RT_ASSERT(tid != RT_NULL); - /* allocate posix thread data */ - ptd = (_pthread_data_t*)rt_malloc(sizeof(_pthread_data_t)); - 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; - ptd->magic = PTHREAD_MAGIC; + /* allocate posix thread data */ + ptd = (_pthread_data_t*)rt_malloc(sizeof(_pthread_data_t)); + 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; + ptd->magic = PTHREAD_MAGIC; - if (attr != RT_NULL) ptd->attr = *attr; - else - { - /* use default attribute */ - pthread_attr_init(&ptd->attr); - } + if (attr != RT_NULL) + ptd->attr = *attr; + else + { + /* use default attribute */ + pthread_attr_init(&ptd->attr); + } - rt_snprintf(name, sizeof(name), "pth%02d", pthread_number ++); - if (ptd->attr.stack_base == 0) - { - stack = (void*)rt_malloc(ptd->attr.stack_size); - } - else stack = (void*)(ptd->attr.stack_base); + rt_snprintf(name, sizeof(name), "pth%02d", pthread_number ++); + if (ptd->attr.stack_base == 0) + { + stack = (void*)rt_malloc(ptd->attr.stack_size); + } + else + stack = (void*)(ptd->attr.stack_base); - if (stack == RT_NULL) - { - rt_free(ptd); - return ENOMEM; - } + if (stack == RT_NULL) + { + rt_free(ptd); - /* pthread is a static thread object */ - ptd->tid = (rt_thread_t) rt_malloc(sizeof(struct rt_thread)); - if (ptd->tid == RT_NULL) - { - if (ptd->attr.stack_base ==0) rt_free(stack); - rt_free(ptd); - return ENOMEM; - } + return ENOMEM; + } - if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE) - { - ptd->joinable_sem = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO); - if (ptd->joinable_sem == RT_NULL) - { - if (ptd->attr.stack_base !=0) rt_free(stack); - rt_free(ptd); - return ENOMEM; - } - } - else ptd->joinable_sem = RT_NULL; + /* pthread is a static thread object */ + ptd->tid = (rt_thread_t) rt_malloc(sizeof(struct rt_thread)); + if (ptd->tid == RT_NULL) + { + if (ptd->attr.stack_base == 0) + rt_free(stack); + rt_free(ptd); - /* set parameter */ - ptd->thread_entry = start; - ptd->thread_parameter = parameter; + return ENOMEM; + } - /* initial this pthread to system */ - if (rt_thread_init(ptd->tid, name, pthread_entry_stub, ptd, - stack, ptd->attr.stack_size, - ptd->attr.priority, 5) != RT_EOK) - { - if (ptd->attr.stack_base ==0) rt_free(stack); - if (ptd->joinable_sem != RT_NULL) rt_sem_delete(ptd->joinable_sem); - rt_free(ptd); - return EINVAL; - } + if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE) + { + ptd->joinable_sem = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO); + if (ptd->joinable_sem == RT_NULL) + { + if (ptd->attr.stack_base != 0) + rt_free(stack); + rt_free(ptd); - /* set pthread id */ - *tid = ptd->tid; + return ENOMEM; + } + } + else + ptd->joinable_sem = RT_NULL; - /* set pthread cleanup function and ptd data */ - (*tid)->cleanup = _pthread_cleanup; - (*tid)->user_data = (rt_uint32_t)ptd; + /* set parameter */ + ptd->thread_entry = start; + ptd->thread_parameter = parameter; - /* start thread */ - result = rt_thread_startup(*tid); - if (result == RT_EOK) return 0; + /* initial this pthread to system */ + if (rt_thread_init(ptd->tid, name, pthread_entry_stub, ptd, + stack, ptd->attr.stack_size, + ptd->attr.priority, 5) != RT_EOK) + { + if (ptd->attr.stack_base == 0) + rt_free(stack); + if (ptd->joinable_sem != RT_NULL) + rt_sem_delete(ptd->joinable_sem); + rt_free(ptd); - /* start thread failed */ - rt_thread_detach(ptd->tid); - if (ptd->attr.stack_base ==0) rt_free(stack); - if (ptd->joinable_sem != RT_NULL) rt_sem_delete(ptd->joinable_sem); + return EINVAL; + } - rt_free(ptd); - return EINVAL; + /* set pthread id */ + *tid = ptd->tid; + + /* set pthread cleanup function and ptd data */ + (*tid)->cleanup = _pthread_cleanup; + (*tid)->user_data = (rt_uint32_t)ptd; + + /* start thread */ + result = rt_thread_startup(*tid); + if (result == RT_EOK) + return 0; + + /* start thread failed */ + rt_thread_detach(ptd->tid); + if (ptd->attr.stack_base == 0) + rt_free(stack); + if (ptd->joinable_sem != RT_NULL) + rt_sem_delete(ptd->joinable_sem); + + rt_free(ptd); + + return EINVAL; } RTM_EXPORT(pthread_create); int pthread_detach(pthread_t thread) { - _pthread_data_t* ptd; + _pthread_data_t* ptd; - ptd = _pthread_get_data(thread); + ptd = _pthread_get_data(thread); - if (thread->stat == RT_THREAD_CLOSE) - { - /* delete joinable semaphore */ - if (ptd->joinable_sem != RT_NULL) - rt_sem_delete(ptd->joinable_sem); - /* detach thread object */ - rt_thread_detach(ptd->tid); + if (thread->stat == RT_THREAD_CLOSE) + { + /* delete joinable semaphore */ + if (ptd->joinable_sem != RT_NULL) + rt_sem_delete(ptd->joinable_sem); + /* detach thread object */ + rt_thread_detach(ptd->tid); - /* release thread resource */ - if (ptd->attr.stack_base == RT_NULL) - { - /* release thread allocated stack */ - rt_free(ptd->tid->stack_addr); - } + /* release thread resource */ + if (ptd->attr.stack_base == RT_NULL) + { + /* 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); - } - else - { - rt_enter_critical(); - /* change to detach state */ - ptd->attr.detachstate = PTHREAD_CREATE_DETACHED; + /* + * 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); + } + else + { + rt_enter_critical(); + /* change to detach state */ + ptd->attr.detachstate = PTHREAD_CREATE_DETACHED; - /* detach joinable semaphore */ - rt_sem_delete(ptd->joinable_sem); - ptd->joinable_sem = RT_NULL; - rt_exit_critical(); - } + /* detach joinable semaphore */ + rt_sem_delete(ptd->joinable_sem); + ptd->joinable_sem = RT_NULL; + rt_exit_critical(); + } - return 0; + return 0; } RTM_EXPORT(pthread_detach); int pthread_join (pthread_t thread, void **value_ptr) { - _pthread_data_t* ptd; - rt_err_t result; + _pthread_data_t* ptd; + rt_err_t result; - if (thread == rt_thread_self()) - { - /* join self */ - return EDEADLK; - } + if (thread == rt_thread_self()) + { + /* join self */ + return EDEADLK; + } - ptd = _pthread_get_data(thread); - if (ptd->attr.detachstate == PTHREAD_CREATE_DETACHED) - return EINVAL; /* join on a detached pthread */ + ptd = _pthread_get_data(thread); + if (ptd->attr.detachstate == PTHREAD_CREATE_DETACHED) + return EINVAL; /* join on a detached pthread */ - result = rt_sem_take(ptd->joinable_sem, RT_WAITING_FOREVER); - if (result == RT_EOK) - { - /* get return value */ - if (value_ptr != RT_NULL) *value_ptr = ptd->return_value; + result = rt_sem_take(ptd->joinable_sem, RT_WAITING_FOREVER); + if (result == RT_EOK) + { + /* get return value */ + if (value_ptr != RT_NULL) + *value_ptr = ptd->return_value; - /* release resource */ - pthread_detach(thread); - } - else return ESRCH; - - return 0; + /* release resource */ + pthread_detach(thread); + } + else + return ESRCH; + + return 0; } RTM_EXPORT(pthread_join); -void pthread_exit (void* value) +void pthread_exit (void *value) { - _pthread_data_t* ptd; - _pthread_cleanup_t* cleanup; - extern _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX]; + _pthread_data_t *ptd; + _pthread_cleanup_t *cleanup; + extern _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX]; - ptd = _pthread_get_data(rt_thread_self()); + 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(); + 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; + /* 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); - } + 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); - } - } + /* 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; - } + /* release tls area */ + rt_free(ptd->tls); + ptd->tls = RT_NULL; + } - if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE) - { - /* release the joinable pthread */ - rt_sem_release(ptd->joinable_sem); - } + if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE) + { + /* release the joinable pthread */ + rt_sem_release(ptd->joinable_sem); + } - /* detach thread */ - rt_thread_detach(ptd->tid); - /* reschedule thread */ - rt_schedule(); + /* detach thread */ + rt_thread_detach(ptd->tid); + /* reschedule thread */ + rt_schedule(); } RTM_EXPORT(pthread_exit); -int pthread_once(pthread_once_t * once_control, void (*init_routine) (void)) +int pthread_once(pthread_once_t *once_control, void (*init_routine) (void)) { - RT_ASSERT(once_control != RT_NULL); - RT_ASSERT(init_routine != RT_NULL); + RT_ASSERT(once_control != RT_NULL); + RT_ASSERT(init_routine != RT_NULL); - rt_enter_critical(); - if (!(*once_control)) - { - /* call routine once */ - *once_control = 1; - rt_exit_critical(); + rt_enter_critical(); + if (!(*once_control)) + { + /* call routine once */ + *once_control = 1; + rt_exit_critical(); - init_routine(); - } - rt_exit_critical(); + init_routine(); + } + rt_exit_critical(); - return 0; + return 0; } RTM_EXPORT(pthread_once); int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) { - return ENOTSUP; + return ENOTSUP; } RTM_EXPORT(pthread_atfork); int pthread_kill(pthread_t thread, int sig) { - return ENOTSUP; + return ENOTSUP; } RTM_EXPORT(pthread_kill); void pthread_cleanup_pop(int execute) { - _pthread_data_t* ptd; - _pthread_cleanup_t* cleanup; + _pthread_data_t *ptd; + _pthread_cleanup_t *cleanup; - /* get posix thread data */ - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != RT_NULL); + /* 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 (execute) + { + rt_enter_critical(); + cleanup = ptd->cleanup; + if (cleanup) + ptd->cleanup = cleanup->next; + rt_exit_critical(); - if (cleanup) - { - cleanup->cleanup_func(cleanup->parameter); + if (cleanup) + { + cleanup->cleanup_func(cleanup->parameter); - rt_free(cleanup); - } - } + rt_free(cleanup); + } + } } RTM_EXPORT(pthread_cleanup_pop); void pthread_cleanup_push(void (*routine)(void*), void *arg) { - _pthread_data_t* ptd; - _pthread_cleanup_t* cleanup; + _pthread_data_t *ptd; + _pthread_cleanup_t *cleanup; - /* get posix thread data */ - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != RT_NULL); + /* 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; + 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(); - } + rt_enter_critical(); + cleanup->next = ptd->cleanup; + ptd->cleanup = cleanup; + rt_exit_critical(); + } } RTM_EXPORT(pthread_cleanup_push); @@ -394,85 +437,90 @@ RTM_EXPORT(pthread_cleanup_push); int pthread_setcancelstate(int state, int *oldstate) { - _pthread_data_t* ptd; + _pthread_data_t *ptd; - /* get posix thread data */ - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != RT_NULL); + /* 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; + if ((state == PTHREAD_CANCEL_ENABLE) || (state == PTHREAD_CANCEL_DISABLE)) + { + if (oldstate) + *oldstate = ptd->cancelstate; + ptd->cancelstate = state; - return 0; - } + return 0; + } - return EINVAL; + return EINVAL; } RTM_EXPORT(pthread_setcancelstate); int pthread_setcanceltype(int type, int *oldtype) { - _pthread_data_t* ptd; + _pthread_data_t *ptd; - /* get posix thread data */ - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != RT_NULL); + /* 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 ((type != PTHREAD_CANCEL_DEFERRED) && (type != PTHREAD_CANCEL_ASYNCHRONOUS)) + return EINVAL; - if (oldtype) *oldtype = ptd->canceltype; - ptd->canceltype = type; + if (oldtype) + *oldtype = ptd->canceltype; + ptd->canceltype = type; - return 0; + return 0; } RTM_EXPORT(pthread_setcanceltype); void pthread_testcancel(void) { - int cancel=0; - _pthread_data_t* ptd; + int cancel=0; + _pthread_data_t* ptd; - /* get posix thread data */ - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != RT_NULL); + /* 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); + if (ptd->cancelstate == PTHREAD_CANCEL_ENABLE) + cancel = ptd->canceled; + if (cancel) + pthread_exit((void*)PTHREAD_CANCELED); } RTM_EXPORT(pthread_testcancel); int pthread_cancel(pthread_t thread) { - _pthread_data_t* ptd; + _pthread_data_t *ptd; - /* cancel self */ - if (thread == rt_thread_self()) return 0; + /* cancel self */ + if (thread == rt_thread_self()) + return 0; - /* get posix thread data */ - ptd = _pthread_get_data(thread); - RT_ASSERT(ptd != RT_NULL); + /* 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) - { - /* - * to detach thread. - * this thread will be removed from scheduler list - * and because there is a cleanup function in the - * thread (pthread_cleanup), it will move to defunct - * thread list and wait for handling in idle thread. - */ - rt_thread_detach(thread); - } - } + /* set canceled */ + if (ptd->cancelstate == PTHREAD_CANCEL_ENABLE) + { + ptd->canceled = 1; + if (ptd->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) + { + /* + * to detach thread. + * this thread will be removed from scheduler list + * and because there is a cleanup function in the + * thread (pthread_cleanup), it will move to defunct + * thread list and wait for handling in idle thread. + */ + rt_thread_detach(thread); + } + } - return 0; + return 0; } RTM_EXPORT(pthread_cancel); diff --git a/components/pthreads/pthread.h b/components/pthreads/pthread.h index 6a87c026f6..e8ea849f0e 100644 --- a/components/pthreads/pthread.h +++ b/components/pthreads/pthread.h @@ -3,31 +3,42 @@ * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Change Logs: * Date Author Notes * 2010-10-26 Bernard the first version */ + #ifndef __PTHREAD_H__ #define __PTHREAD_H__ #include #include -#define PTHREAD_KEY_MAX 8 +#define PTHREAD_KEY_MAX 8 -#define PTHREAD_COND_INITIALIZER {-1, 0} -#define PTHREAD_RWLOCK_INITIALIZER {-1, 0} -#define PTHREAD_MUTEX_INITIALIZER {-1, 0} +#define PTHREAD_COND_INITIALIZER {-1, 0} +#define PTHREAD_RWLOCK_INITIALIZER {-1, 0} +#define PTHREAD_MUTEX_INITIALIZER {-1, 0} -#define PTHREAD_CREATE_JOINABLE 0x00 -#define PTHREAD_CREATE_DETACHED 0x01 +#define PTHREAD_CREATE_JOINABLE 0x00 +#define PTHREAD_CREATE_DETACHED 0x01 -#define PTHREAD_EXPLICIT_SCHED 0 -#define PTHREAD_INHERIT_SCHED 1 +#define PTHREAD_EXPLICIT_SCHED 0 +#define PTHREAD_INHERIT_SCHED 1 typedef rt_thread_t pthread_t; typedef long pthread_condattr_t; @@ -38,15 +49,17 @@ 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 +enum +{ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_ENABLE, + PTHREAD_CANCEL_DEFERRED, + PTHREAD_CANCEL_DISABLE, + PTHREAD_CANCELED }; -enum { +enum +{ PTHREAD_MUTEX_NORMAL = 0, PTHREAD_MUTEX_RECURSIVE = 1, PTHREAD_MUTEX_ERRORCHECK = 2, @@ -56,72 +69,73 @@ enum { }; /* init value for pthread_once_t */ -#define PTHREAD_ONCE_INIT 0 +#define PTHREAD_ONCE_INIT 0 -enum { - PTHREAD_PRIO_INHERIT =0, - PTHREAD_PRIO_NONE, - PTHREAD_PRIO_PROTECT, +enum +{ + PTHREAD_PRIO_INHERIT =0, + PTHREAD_PRIO_NONE, + PTHREAD_PRIO_PROTECT, }; #define PTHREAD_PROCESS_PRIVATE 0 #define PTHREAD_PROCESS_SHARED 1 -#define PTHREAD_SCOPE_PROCESS 0 -#define PTHREAD_SCOPE_SYSTEM 1 +#define PTHREAD_SCOPE_PROCESS 0 +#define PTHREAD_SCOPE_SYSTEM 1 struct pthread_attr { - void* stack_base; - rt_uint16_t stack_size; /* stack size of thread */ + void* stack_base; + rt_uint16_t stack_size; /* stack size of thread */ - rt_uint8_t priority; /* priority of thread */ - rt_uint8_t detachstate; /* detach state */ - rt_uint8_t policy; /* scheduler policy */ - rt_uint8_t inheritsched; /* Inherit parent prio/policy */ + rt_uint8_t priority; /* priority of thread */ + rt_uint8_t detachstate; /* detach state */ + rt_uint8_t policy; /* scheduler policy */ + rt_uint8_t inheritsched; /* Inherit parent prio/policy */ }; typedef struct pthread_attr pthread_attr_t; struct pthread_mutex { - pthread_mutexattr_t attr; - struct rt_mutex lock; + pthread_mutexattr_t attr; + struct rt_mutex lock; }; typedef struct pthread_mutex pthread_mutex_t; struct pthread_cond { - pthread_condattr_t attr; - struct rt_semaphore sem; + pthread_condattr_t attr; + struct rt_semaphore sem; }; typedef struct pthread_cond pthread_cond_t; struct pthread_rwlock { - pthread_rwlockattr_t attr; + pthread_rwlockattr_t attr; - pthread_mutex_t rw_mutex; /* basic lock on this struct */ - pthread_cond_t rw_condreaders; /* for reader threads waiting */ - pthread_cond_t rw_condwriters; /* for writer threads waiting */ + pthread_mutex_t rw_mutex; /* basic lock on this struct */ + pthread_cond_t rw_condreaders; /* for reader threads waiting */ + pthread_cond_t rw_condwriters; /* for writer threads waiting */ - int rw_nwaitreaders; /* the number of reader threads waiting */ - int rw_nwaitwriters; /* the number of writer threads waiting */ - int rw_refcount; /* 0: unlocked, -1: locked by writer, > 0 locked by n readers */ + int rw_nwaitreaders; /* the number of reader threads waiting */ + int rw_nwaitwriters; /* the number of writer threads waiting */ + int rw_refcount; /* 0: unlocked, -1: locked by writer, > 0 locked by n readers */ }; typedef struct pthread_rwlock pthread_rwlock_t; /* spinlock implementation, (ADVANCED REALTIME THREADS)*/ struct pthread_spinlock { - int lock; + int lock; }; typedef struct pthread_spinlock pthread_spinlock_t; struct pthread_barrier { - int count; - pthread_cond_t cond; - pthread_mutex_t mutex; + int count; + pthread_cond_t cond; + pthread_mutex_t mutex; }; typedef struct pthread_barrier pthread_barrier_t; @@ -131,19 +145,19 @@ int pthread_attr_init(pthread_attr_t *attr); int pthread_system_init(void); int pthread_create (pthread_t *tid, const pthread_attr_t *attr, - void *(*start) (void *), void *arg); + void *(*start) (void *), void *arg); int pthread_detach (pthread_t thread); int pthread_join (pthread_t thread, void **value_ptr); rt_inline int pthread_equal (pthread_t t1, pthread_t t2) { - return t1 == t2; + return t1 == t2; } rt_inline pthread_t pthread_self (void) { - return rt_thread_self(); + return rt_thread_self(); } void pthread_exit (void *value_ptr); @@ -182,9 +196,9 @@ int pthread_condattr_init(pthread_condattr_t *attr); /* ADVANCED REALTIME feature in IEEE Std 1003.1, 2004 Edition */ int pthread_condattr_getclock(const pthread_condattr_t *attr, - clockid_t *clock_id); + clockid_t *clock_id); int pthread_condattr_setclock(pthread_condattr_t *attr, - clockid_t clock_id); + clockid_t clock_id); int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_destroy(pthread_cond_t *cond); @@ -192,9 +206,9 @@ int pthread_cond_broadcast(pthread_cond_t *cond); int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); -int pthread_cond_timedwait(pthread_cond_t *cond, - pthread_mutex_t * mutex, - const struct timespec *abstime); +int pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); /* pthread rwlock interface */ int pthread_rwlockattr_init (pthread_rwlockattr_t *attr); @@ -231,36 +245,39 @@ int pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, int *pshar int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared); int pthread_barrier_destroy(pthread_barrier_t *barrier); -int pthread_barrier_init(pthread_barrier_t *barrier, - const pthread_barrierattr_t *attr, unsigned count); +int pthread_barrier_init(pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned count); int pthread_barrier_wait(pthread_barrier_t *barrier); /* Signal Generation and Delivery, P1003.1b-1993, p. 63 NOTE: P1003.1c/D10, p. 34 adds sigev_notify_function and sigev_notify_attributes to the sigevent structure. */ -union sigval { - int sival_int; /* Integer signal value */ - void *sival_ptr; /* Pointer signal value */ +union sigval +{ + int sival_int; /* Integer signal value */ + void *sival_ptr; /* Pointer signal value */ }; -struct sigevent { - int sigev_notify; /* Notification type */ - int sigev_signo; /* Signal number */ - union sigval sigev_value; /* Signal value */ - void (*sigev_notify_function)( union sigval ); +struct sigevent +{ + int sigev_notify; /* Notification type */ + int sigev_signo; /* Signal number */ + union sigval sigev_value; /* Signal value */ + void (*sigev_notify_function)( union sigval ); /* Notification function */ - pthread_attr_t *sigev_notify_attributes; /* Notification Attributes */ + pthread_attr_t *sigev_notify_attributes; /* Notification Attributes */ }; /* posix clock and timer */ -#define MILLISECOND_PER_SECOND 1000UL -#define MICROSECOND_PER_SECOND 1000000UL -#define NANOSECOND_PER_SECOND 1000000000UL +#define MILLISECOND_PER_SECOND 1000UL +#define MICROSECOND_PER_SECOND 1000000UL +#define NANOSECOND_PER_SECOND 1000000000UL -#define MILLISECOND_PER_TICK (MILLISECOND_PER_SECOND / RT_TICK_PER_SECOND) -#define MICROSECOND_PER_TICK (MICROSECOND_PER_SECOND / RT_TICK_PER_SECOND) -#define NANOSECOND_PER_TICK (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND) +#define MILLISECOND_PER_TICK (MILLISECOND_PER_SECOND / RT_TICK_PER_SECOND) +#define MICROSECOND_PER_TICK (MICROSECOND_PER_SECOND / RT_TICK_PER_SECOND) +#define NANOSECOND_PER_TICK (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND) #ifndef CLOCK_REALTIME #define CLOCK_REALTIME 0 diff --git a/components/pthreads/pthread_attr.c b/components/pthreads/pthread_attr.c index c2fe4a85b9..9b84935a83 100644 --- a/components/pthreads/pthread_attr.c +++ b/components/pthreads/pthread_attr.c @@ -1,162 +1,202 @@ +/* + * File : pthread_attr.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-10-26 Bernard the first version + */ + #include #include "pthread.h" #include "sched.h" #include -#define DEFAULT_STACK_SIZE 2048 -#define DEFAULT_PRIORITY (RT_THREAD_PRIORITY_MAX/2 + RT_THREAD_PRIORITY_MAX/4) +#define DEFAULT_STACK_SIZE 2048 +#define DEFAULT_PRIORITY (RT_THREAD_PRIORITY_MAX/2 + RT_THREAD_PRIORITY_MAX/4) const pthread_attr_t pthread_default_attr = { - 0, /* stack base */ - DEFAULT_STACK_SIZE, /* stack size */ - DEFAULT_PRIORITY, /* priority */ - PTHREAD_CREATE_JOINABLE, /* detach state */ - SCHED_FIFO, /* scheduler policy */ - PTHREAD_INHERIT_SCHED /* Inherit parent prio/policy */ + 0, /* stack base */ + DEFAULT_STACK_SIZE, /* stack size */ + DEFAULT_PRIORITY, /* priority */ + PTHREAD_CREATE_JOINABLE, /* detach state */ + SCHED_FIFO, /* scheduler policy */ + PTHREAD_INHERIT_SCHED /* Inherit parent prio/policy */ }; int pthread_attr_init(pthread_attr_t *attr) { - RT_ASSERT(attr != RT_NULL); + RT_ASSERT(attr != RT_NULL); - *attr = pthread_default_attr; + *attr = pthread_default_attr; - return 0; + return 0; } RTM_EXPORT(pthread_attr_init); int pthread_attr_destroy(pthread_attr_t *attr) { - RT_ASSERT(attr != RT_NULL); + RT_ASSERT(attr != RT_NULL); - memset(attr, 0, sizeof(pthread_attr_t)); - return 0; + memset(attr, 0, sizeof(pthread_attr_t)); + + return 0; } RTM_EXPORT(pthread_attr_destroy); -int pthread_attr_setdetachstate(pthread_attr_t * attr, int state) +int pthread_attr_setdetachstate(pthread_attr_t *attr, int state) { - RT_ASSERT(attr != RT_NULL); + RT_ASSERT(attr != RT_NULL); - if (state != PTHREAD_CREATE_JOINABLE && state != PTHREAD_CREATE_DETACHED) - return EINVAL; + if (state != PTHREAD_CREATE_JOINABLE && state != PTHREAD_CREATE_DETACHED) + return EINVAL; - attr->detachstate = state; - return 0; + attr->detachstate = state; + + return 0; } RTM_EXPORT(pthread_attr_setdetachstate); -int pthread_attr_getdetachstate(pthread_attr_t const * attr, int *state) +int pthread_attr_getdetachstate(pthread_attr_t const *attr, int *state) { - RT_ASSERT(attr != RT_NULL); + RT_ASSERT(attr != RT_NULL); - *state = (int)attr->detachstate; + *state = (int)attr->detachstate; - return 0; + return 0; } RTM_EXPORT(pthread_attr_getdetachstate); -int pthread_attr_setschedpolicy(pthread_attr_t * attr, int policy) +int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) { - RT_ASSERT(attr != RT_NULL); + RT_ASSERT(attr != RT_NULL); - attr->policy = policy; - return 0; + attr->policy = policy; + + return 0; } RTM_EXPORT(pthread_attr_setschedpolicy); int pthread_attr_getschedpolicy(pthread_attr_t const *attr, int *policy) { - RT_ASSERT(attr != RT_NULL); + RT_ASSERT(attr != RT_NULL); - *policy = (int)attr->policy; - return 0; + *policy = (int)attr->policy; + + return 0; } RTM_EXPORT(pthread_attr_getschedpolicy); -int pthread_attr_setschedparam(pthread_attr_t *attr, struct sched_param const *param) +int pthread_attr_setschedparam(pthread_attr_t *attr, + struct sched_param const *param) { - RT_ASSERT(attr != RT_NULL); - RT_ASSERT(param != RT_NULL); + RT_ASSERT(attr != RT_NULL); + RT_ASSERT(param != RT_NULL); - attr->priority = param->sched_priority; - return 0; + attr->priority = param->sched_priority; + + return 0; } RTM_EXPORT(pthread_attr_setschedparam); -int pthread_attr_getschedparam(pthread_attr_t const *attr, struct sched_param *param) +int pthread_attr_getschedparam(pthread_attr_t const *attr, + struct sched_param *param) { - RT_ASSERT(attr != RT_NULL); - RT_ASSERT(param != RT_NULL); + RT_ASSERT(attr != RT_NULL); + RT_ASSERT(param != RT_NULL); - param->sched_priority = attr->priority; - return 0; + param->sched_priority = attr->priority; + + return 0; } RTM_EXPORT(pthread_attr_getschedparam); -int pthread_attr_setstacksize(pthread_attr_t * attr, size_t stack_size) +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size) { - RT_ASSERT(attr != RT_NULL); + RT_ASSERT(attr != RT_NULL); - attr->stack_size = stack_size; - return 0; + attr->stack_size = stack_size; + + return 0; } RTM_EXPORT(pthread_attr_setstacksize); -int pthread_attr_getstacksize(pthread_attr_t const * attr, size_t *stack_size) +int pthread_attr_getstacksize(pthread_attr_t const *attr, size_t *stack_size) { - RT_ASSERT(attr != RT_NULL); + RT_ASSERT(attr != RT_NULL); - *stack_size = attr->stack_size; - return 0; + *stack_size = attr->stack_size; + + return 0; } RTM_EXPORT(pthread_attr_getstacksize); -int pthread_attr_setstackaddr(pthread_attr_t * attr, void * stack_addr) +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack_addr) { - RT_ASSERT(attr != RT_NULL); - return ENOTSUP; + RT_ASSERT(attr != RT_NULL); + + return ENOTSUP; } RTM_EXPORT(pthread_attr_setstackaddr); -int pthread_attr_getstackaddr(pthread_attr_t const * attr, void ** stack_addr) +int pthread_attr_getstackaddr(pthread_attr_t const *attr, void **stack_addr) { - RT_ASSERT(attr != RT_NULL); - return ENOTSUP; + RT_ASSERT(attr != RT_NULL); + + return ENOTSUP; } RTM_EXPORT(pthread_attr_getstackaddr); -int pthread_attr_setstack(pthread_attr_t * attr, void *stack_base, size_t stack_size) +int pthread_attr_setstack(pthread_attr_t *attr, + void *stack_base, + size_t stack_size) { - RT_ASSERT(attr != RT_NULL); + RT_ASSERT(attr != RT_NULL); - attr->stack_base = stack_base; - attr->stack_size = RT_ALIGN_DOWN(stack_size, RT_ALIGN_SIZE); + attr->stack_base = stack_base; + attr->stack_size = RT_ALIGN_DOWN(stack_size, RT_ALIGN_SIZE); - return 0; + return 0; } RTM_EXPORT(pthread_attr_setstack); -int pthread_attr_getstack(pthread_attr_t const * attr, void **stack_base, size_t *stack_size) +int pthread_attr_getstack(pthread_attr_t const *attr, + void **stack_base, + size_t *stack_size) { - RT_ASSERT(attr != RT_NULL); + RT_ASSERT(attr != RT_NULL); - *stack_base = attr->stack_base; - *stack_size = attr->stack_size; + *stack_base = attr->stack_base; + *stack_size = attr->stack_size; - return 0; + return 0; } RTM_EXPORT(pthread_attr_getstack); -int pthread_attr_setguardsize(pthread_attr_t * attr, size_t guard_size) +int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guard_size) { - return ENOTSUP; + return ENOTSUP; } -int pthread_attr_getguardsize(pthread_attr_t const * attr, size_t *guard_size) +int pthread_attr_getguardsize(pthread_attr_t const *attr, size_t *guard_size) { - return ENOTSUP; + return ENOTSUP; } RTM_EXPORT(pthread_attr_getguardsize); diff --git a/components/pthreads/pthread_barrier.c b/components/pthreads/pthread_barrier.c index b6f4092e8b..c39a45586e 100644 --- a/components/pthreads/pthread_barrier.c +++ b/components/pthreads/pthread_barrier.c @@ -1,85 +1,124 @@ +/* + * File : pthread_barrier.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-10-26 Bernard the first version + */ + #include int pthread_barrierattr_destroy(pthread_barrierattr_t *attr) { - if (!attr) return EINVAL; - return 0; + if (!attr) + return EINVAL; + + return 0; } RTM_EXPORT(pthread_barrierattr_destroy); int pthread_barrierattr_init(pthread_barrierattr_t *attr) { - if (!attr) return EINVAL; - *attr = PTHREAD_PROCESS_PRIVATE; + if (!attr) + return EINVAL; + *attr = PTHREAD_PROCESS_PRIVATE; - return 0; + return 0; } RTM_EXPORT(pthread_barrierattr_init); -int pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, int *pshared) +int pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, + int *pshared) { - if (!attr) return EINVAL; - *pshared = (int)*attr; + if (!attr) + return EINVAL; + *pshared = (int)*attr; - return 0; + return 0; } RTM_EXPORT(pthread_barrierattr_getpshared); int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) { - if (!attr) return EINVAL; - if (pshared == PTHREAD_PROCESS_PRIVATE) attr = PTHREAD_PROCESS_PRIVATE; + if (!attr) + return EINVAL; + if (pshared == PTHREAD_PROCESS_PRIVATE) + attr = PTHREAD_PROCESS_PRIVATE; - return EINVAL; + return EINVAL; } RTM_EXPORT(pthread_barrierattr_setpshared); int pthread_barrier_destroy(pthread_barrier_t *barrier) { - rt_err_t result; + rt_err_t result; - if (!barrier) return EINVAL; + if (!barrier) + return EINVAL; - result = pthread_cond_destroy(&(barrier->cond)); + result = pthread_cond_destroy(&(barrier->cond)); - return result; + return result; } RTM_EXPORT(pthread_barrier_destroy); -int pthread_barrier_init(pthread_barrier_t *barrier, - const pthread_barrierattr_t *attr, unsigned count) +int pthread_barrier_init(pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned count) { - if (!barrier) return EINVAL; - if (attr &&(*attr != PTHREAD_PROCESS_PRIVATE)) return EINVAL; + if (!barrier) + return EINVAL; + if (attr && (*attr != PTHREAD_PROCESS_PRIVATE)) + return EINVAL; - barrier->count = count; - pthread_cond_init(&(barrier->cond), NULL); - pthread_mutex_init(&(barrier->mutex), NULL); + barrier->count = count; + pthread_cond_init(&(barrier->cond), NULL); + pthread_mutex_init(&(barrier->mutex), NULL); - return 0; + return 0; } RTM_EXPORT(pthread_barrier_init); int pthread_barrier_wait(pthread_barrier_t *barrier) { - rt_err_t result; - if (!barrier) return EINVAL; + rt_err_t result; + if (!barrier) + return EINVAL; - result = pthread_mutex_lock(&(barrier->mutex)); - if (result != 0) return EINVAL; + result = pthread_mutex_lock(&(barrier->mutex)); + if (result != 0) + return EINVAL; - if (barrier->count == 0) result = EINVAL; - else - { - barrier->count -= 1; - if (barrier->count == 0) /* broadcast condition */ - pthread_cond_broadcast(&(barrier->cond)); - else - pthread_cond_wait(&(barrier->cond), &(barrier->mutex)); - } + if (barrier->count == 0) + result = EINVAL; + else + { + barrier->count -= 1; + if (barrier->count == 0) /* broadcast condition */ + pthread_cond_broadcast(&(barrier->cond)); + else + pthread_cond_wait(&(barrier->cond), &(barrier->mutex)); + } - pthread_mutex_unlock(&(barrier->mutex)); - return result; + pthread_mutex_unlock(&(barrier->mutex)); + + return result; } RTM_EXPORT(pthread_barrier_wait); diff --git a/components/pthreads/pthread_cond.c b/components/pthreads/pthread_cond.c index 4f9dba9cd5..e5342dd775 100644 --- a/components/pthreads/pthread_cond.c +++ b/components/pthreads/pthread_cond.c @@ -1,193 +1,239 @@ +/* + * File : pthread_cond.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-10-26 Bernard the first version + */ + #include #include "pthread_internal.h" int pthread_condattr_destroy(pthread_condattr_t *attr) { - if (!attr) return EINVAL; + if (!attr) + return EINVAL; - return 0; + return 0; } RTM_EXPORT(pthread_condattr_destroy); int pthread_condattr_init(pthread_condattr_t *attr) { - if (!attr) return EINVAL; - *attr = PTHREAD_PROCESS_PRIVATE; + if (!attr) + return EINVAL; + *attr = PTHREAD_PROCESS_PRIVATE; - return 0; + return 0; } RTM_EXPORT(pthread_condattr_init); int pthread_condattr_getclock(const pthread_condattr_t *attr, - clockid_t *clock_id) + clockid_t *clock_id) { - return 0; + return 0; } RTM_EXPORT(pthread_condattr_getclock); int pthread_condattr_setclock(pthread_condattr_t *attr, - clockid_t clock_id) + clockid_t clock_id) { - return 0; + return 0; } RTM_EXPORT(pthread_condattr_setclock); int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared) { - if (!attr || !pshared) return EINVAL; + if (!attr || !pshared) + return EINVAL; - *pshared = PTHREAD_PROCESS_PRIVATE; - return 0; + *pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; } RTM_EXPORT(pthread_condattr_getpshared); int pthread_condattr_setpshared(pthread_condattr_t*attr, int pshared) { - if ((pshared != PTHREAD_PROCESS_PRIVATE) && (pshared != PTHREAD_PROCESS_SHARED)) - return EINVAL; + if ((pshared != PTHREAD_PROCESS_PRIVATE) && + (pshared != PTHREAD_PROCESS_SHARED)) + { + return EINVAL; + } - if (pshared != PTHREAD_PROCESS_PRIVATE) - return ENOSYS; + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; - return 0; + return 0; } RTM_EXPORT(pthread_condattr_setpshared); int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { - rt_err_t result; - char cond_name[RT_NAME_MAX]; - static rt_uint16_t cond_num = 0; + rt_err_t result; + char cond_name[RT_NAME_MAX]; + static rt_uint16_t cond_num = 0; - /* parameter check */ - if (cond == RT_NULL) return EINVAL; - if ((attr != RT_NULL) && (*attr != PTHREAD_PROCESS_PRIVATE)) return EINVAL; + /* parameter check */ + if (cond == RT_NULL) + return EINVAL; + if ((attr != RT_NULL) && (*attr != PTHREAD_PROCESS_PRIVATE)) + return EINVAL; - rt_snprintf(cond_name, sizeof(cond_name), - "cond%02d", cond_num++); + rt_snprintf(cond_name, sizeof(cond_name), "cond%02d", cond_num++); - cond->attr = *attr; - result = rt_sem_init(&cond->sem, cond_name, 0, RT_IPC_FLAG_FIFO); - if (result != RT_EOK) return EINVAL; + cond->attr = *attr; + result = rt_sem_init(&cond->sem, cond_name, 0, RT_IPC_FLAG_FIFO); + if (result != RT_EOK) + return EINVAL; - /* detach the object from system object container */ - rt_object_detach(&(cond->sem.parent.parent)); + /* detach the object from system object container */ + rt_object_detach(&(cond->sem.parent.parent)); - return 0; + return 0; } RTM_EXPORT(pthread_cond_init); int pthread_cond_destroy(pthread_cond_t *cond) { - rt_err_t result; - if (cond == RT_NULL) return EINVAL; - if (cond->attr == -1) return 0; /* which is not initialized */ + rt_err_t result; + if (cond == RT_NULL) + return EINVAL; + if (cond->attr == -1) + return 0; /* which is not initialized */ - result = rt_sem_trytake(&(cond->sem)); - if (result != RT_EOK) return EBUSY; + result = rt_sem_trytake(&(cond->sem)); + if (result != RT_EOK) + return EBUSY; - /* clean condition */ - rt_memset(cond, 0, sizeof(pthread_cond_t)); - cond->attr = -1; + /* clean condition */ + rt_memset(cond, 0, sizeof(pthread_cond_t)); + cond->attr = -1; - return 0; + return 0; } RTM_EXPORT(pthread_cond_destroy); int pthread_cond_broadcast(pthread_cond_t *cond) { - rt_err_t result; - if (cond->attr == -1) - pthread_cond_init(cond, RT_NULL); + rt_err_t result; + if (cond->attr == -1) + pthread_cond_init(cond, RT_NULL); - rt_enter_critical(); - while (1) - { - /* try to take condition semaphore */ - result = rt_sem_trytake(&(cond->sem)); - if (result == -RT_ETIMEOUT) - { - /* it's timeout, release this semaphore */ - rt_sem_release(&(cond->sem)); - } - else if (result == RT_EOK) - { - /* has taken this semaphore, release it */ - rt_sem_release(&(cond->sem)); - break; - } - else - { - rt_exit_critical(); - return EINVAL; - } - } - rt_exit_critical(); + rt_enter_critical(); + while (1) + { + /* try to take condition semaphore */ + result = rt_sem_trytake(&(cond->sem)); + if (result == -RT_ETIMEOUT) + { + /* it's timeout, release this semaphore */ + rt_sem_release(&(cond->sem)); + } + else if (result == RT_EOK) + { + /* has taken this semaphore, release it */ + rt_sem_release(&(cond->sem)); + break; + } + else + { + rt_exit_critical(); - return 0; + return EINVAL; + } + } + rt_exit_critical(); + + return 0; } RTM_EXPORT(pthread_cond_broadcast); int pthread_cond_signal(pthread_cond_t *cond) { - rt_err_t result; + rt_err_t result; - if (cond->attr == -1) - pthread_cond_init(cond, RT_NULL); + if (cond->attr == -1) + pthread_cond_init(cond, RT_NULL); - result = rt_sem_release(&(cond->sem)); - if (result == RT_EOK) return 0; + result = rt_sem_release(&(cond->sem)); + if (result == RT_EOK) + return 0; - return 0; + return 0; } RTM_EXPORT(pthread_cond_signal); -rt_err_t _pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - rt_int32_t timeout) +rt_err_t _pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + rt_int32_t timeout) { - rt_err_t result; + rt_err_t result; - if (!cond || !mutex) return -RT_ERROR; - /* check whether initialized */ - if (cond->attr == -1) pthread_cond_init(cond, RT_NULL); + if (!cond || !mutex) + return -RT_ERROR; + /* check whether initialized */ + if (cond->attr == -1) + pthread_cond_init(cond, RT_NULL); - /* The mutex was not owned by the current thread at the time of the call. */ - if (mutex->lock.owner != pthread_self()) return -RT_ERROR; - /* unlock a mutex failed */ - if (pthread_mutex_unlock(mutex) != 0) - return -RT_ERROR; + /* The mutex was not owned by the current thread at the time of the call. */ + if (mutex->lock.owner != pthread_self()) + return -RT_ERROR; + /* unlock a mutex failed */ + if (pthread_mutex_unlock(mutex) != 0) + return -RT_ERROR; - result = rt_sem_take(&(cond->sem), timeout); - /* lock mutex again */ - pthread_mutex_lock(mutex); - return result; + result = rt_sem_take(&(cond->sem), timeout); + /* lock mutex again */ + pthread_mutex_lock(mutex); + + return result; } RTM_EXPORT(_pthread_cond_timedwait); int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { - rt_err_t result; + rt_err_t result; - result = _pthread_cond_timedwait(cond, mutex, RT_WAITING_FOREVER); - if (result == RT_EOK) return 0; + result = _pthread_cond_timedwait(cond, mutex, RT_WAITING_FOREVER); + if (result == RT_EOK) + return 0; - return EINVAL; + return EINVAL; } RTM_EXPORT(pthread_cond_wait); -int pthread_cond_timedwait(pthread_cond_t *cond, - pthread_mutex_t * mutex, - const struct timespec *abstime) +int pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) { - int timeout; - rt_err_t result; + int timeout; + rt_err_t result; - timeout = clock_time_to_tick(abstime); - result = _pthread_cond_timedwait(cond, mutex, timeout); - if (result == RT_EOK) return 0; - if (result == -RT_ETIMEOUT) return ETIMEDOUT; + timeout = clock_time_to_tick(abstime); + result = _pthread_cond_timedwait(cond, mutex, timeout); + if (result == RT_EOK) + return 0; + if (result == -RT_ETIMEOUT) + return ETIMEDOUT; - return EINVAL; + return EINVAL; } RTM_EXPORT(pthread_cond_timedwait); diff --git a/components/pthreads/pthread_internal.h b/components/pthreads/pthread_internal.h index 1fec536fe9..0a21fccb13 100644 --- a/components/pthreads/pthread_internal.h +++ b/components/pthreads/pthread_internal.h @@ -1,3 +1,27 @@ +/* + * File : pthread_internal.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-10-26 Bernard the first version + */ + #ifndef __PTHREAD_INTERNAL_H__ #define __PTHREAD_INTERNAL_H__ @@ -6,56 +30,56 @@ struct _pthread_cleanup { - void (*cleanup_func)(void* parameter); - void* parameter; + void (*cleanup_func)(void *parameter); + void *parameter; - struct _pthread_cleanup* next; + struct _pthread_cleanup *next; }; typedef struct _pthread_cleanup _pthread_cleanup_t; struct _pthread_key_data { - int is_used; - void (*destructor)(void* parameter); + int is_used; + void (*destructor)(void *parameter); }; typedef struct _pthread_key_data _pthread_key_data_t; -#define PTHREAD_MAGIC 0x70746873 +#define PTHREAD_MAGIC 0x70746873 struct _pthread_data { - rt_uint32_t magic; - pthread_attr_t attr; - rt_thread_t tid; + rt_uint32_t magic; + pthread_attr_t attr; + rt_thread_t tid; - void* (*thread_entry)(void* parameter); - void* thread_parameter; + void* (*thread_entry)(void *parameter); + void *thread_parameter; - /* return value */ - void* return_value; + /* return value */ + void *return_value; - /* semaphore for joinable thread */ - rt_sem_t joinable_sem; + /* 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; + /* 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 */ + _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_inline _pthread_data_t *_pthread_get_data(pthread_t thread) { - _pthread_data_t* ptd; - RT_ASSERT(thread != RT_NULL); + _pthread_data_t *ptd; + RT_ASSERT(thread != RT_NULL); - ptd = (_pthread_data_t*)thread->user_data; - RT_ASSERT(ptd != RT_NULL); - RT_ASSERT(ptd->magic == PTHREAD_MAGIC); + ptd = (_pthread_data_t *)thread->user_data; + RT_ASSERT(ptd != RT_NULL); + RT_ASSERT(ptd->magic == PTHREAD_MAGIC); - return ptd; + return ptd; } int clock_time_to_tick(const struct timespec *time); diff --git a/components/pthreads/pthread_mutex.c b/components/pthreads/pthread_mutex.c index 34ff91e451..40fd870e81 100644 --- a/components/pthreads/pthread_mutex.c +++ b/components/pthreads/pthread_mutex.c @@ -1,3 +1,27 @@ +/* + * File : pthread_mutex.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-10-26 Bernard the first version + */ + #include #include "pthread.h" @@ -8,51 +32,54 @@ const pthread_mutexattr_t pthread_default_mutexattr = PTHREAD_PROCESS_PRIVATE; int pthread_mutexattr_init(pthread_mutexattr_t *attr) { - if (attr) - { - *attr = pthread_default_mutexattr; - return 0; - } + if (attr) + { + *attr = pthread_default_mutexattr; - return EINVAL; + return 0; + } + + return EINVAL; } RTM_EXPORT(pthread_mutexattr_init); int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) { - if (attr) - { - *attr = -1; - return 0; - } + if (attr) + { + *attr = -1; - return EINVAL; + return 0; + } + + return EINVAL; } RTM_EXPORT(pthread_mutexattr_destroy); int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) { - if (attr && type) - { + if (attr && type) + { int atype = (*attr & MUTEXATTR_TYPE_MASK); - if (atype >= PTHREAD_MUTEX_NORMAL && atype <= PTHREAD_MUTEX_ERRORCHECK) - { - *type = atype; - return 0; - } - } + if (atype >= PTHREAD_MUTEX_NORMAL && atype <= PTHREAD_MUTEX_ERRORCHECK) + { + *type = atype; - return EINVAL; + return 0; + } + } + + return EINVAL; } RTM_EXPORT(pthread_mutexattr_gettype); int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { - if (attr && type >= PTHREAD_MUTEX_NORMAL && - type <= PTHREAD_MUTEX_ERRORCHECK ) - { + if (attr && type >= PTHREAD_MUTEX_NORMAL && type <= PTHREAD_MUTEX_ERRORCHECK) + { *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type; + return 0; } @@ -60,12 +87,13 @@ int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) } RTM_EXPORT(pthread_mutexattr_settype); -int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) +int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) { - if (!attr) return EINVAL; + if (!attr) + return EINVAL; switch (pshared) - { + { case PTHREAD_PROCESS_PRIVATE: *attr &= ~MUTEXATTR_SHARED_MASK; return 0; @@ -81,7 +109,8 @@ RTM_EXPORT(pthread_mutexattr_setpshared); int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared) { - if (!attr || !pshared) return EINVAL; + if (!attr || !pshared) + return EINVAL; *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE; @@ -91,116 +120,132 @@ RTM_EXPORT(pthread_mutexattr_getpshared); int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { - rt_err_t result; - char name[RT_NAME_MAX]; - static rt_uint16_t pthread_mutex_number = 0; + rt_err_t result; + char name[RT_NAME_MAX]; + static rt_uint16_t pthread_mutex_number = 0; - if (!mutex) return EINVAL; + if (!mutex) + return EINVAL; - /* build mutex name */ - rt_snprintf(name, sizeof(name), "pmtx%02d", pthread_mutex_number ++); - if (attr == RT_NULL) mutex->attr = pthread_default_mutexattr; - else mutex->attr = *attr; + /* build mutex name */ + rt_snprintf(name, sizeof(name), "pmtx%02d", pthread_mutex_number ++); + if (attr == RT_NULL) + mutex->attr = pthread_default_mutexattr; + else + mutex->attr = *attr; - /* init mutex lock */ - result = rt_mutex_init(&(mutex->lock), name, RT_IPC_FLAG_FIFO); - if (result != RT_EOK) return EINVAL; + /* init mutex lock */ + result = rt_mutex_init(&(mutex->lock), name, RT_IPC_FLAG_FIFO); + if (result != RT_EOK) + return EINVAL; - /* detach the object from system object container */ - rt_object_detach(&(mutex->lock.parent.parent)); + /* detach the object from system object container */ + rt_object_detach(&(mutex->lock.parent.parent)); - return 0; + return 0; } RTM_EXPORT(pthread_mutex_init); int pthread_mutex_destroy(pthread_mutex_t *mutex) { - if (!mutex || mutex->attr == -1) return EINVAL; + if (!mutex || mutex->attr == -1) + return EINVAL; - /* it's busy */ - if (mutex->lock.owner != RT_NULL) return EBUSY; + /* it's busy */ + if (mutex->lock.owner != RT_NULL) + return EBUSY; - rt_memset(mutex, 0, sizeof(pthread_mutex_t)); - mutex->attr = -1; + rt_memset(mutex, 0, sizeof(pthread_mutex_t)); + mutex->attr = -1; - return 0; + return 0; } RTM_EXPORT(pthread_mutex_destroy); int pthread_mutex_lock(pthread_mutex_t *mutex) { - int mtype; - rt_err_t result; + int mtype; + rt_err_t result; - if (!mutex) return EINVAL; + if (!mutex) + return EINVAL; - if (mutex->attr == -1) - { - /* init mutex */ - pthread_mutex_init(mutex, RT_NULL); - } + if (mutex->attr == -1) + { + /* init mutex */ + pthread_mutex_init(mutex, RT_NULL); + } - mtype = mutex->attr & MUTEXATTR_TYPE_MASK; - rt_enter_critical(); - if (mutex->lock.owner == rt_thread_self() && mtype != PTHREAD_MUTEX_RECURSIVE) - { - rt_exit_critical(); - return EDEADLK; - } - rt_exit_critical(); + mtype = mutex->attr & MUTEXATTR_TYPE_MASK; + rt_enter_critical(); + if (mutex->lock.owner == rt_thread_self() && + mtype != PTHREAD_MUTEX_RECURSIVE) + { + rt_exit_critical(); - result = rt_mutex_take(&(mutex->lock), RT_WAITING_FOREVER); - if (result == RT_EOK) return 0; + return EDEADLK; + } + rt_exit_critical(); - return EINVAL; + result = rt_mutex_take(&(mutex->lock), RT_WAITING_FOREVER); + if (result == RT_EOK) + return 0; + + return EINVAL; } RTM_EXPORT(pthread_mutex_lock); int pthread_mutex_unlock(pthread_mutex_t *mutex) { - rt_err_t result; + rt_err_t result; - if (!mutex) return EINVAL; - if (mutex->attr == -1) - { - /* init mutex */ - pthread_mutex_init(mutex, RT_NULL); - } + if (!mutex) + return EINVAL; + if (mutex->attr == -1) + { + /* init mutex */ + pthread_mutex_init(mutex, RT_NULL); + } - if (mutex->lock.owner != rt_thread_self()) - { - int mtype; - mtype = mutex->attr & MUTEXATTR_TYPE_MASK; + if (mutex->lock.owner != rt_thread_self()) + { + int mtype; + mtype = mutex->attr & MUTEXATTR_TYPE_MASK; - /* error check, return EPERM */ - if (mtype == PTHREAD_MUTEX_ERRORCHECK) return EPERM; + /* error check, return EPERM */ + if (mtype == PTHREAD_MUTEX_ERRORCHECK) + return EPERM; - /* no thread waiting on this mutex */ - if (mutex->lock.owner == RT_NULL) return 0; - } + /* no thread waiting on this mutex */ + if (mutex->lock.owner == RT_NULL) + return 0; + } - result = rt_mutex_release(&(mutex->lock)); - if (result == RT_EOK) return 0; - - return EINVAL; + result = rt_mutex_release(&(mutex->lock)); + if (result == RT_EOK) + return 0; + + return EINVAL; } RTM_EXPORT(pthread_mutex_unlock); int pthread_mutex_trylock(pthread_mutex_t *mutex) { - rt_err_t result; + rt_err_t result; - if (!mutex) return EINVAL; - if (mutex->attr == -1) - { - /* init mutex */ - pthread_mutex_init(mutex, RT_NULL); - } + if (!mutex) + return EINVAL; + if (mutex->attr == -1) + { + /* init mutex */ + pthread_mutex_init(mutex, RT_NULL); + } - result = rt_mutex_take(&(mutex->lock), 0); - if (result == RT_EOK) return 0; + result = rt_mutex_take(&(mutex->lock), 0); + if (result == RT_EOK) + return 0; - return EBUSY; + return EBUSY; } RTM_EXPORT(pthread_mutex_trylock); diff --git a/components/pthreads/pthread_rwlock.c b/components/pthreads/pthread_rwlock.c index b694cb09ff..968c82b89f 100644 --- a/components/pthreads/pthread_rwlock.c +++ b/components/pthreads/pthread_rwlock.c @@ -1,287 +1,354 @@ +/* + * File : pthread_rwlock.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-10-26 Bernard the first version + */ + #include -int pthread_rwlockattr_init (pthread_rwlockattr_t * attr) +int pthread_rwlockattr_init(pthread_rwlockattr_t *attr) { - if (!attr) return EINVAL; - *attr = PTHREAD_PROCESS_PRIVATE; + if (!attr) + return EINVAL; + *attr = PTHREAD_PROCESS_PRIVATE; - return 0; + return 0; } RTM_EXPORT(pthread_rwlockattr_init); -int pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr) +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr) { - if (!attr) return EINVAL; + if (!attr) + return EINVAL; - return 0; + return 0; } RTM_EXPORT(pthread_rwlockattr_destroy); -int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, int *pshared) +int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, + int *pshared) { - if (!attr || !pshared) return EINVAL; + if (!attr || !pshared) + return EINVAL; - *pshared = PTHREAD_PROCESS_PRIVATE; - return 0; + *pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; } RTM_EXPORT(pthread_rwlockattr_getpshared); -int pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, int pshared) +int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared) { - if (!attr || pshared != PTHREAD_PROCESS_PRIVATE) return EINVAL; + if (!attr || pshared != PTHREAD_PROCESS_PRIVATE) + return EINVAL; - return 0; + return 0; } RTM_EXPORT(pthread_rwlockattr_setpshared); -int pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t * attr) +int pthread_rwlock_init(pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) { - if (!rwlock) return EINVAL; + if (!rwlock) + return EINVAL; - rwlock->attr = PTHREAD_PROCESS_PRIVATE; - pthread_mutex_init(&(rwlock->rw_mutex), NULL); - pthread_cond_init(&(rwlock->rw_condreaders), NULL); - pthread_cond_init(&(rwlock->rw_condwriters), NULL); - - rwlock->rw_nwaitwriters = 0; - rwlock->rw_nwaitreaders = 0; - rwlock->rw_refcount = 0; + rwlock->attr = PTHREAD_PROCESS_PRIVATE; + pthread_mutex_init(&(rwlock->rw_mutex), NULL); + pthread_cond_init(&(rwlock->rw_condreaders), NULL); + pthread_cond_init(&(rwlock->rw_condwriters), NULL); + + rwlock->rw_nwaitwriters = 0; + rwlock->rw_nwaitreaders = 0; + rwlock->rw_refcount = 0; - return 0; + return 0; } RTM_EXPORT(pthread_rwlock_init); int pthread_rwlock_destroy (pthread_rwlock_t *rwlock) { - int result; + int result; - if (!rwlock) return EINVAL; - if (rwlock->attr == -1) return 0; /* rwlock is not initialized */ + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + return 0; /* rwlock is not initialized */ - if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) - return(result); + if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) + return(result); - if (rwlock->rw_refcount != 0 || - rwlock->rw_nwaitreaders != 0 || rwlock->rw_nwaitwriters != 0) - { - result = EBUSY; - return(EBUSY); - } - else - { - /* check whether busy */ - result = rt_sem_trytake(&(rwlock->rw_condreaders.sem)); - if (result == RT_EOK) - { - result = rt_sem_trytake(&(rwlock->rw_condwriters.sem)); - if (result == RT_EOK) - { - rt_sem_release(&(rwlock->rw_condreaders.sem)); - rt_sem_release(&(rwlock->rw_condwriters.sem)); + if (rwlock->rw_refcount != 0 || + rwlock->rw_nwaitreaders != 0 || + rwlock->rw_nwaitwriters != 0) + { + result = EBUSY; - pthread_cond_destroy(&rwlock->rw_condreaders); - pthread_cond_destroy(&rwlock->rw_condwriters); - } - else - { - rt_sem_release(&(rwlock->rw_condreaders.sem)); - result = EBUSY; - } - } - else result = EBUSY; - } + return(EBUSY); + } + else + { + /* check whether busy */ + result = rt_sem_trytake(&(rwlock->rw_condreaders.sem)); + if (result == RT_EOK) + { + result = rt_sem_trytake(&(rwlock->rw_condwriters.sem)); + if (result == RT_EOK) + { + rt_sem_release(&(rwlock->rw_condreaders.sem)); + rt_sem_release(&(rwlock->rw_condwriters.sem)); - pthread_mutex_unlock(&rwlock->rw_mutex); - if (result == 0) pthread_mutex_destroy(&rwlock->rw_mutex); - - return result; + pthread_cond_destroy(&rwlock->rw_condreaders); + pthread_cond_destroy(&rwlock->rw_condwriters); + } + else + { + rt_sem_release(&(rwlock->rw_condreaders.sem)); + result = EBUSY; + } + } + else + result = EBUSY; + } + + pthread_mutex_unlock(&rwlock->rw_mutex); + if (result == 0) + pthread_mutex_destroy(&rwlock->rw_mutex); + + return result; } RTM_EXPORT(pthread_rwlock_destroy); -int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) +int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) { - int result; + int result; - if (!rwlock) return EINVAL; - if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL); + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); - if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) - return(result); + if ((result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) + return(result); - /* give preference to waiting writers */ - while (rwlock->rw_refcount < 0 || rwlock->rw_nwaitwriters > 0) - { - rwlock->rw_nwaitreaders++; - /* rw_mutex will be released when waiting for rw_condreaders */ - result = pthread_cond_wait(&rwlock->rw_condreaders, &rwlock->rw_mutex); - /* rw_mutex should have been taken again when returned from waiting */ - rwlock->rw_nwaitreaders--; - if (result != 0) /* wait error */ - break; - } + /* give preference to waiting writers */ + while (rwlock->rw_refcount < 0 || rwlock->rw_nwaitwriters > 0) + { + rwlock->rw_nwaitreaders++; + /* rw_mutex will be released when waiting for rw_condreaders */ + result = pthread_cond_wait(&rwlock->rw_condreaders, &rwlock->rw_mutex); + /* rw_mutex should have been taken again when returned from waiting */ + rwlock->rw_nwaitreaders--; + if (result != 0) /* wait error */ + break; + } - /* another reader has a read lock */ - if (result == 0) rwlock->rw_refcount++; + /* another reader has a read lock */ + if (result == 0) + rwlock->rw_refcount++; - pthread_mutex_unlock(&rwlock->rw_mutex); - return (result); + pthread_mutex_unlock(&rwlock->rw_mutex); + + return (result); } RTM_EXPORT(pthread_rwlock_rdlock); -int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) +int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) { - int result; + int result; - if (!rwlock) return EINVAL; - if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL); + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); - if ((result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) - return(result); + if ((result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) + return(result); - if (rwlock->rw_refcount < 0 || rwlock->rw_nwaitwriters > 0) - result = EBUSY; /* held by a writer or waiting writers */ - else - rwlock->rw_refcount++; /* increment count of reader locks */ + if (rwlock->rw_refcount < 0 || rwlock->rw_nwaitwriters > 0) + result = EBUSY; /* held by a writer or waiting writers */ + else + rwlock->rw_refcount++; /* increment count of reader locks */ - pthread_mutex_unlock(&rwlock->rw_mutex); - return(result); + pthread_mutex_unlock(&rwlock->rw_mutex); + + return(result); } RTM_EXPORT(pthread_rwlock_tryrdlock); -int pthread_rwlock_timedrdlock (pthread_rwlock_t * rwlock, const struct timespec *abstime) +int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, + const struct timespec *abstime) { - int result; + int result; - if (!rwlock) return EINVAL; - if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL); + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); - if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) - return(result); + if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) + return(result); - /* give preference to waiting writers */ - while (rwlock->rw_refcount < 0 || rwlock->rw_nwaitwriters > 0) - { - rwlock->rw_nwaitreaders++; - /* rw_mutex will be released when waiting for rw_condreaders */ - result = pthread_cond_timedwait(&rwlock->rw_condreaders, &rwlock->rw_mutex, abstime); - /* rw_mutex should have been taken again when returned from waiting */ - rwlock->rw_nwaitreaders--; - if (result != 0) - break; - } + /* give preference to waiting writers */ + while (rwlock->rw_refcount < 0 || rwlock->rw_nwaitwriters > 0) + { + rwlock->rw_nwaitreaders++; + /* rw_mutex will be released when waiting for rw_condreaders */ + result = pthread_cond_timedwait(&rwlock->rw_condreaders, &rwlock->rw_mutex, abstime); + /* rw_mutex should have been taken again when returned from waiting */ + rwlock->rw_nwaitreaders--; + if (result != 0) + break; + } - /* another reader has a read lock */ - if (result == 0) rwlock->rw_refcount++; + /* another reader has a read lock */ + if (result == 0) + rwlock->rw_refcount++; - pthread_mutex_unlock(&rwlock->rw_mutex); - return (result); + pthread_mutex_unlock(&rwlock->rw_mutex); + + return (result); } RTM_EXPORT(pthread_rwlock_timedrdlock); -int pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, const struct timespec *abstime) +int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, + const struct timespec *abstime) { - int result; + int result; - if (!rwlock) return EINVAL; - if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL); + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); - if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) - return(result); + if ((result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) + return(result); - while (rwlock->rw_refcount != 0) - { - rwlock->rw_nwaitwriters++; - /* rw_mutex will be released when waiting for rw_condwriters */ - result = pthread_cond_timedwait(&rwlock->rw_condwriters, &rwlock->rw_mutex, abstime); - /* rw_mutex should have been taken again when returned from waiting */ - rwlock->rw_nwaitwriters--; - - if (result != 0) break; - } + while (rwlock->rw_refcount != 0) + { + rwlock->rw_nwaitwriters++; + /* rw_mutex will be released when waiting for rw_condwriters */ + result = pthread_cond_timedwait(&rwlock->rw_condwriters, &rwlock->rw_mutex, abstime); + /* rw_mutex should have been taken again when returned from waiting */ + rwlock->rw_nwaitwriters--; + + if (result != 0) + break; + } - if (result == 0) rwlock->rw_refcount = -1; + if (result == 0) + rwlock->rw_refcount = -1; - pthread_mutex_unlock(&rwlock->rw_mutex); - return(result); + pthread_mutex_unlock(&rwlock->rw_mutex); + + return(result); } RTM_EXPORT(pthread_rwlock_timedwrlock); -int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) +int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) { - int result; + int result; - if (!rwlock) return EINVAL; - if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL); + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); - if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) - return(result); + if ((result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) + return(result); - if (rwlock->rw_refcount != 0) - result = EBUSY; /* held by either writer or reader(s) */ - else - rwlock->rw_refcount = -1; /* available, indicate a writer has it */ + if (rwlock->rw_refcount != 0) + result = EBUSY; /* held by either writer or reader(s) */ + else + rwlock->rw_refcount = -1; /* available, indicate a writer has it */ - pthread_mutex_unlock(&rwlock->rw_mutex); - return(result); + pthread_mutex_unlock(&rwlock->rw_mutex); + + return(result); } RTM_EXPORT(pthread_rwlock_trywrlock); -int pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) { - int result; + int result; - if (!rwlock) return EINVAL; - if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL); + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); - if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) - return(result); + if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) + return(result); - if (rwlock->rw_refcount > 0) - rwlock->rw_refcount--; /* releasing a reader */ - else if (rwlock->rw_refcount == -1) - rwlock->rw_refcount = 0; /* releasing a writer */ + if (rwlock->rw_refcount > 0) + rwlock->rw_refcount--; /* releasing a reader */ + else if (rwlock->rw_refcount == -1) + rwlock->rw_refcount = 0; /* releasing a writer */ - /* give preference to waiting writers over waiting readers */ - if (rwlock->rw_nwaitwriters > 0) - { - if (rwlock->rw_refcount == 0) - result = pthread_cond_signal(&rwlock->rw_condwriters); - } - else if (rwlock->rw_nwaitreaders > 0) - { - result = pthread_cond_broadcast(&rwlock->rw_condreaders); - } + /* give preference to waiting writers over waiting readers */ + if (rwlock->rw_nwaitwriters > 0) + { + if (rwlock->rw_refcount == 0) + result = pthread_cond_signal(&rwlock->rw_condwriters); + } + else if (rwlock->rw_nwaitreaders > 0) + { + result = pthread_cond_broadcast(&rwlock->rw_condreaders); + } - pthread_mutex_unlock(&rwlock->rw_mutex); - return(result); + pthread_mutex_unlock(&rwlock->rw_mutex); + + return(result); } RTM_EXPORT(pthread_rwlock_unlock); -int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) +int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) { - int result; + int result; - if (!rwlock) return EINVAL; - if (rwlock->attr == -1) pthread_rwlock_init(rwlock, NULL); + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); - if ( (result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) - return(result); + if ((result = pthread_mutex_lock(&rwlock->rw_mutex)) != 0) + return(result); - while (rwlock->rw_refcount != 0) - { - rwlock->rw_nwaitwriters++; - /* rw_mutex will be released when waiting for rw_condwriters */ - result = pthread_cond_wait(&rwlock->rw_condwriters, &rwlock->rw_mutex); - /* rw_mutex should have been taken again when returned from waiting */ - rwlock->rw_nwaitwriters--; - - if (result != 0) break; - } + while (rwlock->rw_refcount != 0) + { + rwlock->rw_nwaitwriters++; + /* rw_mutex will be released when waiting for rw_condwriters */ + result = pthread_cond_wait(&rwlock->rw_condwriters, &rwlock->rw_mutex); + /* rw_mutex should have been taken again when returned from waiting */ + rwlock->rw_nwaitwriters--; + + if (result != 0) + break; + } - if (result == 0) rwlock->rw_refcount = -1; + if (result == 0) + rwlock->rw_refcount = -1; - pthread_mutex_unlock(&rwlock->rw_mutex); - return(result); + pthread_mutex_unlock(&rwlock->rw_mutex); + + return(result); } RTM_EXPORT(pthread_rwlock_wrlock); diff --git a/components/pthreads/pthread_spin.c b/components/pthreads/pthread_spin.c index 27bb0c5762..4c4320dda9 100644 --- a/components/pthreads/pthread_spin.c +++ b/components/pthreads/pthread_spin.c @@ -1,51 +1,83 @@ +/* + * File : pthread_spin.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-10-26 Bernard the first version + */ + #include int pthread_spin_init (pthread_spinlock_t *lock, int pshared) { - if (!lock) return EINVAL; + if (!lock) + return EINVAL; - lock->lock = 0; - return 0; + lock->lock = 0; + + return 0; } int pthread_spin_destroy (pthread_spinlock_t *lock) { - if (!lock) return EINVAL; + if (!lock) + return EINVAL; - return 0; + return 0; } int pthread_spin_lock (pthread_spinlock_t *lock) { - if (!lock) return EINVAL; + if (!lock) + return EINVAL; - while (!(lock->lock)) - { - lock->lock = 1; - } + while (!(lock->lock)) + { + lock->lock = 1; + } - return 0; + return 0; } int pthread_spin_trylock (pthread_spinlock_t *lock) { - if (!lock) return EINVAL; + if (!lock) + return EINVAL; - if (!(lock->lock)) - { - lock->lock = 1; - return 0; - } + if (!(lock->lock)) + { + lock->lock = 1; - return EBUSY; + return 0; + } + + return EBUSY; } int pthread_spin_unlock (pthread_spinlock_t *lock) { - if (!lock) return EINVAL; - if (!(lock->lock)) return EPERM; + if (!lock) + return EINVAL; + if (!(lock->lock)) + return EPERM; - lock->lock = 0; + lock->lock = 0; - return 0; + return 0; } diff --git a/components/pthreads/pthread_tls.c b/components/pthreads/pthread_tls.c index c610ffc617..d689f31e47 100644 --- a/components/pthreads/pthread_tls.c +++ b/components/pthreads/pthread_tls.c @@ -1,3 +1,27 @@ +/* + * File : pthread_tls.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-10-26 Bernard the first version + */ + #include #include "pthread_internal.h" @@ -5,82 +29,87 @@ _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX]; void pthread_key_system_init() { - rt_memset(&_thread_keys[0], 0, sizeof(_thread_keys)); + rt_memset(&_thread_keys[0], 0, sizeof(_thread_keys)); } void *pthread_getspecific(pthread_key_t key) { - struct _pthread_data* ptd; + struct _pthread_data* ptd; - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != NULL); + ptd = _pthread_get_data(rt_thread_self()); + RT_ASSERT(ptd != NULL); - if (ptd->tls == NULL) return NULL; + if (ptd->tls == NULL) + return NULL; - if ((key < PTHREAD_KEY_MAX) && (_thread_keys[key].is_used)) - return ptd->tls[key]; + if ((key < PTHREAD_KEY_MAX) && (_thread_keys[key].is_used)) + return ptd->tls[key]; - return NULL; + return NULL; } RTM_EXPORT(pthread_getspecific); int pthread_setspecific(pthread_key_t key, const void *value) { - struct _pthread_data* ptd; + struct _pthread_data* ptd; - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != NULL); + ptd = _pthread_get_data(rt_thread_self()); + RT_ASSERT(ptd != NULL); - /* check tls area */ - if (ptd->tls == NULL) - { - ptd->tls = (void**)rt_malloc(sizeof(void*) * PTHREAD_KEY_MAX); - } + /* check tls area */ + if (ptd->tls == NULL) + { + ptd->tls = (void**)rt_malloc(sizeof(void*) * PTHREAD_KEY_MAX); + } - if ((key < PTHREAD_KEY_MAX) && _thread_keys[key].is_used) - { - ptd->tls[key] = (void *)value; - return 0; - } + if ((key < PTHREAD_KEY_MAX) && _thread_keys[key].is_used) + { + ptd->tls[key] = (void *)value; - return EINVAL; + return 0; + } + + return EINVAL; } RTM_EXPORT(pthread_setspecific); int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) { - rt_uint32_t index; + 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; + 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; + *key = index; - rt_exit_critical(); - return 0; - } - } + rt_exit_critical(); - rt_exit_critical(); - return EAGAIN; + return 0; + } + } + + rt_exit_critical(); + + return EAGAIN; } RTM_EXPORT(pthread_key_create); int pthread_key_delete(pthread_key_t key) { - if (key >= PTHREAD_KEY_MAX) return EINVAL; + if (key >= PTHREAD_KEY_MAX) + return EINVAL; - rt_enter_critical(); - _thread_keys[key].is_used = 0; - _thread_keys[key].destructor = 0; - rt_exit_critical(); + rt_enter_critical(); + _thread_keys[key].is_used = 0; + _thread_keys[key].destructor = 0; + rt_exit_critical(); - return 0; + return 0; } RTM_EXPORT(pthread_key_delete); diff --git a/components/pthreads/sched.c b/components/pthreads/sched.c index 0ae0253103..83810cd8aa 100644 --- a/components/pthreads/sched.c +++ b/components/pthreads/sched.c @@ -1,32 +1,56 @@ +/* + * File : sched.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + #include int sched_yield(void) { - rt_thread_yield(); - return 0; + rt_thread_yield(); + + return 0; } RTM_EXPORT(sched_yield); int sched_get_priority_min(int policy) { - if (policy != SCHED_FIFO && policy != SCHED_RR) - return EINVAL; + if (policy != SCHED_FIFO && policy != SCHED_RR) + return EINVAL; - return 0; + return 0; } RTM_EXPORT(sched_get_priority_min); int sched_get_priority_max(int policy) { - if (policy != SCHED_FIFO && policy != SCHED_RR) - return EINVAL; + if (policy != SCHED_FIFO && policy != SCHED_RR) + return EINVAL; - return RT_THREAD_PRIORITY_MAX - 1; + return RT_THREAD_PRIORITY_MAX - 1; } RTM_EXPORT(sched_get_priority_max); int sched_setscheduler(pid_t pid, int policy) { - return ENOTSUP; + return ENOTSUP; } RTM_EXPORT(sched_setscheduler); diff --git a/components/pthreads/sched.h b/components/pthreads/sched.h index 015a753f8f..173f3eb2de 100644 --- a/components/pthreads/sched.h +++ b/components/pthreads/sched.h @@ -1,3 +1,26 @@ +/* + * File : sched.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + */ + #ifndef __SCHED_H__ #define __SCHED_H__ @@ -7,16 +30,16 @@ /* Thread scheduling policies */ enum { - SCHED_OTHER = 0, - SCHED_FIFO, - SCHED_RR, - SCHED_MIN = SCHED_OTHER, - SCHED_MAX = SCHED_RR + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR }; struct sched_param { - int sched_priority; + int sched_priority; }; #ifdef __cplusplus diff --git a/components/pthreads/semaphore.c b/components/pthreads/semaphore.c index 23a73ed093..a1bf42e899 100644 --- a/components/pthreads/semaphore.c +++ b/components/pthreads/semaphore.c @@ -1,85 +1,111 @@ +/* + * File : semaphore.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-10-26 Bernard the first version + */ + #include #include "semaphore.h" #include "pthread_internal.h" -static sem_t* posix_sem_list = RT_NULL; +static sem_t *posix_sem_list = RT_NULL; static struct rt_semaphore posix_sem_lock; void posix_sem_system_init() { - rt_sem_init(&posix_sem_lock, "psem", 1, RT_IPC_FLAG_FIFO); + rt_sem_init(&posix_sem_lock, "psem", 1, RT_IPC_FLAG_FIFO); } rt_inline void posix_sem_insert(sem_t *psem) { - psem->next = posix_sem_list; - posix_sem_list = psem; + psem->next = posix_sem_list; + posix_sem_list = psem; } static void posix_sem_delete(sem_t *psem) { - sem_t *iter; - if (posix_sem_list == psem) - { - posix_sem_list = psem->next; + sem_t *iter; + if (posix_sem_list == psem) + { + posix_sem_list = psem->next; - rt_sem_delete(psem->sem); - rt_free(psem); + rt_sem_delete(psem->sem); + rt_free(psem); - return; - } - for (iter = posix_sem_list; iter->next != RT_NULL; iter = iter->next) - { - if (iter->next == psem) - { - /* delete this mq */ - if (psem->next != RT_NULL) - iter->next = psem->next; - else - iter->next = RT_NULL; + return; + } + for (iter = posix_sem_list; iter->next != RT_NULL; iter = iter->next) + { + if (iter->next == psem) + { + /* delete this mq */ + if (psem->next != RT_NULL) + iter->next = psem->next; + else + iter->next = RT_NULL; - /* delete RT-Thread mqueue */ - rt_sem_delete(psem->sem); - rt_free(psem); - return ; - } - } + /* delete RT-Thread mqueue */ + rt_sem_delete(psem->sem); + rt_free(psem); + + return ; + } + } } static sem_t *posix_sem_find(const char* name) { - sem_t *iter; - rt_object_t object; + sem_t *iter; + rt_object_t object; - for (iter = posix_sem_list; iter != RT_NULL; iter = iter->next) - { - object = (rt_object_t)&(iter->sem); + for (iter = posix_sem_list; iter != RT_NULL; iter = iter->next) + { + object = (rt_object_t)&(iter->sem); - if (strncmp(object->name, name, RT_NAME_MAX) == 0) - { - return iter; - } - } - - return RT_NULL; + if (strncmp(object->name, name, RT_NAME_MAX) == 0) + { + return iter; + } + } + + return RT_NULL; } int sem_close(sem_t *sem) { - if (sem == RT_NULL) - { - rt_set_errno(EINVAL); - return -1; - } + if (sem == RT_NULL) + { + rt_set_errno(EINVAL); + + return -1; + } /* lock posix semaphore list */ rt_sem_take(&posix_sem_lock, RT_WAITING_FOREVER); sem->refcount --; if (sem->refcount == 0) { - /* delete from posix semaphore list */ - if (sem->unlinked) - posix_sem_delete(sem); - sem = RT_NULL; + /* delete from posix semaphore list */ + if (sem->unlinked) + posix_sem_delete(sem); + sem = RT_NULL; } rt_sem_release(&posix_sem_lock); @@ -89,13 +115,14 @@ RTM_EXPORT(sem_close); int sem_destroy(sem_t *sem) { - rt_err_t result; + rt_err_t result; - if ((!sem) || !(sem->unamed)) - { - rt_set_errno(EINVAL); - return -1; - } + if ((!sem) || !(sem->unamed)) + { + rt_set_errno(EINVAL); + + return -1; + } /* lock posix semaphore list */ rt_sem_take(&posix_sem_lock, RT_WAITING_FOREVER); @@ -104,11 +131,12 @@ int sem_destroy(sem_t *sem) { rt_sem_release(&posix_sem_lock); rt_set_errno(EBUSY); - return -1; + + return -1; } /* destroy an unamed posix semaphore */ - posix_sem_delete(sem); + posix_sem_delete(sem); rt_sem_release(&posix_sem_lock); return 0; @@ -117,234 +145,256 @@ RTM_EXPORT(sem_destroy); int sem_unlink(const char *name) { - sem_t *psem; + sem_t *psem; /* lock posix semaphore list */ rt_sem_take(&posix_sem_lock, RT_WAITING_FOREVER); psem = posix_sem_find(name); if (psem != RT_NULL) { - psem->unlinked = 1; - if (psem->refcount == 0) - { - /* remove this semaphore */ - posix_sem_delete(psem); - } + psem->unlinked = 1; + if (psem->refcount == 0) + { + /* remove this semaphore */ + posix_sem_delete(psem); + } rt_sem_release(&posix_sem_lock); + return 0; } rt_sem_release(&posix_sem_lock); /* no this entry */ rt_set_errno(ENOENT); + return -1; } RTM_EXPORT(sem_unlink); int sem_getvalue(sem_t *sem, int *sval) { - if (!sem || !sval) - { - rt_set_errno(EINVAL); - return -1; - } - *sval = sem->sem->value; - return 0; + if (!sem || !sval) + { + rt_set_errno(EINVAL); + + return -1; + } + *sval = sem->sem->value; + + return 0; } RTM_EXPORT(sem_getvalue); int sem_init(sem_t *sem, int pshared, unsigned int value) { - char name[RT_NAME_MAX]; - static rt_uint16_t psem_number = 0; + char name[RT_NAME_MAX]; + static rt_uint16_t psem_number = 0; - if (sem == RT_NULL) - { - rt_set_errno(EINVAL); - return -1; - } + if (sem == RT_NULL) + { + rt_set_errno(EINVAL); - rt_snprintf(name, sizeof(name), "psem%02d", psem_number++); - sem->sem = rt_sem_create(name, value, RT_IPC_FLAG_FIFO); - if (sem == RT_NULL) - { - rt_set_errno(ENOMEM); - return -1; - } + return -1; + } - /* initialize posix semaphore */ - sem->refcount = 1; - sem->unlinked = 0; - sem->unamed = 1; + rt_snprintf(name, sizeof(name), "psem%02d", psem_number++); + sem->sem = rt_sem_create(name, value, RT_IPC_FLAG_FIFO); + if (sem == RT_NULL) + { + rt_set_errno(ENOMEM); + + return -1; + } + + /* initialize posix semaphore */ + sem->refcount = 1; + sem->unlinked = 0; + sem->unamed = 1; /* lock posix semaphore list */ rt_sem_take(&posix_sem_lock, RT_WAITING_FOREVER); posix_sem_insert(sem); rt_sem_release(&posix_sem_lock); - return 0; + return 0; } RTM_EXPORT(sem_init); sem_t *sem_open(const char *name, int oflag, ...) { - sem_t* sem; - va_list arg; - mode_t mode; - unsigned int value; + sem_t* sem; + va_list arg; + mode_t mode; + unsigned int value; sem = RT_NULL; /* lock posix semaphore list */ rt_sem_take(&posix_sem_lock, RT_WAITING_FOREVER); - if (oflag & O_CREAT) - { - va_start(arg, oflag); - mode = (mode_t) va_arg( arg, unsigned int); mode = mode; - value = va_arg( arg, unsigned int); - va_end(arg); + if (oflag & O_CREAT) + { + va_start(arg, oflag); + mode = (mode_t) va_arg( arg, unsigned int); mode = mode; + value = va_arg( arg, unsigned int); + va_end(arg); - if (oflag & O_EXCL) - { - if (posix_sem_find(name) != RT_NULL) - { - rt_set_errno(EEXIST); - goto __return; - } - } - sem = (sem_t*) rt_malloc (sizeof(struct posix_sem)); - if (sem == RT_NULL) - { - rt_set_errno(ENFILE); - goto __return; - } + if (oflag & O_EXCL) + { + if (posix_sem_find(name) != RT_NULL) + { + rt_set_errno(EEXIST); + goto __return; + } + } + sem = (sem_t*) rt_malloc (sizeof(struct posix_sem)); + if (sem == RT_NULL) + { + rt_set_errno(ENFILE); + goto __return; + } - /* create RT-Thread semaphore */ - sem->sem = rt_sem_create(name, value, RT_IPC_FLAG_FIFO); - if (sem->sem == RT_NULL) /* create failed */ - { - rt_set_errno(ENFILE); - goto __return; - } - /* initialize reference count */ - sem->refcount = 1; - sem->unlinked = 0; - sem->unamed = 0; + /* create RT-Thread semaphore */ + sem->sem = rt_sem_create(name, value, RT_IPC_FLAG_FIFO); + if (sem->sem == RT_NULL) /* create failed */ + { + rt_set_errno(ENFILE); + goto __return; + } + /* initialize reference count */ + sem->refcount = 1; + sem->unlinked = 0; + sem->unamed = 0; - /* insert semaphore to posix semaphore list */ - posix_sem_insert(sem); - } - else - { - /* find semaphore */ - sem = posix_sem_find(name); - if (sem != RT_NULL) - { - sem->refcount ++; /* increase reference count */ - } - else - { - rt_set_errno(ENOENT); - goto __return; - } - } - rt_sem_release(&posix_sem_lock); - return sem; + /* insert semaphore to posix semaphore list */ + posix_sem_insert(sem); + } + else + { + /* find semaphore */ + sem = posix_sem_find(name); + if (sem != RT_NULL) + { + sem->refcount ++; /* increase reference count */ + } + else + { + rt_set_errno(ENOENT); + goto __return; + } + } + rt_sem_release(&posix_sem_lock); + + return sem; __return: - /* release lock */ - rt_sem_release(&posix_sem_lock); + /* release lock */ + rt_sem_release(&posix_sem_lock); - /* release allocated memory */ - if (sem != RT_NULL) - { - /* delete RT-Thread semaphore */ - if (sem->sem != RT_NULL) - rt_sem_delete(sem->sem); - rt_free(sem); - } - return RT_NULL; + /* release allocated memory */ + if (sem != RT_NULL) + { + /* delete RT-Thread semaphore */ + if (sem->sem != RT_NULL) + rt_sem_delete(sem->sem); + rt_free(sem); + } + + return RT_NULL; } RTM_EXPORT(sem_open); int sem_post(sem_t *sem) { - rt_err_t result; + rt_err_t result; - if (!sem) - { - rt_set_errno(EINVAL); - return -1; - } + if (!sem) + { + rt_set_errno(EINVAL); - result = rt_sem_release(sem->sem); - if (result == RT_EOK) return 0; + return -1; + } - rt_set_errno(EINVAL); - return -1; + result = rt_sem_release(sem->sem); + if (result == RT_EOK) + return 0; + + rt_set_errno(EINVAL); + + return -1; } RTM_EXPORT(sem_post); int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout) { - rt_err_t result; - rt_int32_t tick; + rt_err_t result; + rt_int32_t tick; - if (!sem || !abs_timeout) return EINVAL; + if (!sem || !abs_timeout) + return EINVAL; - /* calculate os tick */ - tick = clock_time_to_tick(abs_timeout); - - result = rt_sem_take(sem->sem, tick); - if (result == -RT_ETIMEOUT) - { - rt_set_errno(ETIMEDOUT); - return -1; - } - if (result == RT_EOK) return 0; + /* calculate os tick */ + tick = clock_time_to_tick(abs_timeout); + + result = rt_sem_take(sem->sem, tick); + if (result == -RT_ETIMEOUT) + { + rt_set_errno(ETIMEDOUT); - rt_set_errno(EINTR); - return -1; + return -1; + } + if (result == RT_EOK) + return 0; + + rt_set_errno(EINTR); + + return -1; } RTM_EXPORT(sem_timedwait); int sem_trywait(sem_t *sem) { - rt_err_t result; + rt_err_t result; - if (!sem) - { - rt_set_errno(EINVAL); - return -1; - } + if (!sem) + { + rt_set_errno(EINVAL); - result = rt_sem_take(sem->sem, RT_WAITING_FOREVER); - if (result == -RT_ETIMEOUT) - { - rt_set_errno(EAGAIN); - return -1; - } - if (result == RT_EOK) return 0; + return -1; + } - rt_set_errno(EINTR); - return -1; + result = rt_sem_take(sem->sem, RT_WAITING_FOREVER); + if (result == -RT_ETIMEOUT) + { + rt_set_errno(EAGAIN); + + return -1; + } + if (result == RT_EOK) + return 0; + + rt_set_errno(EINTR); + + return -1; } RTM_EXPORT(sem_trywait); int sem_wait(sem_t *sem) { - rt_err_t result; + rt_err_t result; - if (!sem) - { - rt_set_errno(EINVAL); - return -1; - } + if (!sem) + { + rt_set_errno(EINVAL); - result = rt_sem_take(sem->sem, RT_WAITING_FOREVER); - if (result == RT_EOK) return 0; + return -1; + } - rt_set_errno(EINTR); - return -1; + result = rt_sem_take(sem->sem, RT_WAITING_FOREVER); + if (result == RT_EOK) + return 0; + + rt_set_errno(EINTR); + + return -1; } RTM_EXPORT(sem_wait); diff --git a/components/pthreads/semaphore.h b/components/pthreads/semaphore.h index e9cface4e6..664c15ee2e 100644 --- a/components/pthreads/semaphore.h +++ b/components/pthreads/semaphore.h @@ -1,3 +1,27 @@ +/* + * File : semaphore.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2010-10-26 Bernard the first version + */ + #ifndef __POSIX_SEMAPHORE_H__ #define __POSIX_SEMAPHORE_H__ @@ -6,16 +30,16 @@ struct posix_sem { - /* reference count and unlinked */ - rt_uint16_t refcount; - rt_uint8_t unlinked; - rt_uint8_t unamed; + /* reference count and unlinked */ + rt_uint16_t refcount; + rt_uint8_t unlinked; + rt_uint8_t unamed; - /* RT-Thread semaphore */ - rt_sem_t sem; + /* RT-Thread semaphore */ + rt_sem_t sem; - /* next posix semaphore */ - struct posix_sem* next; + /* next posix semaphore */ + struct posix_sem* next; }; typedef struct posix_sem sem_t;