From 64feef0dde9d8353ffe4a3f257ab17848ccf6f53 Mon Sep 17 00:00:00 2001 From: Bernard Xiong Date: Tue, 10 May 2016 09:22:01 +0800 Subject: [LIBC] mv pthreads/libdl to libc and rename dfs_lwip to dfs_net --- components/dfs/filesystems/lwip/SConscript | 11 - components/dfs/filesystems/lwip/arpa/inet.h | 30 -- components/dfs/filesystems/lwip/dfs_lwip.c | 127 ----- components/dfs/filesystems/lwip/dfs_lwip.h | 43 -- components/dfs/filesystems/lwip/lwip_netdb.c | 53 --- components/dfs/filesystems/lwip/lwip_select.c | 123 ----- components/dfs/filesystems/lwip/lwip_sockets.c | 237 ---------- components/dfs/filesystems/lwip/netdb.h | 48 -- components/dfs/filesystems/lwip/netinet/in.h | 30 -- components/dfs/filesystems/lwip/netinet/tcp.h | 30 -- components/dfs/filesystems/lwip/netinet/udp.h | 30 -- components/dfs/filesystems/lwip/sys/select.h | 46 -- components/dfs/filesystems/lwip/sys/socket.h | 65 --- components/dfs/filesystems/net/SConscript | 11 + components/dfs/filesystems/net/arpa/inet.h | 30 ++ components/dfs/filesystems/net/dfs_net.c | 128 +++++ components/dfs/filesystems/net/dfs_net.h | 44 ++ components/dfs/filesystems/net/net_netdb.c | 53 +++ components/dfs/filesystems/net/net_select.c | 123 +++++ components/dfs/filesystems/net/net_sockets.c | 237 ++++++++++ components/dfs/filesystems/net/netdb.h | 48 ++ components/dfs/filesystems/net/netinet/in.h | 30 ++ components/dfs/filesystems/net/netinet/tcp.h | 30 ++ components/dfs/filesystems/net/netinet/udp.h | 30 ++ components/dfs/filesystems/net/sys/select.h | 46 ++ components/dfs/filesystems/net/sys/socket.h | 65 +++ components/libc/SConscript | 3 + components/libc/libdl/SConscript | 9 + components/libc/libdl/dlclose.c | 36 ++ components/libc/libdl/dlerror.c | 24 + components/libc/libdl/dlfcn.h | 18 + components/libc/libdl/dlopen.c | 55 +++ components/libc/libdl/dlsym.c | 37 ++ components/libc/newlib/syscalls.c | 12 +- components/libc/pthreads/SConscript | 9 + components/libc/pthreads/clock_time.c | 155 ++++++ components/libc/pthreads/mqueue.c | 344 ++++++++++++++ components/libc/pthreads/mqueue.h | 73 +++ components/libc/pthreads/posix_types.h | 48 ++ components/libc/pthreads/pthread.c | 526 +++++++++++++++++++++ components/libc/pthreads/pthread.h | 305 ++++++++++++ components/libc/pthreads/pthread_attr.c | 218 +++++++++ components/libc/pthreads/pthread_barrier.c | 124 +++++ components/libc/pthreads/pthread_cond.c | 243 ++++++++++ components/libc/pthreads/pthread_internal.h | 91 ++++ components/libc/pthreads/pthread_mutex.c | 251 ++++++++++ components/libc/pthreads/pthread_rwlock.c | 354 ++++++++++++++ components/libc/pthreads/pthread_spin.c | 83 ++++ components/libc/pthreads/pthread_tls.c | 115 +++++ components/libc/pthreads/sched.c | 56 +++ components/libc/pthreads/sched.h | 59 +++ components/libc/pthreads/semaphore.c | 401 ++++++++++++++++ components/libc/pthreads/semaphore.h | 57 +++ components/libdl/SConscript | 9 - components/libdl/dlclose.c | 36 -- components/libdl/dlerror.c | 24 - components/libdl/dlfcn.h | 18 - components/libdl/dlopen.c | 55 --- components/libdl/dlsym.c | 37 -- .../net/lwip-1.4.1/src/arch/include/arch/cc.h | 2 +- components/pthreads/SConscript | 8 - components/pthreads/clock_time.c | 155 ------ components/pthreads/mqueue.c | 344 -------------- components/pthreads/mqueue.h | 73 --- components/pthreads/posix_types.h | 48 -- components/pthreads/pthread.c | 526 --------------------- components/pthreads/pthread.h | 305 ------------ components/pthreads/pthread_attr.c | 218 --------- components/pthreads/pthread_barrier.c | 124 ----- components/pthreads/pthread_cond.c | 243 ---------- components/pthreads/pthread_internal.h | 91 ---- components/pthreads/pthread_mutex.c | 251 ---------- components/pthreads/pthread_rwlock.c | 354 -------------- components/pthreads/pthread_spin.c | 83 ---- components/pthreads/pthread_tls.c | 115 ----- components/pthreads/sched.c | 56 --- components/pthreads/sched.h | 59 --- components/pthreads/semaphore.c | 401 ---------------- components/pthreads/semaphore.h | 57 --- 79 files changed, 4581 insertions(+), 4565 deletions(-) delete mode 100644 components/dfs/filesystems/lwip/SConscript delete mode 100644 components/dfs/filesystems/lwip/arpa/inet.h delete mode 100644 components/dfs/filesystems/lwip/dfs_lwip.c delete mode 100644 components/dfs/filesystems/lwip/dfs_lwip.h delete mode 100644 components/dfs/filesystems/lwip/lwip_netdb.c delete mode 100644 components/dfs/filesystems/lwip/lwip_select.c delete mode 100644 components/dfs/filesystems/lwip/lwip_sockets.c delete mode 100644 components/dfs/filesystems/lwip/netdb.h delete mode 100644 components/dfs/filesystems/lwip/netinet/in.h delete mode 100644 components/dfs/filesystems/lwip/netinet/tcp.h delete mode 100644 components/dfs/filesystems/lwip/netinet/udp.h delete mode 100644 components/dfs/filesystems/lwip/sys/select.h delete mode 100644 components/dfs/filesystems/lwip/sys/socket.h create mode 100644 components/dfs/filesystems/net/SConscript create mode 100644 components/dfs/filesystems/net/arpa/inet.h create mode 100644 components/dfs/filesystems/net/dfs_net.c create mode 100644 components/dfs/filesystems/net/dfs_net.h create mode 100644 components/dfs/filesystems/net/net_netdb.c create mode 100644 components/dfs/filesystems/net/net_select.c create mode 100644 components/dfs/filesystems/net/net_sockets.c create mode 100644 components/dfs/filesystems/net/netdb.h create mode 100644 components/dfs/filesystems/net/netinet/in.h create mode 100644 components/dfs/filesystems/net/netinet/tcp.h create mode 100644 components/dfs/filesystems/net/netinet/udp.h create mode 100644 components/dfs/filesystems/net/sys/select.h create mode 100644 components/dfs/filesystems/net/sys/socket.h create mode 100644 components/libc/libdl/SConscript create mode 100644 components/libc/libdl/dlclose.c create mode 100644 components/libc/libdl/dlerror.c create mode 100644 components/libc/libdl/dlfcn.h create mode 100644 components/libc/libdl/dlopen.c create mode 100644 components/libc/libdl/dlsym.c create mode 100644 components/libc/pthreads/SConscript create mode 100644 components/libc/pthreads/clock_time.c create mode 100644 components/libc/pthreads/mqueue.c create mode 100644 components/libc/pthreads/mqueue.h create mode 100644 components/libc/pthreads/posix_types.h create mode 100644 components/libc/pthreads/pthread.c create mode 100644 components/libc/pthreads/pthread.h create mode 100644 components/libc/pthreads/pthread_attr.c create mode 100644 components/libc/pthreads/pthread_barrier.c create mode 100644 components/libc/pthreads/pthread_cond.c create mode 100644 components/libc/pthreads/pthread_internal.h create mode 100644 components/libc/pthreads/pthread_mutex.c create mode 100644 components/libc/pthreads/pthread_rwlock.c create mode 100644 components/libc/pthreads/pthread_spin.c create mode 100644 components/libc/pthreads/pthread_tls.c create mode 100644 components/libc/pthreads/sched.c create mode 100644 components/libc/pthreads/sched.h create mode 100644 components/libc/pthreads/semaphore.c create mode 100644 components/libc/pthreads/semaphore.h delete mode 100644 components/libdl/SConscript delete mode 100644 components/libdl/dlclose.c delete mode 100644 components/libdl/dlerror.c delete mode 100644 components/libdl/dlfcn.h delete mode 100644 components/libdl/dlopen.c delete mode 100644 components/libdl/dlsym.c delete mode 100644 components/pthreads/SConscript delete mode 100644 components/pthreads/clock_time.c delete mode 100644 components/pthreads/mqueue.c delete mode 100644 components/pthreads/mqueue.h delete mode 100644 components/pthreads/posix_types.h delete mode 100644 components/pthreads/pthread.c delete mode 100644 components/pthreads/pthread.h delete mode 100644 components/pthreads/pthread_attr.c delete mode 100644 components/pthreads/pthread_barrier.c delete mode 100644 components/pthreads/pthread_cond.c delete mode 100644 components/pthreads/pthread_internal.h delete mode 100644 components/pthreads/pthread_mutex.c delete mode 100644 components/pthreads/pthread_rwlock.c delete mode 100644 components/pthreads/pthread_spin.c delete mode 100644 components/pthreads/pthread_tls.c delete mode 100644 components/pthreads/sched.c delete mode 100644 components/pthreads/sched.h delete mode 100644 components/pthreads/semaphore.c delete mode 100644 components/pthreads/semaphore.h diff --git a/components/dfs/filesystems/lwip/SConscript b/components/dfs/filesystems/lwip/SConscript deleted file mode 100644 index 7bc160af84..0000000000 --- a/components/dfs/filesystems/lwip/SConscript +++ /dev/null @@ -1,11 +0,0 @@ -# RT-Thread building script for component - -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') -CPPPATH = [cwd] - -group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_LWIP'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/dfs/filesystems/lwip/arpa/inet.h b/components/dfs/filesystems/lwip/arpa/inet.h deleted file mode 100644 index 395f3489ba..0000000000 --- a/components/dfs/filesystems/lwip/arpa/inet.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * File : inet.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-02-17 Bernard First version - */ - -#ifndef INET_H__ -#define INET_H__ - -#include - -#endif diff --git a/components/dfs/filesystems/lwip/dfs_lwip.c b/components/dfs/filesystems/lwip/dfs_lwip.c deleted file mode 100644 index 86494c9d69..0000000000 --- a/components/dfs/filesystems/lwip/dfs_lwip.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * File : dfs_lwip.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-02-17 Bernard First version - */ - -#include -#include -#include - -#include "dfs_lwip.h" - -int dfs_lwip_getsocket(int fd) -{ - struct dfs_fd *_dfs_fd; - - _dfs_fd = fd_get(fd); - if (_dfs_fd == RT_NULL) return -1; - - if (_dfs_fd->type != FT_SOCKET) return -1; - - return (int)_dfs_fd->data; -} - -int dfs_lwip_ioctl(struct dfs_fd* file, int cmd, void* args) -{ - return -DFS_STATUS_EIO; -} - -int dfs_lwip_read(struct dfs_fd* file, void *buf, rt_size_t count) -{ - int sock; - - sock = (int)file->data; - count = lwip_read(sock, buf, count); - - return count; -} - -int dfs_lwip_write(struct dfs_fd *file, const void *buf, rt_size_t count) -{ - int sock; - - sock = (int)file->data; - count = lwip_write(sock, buf, count); - - return count; -} - -int dfs_lwip_close(struct dfs_fd* file) -{ - int sock; - int result; - - sock = (int)file->data; - result = lwip_close(sock); - - if (result == 0) return DFS_STATUS_OK; - - return -result; -} - -static const struct dfs_filesystem_operation _lwip_fs_ops = -{ - "lwip", - DFS_FS_FLAG_DEFAULT, - RT_NULL, /* mount */ - RT_NULL, /* unmont */ - RT_NULL, /* mkfs */ - RT_NULL, /* statfs */ - - RT_NULL, /* open */ - dfs_lwip_close, - dfs_lwip_ioctl, - dfs_lwip_read, - dfs_lwip_write, - RT_NULL, - RT_NULL, /* lseek */ - RT_NULL, /* getdents */ - RT_NULL, /* unlink */ - RT_NULL, /* stat */ - RT_NULL, /* rename */ -}; - -static struct dfs_filesystem _lwip_fs = -{ - 0, /* dev_id */ - RT_NULL, /* path */ - &_lwip_fs_ops, - RT_NULL /* data */ -}; - -struct dfs_filesystem* dfs_lwip_get_fs(void) -{ - return &_lwip_fs; -} - -/* -NOTE: Beause we don't need to mount lwIP file system, the filesystem_ops is not -registered to the system. - -int dfs_lwip_system_init(void) -{ - dfs_register(&_lwip_fs_ops); - - return 0; -} -INIT_FS_EXPORT(dfs_lwip_system_init); -*/ diff --git a/components/dfs/filesystems/lwip/dfs_lwip.h b/components/dfs/filesystems/lwip/dfs_lwip.h deleted file mode 100644 index 0c100f9d34..0000000000 --- a/components/dfs/filesystems/lwip/dfs_lwip.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * File : dfs_lwip.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-02-17 Bernard First version - */ - -#ifndef DFS_LWIP_H__ -#define DFS_LWIP_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -struct dfs_filesystem* dfs_lwip_get_fs(void); -int dfs_lwip_getsocket(int fd); - -int dfs_lwip_system_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/dfs/filesystems/lwip/lwip_netdb.c b/components/dfs/filesystems/lwip/lwip_netdb.c deleted file mode 100644 index 1e14dfb093..0000000000 --- a/components/dfs/filesystems/lwip/lwip_netdb.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * File : netdb.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-02-17 Bernard First version - */ - -#include "netdb.h" -#include - -struct hostent *gethostbyname(const char *name) -{ - return lwip_gethostbyname(name); -} -RTM_EXPORT(gethostbyname); - -int gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop) -{ - return lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); -} - -void freeaddrinfo(struct addrinfo *ai) -{ - lwip_freeaddrinfo(ai); -} -RTM_EXPORT(freeaddrinfo); - -int getaddrinfo(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct addrinfo **res) -{ - return lwip_getaddrinfo(nodename, servname, hints, res); -} -RTM_EXPORT(getaddrinfo); diff --git a/components/dfs/filesystems/lwip/lwip_select.c b/components/dfs/filesystems/lwip/lwip_select.c deleted file mode 100644 index 31d9190cfc..0000000000 --- a/components/dfs/filesystems/lwip/lwip_select.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * File : lwip_select.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-05-05 Bernard First version - */ - -#include -#include - -#ifdef RT_USING_LWIP - -#include "dfs_lwip.h" - -int -select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, - struct timeval *timeout) -{ - int index, result; - int sock, maxfd; - - fd_set sock_readset; - fd_set sock_writeset; - fd_set sock_exceptset; - - FD_ZERO(&sock_readset); - FD_ZERO(&sock_writeset); - FD_ZERO(&sock_exceptset); - - maxfd = 0; - for (index = 0; index < maxfdp1; index ++) - { - /* convert fd to sock */ - sock = dfs_lwip_getsocket(index); - if (sock == -1) continue; - - if (sock > maxfd) maxfd = sock; - - /* if FD is set, set the socket set */ - if (readset && FD_ISSET(index, readset)) - { - FD_SET(sock, &sock_readset); - } - if (writeset && FD_ISSET(index, writeset)) - { - FD_SET(sock, &sock_writeset); - } - if (exceptset && FD_ISSET(index, exceptset)) - { - FD_SET(sock, &sock_exceptset); - } - } - - /* no socket found, return bad file descriptor */ - if (maxfd == 0) return -EBADF; - maxfd += 1; - - result = lwip_select(maxfd, &sock_readset, &sock_writeset, &sock_exceptset, timeout); - - if (readset) FD_ZERO(readset); - if (writeset) FD_ZERO(writeset); - if (exceptset) FD_ZERO(exceptset); - - if (result != -1) - { - for (index = 0; index < maxfd; index ++) - { - /* check each socket */ - if ((FD_ISSET(index, &sock_readset)) || - (FD_ISSET(index, &sock_writeset)) || - (FD_ISSET(index, &sock_exceptset))) - { - int fd_index; - - /* Because we can not get the corresponding fd, we have to search it one by one */ - for (fd_index = 0; fd_index < maxfdp1; fd_index ++) - { - sock = dfs_lwip_getsocket(fd_index); - if (sock == index) /* found it */ - { - if (readset && FD_ISSET(index, &sock_readset)) - { - FD_SET(sock, readset); - } - if (writeset && FD_ISSET(index, &sock_writeset)) - { - FD_SET(sock, writeset); - } - if (exceptset && FD_ISSET(index, &sock_exceptset)) - { - FD_SET(sock, exceptset); - } - - /* end of search */ - break; - } - } - } - } - } - - return result; -} -RTM_EXPORT(select); - -#endif diff --git a/components/dfs/filesystems/lwip/lwip_sockets.c b/components/dfs/filesystems/lwip/lwip_sockets.c deleted file mode 100644 index 6b68378f7d..0000000000 --- a/components/dfs/filesystems/lwip/lwip_sockets.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * File : lwip_sockets.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-02-17 Bernard First version - */ - -#include -#include -#include - -#include - -#include "dfs_lwip.h" - -int accept(int s, struct sockaddr *addr, socklen_t *addrlen) -{ - int new_client = -1; - int sock = dfs_lwip_getsocket(s); - - new_client = lwip_accept(sock, addr, addrlen); - if (new_client != -1) - { - /* this is a new socket, create it in file system fd */ - int fd; - struct dfs_fd *d; - - /* allocate a fd */ - fd = fd_new(); - if (fd < 0) - { - rt_set_errno(-DFS_STATUS_ENOMEM); - lwip_close(sock); - - rt_kprintf("no fd yet!\n"); - return -1; - } - d = fd_get(fd); - - /* this is a socket fd */ - d->type = FT_SOCKET; - d->path = RT_NULL; - - d->fs = dfs_lwip_get_fs(); - - d->flags = DFS_O_RDWR; /* set flags as read and write */ - d->size = 0; - d->pos = 0; - - /* set socket to the data of dfs_fd */ - d->data = (void *) new_client; - - /* release the ref-count of fd */ - fd_put(d); - - return fd; - } - - return new_client; -} -RTM_EXPORT(accept); - -int bind(int s, const struct sockaddr *name, socklen_t namelen) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_bind(sock, name, namelen); -} -RTM_EXPORT(bind); - -int shutdown(int s, int how) -{ - int sock; - struct dfs_fd *d; - - d = fd_get(s); - if (d == RT_NULL) - { - rt_set_errno(-DFS_STATUS_EBADF); - - return -1; - } - - sock = dfs_lwip_getsocket(s); - if (lwip_shutdown(sock, how) == 0) - { - /* socket has been closed, delete it from file system fd */ - fd_put(d); - fd_put(d); - - return 0; - } - - return -1; -} -RTM_EXPORT(shutdown); - -int getpeername(int s, struct sockaddr *name, socklen_t *namelen) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_getpeername(sock, name, namelen); -} -RTM_EXPORT(getpeername); - -int getsockname(int s, struct sockaddr *name, socklen_t *namelen) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_getsockname(sock, name, namelen); -} -RTM_EXPORT(getsockname); - -int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_getsockopt(sock, level, optname, optval, optlen); -} -RTM_EXPORT(getsockopt); - -int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_setsockopt(sock, level, optname, optval, optlen); -} -RTM_EXPORT(setsockopt); - -int connect(int s, const struct sockaddr *name, socklen_t namelen) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_connect(sock, name, namelen); -} -RTM_EXPORT(connect); - -int listen(int s, int backlog) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_listen(sock, backlog); -} -RTM_EXPORT(listen); - -int recv(int s, void *mem, size_t len, int flags) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_recv(sock, mem, len, flags); -} -RTM_EXPORT(recv); - -int recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_recvfrom(sock, mem, len, flags, from, fromlen); -} -RTM_EXPORT(recvfrom); - -int send(int s, const void *dataptr, size_t size, int flags) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_send(sock, dataptr, size, flags); -} -RTM_EXPORT(send); - -int sendto(int s, const void *dataptr, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) -{ - int sock = dfs_lwip_getsocket(s); - - return lwip_sendto(sock, dataptr, size, flags, to, tolen); -} -RTM_EXPORT(sendto); - -int socket(int domain, int type, int protocol) -{ - /* create a BSD socket */ - int fd; - int sock; - struct dfs_fd *d; - - /* allocate a fd */ - fd = fd_new(); - if (fd < 0) - { - rt_set_errno(-DFS_STATUS_ENOMEM); - - return -1; - } - d = fd_get(fd); - - /* create socket in lwip and then put it to the dfs_fd */ - sock = lwip_socket(domain, type, protocol); - if (sock > 0) - { - /* this is a socket fd */ - d->type = FT_SOCKET; - d->path = RT_NULL; - - d->fs = dfs_lwip_get_fs(); - - d->flags = DFS_O_RDWR; /* set flags as read and write */ - d->size = 0; - d->pos = 0; - - /* set socket to the data of dfs_fd */ - d->data = (void *) sock; - } - - /* release the ref-count of fd */ - fd_put(d); - - return fd; -} -RTM_EXPORT(socket); diff --git a/components/dfs/filesystems/lwip/netdb.h b/components/dfs/filesystems/lwip/netdb.h deleted file mode 100644 index bf509c371a..0000000000 --- a/components/dfs/filesystems/lwip/netdb.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * File : netdb.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-02-17 Bernard First version - */ - -#ifndef NETDB_H__ -#define NETDB_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -struct hostent *gethostbyname(const char *name); - -int gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop); -void freeaddrinfo(struct addrinfo *ai); -int getaddrinfo(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct addrinfo **res); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/dfs/filesystems/lwip/netinet/in.h b/components/dfs/filesystems/lwip/netinet/in.h deleted file mode 100644 index 93469bc8e3..0000000000 --- a/components/dfs/filesystems/lwip/netinet/in.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * File : in.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-02-17 Bernard First version - */ - -#ifndef IN_H__ -#define IN_H__ - -#include - -#endif diff --git a/components/dfs/filesystems/lwip/netinet/tcp.h b/components/dfs/filesystems/lwip/netinet/tcp.h deleted file mode 100644 index c157b0bb38..0000000000 --- a/components/dfs/filesystems/lwip/netinet/tcp.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * File : tcp.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-02-17 Bernard First version - */ - -#ifndef TCP_H__ -#define TCP_H__ - -#include - -#endif diff --git a/components/dfs/filesystems/lwip/netinet/udp.h b/components/dfs/filesystems/lwip/netinet/udp.h deleted file mode 100644 index 6eef3ee774..0000000000 --- a/components/dfs/filesystems/lwip/netinet/udp.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * File : udp.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-02-17 Bernard First version - */ - -#ifndef UDP_H__ -#define UDP_H__ - -#include - -#endif diff --git a/components/dfs/filesystems/lwip/sys/select.h b/components/dfs/filesystems/lwip/sys/select.h deleted file mode 100644 index 406913d5db..0000000000 --- a/components/dfs/filesystems/lwip/sys/select.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * File : select.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-05-02 Bernard First version - */ - -#ifndef SELECT_H__ -#define SELECT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* select API */ -#ifdef RT_USING_LWIP -/* we use lwIP's structure definitions. */ -#include - -int -select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, - struct timeval *timeout); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/dfs/filesystems/lwip/sys/socket.h b/components/dfs/filesystems/lwip/sys/socket.h deleted file mode 100644 index b9608d97ed..0000000000 --- a/components/dfs/filesystems/lwip/sys/socket.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * File : socket.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, 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 - * 2015-02-17 Bernard First version - */ - -#ifndef SOCKET_H__ -#define SOCKET_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -typedef uint16_t sa_family_t; -typedef uint16_t in_port_t; - -struct sockaddr_storage -{ - sa_family_t ss_family; /* Address family */ - char ss_data[14]; /* 14-bytes of address data */ -}; - -int accept(int s, struct sockaddr *addr, socklen_t *addrlen); -int bind(int s, const struct sockaddr *name, socklen_t namelen); -int shutdown(int s, int how); -int getpeername (int s, struct sockaddr *name, socklen_t *namelen); -int getsockname (int s, struct sockaddr *name, socklen_t *namelen); -int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); -int setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); -int connect(int s, const struct sockaddr *name, socklen_t namelen); -int listen(int s, int backlog); -int recv(int s, void *mem, size_t len, int flags); -int recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen); -int send(int s, const void *dataptr, size_t size, int flags); -int sendto(int s, const void *dataptr, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen); -int socket(int domain, int type, int protocol); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/dfs/filesystems/net/SConscript b/components/dfs/filesystems/net/SConscript new file mode 100644 index 0000000000..810ca16fef --- /dev/null +++ b/components/dfs/filesystems/net/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_NET'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/dfs/filesystems/net/arpa/inet.h b/components/dfs/filesystems/net/arpa/inet.h new file mode 100644 index 0000000000..395f3489ba --- /dev/null +++ b/components/dfs/filesystems/net/arpa/inet.h @@ -0,0 +1,30 @@ +/* + * File : inet.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, 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 + * 2015-02-17 Bernard First version + */ + +#ifndef INET_H__ +#define INET_H__ + +#include + +#endif diff --git a/components/dfs/filesystems/net/dfs_net.c b/components/dfs/filesystems/net/dfs_net.c new file mode 100644 index 0000000000..cda8407f17 --- /dev/null +++ b/components/dfs/filesystems/net/dfs_net.c @@ -0,0 +1,128 @@ +/* + * File : dfs_net.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015-2016, 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 + * 2015-02-17 Bernard First version + * 2016-05-07 Bernard Rename dfs_lwip to dfs_net + */ + +#include +#include +#include + +#include "dfs_net.h" + +int dfs_net_getsocket(int fd) +{ + struct dfs_fd *_dfs_fd; + + _dfs_fd = fd_get(fd); + if (_dfs_fd == RT_NULL) return -1; + + if (_dfs_fd->type != FT_SOCKET) return -1; + + return (int)_dfs_fd->data; +} + +int dfs_net_ioctl(struct dfs_fd* file, int cmd, void* args) +{ + return -DFS_STATUS_EIO; +} + +int dfs_net_read(struct dfs_fd* file, void *buf, rt_size_t count) +{ + int sock; + + sock = (int)file->data; + count = lwip_read(sock, buf, count); + + return count; +} + +int dfs_net_write(struct dfs_fd *file, const void *buf, rt_size_t count) +{ + int sock; + + sock = (int)file->data; + count = lwip_write(sock, buf, count); + + return count; +} + +int dfs_net_close(struct dfs_fd* file) +{ + int sock; + int result; + + sock = (int)file->data; + result = lwip_close(sock); + + if (result == 0) return DFS_STATUS_OK; + + return -result; +} + +static const struct dfs_filesystem_operation _net_fs_ops = +{ + "net", + DFS_FS_FLAG_DEFAULT, + RT_NULL, /* mount */ + RT_NULL, /* unmont */ + RT_NULL, /* mkfs */ + RT_NULL, /* statfs */ + + RT_NULL, /* open */ + dfs_net_close, + dfs_net_ioctl, + dfs_net_read, + dfs_net_write, + RT_NULL, + RT_NULL, /* lseek */ + RT_NULL, /* getdents */ + RT_NULL, /* unlink */ + RT_NULL, /* stat */ + RT_NULL, /* rename */ +}; + +static struct dfs_filesystem _net_fs = +{ + 0, /* dev_id */ + RT_NULL, /* path */ + &_net_fs_ops, + RT_NULL /* data */ +}; + +struct dfs_filesystem* dfs_net_get_fs(void) +{ + return &_net_fs; +} + +/* +NOTE: Beause we don't need to mount lwIP file system, the filesystem_ops is not +registered to the system. + +int dfs_net_system_init(void) +{ + dfs_register(&_net_fs_ops); + + return 0; +} +INIT_FS_EXPORT(dfs_net_system_init); +*/ diff --git a/components/dfs/filesystems/net/dfs_net.h b/components/dfs/filesystems/net/dfs_net.h new file mode 100644 index 0000000000..d98b719b89 --- /dev/null +++ b/components/dfs/filesystems/net/dfs_net.h @@ -0,0 +1,44 @@ +/* + * File : dfs_net.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015-2016, 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 + * 2015-02-17 Bernard First version + * 2016-05-05 Bernard rename dfs_lwip to dfs_net. + */ + +#ifndef DFS_NET_H__ +#define DFS_NET_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct dfs_filesystem* dfs_net_get_fs(void); +int dfs_net_getsocket(int fd); + +int dfs_net_system_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/dfs/filesystems/net/net_netdb.c b/components/dfs/filesystems/net/net_netdb.c new file mode 100644 index 0000000000..1e14dfb093 --- /dev/null +++ b/components/dfs/filesystems/net/net_netdb.c @@ -0,0 +1,53 @@ +/* + * File : netdb.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, 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 + * 2015-02-17 Bernard First version + */ + +#include "netdb.h" +#include + +struct hostent *gethostbyname(const char *name) +{ + return lwip_gethostbyname(name); +} +RTM_EXPORT(gethostbyname); + +int gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop) +{ + return lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); +} + +void freeaddrinfo(struct addrinfo *ai) +{ + lwip_freeaddrinfo(ai); +} +RTM_EXPORT(freeaddrinfo); + +int getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res) +{ + return lwip_getaddrinfo(nodename, servname, hints, res); +} +RTM_EXPORT(getaddrinfo); diff --git a/components/dfs/filesystems/net/net_select.c b/components/dfs/filesystems/net/net_select.c new file mode 100644 index 0000000000..d19ff0ed1b --- /dev/null +++ b/components/dfs/filesystems/net/net_select.c @@ -0,0 +1,123 @@ +/* + * File : lwip_select.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, 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 + * 2015-05-05 Bernard First version + */ + +#include +#include + +#ifdef RT_USING_LWIP + +#include "dfs_net.h" + +int +select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + int index, result; + int sock, maxfd; + + fd_set sock_readset; + fd_set sock_writeset; + fd_set sock_exceptset; + + FD_ZERO(&sock_readset); + FD_ZERO(&sock_writeset); + FD_ZERO(&sock_exceptset); + + maxfd = 0; + for (index = 0; index < maxfdp1; index ++) + { + /* convert fd to sock */ + sock = dfs_net_getsocket(index); + if (sock == -1) continue; + + if (sock > maxfd) maxfd = sock; + + /* if FD is set, set the socket set */ + if (readset && FD_ISSET(index, readset)) + { + FD_SET(sock, &sock_readset); + } + if (writeset && FD_ISSET(index, writeset)) + { + FD_SET(sock, &sock_writeset); + } + if (exceptset && FD_ISSET(index, exceptset)) + { + FD_SET(sock, &sock_exceptset); + } + } + + /* no socket found, return bad file descriptor */ + if (maxfd == 0) return -EBADF; + maxfd += 1; + + result = lwip_select(maxfd, &sock_readset, &sock_writeset, &sock_exceptset, timeout); + + if (readset) FD_ZERO(readset); + if (writeset) FD_ZERO(writeset); + if (exceptset) FD_ZERO(exceptset); + + if (result != -1) + { + for (index = 0; index < maxfd; index ++) + { + /* check each socket */ + if ((FD_ISSET(index, &sock_readset)) || + (FD_ISSET(index, &sock_writeset)) || + (FD_ISSET(index, &sock_exceptset))) + { + int fd_index; + + /* Because we can not get the corresponding fd, we have to search it one by one */ + for (fd_index = 0; fd_index < maxfdp1; fd_index ++) + { + sock = dfs_lwip_getsocket(fd_index); + if (sock == index) /* found it */ + { + if (readset && FD_ISSET(index, &sock_readset)) + { + FD_SET(sock, readset); + } + if (writeset && FD_ISSET(index, &sock_writeset)) + { + FD_SET(sock, writeset); + } + if (exceptset && FD_ISSET(index, &sock_exceptset)) + { + FD_SET(sock, exceptset); + } + + /* end of search */ + break; + } + } + } + } + } + + return result; +} +RTM_EXPORT(select); + +#endif diff --git a/components/dfs/filesystems/net/net_sockets.c b/components/dfs/filesystems/net/net_sockets.c new file mode 100644 index 0000000000..2a5a385ece --- /dev/null +++ b/components/dfs/filesystems/net/net_sockets.c @@ -0,0 +1,237 @@ +/* + * File : lwip_sockets.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, 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 + * 2015-02-17 Bernard First version + */ + +#include +#include +#include + +#include + +#include "dfs_net.h" + +int accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + int new_client = -1; + int sock = dfs_net_getsocket(s); + + new_client = lwip_accept(sock, addr, addrlen); + if (new_client != -1) + { + /* this is a new socket, create it in file system fd */ + int fd; + struct dfs_fd *d; + + /* allocate a fd */ + fd = fd_new(); + if (fd < 0) + { + rt_set_errno(-DFS_STATUS_ENOMEM); + lwip_close(sock); + + rt_kprintf("no fd yet!\n"); + return -1; + } + d = fd_get(fd); + + /* this is a socket fd */ + d->type = FT_SOCKET; + d->path = RT_NULL; + + d->fs = dfs_net_get_fs(); + + d->flags = DFS_O_RDWR; /* set flags as read and write */ + d->size = 0; + d->pos = 0; + + /* set socket to the data of dfs_fd */ + d->data = (void *) new_client; + + /* release the ref-count of fd */ + fd_put(d); + + return fd; + } + + return new_client; +} +RTM_EXPORT(accept); + +int bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + int sock = dfs_net_getsocket(s); + + return lwip_bind(sock, name, namelen); +} +RTM_EXPORT(bind); + +int shutdown(int s, int how) +{ + int sock; + struct dfs_fd *d; + + d = fd_get(s); + if (d == RT_NULL) + { + rt_set_errno(-DFS_STATUS_EBADF); + + return -1; + } + + sock = dfs_net_getsocket(s); + if (lwip_shutdown(sock, how) == 0) + { + /* socket has been closed, delete it from file system fd */ + fd_put(d); + fd_put(d); + + return 0; + } + + return -1; +} +RTM_EXPORT(shutdown); + +int getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + int sock = dfs_net_getsocket(s); + + return lwip_getpeername(sock, name, namelen); +} +RTM_EXPORT(getpeername); + +int getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + int sock = dfs_net_getsocket(s); + + return lwip_getsockname(sock, name, namelen); +} +RTM_EXPORT(getsockname); + +int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + int sock = dfs_net_getsocket(s); + + return lwip_getsockopt(sock, level, optname, optval, optlen); +} +RTM_EXPORT(getsockopt); + +int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + int sock = dfs_net_getsocket(s); + + return lwip_setsockopt(sock, level, optname, optval, optlen); +} +RTM_EXPORT(setsockopt); + +int connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + int sock = dfs_net_getsocket(s); + + return lwip_connect(sock, name, namelen); +} +RTM_EXPORT(connect); + +int listen(int s, int backlog) +{ + int sock = dfs_net_getsocket(s); + + return lwip_listen(sock, backlog); +} +RTM_EXPORT(listen); + +int recv(int s, void *mem, size_t len, int flags) +{ + int sock = dfs_net_getsocket(s); + + return lwip_recv(sock, mem, len, flags); +} +RTM_EXPORT(recv); + +int recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + int sock = dfs_net_getsocket(s); + + return lwip_recvfrom(sock, mem, len, flags, from, fromlen); +} +RTM_EXPORT(recvfrom); + +int send(int s, const void *dataptr, size_t size, int flags) +{ + int sock = dfs_net_getsocket(s); + + return lwip_send(sock, dataptr, size, flags); +} +RTM_EXPORT(send); + +int sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + int sock = dfs_net_getsocket(s); + + return lwip_sendto(sock, dataptr, size, flags, to, tolen); +} +RTM_EXPORT(sendto); + +int socket(int domain, int type, int protocol) +{ + /* create a BSD socket */ + int fd; + int sock; + struct dfs_fd *d; + + /* allocate a fd */ + fd = fd_new(); + if (fd < 0) + { + rt_set_errno(-DFS_STATUS_ENOMEM); + + return -1; + } + d = fd_get(fd); + + /* create socket in lwip and then put it to the dfs_fd */ + sock = lwip_socket(domain, type, protocol); + if (sock > 0) + { + /* this is a socket fd */ + d->type = FT_SOCKET; + d->path = RT_NULL; + + d->fs = dfs_lwip_get_fs(); + + d->flags = DFS_O_RDWR; /* set flags as read and write */ + d->size = 0; + d->pos = 0; + + /* set socket to the data of dfs_fd */ + d->data = (void *) sock; + } + + /* release the ref-count of fd */ + fd_put(d); + + return fd; +} +RTM_EXPORT(socket); diff --git a/components/dfs/filesystems/net/netdb.h b/components/dfs/filesystems/net/netdb.h new file mode 100644 index 0000000000..bf509c371a --- /dev/null +++ b/components/dfs/filesystems/net/netdb.h @@ -0,0 +1,48 @@ +/* + * File : netdb.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, 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 + * 2015-02-17 Bernard First version + */ + +#ifndef NETDB_H__ +#define NETDB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct hostent *gethostbyname(const char *name); + +int gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); +void freeaddrinfo(struct addrinfo *ai); +int getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/dfs/filesystems/net/netinet/in.h b/components/dfs/filesystems/net/netinet/in.h new file mode 100644 index 0000000000..93469bc8e3 --- /dev/null +++ b/components/dfs/filesystems/net/netinet/in.h @@ -0,0 +1,30 @@ +/* + * File : in.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, 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 + * 2015-02-17 Bernard First version + */ + +#ifndef IN_H__ +#define IN_H__ + +#include + +#endif diff --git a/components/dfs/filesystems/net/netinet/tcp.h b/components/dfs/filesystems/net/netinet/tcp.h new file mode 100644 index 0000000000..c157b0bb38 --- /dev/null +++ b/components/dfs/filesystems/net/netinet/tcp.h @@ -0,0 +1,30 @@ +/* + * File : tcp.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, 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 + * 2015-02-17 Bernard First version + */ + +#ifndef TCP_H__ +#define TCP_H__ + +#include + +#endif diff --git a/components/dfs/filesystems/net/netinet/udp.h b/components/dfs/filesystems/net/netinet/udp.h new file mode 100644 index 0000000000..6eef3ee774 --- /dev/null +++ b/components/dfs/filesystems/net/netinet/udp.h @@ -0,0 +1,30 @@ +/* + * File : udp.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, 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 + * 2015-02-17 Bernard First version + */ + +#ifndef UDP_H__ +#define UDP_H__ + +#include + +#endif diff --git a/components/dfs/filesystems/net/sys/select.h b/components/dfs/filesystems/net/sys/select.h new file mode 100644 index 0000000000..406913d5db --- /dev/null +++ b/components/dfs/filesystems/net/sys/select.h @@ -0,0 +1,46 @@ +/* + * File : select.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, 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 + * 2015-05-02 Bernard First version + */ + +#ifndef SELECT_H__ +#define SELECT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* select API */ +#ifdef RT_USING_LWIP +/* we use lwIP's structure definitions. */ +#include + +int +select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/dfs/filesystems/net/sys/socket.h b/components/dfs/filesystems/net/sys/socket.h new file mode 100644 index 0000000000..b9608d97ed --- /dev/null +++ b/components/dfs/filesystems/net/sys/socket.h @@ -0,0 +1,65 @@ +/* + * File : socket.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, 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 + * 2015-02-17 Bernard First version + */ + +#ifndef SOCKET_H__ +#define SOCKET_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef uint16_t sa_family_t; +typedef uint16_t in_port_t; + +struct sockaddr_storage +{ + sa_family_t ss_family; /* Address family */ + char ss_data[14]; /* 14-bytes of address data */ +}; + +int accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int bind(int s, const struct sockaddr *name, socklen_t namelen); +int shutdown(int s, int how); +int getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int connect(int s, const struct sockaddr *name, socklen_t namelen); +int listen(int s, int backlog); +int recv(int s, void *mem, size_t len, int flags); +int recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int send(int s, const void *dataptr, size_t size, int flags); +int sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int socket(int domain, int type, int protocol); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/libc/SConscript b/components/libc/SConscript index 4ed1dde123..a7913ed744 100644 --- a/components/libc/SConscript +++ b/components/libc/SConscript @@ -17,4 +17,7 @@ else: if rtconfig.PLATFORM == 'gcc' and rtconfig.ARCH != 'sim': objs = objs + SConscript('minilibc/SConscript') +objs = objs + SConscript('pthreads/SConscript') +objs = objs + SConscript('libdl/SConscript') + Return('objs') diff --git a/components/libc/libdl/SConscript b/components/libc/libdl/SConscript new file mode 100644 index 0000000000..f7f588858a --- /dev/null +++ b/components/libc/libdl/SConscript @@ -0,0 +1,9 @@ +from building import * + +src = Glob('*.c') +cwd = GetCurrentDir() +CPPPATH = [cwd] + +group = DefineGroup('libdl', src, depend = ['RT_USING_MODULE', 'RT_USING_LIBDL'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/libc/libdl/dlclose.c b/components/libc/libdl/dlclose.c new file mode 100644 index 0000000000..af070891fc --- /dev/null +++ b/components/libc/libdl/dlclose.c @@ -0,0 +1,36 @@ +/* + * File : dlclose.c + * 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 + * + * Change Logs: + * Date Author Notes + * 2010-11-17 yi.qiu first version + */ + +#include +#include + +int dlclose (void *handle) +{ + rt_module_t module; + + RT_ASSERT(handle != RT_NULL); + + module = (rt_module_t)handle; + module->nref--; + + if(module->nref <= 0) + { + rt_module_unload(module); + } + + return RT_TRUE; +} + +RTM_EXPORT(dlclose) + diff --git a/components/libc/libdl/dlerror.c b/components/libc/libdl/dlerror.c new file mode 100644 index 0000000000..dd076412fe --- /dev/null +++ b/components/libc/libdl/dlerror.c @@ -0,0 +1,24 @@ +/* + * File : dlerror.c + * 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 + * + * Change Logs: + * Date Author Notes + * 2010-11-17 yi.qiu first version + */ + +#include +#include + +const char *dlerror(void) +{ + return "TODO"; +} + +RTM_EXPORT(dlerror) + diff --git a/components/libc/libdl/dlfcn.h b/components/libc/libdl/dlfcn.h new file mode 100644 index 0000000000..069f0d9c46 --- /dev/null +++ b/components/libc/libdl/dlfcn.h @@ -0,0 +1,18 @@ +#ifndef __DLFCN_H_ +#define __DLFCN_H_ + +#define RTLD_LAZY 0x00000 +#define RTLD_NOW 0x00001 + +#define RTLD_LOCAL 0x00000 +#define RTLD_GLOBAL 0x10000 + +#define RTLD_DEFAULT ((void*)1) +#define RTLD_NEXT ((void*)2) + +void *dlopen (const char *filename, int flag); +const char *dlerror(void); +void *dlsym(void *handle, const char *symbol); +int dlclose (void *handle); + +#endif diff --git a/components/libc/libdl/dlopen.c b/components/libc/libdl/dlopen.c new file mode 100644 index 0000000000..5e063eed96 --- /dev/null +++ b/components/libc/libdl/dlopen.c @@ -0,0 +1,55 @@ +/* + * File : dlopen.c + * 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 + * + * Change Logs: + * Date Author Notes + * 2010-11-17 yi.qiu first version + */ + +#include +#include +#include + +#define MODULE_ROOT_DIR "/module/lib" + +void* dlopen(const char *filename, int flags) +{ + rt_module_t module; + char *fullpath; + const char*def_path = MODULE_ROOT_DIR; + + /* check parameters */ + RT_ASSERT(filename != RT_NULL); + + if (filename[0] != '/') /* it's a absolute path, use it directly */ + { + fullpath = rt_malloc(strlen(def_path) + strlen(filename) + 2); + + /* join path and file name */ + rt_snprintf(fullpath, strlen(def_path) + strlen(filename) + 2, + "%s/%s", def_path, filename); + } + else + { + rt_kprintf("use absolute path\n"); + return RT_NULL; + } + + /* find in module list */ + module = rt_module_find(fullpath); + + if(module != RT_NULL) module->nref++; + else module = rt_module_open(fullpath); + + rt_free(fullpath); + return (void*)module; +} + +RTM_EXPORT(dlopen) + diff --git a/components/libc/libdl/dlsym.c b/components/libc/libdl/dlsym.c new file mode 100644 index 0000000000..36c7b01fce --- /dev/null +++ b/components/libc/libdl/dlsym.c @@ -0,0 +1,37 @@ +/* + * File : dlsym.c + * 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 + * + * Change Logs: + * Date Author Notes + * 2010-11-17 yi.qiu first version + */ + +#include +#include + +void* dlsym(void *handle, const char* symbol) +{ + int i; + rt_module_t module; + + RT_ASSERT(handle != RT_NULL); + + module = (rt_module_t)handle; + + for(i=0; insym; i++) + { + if (rt_strcmp(module->symtab[i].name, symbol) == 0) + return (void*)module->symtab[i].addr; + } + + return RT_NULL; +} + +RTM_EXPORT(dlsym) + diff --git a/components/libc/newlib/syscalls.c b/components/libc/newlib/syscalls.c index b5d4ec5bf6..55c19ccee9 100644 --- a/components/libc/newlib/syscalls.c +++ b/components/libc/newlib/syscalls.c @@ -450,5 +450,15 @@ void __libc_init_array(void) void abort(void) { - return ; + if (rt_thread_self()) + { + rt_thread_t self = rt_thread_self(); + + rt_kprintf("thread:%-8.*s abort!\n", RT_NAME_MAX, self->name); + rt_thread_suspend(self); + + rt_schedule(); + } + + while (1); } diff --git a/components/libc/pthreads/SConscript b/components/libc/pthreads/SConscript new file mode 100644 index 0000000000..9023e12c13 --- /dev/null +++ b/components/libc/pthreads/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('pthreads', src, depend = ['RT_USING_PTHREADS', 'RT_USING_LIBC'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/libc/pthreads/clock_time.c b/components/libc/pthreads/clock_time.c new file mode 100644 index 0000000000..06227e17e7 --- /dev/null +++ b/components/libc/pthreads/clock_time.c @@ -0,0 +1,155 @@ +/* + * File : clock_time.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 + * 2012-12-08 Bernard fix the issue of _timevalue.tv_usec initialization, + * which found by Rob + */ + +#include +#include + +struct timeval _timevalue; +void clock_time_system_init() +{ + time_t time; + rt_tick_t tick; + rt_device_t device; + + time = 0; + device = rt_device_find("rtc"); + if (device != RT_NULL) + { + /* get realtime seconds */ + rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time); + } + + /* get tick */ + tick = rt_tick_get(); + + _timevalue.tv_usec = (tick%RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK; + _timevalue.tv_sec = time - tick/RT_TICK_PER_SECOND - 1; +} + +int clock_time_to_tick(const struct timespec *time) +{ + int tick; + int nsecond, second; + struct timespec tp; + + RT_ASSERT(time != RT_NULL); + + 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; + } + + tick = second * RT_TICK_PER_SECOND + nsecond * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND; + if (tick < 0) tick = 0; + } + + return tick; +} +RTM_EXPORT(clock_time_to_tick); + +int clock_getres(clockid_t clockid, struct timespec *res) +{ + if ((clockid != CLOCK_REALTIME) || (res == RT_NULL)) + { + rt_set_errno(EINVAL); + + return -1; + } + + 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) +{ + rt_tick_t tick; + + if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL)) + { + rt_set_errno(EINVAL); + + return -1; + } + + /* 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 second; + rt_tick_t tick; + rt_device_t device; + + if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL)) + { + rt_set_errno(EINVAL); + + return -1; + } + + /* get second */ + second = tp->tv_sec; + /* get tick */ + tick = rt_tick_get(); + + /* 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 */ + device = rt_device_find("rtc"); + if (device != RT_NULL) + { + /* set realtime seconds */ + rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &second); + } + else + return -1; + + return 0; +} +RTM_EXPORT(clock_settime); diff --git a/components/libc/pthreads/mqueue.c b/components/libc/pthreads/mqueue.c new file mode 100644 index 0000000000..7b669dc367 --- /dev/null +++ b/components/libc/pthreads/mqueue.c @@ -0,0 +1,344 @@ +/* + * 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 +#include "mqueue.h" +#include "pthread_internal.h" + +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_inline void posix_mq_insert(mqd_t 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; + + 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; + + /* 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; + + 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; + } + } + + return RT_NULL; +} + +int mq_setattr(mqd_t mqdes, + const struct mq_attr *mqstat, + struct mq_attr *omqstat) +{ + 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; + } + + 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; + + /* 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_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; + + /* 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 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; + + if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) + { + rt_set_errno(EINVAL); + + 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; + + if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) + { + rt_set_errno(EINVAL); + + 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) +{ + int tick; + rt_err_t result; + + /* parameters check */ + if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) + { + rt_set_errno(EINVAL); + + return -1; + } + + tick = clock_time_to_tick(abs_timeout); + + result = rt_mq_recv(mqdes->mq, msg_ptr, msg_len, tick); + if (result == RT_EOK) + return msg_len; + + 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) +{ + /* 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; +} +RTM_EXPORT(mq_notify); + +int mq_close(mqd_t mqdes) +{ + 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); + } + rt_sem_release(&posix_mq_lock); + + return 0; +} +RTM_EXPORT(mq_close); + +int mq_unlink(const char *name) +{ + 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); + } + 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/libc/pthreads/mqueue.h b/components/libc/pthreads/mqueue.h new file mode 100644 index 0000000000..de2925837f --- /dev/null +++ b/components/libc/pthreads/mqueue.h @@ -0,0 +1,73 @@ +/* + * 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__ + +#include +#include + +struct mqdes +{ + /* 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; +}; +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. */ +}; + +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); + +#endif diff --git a/components/libc/pthreads/posix_types.h b/components/libc/pthreads/posix_types.h new file mode 100644 index 0000000000..1e401e2de3 --- /dev/null +++ b/components/libc/pthreads/posix_types.h @@ -0,0 +1,48 @@ +/* + * 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 + * 2013-12-23 Bernard Add the checking for ESHUTDOWN + */ + +#ifndef __POSIX_TYPES_H__ +#define __POSIX_TYPES_H__ + +#include + +#include +#include +#include + +#include +#include + +/* errno for Keil MDK */ +#if defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) +#include +#include +#else +#include +#include +#include +#endif + +#endif + diff --git a/components/libc/pthreads/pthread.c b/components/libc/pthreads/pthread.c new file mode 100644 index 0000000000..41432f760f --- /dev/null +++ b/components/libc/pthreads/pthread.c @@ -0,0 +1,526 @@ +/* + * 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 key area */ + pthread_key_system_init(); + /* initialize posix mqueue */ + posix_mq_system_init(); + /* initialize posix semaphore */ + posix_sem_system_init(); + + return 0; +} + +static void _pthread_cleanup(rt_thread_t 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); + } +} + +static void pthread_entry_stub(void *parameter) +{ + _pthread_data_t *ptd; + void *value; + + ptd = (_pthread_data_t*)parameter; + + /* 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 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); + + /* 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); + } + + 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; + } + + /* 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; + } + + 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; + + /* set parameter */ + ptd->thread_entry = start; + ptd->thread_parameter = parameter; + + /* 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; + } + + /* 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; + + 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); + + /* 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; + + /* detach joinable semaphore */ + rt_sem_delete(ptd->joinable_sem); + ptd->joinable_sem = RT_NULL; + rt_exit_critical(); + } + + return 0; +} +RTM_EXPORT(pthread_detach); + +int pthread_join (pthread_t thread, void **value_ptr) +{ + _pthread_data_t* ptd; + rt_err_t result; + + 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 */ + + 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; +} +RTM_EXPORT(pthread_join); + +void pthread_exit (void *value) +{ + _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()); + + rt_enter_critical(); + /* disable cancel */ + ptd->cancelstate = PTHREAD_CANCEL_DISABLE; + /* set return value */ + ptd->return_value = value; + rt_exit_critical(); + + /* invoke pushed cleanup */ + while (ptd->cleanup != RT_NULL) + { + cleanup = ptd->cleanup; + ptd->cleanup = cleanup->next; + + cleanup->cleanup_func(cleanup->parameter); + /* release this cleanup function */ + rt_free(cleanup); + } + + /* destruct thread local key */ + if (ptd->tls != RT_NULL) + { + void *data; + rt_uint32_t index; + + for (index = 0; index < PTHREAD_KEY_MAX; index ++) + { + if (_thread_keys[index].is_used) + { + data = ptd->tls[index]; + if (data) + _thread_keys[index].destructor(data); + } + } + + /* release tls area */ + rt_free(ptd->tls); + ptd->tls = RT_NULL; + } + + if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE) + { + /* release the joinable pthread */ + rt_sem_release(ptd->joinable_sem); + } + + /* 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)) +{ + 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(); + + init_routine(); + } + rt_exit_critical(); + + return 0; +} +RTM_EXPORT(pthread_once); + +int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) +{ + return EOPNOTSUPP; +} +RTM_EXPORT(pthread_atfork); + +int pthread_kill(pthread_t thread, int sig) +{ + return EOPNOTSUPP; +} +RTM_EXPORT(pthread_kill); + +void pthread_cleanup_pop(int execute) +{ + _pthread_data_t *ptd; + _pthread_cleanup_t *cleanup; + + /* get posix thread data */ + ptd = _pthread_get_data(rt_thread_self()); + RT_ASSERT(ptd != RT_NULL); + + if (execute) + { + rt_enter_critical(); + cleanup = ptd->cleanup; + if (cleanup) + ptd->cleanup = cleanup->next; + rt_exit_critical(); + + if (cleanup) + { + cleanup->cleanup_func(cleanup->parameter); + + rt_free(cleanup); + } + } +} +RTM_EXPORT(pthread_cleanup_pop); + +void pthread_cleanup_push(void (*routine)(void*), void *arg) +{ + _pthread_data_t *ptd; + _pthread_cleanup_t *cleanup; + + /* get posix thread data */ + ptd = _pthread_get_data(rt_thread_self()); + RT_ASSERT(ptd != RT_NULL); + + cleanup = (_pthread_cleanup_t *)rt_malloc(sizeof(_pthread_cleanup_t)); + if (cleanup != RT_NULL) + { + cleanup->cleanup_func = routine; + cleanup->parameter = arg; + + rt_enter_critical(); + cleanup->next = ptd->cleanup; + ptd->cleanup = cleanup; + rt_exit_critical(); + } +} +RTM_EXPORT(pthread_cleanup_push); + +/* + * According to IEEE Std 1003.1, 2004 Edition , following pthreads + * interface support cancellation point: + * mq_receive() + * mq_send() + * mq_timedreceive() + * mq_timedsend() + * msgrcv() + * msgsnd() + * msync() + * pthread_cond_timedwait() + * pthread_cond_wait() + * pthread_join() + * pthread_testcancel() + * sem_timedwait() + * sem_wait() + * + * A cancellation point may also occur when a thread is + * executing the following functions: + * pthread_rwlock_rdlock() + * pthread_rwlock_timedrdlock() + * pthread_rwlock_timedwrlock() + * pthread_rwlock_wrlock() + * + * The pthread_cancel(), pthread_setcancelstate(), and pthread_setcanceltype() + * functions are defined to be async-cancel safe. + */ + +int pthread_setcancelstate(int state, int *oldstate) +{ + _pthread_data_t *ptd; + + /* get posix thread data */ + ptd = _pthread_get_data(rt_thread_self()); + RT_ASSERT(ptd != RT_NULL); + + if ((state == PTHREAD_CANCEL_ENABLE) || (state == PTHREAD_CANCEL_DISABLE)) + { + if (oldstate) + *oldstate = ptd->cancelstate; + ptd->cancelstate = state; + + return 0; + } + + return EINVAL; +} +RTM_EXPORT(pthread_setcancelstate); + +int pthread_setcanceltype(int type, int *oldtype) +{ + _pthread_data_t *ptd; + + /* get posix thread data */ + ptd = _pthread_get_data(rt_thread_self()); + RT_ASSERT(ptd != RT_NULL); + + if ((type != PTHREAD_CANCEL_DEFERRED) && (type != PTHREAD_CANCEL_ASYNCHRONOUS)) + return EINVAL; + + if (oldtype) + *oldtype = ptd->canceltype; + ptd->canceltype = type; + + return 0; +} +RTM_EXPORT(pthread_setcanceltype); + +void pthread_testcancel(void) +{ + int cancel=0; + _pthread_data_t* ptd; + + /* get posix thread data */ + ptd = _pthread_get_data(rt_thread_self()); + RT_ASSERT(ptd != RT_NULL); + + if (ptd->cancelstate == PTHREAD_CANCEL_ENABLE) + cancel = ptd->canceled; + if (cancel) + pthread_exit((void*)PTHREAD_CANCELED); +} +RTM_EXPORT(pthread_testcancel); + +int pthread_cancel(pthread_t thread) +{ + _pthread_data_t *ptd; + + /* cancel self */ + if (thread == rt_thread_self()) + return 0; + + /* 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); + } + } + + return 0; +} +RTM_EXPORT(pthread_cancel); + diff --git a/components/libc/pthreads/pthread.h b/components/libc/pthreads/pthread.h new file mode 100644 index 0000000000..7481595682 --- /dev/null +++ b/components/libc/pthreads/pthread.h @@ -0,0 +1,305 @@ +/* + * File : pthread.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_H__ +#define __PTHREAD_H__ + +#include +#include + +#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_CREATE_JOINABLE 0x00 +#define PTHREAD_CREATE_DETACHED 0x01 + +#define PTHREAD_EXPLICIT_SCHED 0 +#define PTHREAD_INHERIT_SCHED 1 + +typedef rt_thread_t pthread_t; +typedef long pthread_condattr_t; +typedef long pthread_rwlockattr_t; +typedef long pthread_mutexattr_t; +typedef long pthread_barrierattr_t; + +typedef int pthread_key_t; +typedef int pthread_once_t; + +enum +{ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_ENABLE, + PTHREAD_CANCEL_DEFERRED, + PTHREAD_CANCEL_DISABLE, + PTHREAD_CANCELED +}; + +enum +{ + PTHREAD_MUTEX_NORMAL = 0, + PTHREAD_MUTEX_RECURSIVE = 1, + PTHREAD_MUTEX_ERRORCHECK = 2, + PTHREAD_MUTEX_ERRORCHECK_NP = PTHREAD_MUTEX_ERRORCHECK, + PTHREAD_MUTEX_RECURSIVE_NP = PTHREAD_MUTEX_RECURSIVE, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + +/* init value for pthread_once_t */ +#define PTHREAD_ONCE_INIT 0 + +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 + +struct pthread_attr +{ + 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 */ +}; +typedef struct pthread_attr pthread_attr_t; + +struct pthread_mutex +{ + 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; +}; +typedef struct pthread_cond pthread_cond_t; + +struct pthread_rwlock +{ + 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 */ + + 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; +}; +typedef struct pthread_spinlock pthread_spinlock_t; + +struct pthread_barrier +{ + int count; + pthread_cond_t cond; + pthread_mutex_t mutex; +}; +typedef struct pthread_barrier pthread_barrier_t; + +/* pthread thread interface */ +int pthread_attr_destroy(pthread_attr_t *attr); +int pthread_attr_init(pthread_attr_t *attr); +int pthread_attr_setdetachstate(pthread_attr_t *attr, int state); +int pthread_attr_getdetachstate(pthread_attr_t const *attr, int *state); +int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); +int pthread_attr_getschedpolicy(pthread_attr_t const *attr, int *policy); +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size); +int pthread_attr_getstacksize(pthread_attr_t const *attr, size_t *stack_size); +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack_addr); +int pthread_attr_getstackaddr(pthread_attr_t const *attr, void **stack_addr); +int pthread_attr_setstack(pthread_attr_t *attr, + void *stack_base, + size_t stack_size); +int pthread_attr_getstack(pthread_attr_t const *attr, + void **stack_base, + size_t *stack_size); + +int pthread_system_init(void); +int pthread_create (pthread_t *tid, const pthread_attr_t *attr, + 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; +} + +rt_inline pthread_t pthread_self (void) +{ + return rt_thread_self(); +} + +void pthread_exit (void *value_ptr); +int pthread_once(pthread_once_t * once_control, void (*init_routine) (void)); + +/* pthread cleanup */ +void pthread_cleanup_pop(int execute); +void pthread_cleanup_push(void (*routine)(void*), void *arg); + +/* pthread cancel */ +int pthread_cancel(pthread_t thread); +void pthread_testcancel(void); +int pthread_setcancelstate(int state, int *oldstate); +int pthread_setcanceltype(int type, int *oldtype); + +int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)); +int pthread_kill(pthread_t thread, int sig); + +/* pthread mutex interface */ +int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); +int pthread_mutex_destroy(pthread_mutex_t *mutex); +int pthread_mutex_lock(pthread_mutex_t *mutex); +int pthread_mutex_unlock(pthread_mutex_t *mutex); +int pthread_mutex_trylock(pthread_mutex_t *mutex); + +int pthread_mutexattr_init(pthread_mutexattr_t *attr); +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); +int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type); +int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type); +int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared); +int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared); + +/* pthread condition interface */ +int pthread_condattr_destroy(pthread_condattr_t *attr); +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); +int pthread_condattr_setclock(pthread_condattr_t *attr, + 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); +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); + +/* pthread rwlock interface */ +int pthread_rwlockattr_init (pthread_rwlockattr_t *attr); +int pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr); +int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared); +int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared); + +int pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); +int pthread_rwlock_destroy (pthread_rwlock_t *rwlock); + +int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock); +int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock); + +int pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock, const struct timespec *abstime); +int pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, const struct timespec *abstime); + +int pthread_rwlock_unlock (pthread_rwlock_t *rwlock); + +int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock); +int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock); + +/* pthread spinlock interface */ +int pthread_spin_init (pthread_spinlock_t *lock, int pshared); +int pthread_spin_destroy (pthread_spinlock_t *lock); + +int pthread_spin_lock (pthread_spinlock_t * lock); +int pthread_spin_trylock (pthread_spinlock_t * lock); +int pthread_spin_unlock (pthread_spinlock_t * lock); + +/* pthread barrier interface */ +int pthread_barrierattr_destroy(pthread_barrierattr_t *attr); +int pthread_barrierattr_init(pthread_barrierattr_t *attr); +int pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, int *pshared); +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_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 */ +}; + +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 */ +}; + +/* posix clock and timer */ +#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) + +#ifndef CLOCK_REALTIME +#define CLOCK_REALTIME 0 +#endif + +int clock_getres (clockid_t clockid, struct timespec *res); +int clock_gettime (clockid_t clockid, struct timespec *tp); +int clock_settime (clockid_t clockid, const struct timespec *tp); + +#endif + diff --git a/components/libc/pthreads/pthread_attr.c b/components/libc/pthreads/pthread_attr.c new file mode 100644 index 0000000000..3e0f7b1e4c --- /dev/null +++ b/components/libc/pthreads/pthread_attr.c @@ -0,0 +1,218 @@ +/* + * 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) + +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 */ +}; + +int pthread_attr_init(pthread_attr_t *attr) +{ + RT_ASSERT(attr != RT_NULL); + + *attr = pthread_default_attr; + + return 0; +} +RTM_EXPORT(pthread_attr_init); + +int pthread_attr_destroy(pthread_attr_t *attr) +{ + RT_ASSERT(attr != RT_NULL); + + memset(attr, 0, sizeof(pthread_attr_t)); + + return 0; +} +RTM_EXPORT(pthread_attr_destroy); + +int pthread_attr_setdetachstate(pthread_attr_t *attr, int state) +{ + RT_ASSERT(attr != RT_NULL); + + if (state != PTHREAD_CREATE_JOINABLE && state != PTHREAD_CREATE_DETACHED) + return EINVAL; + + attr->detachstate = state; + + return 0; +} +RTM_EXPORT(pthread_attr_setdetachstate); + +int pthread_attr_getdetachstate(pthread_attr_t const *attr, int *state) +{ + RT_ASSERT(attr != RT_NULL); + + *state = (int)attr->detachstate; + + return 0; +} +RTM_EXPORT(pthread_attr_getdetachstate); + +int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +{ + RT_ASSERT(attr != RT_NULL); + + 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); + + *policy = (int)attr->policy; + + return 0; +} +RTM_EXPORT(pthread_attr_getschedpolicy); + +int pthread_attr_setschedparam(pthread_attr_t *attr, + struct sched_param const *param) +{ + RT_ASSERT(attr != RT_NULL); + RT_ASSERT(param != RT_NULL); + + 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) +{ + RT_ASSERT(attr != RT_NULL); + RT_ASSERT(param != RT_NULL); + + param->sched_priority = attr->priority; + + return 0; +} +RTM_EXPORT(pthread_attr_getschedparam); + +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size) +{ + RT_ASSERT(attr != RT_NULL); + + 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) +{ + RT_ASSERT(attr != RT_NULL); + + *stack_size = attr->stack_size; + + return 0; +} +RTM_EXPORT(pthread_attr_getstacksize); + +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack_addr) +{ + RT_ASSERT(attr != RT_NULL); + + return EOPNOTSUPP; +} +RTM_EXPORT(pthread_attr_setstackaddr); + +int pthread_attr_getstackaddr(pthread_attr_t const *attr, void **stack_addr) +{ + RT_ASSERT(attr != RT_NULL); + + return EOPNOTSUPP; +} +RTM_EXPORT(pthread_attr_getstackaddr); + +int pthread_attr_setstack(pthread_attr_t *attr, + void *stack_base, + size_t stack_size) +{ + RT_ASSERT(attr != RT_NULL); + + attr->stack_base = stack_base; + attr->stack_size = RT_ALIGN_DOWN(stack_size, RT_ALIGN_SIZE); + + return 0; +} +RTM_EXPORT(pthread_attr_setstack); + +int pthread_attr_getstack(pthread_attr_t const *attr, + void **stack_base, + size_t *stack_size) +{ + RT_ASSERT(attr != RT_NULL); + + *stack_base = attr->stack_base; + *stack_size = attr->stack_size; + + return 0; +} +RTM_EXPORT(pthread_attr_getstack); + +int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guard_size) +{ + return EOPNOTSUPP; +} + +int pthread_attr_getguardsize(pthread_attr_t const *attr, size_t *guard_size) +{ + return EOPNOTSUPP; +} +RTM_EXPORT(pthread_attr_getguardsize); + +int pthread_attr_setscope(pthread_attr_t *attr, int scope) +{ + if (scope == PTHREAD_SCOPE_SYSTEM) + return 0; + if (scope == PTHREAD_SCOPE_PROCESS) + return EOPNOTSUPP; + + return EINVAL; +} +RTM_EXPORT(pthread_attr_setscope); + +int pthread_attr_getscope(pthread_attr_t const *attr) +{ + return PTHREAD_SCOPE_SYSTEM; +} +RTM_EXPORT(pthread_attr_getscope); diff --git a/components/libc/pthreads/pthread_barrier.c b/components/libc/pthreads/pthread_barrier.c new file mode 100644 index 0000000000..c39a45586e --- /dev/null +++ b/components/libc/pthreads/pthread_barrier.c @@ -0,0 +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; +} +RTM_EXPORT(pthread_barrierattr_destroy); + +int pthread_barrierattr_init(pthread_barrierattr_t *attr) +{ + if (!attr) + return EINVAL; + *attr = PTHREAD_PROCESS_PRIVATE; + + return 0; +} +RTM_EXPORT(pthread_barrierattr_init); + +int pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, + int *pshared) +{ + if (!attr) + return EINVAL; + *pshared = (int)*attr; + + 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; + + return EINVAL; +} +RTM_EXPORT(pthread_barrierattr_setpshared); + +int pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + rt_err_t result; + + if (!barrier) + return EINVAL; + + result = pthread_cond_destroy(&(barrier->cond)); + + return result; +} +RTM_EXPORT(pthread_barrier_destroy); + +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; + + barrier->count = count; + pthread_cond_init(&(barrier->cond), NULL); + pthread_mutex_init(&(barrier->mutex), NULL); + + return 0; +} +RTM_EXPORT(pthread_barrier_init); + +int pthread_barrier_wait(pthread_barrier_t *barrier) +{ + rt_err_t result; + if (!barrier) + 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)); + } + + pthread_mutex_unlock(&(barrier->mutex)); + + return result; +} +RTM_EXPORT(pthread_barrier_wait); + diff --git a/components/libc/pthreads/pthread_cond.c b/components/libc/pthreads/pthread_cond.c new file mode 100644 index 0000000000..25628fc2b3 --- /dev/null +++ b/components/libc/pthreads/pthread_cond.c @@ -0,0 +1,243 @@ +/* + * 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; + + return 0; +} +RTM_EXPORT(pthread_condattr_destroy); + +int pthread_condattr_init(pthread_condattr_t *attr) +{ + if (!attr) + return EINVAL; + *attr = PTHREAD_PROCESS_PRIVATE; + + return 0; +} +RTM_EXPORT(pthread_condattr_init); + +int pthread_condattr_getclock(const pthread_condattr_t *attr, + clockid_t *clock_id) +{ + return 0; +} +RTM_EXPORT(pthread_condattr_getclock); + +int pthread_condattr_setclock(pthread_condattr_t *attr, + clockid_t clock_id) +{ + return 0; +} +RTM_EXPORT(pthread_condattr_setclock); + +int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared) +{ + if (!attr || !pshared) + return EINVAL; + + *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) + return ENOSYS; + + 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; + + /* 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++); + + if (attr == RT_NULL) /* use default value */ + cond->attr = PTHREAD_PROCESS_PRIVATE; + else + 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)); + + 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 */ + + 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; + + 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_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(); + + return 0; +} +RTM_EXPORT(pthread_cond_broadcast); + +int pthread_cond_signal(pthread_cond_t *cond) +{ + rt_err_t result; + + if (cond->attr == -1) + pthread_cond_init(cond, RT_NULL); + + result = rt_sem_release(&(cond->sem)); + if (result == RT_EOK) + 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 result; + + 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; + + 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; + + result = _pthread_cond_timedwait(cond, mutex, RT_WAITING_FOREVER); + if (result == RT_EOK) + return 0; + + return EINVAL; +} +RTM_EXPORT(pthread_cond_wait); + +int pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + 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; + + return EINVAL; +} +RTM_EXPORT(pthread_cond_timedwait); + diff --git a/components/libc/pthreads/pthread_internal.h b/components/libc/pthreads/pthread_internal.h new file mode 100644 index 0000000000..0a21fccb13 --- /dev/null +++ b/components/libc/pthreads/pthread_internal.h @@ -0,0 +1,91 @@ +/* + * 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__ + +#include +#include + +struct _pthread_cleanup +{ + void (*cleanup_func)(void *parameter); + void *parameter; + + struct _pthread_cleanup *next; +}; +typedef struct _pthread_cleanup _pthread_cleanup_t; + +struct _pthread_key_data +{ + int is_used; + void (*destructor)(void *parameter); +}; +typedef struct _pthread_key_data _pthread_key_data_t; + +#define PTHREAD_MAGIC 0x70746873 +struct _pthread_data +{ + rt_uint32_t magic; + pthread_attr_t attr; + rt_thread_t tid; + + void* (*thread_entry)(void *parameter); + void *thread_parameter; + + /* return value */ + void *return_value; + + /* semaphore for joinable thread */ + rt_sem_t joinable_sem; + + /* 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 */ +}; +typedef struct _pthread_data _pthread_data_t; + +rt_inline _pthread_data_t *_pthread_get_data(pthread_t thread) +{ + _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); + + return ptd; +} + +int clock_time_to_tick(const struct timespec *time); +void clock_time_system_init(void); +void posix_mq_system_init(void); +void posix_sem_system_init(void); +void pthread_key_system_init(void); + +#endif diff --git a/components/libc/pthreads/pthread_mutex.c b/components/libc/pthreads/pthread_mutex.c new file mode 100644 index 0000000000..40fd870e81 --- /dev/null +++ b/components/libc/pthreads/pthread_mutex.c @@ -0,0 +1,251 @@ +/* + * 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" + +#define MUTEXATTR_SHARED_MASK 0x0010 +#define MUTEXATTR_TYPE_MASK 0x000f + +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; + } + + return EINVAL; +} +RTM_EXPORT(pthread_mutexattr_init); + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + if (attr) + { + *attr = -1; + + return 0; + } + + return EINVAL; +} +RTM_EXPORT(pthread_mutexattr_destroy); + +int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) +{ + if (attr && type) + { + int atype = (*attr & MUTEXATTR_TYPE_MASK); + + if (atype >= PTHREAD_MUTEX_NORMAL && atype <= PTHREAD_MUTEX_ERRORCHECK) + { + *type = atype; + + 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) + { + *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type; + + return 0; + } + + return EINVAL; +} +RTM_EXPORT(pthread_mutexattr_settype); + +int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) +{ + if (!attr) + return EINVAL; + + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + *attr &= ~MUTEXATTR_SHARED_MASK; + return 0; + + case PTHREAD_PROCESS_SHARED: + *attr |= MUTEXATTR_SHARED_MASK; + return 0; + } + + return EINVAL; +} +RTM_EXPORT(pthread_mutexattr_setpshared); + +int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared) +{ + if (!attr || !pshared) + return EINVAL; + + *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED + : PTHREAD_PROCESS_PRIVATE; + return 0; +} +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; + + 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; + + /* 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)); + + return 0; +} +RTM_EXPORT(pthread_mutex_init); + +int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + if (!mutex || mutex->attr == -1) + return EINVAL; + + /* it's busy */ + if (mutex->lock.owner != RT_NULL) + return EBUSY; + + rt_memset(mutex, 0, sizeof(pthread_mutex_t)); + mutex->attr = -1; + + return 0; +} +RTM_EXPORT(pthread_mutex_destroy); + +int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + int mtype; + rt_err_t result; + + if (!mutex) + return EINVAL; + + 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(); + + 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; + + 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; + + /* 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; + } + + 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; + + 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; + + return EBUSY; +} +RTM_EXPORT(pthread_mutex_trylock); + diff --git a/components/libc/pthreads/pthread_rwlock.c b/components/libc/pthreads/pthread_rwlock.c new file mode 100644 index 0000000000..3e009034cc --- /dev/null +++ b/components/libc/pthreads/pthread_rwlock.c @@ -0,0 +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) +{ + if (!attr) + return EINVAL; + *attr = PTHREAD_PROCESS_PRIVATE; + + return 0; +} +RTM_EXPORT(pthread_rwlockattr_init); + +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr) +{ + if (!attr) + return EINVAL; + + return 0; +} +RTM_EXPORT(pthread_rwlockattr_destroy); + +int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, + int *pshared) +{ + if (!attr || !pshared) + return EINVAL; + + *pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; +} +RTM_EXPORT(pthread_rwlockattr_getpshared); + +int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared) +{ + if (!attr || pshared != PTHREAD_PROCESS_PRIVATE) + return EINVAL; + + return 0; +} +RTM_EXPORT(pthread_rwlockattr_setpshared); + +int pthread_rwlock_init(pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + 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; + + return 0; +} +RTM_EXPORT(pthread_rwlock_init); + +int pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + int result; + + 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 (rwlock->rw_refcount != 0 || + rwlock->rw_nwaitreaders != 0 || + rwlock->rw_nwaitwriters != 0) + { + result = EBUSY; + + return result; + } + 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_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 result; + + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); + + 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; + } + + /* another reader has a read lock */ + if (result == 0) + rwlock->rw_refcount++; + + pthread_mutex_unlock(&rwlock->rw_mutex); + + return (result); +} +RTM_EXPORT(pthread_rwlock_rdlock); + +int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) +{ + int result; + + 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 (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); +} +RTM_EXPORT(pthread_rwlock_tryrdlock); + +int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + int result; + + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); + + 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; + } + + /* another reader has a read lock */ + if (result == 0) + rwlock->rw_refcount++; + + 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 result; + + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); + + 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; + } + + if (result == 0) + rwlock->rw_refcount = -1; + + pthread_mutex_unlock(&rwlock->rw_mutex); + + return(result); +} +RTM_EXPORT(pthread_rwlock_timedwrlock); + +int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) +{ + int result; + + 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 (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); +} +RTM_EXPORT(pthread_rwlock_trywrlock); + +int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) +{ + int result; + + 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 (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); + } + + pthread_mutex_unlock(&rwlock->rw_mutex); + + return(result); +} +RTM_EXPORT(pthread_rwlock_unlock); + +int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) +{ + int result; + + if (!rwlock) + return EINVAL; + if (rwlock->attr == -1) + pthread_rwlock_init(rwlock, NULL); + + 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; + } + + if (result == 0) + rwlock->rw_refcount = -1; + + pthread_mutex_unlock(&rwlock->rw_mutex); + + return(result); +} +RTM_EXPORT(pthread_rwlock_wrlock); + diff --git a/components/libc/pthreads/pthread_spin.c b/components/libc/pthreads/pthread_spin.c new file mode 100644 index 0000000000..4c4320dda9 --- /dev/null +++ b/components/libc/pthreads/pthread_spin.c @@ -0,0 +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; + + lock->lock = 0; + + return 0; +} + +int pthread_spin_destroy (pthread_spinlock_t *lock) +{ + if (!lock) + return EINVAL; + + return 0; +} + +int pthread_spin_lock (pthread_spinlock_t *lock) +{ + if (!lock) + return EINVAL; + + while (!(lock->lock)) + { + lock->lock = 1; + } + + return 0; +} + +int pthread_spin_trylock (pthread_spinlock_t *lock) +{ + if (!lock) + return EINVAL; + + if (!(lock->lock)) + { + lock->lock = 1; + + return 0; + } + + return EBUSY; +} + +int pthread_spin_unlock (pthread_spinlock_t *lock) +{ + if (!lock) + return EINVAL; + if (!(lock->lock)) + return EPERM; + + lock->lock = 0; + + return 0; +} diff --git a/components/libc/pthreads/pthread_tls.c b/components/libc/pthreads/pthread_tls.c new file mode 100644 index 0000000000..d689f31e47 --- /dev/null +++ b/components/libc/pthreads/pthread_tls.c @@ -0,0 +1,115 @@ +/* + * 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" + +_pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX]; + +void pthread_key_system_init() +{ + rt_memset(&_thread_keys[0], 0, sizeof(_thread_keys)); +} + +void *pthread_getspecific(pthread_key_t key) +{ + struct _pthread_data* ptd; + + ptd = _pthread_get_data(rt_thread_self()); + RT_ASSERT(ptd != NULL); + + if (ptd->tls == NULL) + return NULL; + + if ((key < PTHREAD_KEY_MAX) && (_thread_keys[key].is_used)) + return ptd->tls[key]; + + return NULL; +} +RTM_EXPORT(pthread_getspecific); + +int pthread_setspecific(pthread_key_t key, const void *value) +{ + struct _pthread_data* ptd; + + ptd = _pthread_get_data(rt_thread_self()); + RT_ASSERT(ptd != NULL); + + /* check tls area */ + if (ptd->tls == NULL) + { + ptd->tls = (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; + } + + return EINVAL; +} +RTM_EXPORT(pthread_setspecific); + +int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) +{ + rt_uint32_t index; + + rt_enter_critical(); + for (index = 0; index < PTHREAD_KEY_MAX; index ++) + { + if (_thread_keys[index].is_used == 0) + { + _thread_keys[index].is_used = 1; + _thread_keys[index].destructor = destructor; + + *key = index; + + rt_exit_critical(); + + return 0; + } + } + + rt_exit_critical(); + + return EAGAIN; +} +RTM_EXPORT(pthread_key_create); + +int pthread_key_delete(pthread_key_t key) +{ + if (key >= PTHREAD_KEY_MAX) + return EINVAL; + + rt_enter_critical(); + _thread_keys[key].is_used = 0; + _thread_keys[key].destructor = 0; + rt_exit_critical(); + + return 0; +} +RTM_EXPORT(pthread_key_delete); + diff --git a/components/libc/pthreads/sched.c b/components/libc/pthreads/sched.c new file mode 100644 index 0000000000..6f75127bf2 --- /dev/null +++ b/components/libc/pthreads/sched.c @@ -0,0 +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; +} +RTM_EXPORT(sched_yield); + +int sched_get_priority_min(int policy) +{ + if (policy != SCHED_FIFO && policy != SCHED_RR) + return EINVAL; + + return 0; +} +RTM_EXPORT(sched_get_priority_min); + +int sched_get_priority_max(int policy) +{ + if (policy != SCHED_FIFO && policy != SCHED_RR) + return EINVAL; + + return RT_THREAD_PRIORITY_MAX - 1; +} +RTM_EXPORT(sched_get_priority_max); + +int sched_setscheduler(pid_t pid, int policy) +{ + return EOPNOTSUPP; +} +RTM_EXPORT(sched_setscheduler); diff --git a/components/libc/pthreads/sched.h b/components/libc/pthreads/sched.h new file mode 100644 index 0000000000..173f3eb2de --- /dev/null +++ b/components/libc/pthreads/sched.h @@ -0,0 +1,59 @@ +/* + * 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__ + +#include +#include + +/* Thread scheduling policies */ +enum +{ + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param +{ + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +int sched_yield(void); +int sched_get_priority_min(int policy); +int sched_get_priority_max(int policy); +int sched_setscheduler(pid_t pid, int policy); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/libc/pthreads/semaphore.c b/components/libc/pthreads/semaphore.c new file mode 100644 index 0000000000..ae69e0d1bc --- /dev/null +++ b/components/libc/pthreads/semaphore.c @@ -0,0 +1,401 @@ +/* + * 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 +#include "semaphore.h" +#include "pthread_internal.h" + +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_inline void posix_sem_insert(sem_t *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; + + 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; + + /* 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; + + 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; +} + +int sem_close(sem_t *sem) +{ + 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; + } + rt_sem_release(&posix_sem_lock); + + return 0; +} +RTM_EXPORT(sem_close); + +int sem_destroy(sem_t *sem) +{ + rt_err_t result; + + if ((!sem) || !(sem->unamed)) + { + rt_set_errno(EINVAL); + + return -1; + } + + /* lock posix semaphore list */ + rt_sem_take(&posix_sem_lock, RT_WAITING_FOREVER); + result = rt_sem_trytake(sem->sem); + if (result != RT_EOK) + { + rt_sem_release(&posix_sem_lock); + rt_set_errno(EBUSY); + + return -1; + } + + /* destroy an unamed posix semaphore */ + posix_sem_delete(sem); + rt_sem_release(&posix_sem_lock); + + return 0; +} +RTM_EXPORT(sem_destroy); + +int sem_unlink(const char *name) +{ + 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); + } + 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; +} +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; + + if (sem == RT_NULL) + { + rt_set_errno(EINVAL); + + return -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; +} +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 = 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_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; + + /* 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 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; + + if (!sem) + { + 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; + + 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; + + rt_set_errno(EINTR); + + return -1; +} +RTM_EXPORT(sem_timedwait); + +int sem_trywait(sem_t *sem) +{ + rt_err_t result; + + if (!sem) + { + rt_set_errno(EINVAL); + + 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; + + if (!sem) + { + rt_set_errno(EINVAL); + + 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/libc/pthreads/semaphore.h b/components/libc/pthreads/semaphore.h new file mode 100644 index 0000000000..664c15ee2e --- /dev/null +++ b/components/libc/pthreads/semaphore.h @@ -0,0 +1,57 @@ +/* + * 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__ + +#include +#include + +struct posix_sem +{ + /* reference count and unlinked */ + rt_uint16_t refcount; + rt_uint8_t unlinked; + rt_uint8_t unamed; + + /* RT-Thread semaphore */ + rt_sem_t sem; + + /* next posix semaphore */ + struct posix_sem* next; +}; +typedef struct posix_sem sem_t; + +int sem_close(sem_t *sem); +int sem_destroy(sem_t *sem); +int sem_getvalue(sem_t *sem, int *sval); +int sem_init(sem_t *sem, int pshared, unsigned int value); +sem_t *sem_open(const char *name, int oflag, ...); +int sem_post(sem_t *sem); +int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); +int sem_trywait(sem_t *sem); +int sem_unlink(const char *name); +int sem_wait(sem_t *sem); + +#endif diff --git a/components/libdl/SConscript b/components/libdl/SConscript deleted file mode 100644 index 4b16063eb3..0000000000 --- a/components/libdl/SConscript +++ /dev/null @@ -1,9 +0,0 @@ -Import('RTT_ROOT') -Import('rtconfig') -from building import * - -src = Glob('*.c') -CPPPATH = [RTT_ROOT + '/components/libdl'] -group = DefineGroup('libdl', src, depend = ['RT_USING_MODULE', 'RT_USING_LIBDL'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/libdl/dlclose.c b/components/libdl/dlclose.c deleted file mode 100644 index af070891fc..0000000000 --- a/components/libdl/dlclose.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * File : dlclose.c - * 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 - * - * Change Logs: - * Date Author Notes - * 2010-11-17 yi.qiu first version - */ - -#include -#include - -int dlclose (void *handle) -{ - rt_module_t module; - - RT_ASSERT(handle != RT_NULL); - - module = (rt_module_t)handle; - module->nref--; - - if(module->nref <= 0) - { - rt_module_unload(module); - } - - return RT_TRUE; -} - -RTM_EXPORT(dlclose) - diff --git a/components/libdl/dlerror.c b/components/libdl/dlerror.c deleted file mode 100644 index dd076412fe..0000000000 --- a/components/libdl/dlerror.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * File : dlerror.c - * 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 - * - * Change Logs: - * Date Author Notes - * 2010-11-17 yi.qiu first version - */ - -#include -#include - -const char *dlerror(void) -{ - return "TODO"; -} - -RTM_EXPORT(dlerror) - diff --git a/components/libdl/dlfcn.h b/components/libdl/dlfcn.h deleted file mode 100644 index 069f0d9c46..0000000000 --- a/components/libdl/dlfcn.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __DLFCN_H_ -#define __DLFCN_H_ - -#define RTLD_LAZY 0x00000 -#define RTLD_NOW 0x00001 - -#define RTLD_LOCAL 0x00000 -#define RTLD_GLOBAL 0x10000 - -#define RTLD_DEFAULT ((void*)1) -#define RTLD_NEXT ((void*)2) - -void *dlopen (const char *filename, int flag); -const char *dlerror(void); -void *dlsym(void *handle, const char *symbol); -int dlclose (void *handle); - -#endif diff --git a/components/libdl/dlopen.c b/components/libdl/dlopen.c deleted file mode 100644 index 5e063eed96..0000000000 --- a/components/libdl/dlopen.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * File : dlopen.c - * 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 - * - * Change Logs: - * Date Author Notes - * 2010-11-17 yi.qiu first version - */ - -#include -#include -#include - -#define MODULE_ROOT_DIR "/module/lib" - -void* dlopen(const char *filename, int flags) -{ - rt_module_t module; - char *fullpath; - const char*def_path = MODULE_ROOT_DIR; - - /* check parameters */ - RT_ASSERT(filename != RT_NULL); - - if (filename[0] != '/') /* it's a absolute path, use it directly */ - { - fullpath = rt_malloc(strlen(def_path) + strlen(filename) + 2); - - /* join path and file name */ - rt_snprintf(fullpath, strlen(def_path) + strlen(filename) + 2, - "%s/%s", def_path, filename); - } - else - { - rt_kprintf("use absolute path\n"); - return RT_NULL; - } - - /* find in module list */ - module = rt_module_find(fullpath); - - if(module != RT_NULL) module->nref++; - else module = rt_module_open(fullpath); - - rt_free(fullpath); - return (void*)module; -} - -RTM_EXPORT(dlopen) - diff --git a/components/libdl/dlsym.c b/components/libdl/dlsym.c deleted file mode 100644 index 36c7b01fce..0000000000 --- a/components/libdl/dlsym.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * File : dlsym.c - * 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 - * - * Change Logs: - * Date Author Notes - * 2010-11-17 yi.qiu first version - */ - -#include -#include - -void* dlsym(void *handle, const char* symbol) -{ - int i; - rt_module_t module; - - RT_ASSERT(handle != RT_NULL); - - module = (rt_module_t)handle; - - for(i=0; insym; i++) - { - if (rt_strcmp(module->symtab[i].name, symbol) == 0) - return (void*)module->symtab[i].addr; - } - - return RT_NULL; -} - -RTM_EXPORT(dlsym) - diff --git a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h index a4dc1732f8..02b2f43907 100644 --- a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h +++ b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h @@ -76,7 +76,7 @@ typedef rt_uint32_t mem_ptr_t; #define LWIP_TIMEVAL_PRIVATE 1 #endif -#if defined(RT_USING_DFS_LWIP) +#if defined(RT_USING_DFS_NET) #define LWIP_COMPAT_SOCKETS 0 #endif diff --git a/components/pthreads/SConscript b/components/pthreads/SConscript deleted file mode 100644 index f220fb1992..0000000000 --- a/components/pthreads/SConscript +++ /dev/null @@ -1,8 +0,0 @@ -Import('RTT_ROOT') -from building import * - -src = Glob('*.c') -CPPPATH = [RTT_ROOT + '/components/pthreads'] -group = DefineGroup('pthreads', src, depend = ['RT_USING_PTHREADS', 'RT_USING_LIBC'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/pthreads/clock_time.c b/components/pthreads/clock_time.c deleted file mode 100644 index 06227e17e7..0000000000 --- a/components/pthreads/clock_time.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * File : clock_time.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 - * 2012-12-08 Bernard fix the issue of _timevalue.tv_usec initialization, - * which found by Rob - */ - -#include -#include - -struct timeval _timevalue; -void clock_time_system_init() -{ - time_t time; - rt_tick_t tick; - rt_device_t device; - - time = 0; - device = rt_device_find("rtc"); - if (device != RT_NULL) - { - /* get realtime seconds */ - rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time); - } - - /* get tick */ - tick = rt_tick_get(); - - _timevalue.tv_usec = (tick%RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK; - _timevalue.tv_sec = time - tick/RT_TICK_PER_SECOND - 1; -} - -int clock_time_to_tick(const struct timespec *time) -{ - int tick; - int nsecond, second; - struct timespec tp; - - RT_ASSERT(time != RT_NULL); - - 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; - } - - tick = second * RT_TICK_PER_SECOND + nsecond * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND; - if (tick < 0) tick = 0; - } - - return tick; -} -RTM_EXPORT(clock_time_to_tick); - -int clock_getres(clockid_t clockid, struct timespec *res) -{ - if ((clockid != CLOCK_REALTIME) || (res == RT_NULL)) - { - rt_set_errno(EINVAL); - - return -1; - } - - 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) -{ - rt_tick_t tick; - - if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL)) - { - rt_set_errno(EINVAL); - - return -1; - } - - /* 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 second; - rt_tick_t tick; - rt_device_t device; - - if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL)) - { - rt_set_errno(EINVAL); - - return -1; - } - - /* get second */ - second = tp->tv_sec; - /* get tick */ - tick = rt_tick_get(); - - /* 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 */ - device = rt_device_find("rtc"); - if (device != RT_NULL) - { - /* set realtime seconds */ - rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &second); - } - else - return -1; - - return 0; -} -RTM_EXPORT(clock_settime); diff --git a/components/pthreads/mqueue.c b/components/pthreads/mqueue.c deleted file mode 100644 index 7b669dc367..0000000000 --- a/components/pthreads/mqueue.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * 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 -#include "mqueue.h" -#include "pthread_internal.h" - -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_inline void posix_mq_insert(mqd_t 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; - - 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; - - /* 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; - - 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; - } - } - - return RT_NULL; -} - -int mq_setattr(mqd_t mqdes, - const struct mq_attr *mqstat, - struct mq_attr *omqstat) -{ - 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; - } - - 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; - - /* 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_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; - - /* 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 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; - - if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) - { - rt_set_errno(EINVAL); - - 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; - - if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) - { - rt_set_errno(EINVAL); - - 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) -{ - int tick; - rt_err_t result; - - /* parameters check */ - if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) - { - rt_set_errno(EINVAL); - - return -1; - } - - tick = clock_time_to_tick(abs_timeout); - - result = rt_mq_recv(mqdes->mq, msg_ptr, msg_len, tick); - if (result == RT_EOK) - return msg_len; - - 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) -{ - /* 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; -} -RTM_EXPORT(mq_notify); - -int mq_close(mqd_t mqdes) -{ - 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); - } - rt_sem_release(&posix_mq_lock); - - return 0; -} -RTM_EXPORT(mq_close); - -int mq_unlink(const char *name) -{ - 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); - } - 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 deleted file mode 100644 index de2925837f..0000000000 --- a/components/pthreads/mqueue.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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__ - -#include -#include - -struct mqdes -{ - /* 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; -}; -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. */ -}; - -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); - -#endif diff --git a/components/pthreads/posix_types.h b/components/pthreads/posix_types.h deleted file mode 100644 index 1e401e2de3..0000000000 --- a/components/pthreads/posix_types.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 - * 2013-12-23 Bernard Add the checking for ESHUTDOWN - */ - -#ifndef __POSIX_TYPES_H__ -#define __POSIX_TYPES_H__ - -#include - -#include -#include -#include - -#include -#include - -/* errno for Keil MDK */ -#if defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) -#include -#include -#else -#include -#include -#include -#endif - -#endif - diff --git a/components/pthreads/pthread.c b/components/pthreads/pthread.c deleted file mode 100644 index 41432f760f..0000000000 --- a/components/pthreads/pthread.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * 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 key area */ - pthread_key_system_init(); - /* initialize posix mqueue */ - posix_mq_system_init(); - /* initialize posix semaphore */ - posix_sem_system_init(); - - return 0; -} - -static void _pthread_cleanup(rt_thread_t 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); - } -} - -static void pthread_entry_stub(void *parameter) -{ - _pthread_data_t *ptd; - void *value; - - ptd = (_pthread_data_t*)parameter; - - /* 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 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); - - /* 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); - } - - 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; - } - - /* 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; - } - - 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; - - /* set parameter */ - ptd->thread_entry = start; - ptd->thread_parameter = parameter; - - /* 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; - } - - /* 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; - - 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); - - /* 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; - - /* detach joinable semaphore */ - rt_sem_delete(ptd->joinable_sem); - ptd->joinable_sem = RT_NULL; - rt_exit_critical(); - } - - return 0; -} -RTM_EXPORT(pthread_detach); - -int pthread_join (pthread_t thread, void **value_ptr) -{ - _pthread_data_t* ptd; - rt_err_t result; - - 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 */ - - 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; -} -RTM_EXPORT(pthread_join); - -void pthread_exit (void *value) -{ - _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()); - - rt_enter_critical(); - /* disable cancel */ - ptd->cancelstate = PTHREAD_CANCEL_DISABLE; - /* set return value */ - ptd->return_value = value; - rt_exit_critical(); - - /* invoke pushed cleanup */ - while (ptd->cleanup != RT_NULL) - { - cleanup = ptd->cleanup; - ptd->cleanup = cleanup->next; - - cleanup->cleanup_func(cleanup->parameter); - /* release this cleanup function */ - rt_free(cleanup); - } - - /* destruct thread local key */ - if (ptd->tls != RT_NULL) - { - void *data; - rt_uint32_t index; - - for (index = 0; index < PTHREAD_KEY_MAX; index ++) - { - if (_thread_keys[index].is_used) - { - data = ptd->tls[index]; - if (data) - _thread_keys[index].destructor(data); - } - } - - /* release tls area */ - rt_free(ptd->tls); - ptd->tls = RT_NULL; - } - - if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE) - { - /* release the joinable pthread */ - rt_sem_release(ptd->joinable_sem); - } - - /* 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)) -{ - 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(); - - init_routine(); - } - rt_exit_critical(); - - return 0; -} -RTM_EXPORT(pthread_once); - -int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) -{ - return EOPNOTSUPP; -} -RTM_EXPORT(pthread_atfork); - -int pthread_kill(pthread_t thread, int sig) -{ - return EOPNOTSUPP; -} -RTM_EXPORT(pthread_kill); - -void pthread_cleanup_pop(int execute) -{ - _pthread_data_t *ptd; - _pthread_cleanup_t *cleanup; - - /* get posix thread data */ - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != RT_NULL); - - if (execute) - { - rt_enter_critical(); - cleanup = ptd->cleanup; - if (cleanup) - ptd->cleanup = cleanup->next; - rt_exit_critical(); - - if (cleanup) - { - cleanup->cleanup_func(cleanup->parameter); - - rt_free(cleanup); - } - } -} -RTM_EXPORT(pthread_cleanup_pop); - -void pthread_cleanup_push(void (*routine)(void*), void *arg) -{ - _pthread_data_t *ptd; - _pthread_cleanup_t *cleanup; - - /* get posix thread data */ - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != RT_NULL); - - cleanup = (_pthread_cleanup_t *)rt_malloc(sizeof(_pthread_cleanup_t)); - if (cleanup != RT_NULL) - { - cleanup->cleanup_func = routine; - cleanup->parameter = arg; - - rt_enter_critical(); - cleanup->next = ptd->cleanup; - ptd->cleanup = cleanup; - rt_exit_critical(); - } -} -RTM_EXPORT(pthread_cleanup_push); - -/* - * According to IEEE Std 1003.1, 2004 Edition , following pthreads - * interface support cancellation point: - * mq_receive() - * mq_send() - * mq_timedreceive() - * mq_timedsend() - * msgrcv() - * msgsnd() - * msync() - * pthread_cond_timedwait() - * pthread_cond_wait() - * pthread_join() - * pthread_testcancel() - * sem_timedwait() - * sem_wait() - * - * A cancellation point may also occur when a thread is - * executing the following functions: - * pthread_rwlock_rdlock() - * pthread_rwlock_timedrdlock() - * pthread_rwlock_timedwrlock() - * pthread_rwlock_wrlock() - * - * The pthread_cancel(), pthread_setcancelstate(), and pthread_setcanceltype() - * functions are defined to be async-cancel safe. - */ - -int pthread_setcancelstate(int state, int *oldstate) -{ - _pthread_data_t *ptd; - - /* get posix thread data */ - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != RT_NULL); - - if ((state == PTHREAD_CANCEL_ENABLE) || (state == PTHREAD_CANCEL_DISABLE)) - { - if (oldstate) - *oldstate = ptd->cancelstate; - ptd->cancelstate = state; - - return 0; - } - - return EINVAL; -} -RTM_EXPORT(pthread_setcancelstate); - -int pthread_setcanceltype(int type, int *oldtype) -{ - _pthread_data_t *ptd; - - /* get posix thread data */ - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != RT_NULL); - - if ((type != PTHREAD_CANCEL_DEFERRED) && (type != PTHREAD_CANCEL_ASYNCHRONOUS)) - return EINVAL; - - if (oldtype) - *oldtype = ptd->canceltype; - ptd->canceltype = type; - - return 0; -} -RTM_EXPORT(pthread_setcanceltype); - -void pthread_testcancel(void) -{ - int cancel=0; - _pthread_data_t* ptd; - - /* get posix thread data */ - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != RT_NULL); - - if (ptd->cancelstate == PTHREAD_CANCEL_ENABLE) - cancel = ptd->canceled; - if (cancel) - pthread_exit((void*)PTHREAD_CANCELED); -} -RTM_EXPORT(pthread_testcancel); - -int pthread_cancel(pthread_t thread) -{ - _pthread_data_t *ptd; - - /* cancel self */ - if (thread == rt_thread_self()) - return 0; - - /* 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); - } - } - - return 0; -} -RTM_EXPORT(pthread_cancel); - diff --git a/components/pthreads/pthread.h b/components/pthreads/pthread.h deleted file mode 100644 index 7481595682..0000000000 --- a/components/pthreads/pthread.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * File : pthread.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_H__ -#define __PTHREAD_H__ - -#include -#include - -#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_CREATE_JOINABLE 0x00 -#define PTHREAD_CREATE_DETACHED 0x01 - -#define PTHREAD_EXPLICIT_SCHED 0 -#define PTHREAD_INHERIT_SCHED 1 - -typedef rt_thread_t pthread_t; -typedef long pthread_condattr_t; -typedef long pthread_rwlockattr_t; -typedef long pthread_mutexattr_t; -typedef long pthread_barrierattr_t; - -typedef int pthread_key_t; -typedef int pthread_once_t; - -enum -{ - PTHREAD_CANCEL_ASYNCHRONOUS = 0, - PTHREAD_CANCEL_ENABLE, - PTHREAD_CANCEL_DEFERRED, - PTHREAD_CANCEL_DISABLE, - PTHREAD_CANCELED -}; - -enum -{ - PTHREAD_MUTEX_NORMAL = 0, - PTHREAD_MUTEX_RECURSIVE = 1, - PTHREAD_MUTEX_ERRORCHECK = 2, - PTHREAD_MUTEX_ERRORCHECK_NP = PTHREAD_MUTEX_ERRORCHECK, - PTHREAD_MUTEX_RECURSIVE_NP = PTHREAD_MUTEX_RECURSIVE, - PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL -}; - -/* init value for pthread_once_t */ -#define PTHREAD_ONCE_INIT 0 - -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 - -struct pthread_attr -{ - 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 */ -}; -typedef struct pthread_attr pthread_attr_t; - -struct pthread_mutex -{ - 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; -}; -typedef struct pthread_cond pthread_cond_t; - -struct pthread_rwlock -{ - 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 */ - - 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; -}; -typedef struct pthread_spinlock pthread_spinlock_t; - -struct pthread_barrier -{ - int count; - pthread_cond_t cond; - pthread_mutex_t mutex; -}; -typedef struct pthread_barrier pthread_barrier_t; - -/* pthread thread interface */ -int pthread_attr_destroy(pthread_attr_t *attr); -int pthread_attr_init(pthread_attr_t *attr); -int pthread_attr_setdetachstate(pthread_attr_t *attr, int state); -int pthread_attr_getdetachstate(pthread_attr_t const *attr, int *state); -int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); -int pthread_attr_getschedpolicy(pthread_attr_t const *attr, int *policy); -int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size); -int pthread_attr_getstacksize(pthread_attr_t const *attr, size_t *stack_size); -int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack_addr); -int pthread_attr_getstackaddr(pthread_attr_t const *attr, void **stack_addr); -int pthread_attr_setstack(pthread_attr_t *attr, - void *stack_base, - size_t stack_size); -int pthread_attr_getstack(pthread_attr_t const *attr, - void **stack_base, - size_t *stack_size); - -int pthread_system_init(void); -int pthread_create (pthread_t *tid, const pthread_attr_t *attr, - 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; -} - -rt_inline pthread_t pthread_self (void) -{ - return rt_thread_self(); -} - -void pthread_exit (void *value_ptr); -int pthread_once(pthread_once_t * once_control, void (*init_routine) (void)); - -/* pthread cleanup */ -void pthread_cleanup_pop(int execute); -void pthread_cleanup_push(void (*routine)(void*), void *arg); - -/* pthread cancel */ -int pthread_cancel(pthread_t thread); -void pthread_testcancel(void); -int pthread_setcancelstate(int state, int *oldstate); -int pthread_setcanceltype(int type, int *oldtype); - -int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)); -int pthread_kill(pthread_t thread, int sig); - -/* pthread mutex interface */ -int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); -int pthread_mutex_destroy(pthread_mutex_t *mutex); -int pthread_mutex_lock(pthread_mutex_t *mutex); -int pthread_mutex_unlock(pthread_mutex_t *mutex); -int pthread_mutex_trylock(pthread_mutex_t *mutex); - -int pthread_mutexattr_init(pthread_mutexattr_t *attr); -int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); -int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type); -int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type); -int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared); -int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared); - -/* pthread condition interface */ -int pthread_condattr_destroy(pthread_condattr_t *attr); -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); -int pthread_condattr_setclock(pthread_condattr_t *attr, - 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); -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); - -/* pthread rwlock interface */ -int pthread_rwlockattr_init (pthread_rwlockattr_t *attr); -int pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr); -int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared); -int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared); - -int pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); -int pthread_rwlock_destroy (pthread_rwlock_t *rwlock); - -int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock); -int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock); - -int pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock, const struct timespec *abstime); -int pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, const struct timespec *abstime); - -int pthread_rwlock_unlock (pthread_rwlock_t *rwlock); - -int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock); -int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock); - -/* pthread spinlock interface */ -int pthread_spin_init (pthread_spinlock_t *lock, int pshared); -int pthread_spin_destroy (pthread_spinlock_t *lock); - -int pthread_spin_lock (pthread_spinlock_t * lock); -int pthread_spin_trylock (pthread_spinlock_t * lock); -int pthread_spin_unlock (pthread_spinlock_t * lock); - -/* pthread barrier interface */ -int pthread_barrierattr_destroy(pthread_barrierattr_t *attr); -int pthread_barrierattr_init(pthread_barrierattr_t *attr); -int pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, int *pshared); -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_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 */ -}; - -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 */ -}; - -/* posix clock and timer */ -#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) - -#ifndef CLOCK_REALTIME -#define CLOCK_REALTIME 0 -#endif - -int clock_getres (clockid_t clockid, struct timespec *res); -int clock_gettime (clockid_t clockid, struct timespec *tp); -int clock_settime (clockid_t clockid, const struct timespec *tp); - -#endif - diff --git a/components/pthreads/pthread_attr.c b/components/pthreads/pthread_attr.c deleted file mode 100644 index 3e0f7b1e4c..0000000000 --- a/components/pthreads/pthread_attr.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * 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) - -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 */ -}; - -int pthread_attr_init(pthread_attr_t *attr) -{ - RT_ASSERT(attr != RT_NULL); - - *attr = pthread_default_attr; - - return 0; -} -RTM_EXPORT(pthread_attr_init); - -int pthread_attr_destroy(pthread_attr_t *attr) -{ - RT_ASSERT(attr != RT_NULL); - - memset(attr, 0, sizeof(pthread_attr_t)); - - return 0; -} -RTM_EXPORT(pthread_attr_destroy); - -int pthread_attr_setdetachstate(pthread_attr_t *attr, int state) -{ - RT_ASSERT(attr != RT_NULL); - - if (state != PTHREAD_CREATE_JOINABLE && state != PTHREAD_CREATE_DETACHED) - return EINVAL; - - attr->detachstate = state; - - return 0; -} -RTM_EXPORT(pthread_attr_setdetachstate); - -int pthread_attr_getdetachstate(pthread_attr_t const *attr, int *state) -{ - RT_ASSERT(attr != RT_NULL); - - *state = (int)attr->detachstate; - - return 0; -} -RTM_EXPORT(pthread_attr_getdetachstate); - -int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) -{ - RT_ASSERT(attr != RT_NULL); - - 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); - - *policy = (int)attr->policy; - - return 0; -} -RTM_EXPORT(pthread_attr_getschedpolicy); - -int pthread_attr_setschedparam(pthread_attr_t *attr, - struct sched_param const *param) -{ - RT_ASSERT(attr != RT_NULL); - RT_ASSERT(param != RT_NULL); - - 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) -{ - RT_ASSERT(attr != RT_NULL); - RT_ASSERT(param != RT_NULL); - - param->sched_priority = attr->priority; - - return 0; -} -RTM_EXPORT(pthread_attr_getschedparam); - -int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size) -{ - RT_ASSERT(attr != RT_NULL); - - 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) -{ - RT_ASSERT(attr != RT_NULL); - - *stack_size = attr->stack_size; - - return 0; -} -RTM_EXPORT(pthread_attr_getstacksize); - -int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack_addr) -{ - RT_ASSERT(attr != RT_NULL); - - return EOPNOTSUPP; -} -RTM_EXPORT(pthread_attr_setstackaddr); - -int pthread_attr_getstackaddr(pthread_attr_t const *attr, void **stack_addr) -{ - RT_ASSERT(attr != RT_NULL); - - return EOPNOTSUPP; -} -RTM_EXPORT(pthread_attr_getstackaddr); - -int pthread_attr_setstack(pthread_attr_t *attr, - void *stack_base, - size_t stack_size) -{ - RT_ASSERT(attr != RT_NULL); - - attr->stack_base = stack_base; - attr->stack_size = RT_ALIGN_DOWN(stack_size, RT_ALIGN_SIZE); - - return 0; -} -RTM_EXPORT(pthread_attr_setstack); - -int pthread_attr_getstack(pthread_attr_t const *attr, - void **stack_base, - size_t *stack_size) -{ - RT_ASSERT(attr != RT_NULL); - - *stack_base = attr->stack_base; - *stack_size = attr->stack_size; - - return 0; -} -RTM_EXPORT(pthread_attr_getstack); - -int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guard_size) -{ - return EOPNOTSUPP; -} - -int pthread_attr_getguardsize(pthread_attr_t const *attr, size_t *guard_size) -{ - return EOPNOTSUPP; -} -RTM_EXPORT(pthread_attr_getguardsize); - -int pthread_attr_setscope(pthread_attr_t *attr, int scope) -{ - if (scope == PTHREAD_SCOPE_SYSTEM) - return 0; - if (scope == PTHREAD_SCOPE_PROCESS) - return EOPNOTSUPP; - - return EINVAL; -} -RTM_EXPORT(pthread_attr_setscope); - -int pthread_attr_getscope(pthread_attr_t const *attr) -{ - return PTHREAD_SCOPE_SYSTEM; -} -RTM_EXPORT(pthread_attr_getscope); diff --git a/components/pthreads/pthread_barrier.c b/components/pthreads/pthread_barrier.c deleted file mode 100644 index c39a45586e..0000000000 --- a/components/pthreads/pthread_barrier.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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; -} -RTM_EXPORT(pthread_barrierattr_destroy); - -int pthread_barrierattr_init(pthread_barrierattr_t *attr) -{ - if (!attr) - return EINVAL; - *attr = PTHREAD_PROCESS_PRIVATE; - - return 0; -} -RTM_EXPORT(pthread_barrierattr_init); - -int pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, - int *pshared) -{ - if (!attr) - return EINVAL; - *pshared = (int)*attr; - - 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; - - return EINVAL; -} -RTM_EXPORT(pthread_barrierattr_setpshared); - -int pthread_barrier_destroy(pthread_barrier_t *barrier) -{ - rt_err_t result; - - if (!barrier) - return EINVAL; - - result = pthread_cond_destroy(&(barrier->cond)); - - return result; -} -RTM_EXPORT(pthread_barrier_destroy); - -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; - - barrier->count = count; - pthread_cond_init(&(barrier->cond), NULL); - pthread_mutex_init(&(barrier->mutex), NULL); - - return 0; -} -RTM_EXPORT(pthread_barrier_init); - -int pthread_barrier_wait(pthread_barrier_t *barrier) -{ - rt_err_t result; - if (!barrier) - 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)); - } - - 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 deleted file mode 100644 index 25628fc2b3..0000000000 --- a/components/pthreads/pthread_cond.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * 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; - - return 0; -} -RTM_EXPORT(pthread_condattr_destroy); - -int pthread_condattr_init(pthread_condattr_t *attr) -{ - if (!attr) - return EINVAL; - *attr = PTHREAD_PROCESS_PRIVATE; - - return 0; -} -RTM_EXPORT(pthread_condattr_init); - -int pthread_condattr_getclock(const pthread_condattr_t *attr, - clockid_t *clock_id) -{ - return 0; -} -RTM_EXPORT(pthread_condattr_getclock); - -int pthread_condattr_setclock(pthread_condattr_t *attr, - clockid_t clock_id) -{ - return 0; -} -RTM_EXPORT(pthread_condattr_setclock); - -int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared) -{ - if (!attr || !pshared) - return EINVAL; - - *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) - return ENOSYS; - - 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; - - /* 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++); - - if (attr == RT_NULL) /* use default value */ - cond->attr = PTHREAD_PROCESS_PRIVATE; - else - 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)); - - 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 */ - - 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; - - 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_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(); - - return 0; -} -RTM_EXPORT(pthread_cond_broadcast); - -int pthread_cond_signal(pthread_cond_t *cond) -{ - rt_err_t result; - - if (cond->attr == -1) - pthread_cond_init(cond, RT_NULL); - - result = rt_sem_release(&(cond->sem)); - if (result == RT_EOK) - 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 result; - - 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; - - 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; - - result = _pthread_cond_timedwait(cond, mutex, RT_WAITING_FOREVER); - if (result == RT_EOK) - return 0; - - return EINVAL; -} -RTM_EXPORT(pthread_cond_wait); - -int pthread_cond_timedwait(pthread_cond_t *cond, - pthread_mutex_t *mutex, - const struct timespec *abstime) -{ - 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; - - return EINVAL; -} -RTM_EXPORT(pthread_cond_timedwait); - diff --git a/components/pthreads/pthread_internal.h b/components/pthreads/pthread_internal.h deleted file mode 100644 index 0a21fccb13..0000000000 --- a/components/pthreads/pthread_internal.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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__ - -#include -#include - -struct _pthread_cleanup -{ - void (*cleanup_func)(void *parameter); - void *parameter; - - struct _pthread_cleanup *next; -}; -typedef struct _pthread_cleanup _pthread_cleanup_t; - -struct _pthread_key_data -{ - int is_used; - void (*destructor)(void *parameter); -}; -typedef struct _pthread_key_data _pthread_key_data_t; - -#define PTHREAD_MAGIC 0x70746873 -struct _pthread_data -{ - rt_uint32_t magic; - pthread_attr_t attr; - rt_thread_t tid; - - void* (*thread_entry)(void *parameter); - void *thread_parameter; - - /* return value */ - void *return_value; - - /* semaphore for joinable thread */ - rt_sem_t joinable_sem; - - /* 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 */ -}; -typedef struct _pthread_data _pthread_data_t; - -rt_inline _pthread_data_t *_pthread_get_data(pthread_t thread) -{ - _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); - - return ptd; -} - -int clock_time_to_tick(const struct timespec *time); -void clock_time_system_init(void); -void posix_mq_system_init(void); -void posix_sem_system_init(void); -void pthread_key_system_init(void); - -#endif diff --git a/components/pthreads/pthread_mutex.c b/components/pthreads/pthread_mutex.c deleted file mode 100644 index 40fd870e81..0000000000 --- a/components/pthreads/pthread_mutex.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * 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" - -#define MUTEXATTR_SHARED_MASK 0x0010 -#define MUTEXATTR_TYPE_MASK 0x000f - -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; - } - - return EINVAL; -} -RTM_EXPORT(pthread_mutexattr_init); - -int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) -{ - if (attr) - { - *attr = -1; - - return 0; - } - - return EINVAL; -} -RTM_EXPORT(pthread_mutexattr_destroy); - -int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) -{ - if (attr && type) - { - int atype = (*attr & MUTEXATTR_TYPE_MASK); - - if (atype >= PTHREAD_MUTEX_NORMAL && atype <= PTHREAD_MUTEX_ERRORCHECK) - { - *type = atype; - - 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) - { - *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type; - - return 0; - } - - return EINVAL; -} -RTM_EXPORT(pthread_mutexattr_settype); - -int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) -{ - if (!attr) - return EINVAL; - - switch (pshared) - { - case PTHREAD_PROCESS_PRIVATE: - *attr &= ~MUTEXATTR_SHARED_MASK; - return 0; - - case PTHREAD_PROCESS_SHARED: - *attr |= MUTEXATTR_SHARED_MASK; - return 0; - } - - return EINVAL; -} -RTM_EXPORT(pthread_mutexattr_setpshared); - -int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared) -{ - if (!attr || !pshared) - return EINVAL; - - *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED - : PTHREAD_PROCESS_PRIVATE; - return 0; -} -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; - - 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; - - /* 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)); - - return 0; -} -RTM_EXPORT(pthread_mutex_init); - -int pthread_mutex_destroy(pthread_mutex_t *mutex) -{ - if (!mutex || mutex->attr == -1) - return EINVAL; - - /* it's busy */ - if (mutex->lock.owner != RT_NULL) - return EBUSY; - - rt_memset(mutex, 0, sizeof(pthread_mutex_t)); - mutex->attr = -1; - - return 0; -} -RTM_EXPORT(pthread_mutex_destroy); - -int pthread_mutex_lock(pthread_mutex_t *mutex) -{ - int mtype; - rt_err_t result; - - if (!mutex) - return EINVAL; - - 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(); - - 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; - - 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; - - /* 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; - } - - 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; - - 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; - - return EBUSY; -} -RTM_EXPORT(pthread_mutex_trylock); - diff --git a/components/pthreads/pthread_rwlock.c b/components/pthreads/pthread_rwlock.c deleted file mode 100644 index 3e009034cc..0000000000 --- a/components/pthreads/pthread_rwlock.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * 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) -{ - if (!attr) - return EINVAL; - *attr = PTHREAD_PROCESS_PRIVATE; - - return 0; -} -RTM_EXPORT(pthread_rwlockattr_init); - -int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr) -{ - if (!attr) - return EINVAL; - - return 0; -} -RTM_EXPORT(pthread_rwlockattr_destroy); - -int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, - int *pshared) -{ - if (!attr || !pshared) - return EINVAL; - - *pshared = PTHREAD_PROCESS_PRIVATE; - - return 0; -} -RTM_EXPORT(pthread_rwlockattr_getpshared); - -int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared) -{ - if (!attr || pshared != PTHREAD_PROCESS_PRIVATE) - return EINVAL; - - return 0; -} -RTM_EXPORT(pthread_rwlockattr_setpshared); - -int pthread_rwlock_init(pthread_rwlock_t *rwlock, - const pthread_rwlockattr_t *attr) -{ - 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; - - return 0; -} -RTM_EXPORT(pthread_rwlock_init); - -int pthread_rwlock_destroy (pthread_rwlock_t *rwlock) -{ - int result; - - 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 (rwlock->rw_refcount != 0 || - rwlock->rw_nwaitreaders != 0 || - rwlock->rw_nwaitwriters != 0) - { - result = EBUSY; - - return result; - } - 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_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 result; - - if (!rwlock) - return EINVAL; - if (rwlock->attr == -1) - pthread_rwlock_init(rwlock, NULL); - - 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; - } - - /* another reader has a read lock */ - if (result == 0) - rwlock->rw_refcount++; - - pthread_mutex_unlock(&rwlock->rw_mutex); - - return (result); -} -RTM_EXPORT(pthread_rwlock_rdlock); - -int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) -{ - int result; - - 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 (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); -} -RTM_EXPORT(pthread_rwlock_tryrdlock); - -int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, - const struct timespec *abstime) -{ - int result; - - if (!rwlock) - return EINVAL; - if (rwlock->attr == -1) - pthread_rwlock_init(rwlock, NULL); - - 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; - } - - /* another reader has a read lock */ - if (result == 0) - rwlock->rw_refcount++; - - 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 result; - - if (!rwlock) - return EINVAL; - if (rwlock->attr == -1) - pthread_rwlock_init(rwlock, NULL); - - 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; - } - - if (result == 0) - rwlock->rw_refcount = -1; - - pthread_mutex_unlock(&rwlock->rw_mutex); - - return(result); -} -RTM_EXPORT(pthread_rwlock_timedwrlock); - -int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) -{ - int result; - - 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 (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); -} -RTM_EXPORT(pthread_rwlock_trywrlock); - -int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) -{ - int result; - - 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 (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); - } - - pthread_mutex_unlock(&rwlock->rw_mutex); - - return(result); -} -RTM_EXPORT(pthread_rwlock_unlock); - -int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) -{ - int result; - - if (!rwlock) - return EINVAL; - if (rwlock->attr == -1) - pthread_rwlock_init(rwlock, NULL); - - 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; - } - - if (result == 0) - rwlock->rw_refcount = -1; - - 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 deleted file mode 100644 index 4c4320dda9..0000000000 --- a/components/pthreads/pthread_spin.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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; - - lock->lock = 0; - - return 0; -} - -int pthread_spin_destroy (pthread_spinlock_t *lock) -{ - if (!lock) - return EINVAL; - - return 0; -} - -int pthread_spin_lock (pthread_spinlock_t *lock) -{ - if (!lock) - return EINVAL; - - while (!(lock->lock)) - { - lock->lock = 1; - } - - return 0; -} - -int pthread_spin_trylock (pthread_spinlock_t *lock) -{ - if (!lock) - return EINVAL; - - if (!(lock->lock)) - { - lock->lock = 1; - - return 0; - } - - return EBUSY; -} - -int pthread_spin_unlock (pthread_spinlock_t *lock) -{ - if (!lock) - return EINVAL; - if (!(lock->lock)) - return EPERM; - - lock->lock = 0; - - return 0; -} diff --git a/components/pthreads/pthread_tls.c b/components/pthreads/pthread_tls.c deleted file mode 100644 index d689f31e47..0000000000 --- a/components/pthreads/pthread_tls.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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" - -_pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX]; - -void pthread_key_system_init() -{ - rt_memset(&_thread_keys[0], 0, sizeof(_thread_keys)); -} - -void *pthread_getspecific(pthread_key_t key) -{ - struct _pthread_data* ptd; - - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != NULL); - - if (ptd->tls == NULL) - return NULL; - - if ((key < PTHREAD_KEY_MAX) && (_thread_keys[key].is_used)) - return ptd->tls[key]; - - return NULL; -} -RTM_EXPORT(pthread_getspecific); - -int pthread_setspecific(pthread_key_t key, const void *value) -{ - struct _pthread_data* ptd; - - ptd = _pthread_get_data(rt_thread_self()); - RT_ASSERT(ptd != NULL); - - /* check tls area */ - if (ptd->tls == NULL) - { - ptd->tls = (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; - } - - return EINVAL; -} -RTM_EXPORT(pthread_setspecific); - -int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) -{ - rt_uint32_t index; - - rt_enter_critical(); - for (index = 0; index < PTHREAD_KEY_MAX; index ++) - { - if (_thread_keys[index].is_used == 0) - { - _thread_keys[index].is_used = 1; - _thread_keys[index].destructor = destructor; - - *key = index; - - rt_exit_critical(); - - return 0; - } - } - - rt_exit_critical(); - - return EAGAIN; -} -RTM_EXPORT(pthread_key_create); - -int pthread_key_delete(pthread_key_t key) -{ - if (key >= PTHREAD_KEY_MAX) - return EINVAL; - - rt_enter_critical(); - _thread_keys[key].is_used = 0; - _thread_keys[key].destructor = 0; - rt_exit_critical(); - - return 0; -} -RTM_EXPORT(pthread_key_delete); - diff --git a/components/pthreads/sched.c b/components/pthreads/sched.c deleted file mode 100644 index 6f75127bf2..0000000000 --- a/components/pthreads/sched.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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; -} -RTM_EXPORT(sched_yield); - -int sched_get_priority_min(int policy) -{ - if (policy != SCHED_FIFO && policy != SCHED_RR) - return EINVAL; - - return 0; -} -RTM_EXPORT(sched_get_priority_min); - -int sched_get_priority_max(int policy) -{ - if (policy != SCHED_FIFO && policy != SCHED_RR) - return EINVAL; - - return RT_THREAD_PRIORITY_MAX - 1; -} -RTM_EXPORT(sched_get_priority_max); - -int sched_setscheduler(pid_t pid, int policy) -{ - return EOPNOTSUPP; -} -RTM_EXPORT(sched_setscheduler); diff --git a/components/pthreads/sched.h b/components/pthreads/sched.h deleted file mode 100644 index 173f3eb2de..0000000000 --- a/components/pthreads/sched.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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__ - -#include -#include - -/* Thread scheduling policies */ -enum -{ - SCHED_OTHER = 0, - SCHED_FIFO, - SCHED_RR, - SCHED_MIN = SCHED_OTHER, - SCHED_MAX = SCHED_RR -}; - -struct sched_param -{ - int sched_priority; -}; - -#ifdef __cplusplus -extern "C" -{ -#endif - -int sched_yield(void); -int sched_get_priority_min(int policy); -int sched_get_priority_max(int policy); -int sched_setscheduler(pid_t pid, int policy); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/pthreads/semaphore.c b/components/pthreads/semaphore.c deleted file mode 100644 index ae69e0d1bc..0000000000 --- a/components/pthreads/semaphore.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * 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 -#include "semaphore.h" -#include "pthread_internal.h" - -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_inline void posix_sem_insert(sem_t *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; - - 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; - - /* 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; - - 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; -} - -int sem_close(sem_t *sem) -{ - 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; - } - rt_sem_release(&posix_sem_lock); - - return 0; -} -RTM_EXPORT(sem_close); - -int sem_destroy(sem_t *sem) -{ - rt_err_t result; - - if ((!sem) || !(sem->unamed)) - { - rt_set_errno(EINVAL); - - return -1; - } - - /* lock posix semaphore list */ - rt_sem_take(&posix_sem_lock, RT_WAITING_FOREVER); - result = rt_sem_trytake(sem->sem); - if (result != RT_EOK) - { - rt_sem_release(&posix_sem_lock); - rt_set_errno(EBUSY); - - return -1; - } - - /* destroy an unamed posix semaphore */ - posix_sem_delete(sem); - rt_sem_release(&posix_sem_lock); - - return 0; -} -RTM_EXPORT(sem_destroy); - -int sem_unlink(const char *name) -{ - 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); - } - 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; -} -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; - - if (sem == RT_NULL) - { - rt_set_errno(EINVAL); - - return -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; -} -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 = 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_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; - - /* 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 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; - - if (!sem) - { - 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; - - 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; - - rt_set_errno(EINTR); - - return -1; -} -RTM_EXPORT(sem_timedwait); - -int sem_trywait(sem_t *sem) -{ - rt_err_t result; - - if (!sem) - { - rt_set_errno(EINVAL); - - 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; - - if (!sem) - { - rt_set_errno(EINVAL); - - 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 deleted file mode 100644 index 664c15ee2e..0000000000 --- a/components/pthreads/semaphore.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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__ - -#include -#include - -struct posix_sem -{ - /* reference count and unlinked */ - rt_uint16_t refcount; - rt_uint8_t unlinked; - rt_uint8_t unamed; - - /* RT-Thread semaphore */ - rt_sem_t sem; - - /* next posix semaphore */ - struct posix_sem* next; -}; -typedef struct posix_sem sem_t; - -int sem_close(sem_t *sem); -int sem_destroy(sem_t *sem); -int sem_getvalue(sem_t *sem, int *sval); -int sem_init(sem_t *sem, int pshared, unsigned int value); -sem_t *sem_open(const char *name, int oflag, ...); -int sem_post(sem_t *sem); -int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); -int sem_trywait(sem_t *sem); -int sem_unlink(const char *name); -int sem_wait(sem_t *sem); - -#endif -- cgit v1.3.1