diff --git a/kal/posix/include/README b/kal/posix/include/README index 49d4d90b..57e9708a 100644 --- a/kal/posix/include/README +++ b/kal/posix/include/README @@ -1,12 +1,2 @@ -Root directory "//" refers to "/vendor/hisi/hi3861/hi3861". -We use header files from musl ("//platform/os/Huawei_LiteOS/components/lib/libc/musl/include"). - -Some posix apis are already defined in different places: -errno is defined in //build/libs/libc_base.o -malloc and free are defined in //build/libs/libc_base.o -pthread_mutex_* are defined in //build/libs/hi3861/release/no_mesh/liblitekernel_flash.a -semaphore is defined in //build/libs/hi3861/release/no_mesh/liblitekernel_flash.a -usleep is defined in //build/libs/hi3861/release/no_mesh/liblitekernel_flash.a -clock_* are defined in //build/libs/liblitekernel_base.o -printf is defined in //build/libs/liblitekernel_base.o -fcntl and socket apis are defined in //build/libs/liblwip.a + ** DO NOT EDIT FILES HERE ** +These header files are copied from musl ("//third_party/musl") except `libc.h'. diff --git a/kal/posix/include/version.h b/kal/posix/include/libc.h similarity index 94% rename from kal/posix/include/version.h rename to kal/posix/include/libc.h index 0394ff96..92c9e265 100644 --- a/kal/posix/include/version.h +++ b/kal/posix/include/libc.h @@ -1,46 +1,46 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef VERSION_H_ -#define VERSION_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -const char *libc_get_version_string(void); -int libc_get_version(void); - -#ifdef __cplusplus -} -#endif - -#endif // VERSION_H_ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LIBC_H_ +#define LIBC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +const char *libc_get_version_string(void); +int libc_get_version(void); + +#ifdef __cplusplus +} +#endif + +#endif // LIBC_H_ diff --git a/kal/posix/src/errno.c b/kal/posix/src/errno.c new file mode 100644 index 00000000..0d3bda0d --- /dev/null +++ b/kal/posix/src/errno.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "los_interrupt.h" +#include "los_task.h" + +/* the specific errno get or set in interrupt service routine */ +static int g_isrErrno; + +int *__errno_location(void) +{ + LosTaskCB *runTask = NULL; + + if (OS_INT_INACTIVE) { + runTask = OS_TCB_FROM_TID(LOS_CurTaskIDGet()); + return &runTask->errorNo; + } else { + return &g_isrErrno; + } +} diff --git a/kal/posix/src/file.c b/kal/posix/src/file.c index fc604a94..ff2d99f4 100644 --- a/kal/posix/src/file.c +++ b/kal/posix/src/file.c @@ -33,21 +33,151 @@ #include #include #include -#include "lwip/sockets.h" +#include +#include + #include "hks_client.h" -#define RANDOM_DEV_FD LWIP_CONFIG_NUM_SOCKETS +#ifdef LOSCFG_NET_LWIP_SACK +#include "lwip/lwipopts.h" +#define CONFIG_NSOCKET_DESCRIPTORS LWIP_CONFIG_NUM_SOCKETS +#else +#define CONFIG_NSOCKET_DESCRIPTORS 0 +#endif +#define CONFIG_NFILE_DESCRIPTORS 1 /* only for random currently */ + +#define RANDOM_DEV_FD CONFIG_NSOCKET_DESCRIPTORS #define RANDOM_DEV_PATH "/dev/random" +#define FREE_AND_SET_NULL(ptr) do { \ + free(ptr); \ + ptr = NULL; \ +} while (0) + +/** + * @brief Get canonical form of a given path based on cwd(Current working directory). + * + * @param cwd Indicates the current working directory. + * @param path Indicates the path to be canonicalization. + * @param buf Indicates the pointer to the buffer where the result will be return. + * @param bufSize Indicates the size of the buffer. + * @return Returns the length of the canonical path. + * + * @attention if path is an absolute path, cwd is ignored. if cwd if not specified, it is assumed to be root('/'). + * if the buffer is not big enough the result will be truncated, but the return value will always be the + * length of the canonical path. + */ +static size_t GetCanonicalPath(const char *cwd, const char *path, char *buf, size_t bufSize) +{ + if (!path) { + path = ""; + } + + if (!cwd || path[0] == '/') { + cwd = ""; + } + + size_t tmpLen = strlen(cwd) + strlen(path) + 4; // three '/' and one '\0' + char *tmpBuf = (char *)malloc(tmpLen); + if (tmpBuf == NULL) { + return 0; + } + + if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) { + free(tmpBuf); + return 0; + } + + char *p; + /* replace /./ to / */ + while ((p = strstr(tmpBuf, "/./")) != NULL) { + if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 2, tmpLen - (p - tmpBuf) - 2)) { + free(tmpBuf); + return 0; + } + } + + /* replace // to / */ + while ((p = strstr(tmpBuf, "//")) != NULL) { + if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) { + free(tmpBuf); + return 0; + } + } + + /* handle /../ (e.g., replace /aa/bb/../ to /aa/) */ + while ((p = strstr(tmpBuf, "/../")) != NULL) { + char *start = p; + while (start > tmpBuf && *--start != '/') { + } + if (EOK != memmove_s(start, tmpLen - (start - tmpBuf), p + 3, tmpLen - (p - tmpBuf) - 3)) { + free(tmpBuf); + return 0; + } + } + + size_t totalLen = strlen(tmpBuf); + + /* strip the last / */ + if (totalLen > 1 && tmpBuf[totalLen - 1] == '/') { + tmpBuf[--totalLen] = 0; + } + + if (!buf || bufSize == 0) { + free(tmpBuf); + return totalLen; + } + + if (EOK != memcpy_s(buf, bufSize, tmpBuf, (totalLen + 1 > bufSize) ? bufSize : totalLen + 1)) { + free(tmpBuf); + return 0; + } + + buf[bufSize - 1] = 0; + free(tmpBuf); + return totalLen; +} + int open(const char *file, int oflag, ...) { - if (strcmp(file, RANDOM_DEV_PATH) == 0) { - if (oflag != O_RDONLY) { - errno = EINVAL; + unsigned flags = O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_LARGEFILE | O_TRUNC | O_EXCL | O_DIRECTORY; + if ((unsigned)oflag & ~flags) { + errno = EINVAL; + return -1; + } + size_t pathLen = strlen(file) + 1; + char *canonicalPath = (char *)malloc(pathLen); + if (!canonicalPath) { + errno = ENOMEM; + return -1; + } + if (GetCanonicalPath(NULL, file, canonicalPath, pathLen) == 0) { + FREE_AND_SET_NULL(canonicalPath); + errno = ENOMEM; + return -1; + } + if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) { + FREE_AND_SET_NULL(canonicalPath); + if ((O_ACCMODE & (unsigned)oflag) != O_RDONLY) { + errno = EPERM; + return -1; + } + if ((unsigned)oflag & O_DIRECTORY) { + errno = ENOTDIR; return -1; } return RANDOM_DEV_FD; } + if (strcmp(canonicalPath, "/") == 0 || strcmp(canonicalPath, "/dev") == 0) { + FREE_AND_SET_NULL(canonicalPath); + if ((unsigned)oflag & O_DIRECTORY) { + errno = EPERM; + return -1; + } + errno = EISDIR; + return -1; + } + FREE_AND_SET_NULL(canonicalPath); errno = ENOENT; return -1; } @@ -57,7 +187,13 @@ int close(int fd) if (fd == RANDOM_DEV_FD) { return 0; } - return closesocket(fd); +#ifdef LOSCFG_NET_LWIP_SACK + if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { + return closesocket(fd); + } +#endif + errno = EBADF; + return -1; } ssize_t read(int fd, void *buf, size_t nbytes) @@ -80,7 +216,13 @@ ssize_t read(int fd, void *buf, size_t nbytes) } return (ssize_t)nbytes; } - return recv(fd, buf, nbytes, 0); +#ifdef LOSCFG_NET_LWIP_SACK + if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { + return recv(fd, buf, nbytes, 0); + } +#endif + errno = EBADF; + return -1; } ssize_t write(int fd, const void *buf, size_t nbytes) @@ -89,5 +231,11 @@ ssize_t write(int fd, const void *buf, size_t nbytes) errno = EBADF; /* "/dev/random" is readonly */ return -1; } - return send(fd, buf, nbytes, 0); +#ifdef LOSCFG_NET_LWIP_SACK + if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) { + return send(fd, buf, nbytes, 0); + } +#endif + errno = EBADF; + return -1; } diff --git a/kal/posix/src/version.c b/kal/posix/src/libc.c similarity index 97% rename from kal/posix/src/version.c rename to kal/posix/src/libc.c index a701d930..dd48eba0 100644 --- a/kal/posix/src/version.c +++ b/kal/posix/src/libc.c @@ -29,7 +29,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include "libc_config.h" /** * get libc version string. diff --git a/kal/posix/src/libc_config.h b/kal/posix/src/libc_config.h new file mode 100644 index 00000000..eca96f86 --- /dev/null +++ b/kal/posix/src/libc_config.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LIBC_CONFIG_H_ +#define LIBC_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBC_VERSION_STR +#define LIBC_VERSION_STR "1.0.0-LiteOS_M" +#endif + +#ifndef LIBC_VERSION_NUM +#define LIBC_VERSION_NUM 0x00010000 +#endif + +#ifdef __cplusplus +} +#endif + +#endif // LIBC_CONFIG_H_ diff --git a/kal/posix/src/malloc.c b/kal/posix/src/malloc.c new file mode 100644 index 00000000..c594837c --- /dev/null +++ b/kal/posix/src/malloc.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "securec.h" +#include "los_config.h" +#include "los_memory.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ + +void *calloc(size_t nitems, size_t size) +{ + size_t real_size; + void *ptr = NULL; + + if (nitems == 0 || size == 0) { + return NULL; + } + + real_size = (size_t)(nitems * size); + ptr = LOS_MemAlloc(OS_SYS_MEM_ADDR, real_size); + if (ptr != NULL) { + (void)memset_s(ptr, real_size, 0, real_size); + } + return ptr; +} + +void free(void *ptr) +{ + if (ptr == NULL) { + return; + } + + LOS_MemFree(OS_SYS_MEM_ADDR, ptr); +} + +void *malloc(size_t size) +{ + if (size == 0) { + return NULL; + } + + return LOS_MemAlloc(OS_SYS_MEM_ADDR, size); +} + +void *zalloc(size_t size) +{ + void *ptr = NULL; + + if (size == 0) { + return NULL; + } + + ptr = LOS_MemAlloc(OS_SYS_MEM_ADDR, size); + if (ptr != NULL) { + (void)memset_s(ptr, size, 0, size); + } + return ptr; +} + +void *memalign(size_t boundary, size_t size) +{ + if (size == 0) { + return NULL; + } + + return LOS_MemAllocAlign(OS_SYS_MEM_ADDR, size, boundary); +} + +void *realloc(void *ptr, size_t size) +{ + if (ptr == NULL) { + return malloc(size); + } + + if (size == 0) { + free(ptr); + return NULL; + } + + return LOS_MemRealloc(OS_SYS_MEM_ADDR, ptr, size); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cpluscplus */ +#endif /* __cpluscplus */ diff --git a/kal/posix/src/pthread.c b/kal/posix/src/pthread.c index f7789932..2ef0dcc5 100644 --- a/kal/posix/src/pthread.c +++ b/kal/posix/src/pthread.c @@ -29,43 +29,42 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "pthread_impl.h" #include -#include +#include #include #include +#include "los_config.h" #include "los_task.h" -#include "los_task_pri.h" #define PTHREAD_NAMELEN 16 -/* this is just an assertion: LOS_TASK_ARG_NUM >= 4 */ -typedef char NULNAM[-!((LOS_TASK_ARG_NUM * 4) >= PTHREAD_NAMELEN)]; +typedef struct { + void *(*startRoutine)(void *); + void *param; + char name[PTHREAD_NAMELEN]; +}PthreadData; -static void *_pthread_entry(UINT32 param1, UINT32 param2, UINT32 param3, UINT32 param4) +static void *PthreadEntry(UINT32 param) { - void *(*startRoutine)(void *) = (void *)(UINTPTR)param1; - void *param = (void *)(UINTPTR)param2; - (void)param3; - (void)param4; - int ret; + PthreadData *pthreadData = (PthreadData *)(UINTPTR)param; + void *(*startRoutine)(void *) = pthreadData->startRoutine; + void *ret = startRoutine(pthreadData->param); + free(pthreadData); + return ret; +} - LosTaskCB *tcb = OS_TCB_FROM_TID(LOS_CurTaskIDGet()); - char *tmp = tcb->taskName; - tcb->taskName = (char *)tcb->args; /* args are reused as task name */ - ret = strcpy_s(tcb->taskName, PTHREAD_NAMELEN, tmp); - if (ret != 0) { - free(tmp); - return NULL; - } - free(tmp); - - return startRoutine(param); +static inline int IsPthread(pthread_t thread) +{ + return ((UINT32)thread <= LOSCFG_BASE_CORE_TSK_LIMIT) && + (OS_TCB_FROM_TID((UINT32)thread)->taskEntry == PthreadEntry); } int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*startRoutine)(void *), void *arg) { TSK_INIT_PARAM_S taskInitParam = {0}; + PthreadData *pthreadData = NULL; UINT32 taskID; if ((thread == NULL) || (startRoutine == NULL)) { @@ -87,17 +86,17 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr, taskInitParam.usTaskPrio = (UINT16)attr->schedparam.sched_priority; } - taskInitParam.pcName = malloc(PTHREAD_NAMELEN); - if (taskInitParam.pcName == NULL) { + pthreadData = (PthreadData *)malloc(sizeof(PthreadData)); + if (pthreadData == NULL) { return ENOMEM; } - taskInitParam.pfnTaskEntry = _pthread_entry; - taskInitParam.auwArgs[0] = (UINT32)(UINTPTR)startRoutine; - taskInitParam.auwArgs[1] = (UINT32)(UINTPTR)arg; + taskInitParam.pcName = pthreadData->name; + taskInitParam.pfnTaskEntry = PthreadEntry; + taskInitParam.uwArg = (UINT32)(UINTPTR)pthreadData; if (LOS_TaskCreate(&taskID, &taskInitParam) != LOS_OK) { - free(taskInitParam.pcName); + free(pthreadData); return EINVAL; } @@ -105,12 +104,13 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr, (void)sprintf_s(taskInitParam.pcName, PTHREAD_NAMELEN, "pthread%u", taskID); *thread = (pthread_t)taskID; - return ENOERR; + return 0; } int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param) { - if ((param == NULL) || (param->sched_priority > OS_TASK_PRIORITY_LOWEST)) { + if ((param == NULL) || (param->sched_priority < OS_TASK_PRIORITY_HIGHEST) || + (param->sched_priority >= OS_TASK_PRIORITY_LOWEST) || !IsPthread(thread)) { return EINVAL; } @@ -123,14 +123,14 @@ int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param return EINVAL; } - return ENOERR; + return 0; } int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param) { UINT32 prio; - if ((policy == NULL) || (param == NULL)) { + if ((policy == NULL) || (param == NULL) || !IsPthread(thread)) { return EINVAL; } @@ -141,7 +141,7 @@ int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *par *policy = SCHED_RR; param->sched_priority = prio; - return ENOERR; + return 0; } pthread_t pthread_self(void) @@ -151,36 +151,21 @@ pthread_t pthread_self(void) int pthread_cancel(pthread_t thread) { - (void)thread; + if (!IsPthread(thread)) { + return EINVAL; + } + return ENOSYS; } -static void *void_task(UINT32 param1, UINT32 param2, UINT32 param3, UINT32 param4) -{ - (void)param1; - (void)param2; - (void)param3; - (void)param4; - return 0; -} - -static void cleanup_task_resource(void) -{ - TSK_INIT_PARAM_S taskInitParam = {0}; - UINT32 taskID; - - taskInitParam.pcName = "void"; - taskInitParam.pfnTaskEntry = void_task; - taskInitParam.usTaskPrio = LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO; - taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_MIN_STACK_SIZE; - - (void)LOS_TaskCreate(&taskID, &taskInitParam); -} - int pthread_join(pthread_t thread, void **retval) { UINT32 taskStatus; + if (!IsPthread(thread)) { + return EINVAL; + } + if (retval) { /* retrieve thread exit code is not supported currently */ return ENOTSUP; @@ -194,26 +179,30 @@ int pthread_join(pthread_t thread, void **retval) usleep(10000); } - cleanup_task_resource(); return 0; } int pthread_detach(pthread_t thread) { - (void)thread; + if (!IsPthread(thread)) { + return EINVAL; + } + return ENOSYS; } void pthread_exit(void *retVal) { (void)retVal; + LosTaskCB *tcb = OS_TCB_FROM_TID(LOS_CurTaskIDGet()); + free((PthreadData *)(UINTPTR)tcb->arg); (void)LOS_TaskDelete(LOS_CurTaskIDGet()); } int pthread_setname_np(pthread_t thread, const char *name) { char *taskName = LOS_TaskNameGet((UINT32)thread); - if (taskName == NULL) { + if (taskName == NULL || !IsPthread(thread)) { return EINVAL; } if (strnlen(name, PTHREAD_NAMELEN) >= PTHREAD_NAMELEN) { @@ -228,7 +217,7 @@ int pthread_getname_np(pthread_t thread, char *buf, size_t buflen) int ret; const char *name = LOS_TaskNameGet((UINT32)thread); - if (name == NULL) { + if (name == NULL || !IsPthread(thread)) { return EINVAL; } if (buflen > strlen(name)) { diff --git a/kal/posix/src/pthread_attr.c b/kal/posix/src/pthread_attr.c index 7ba709c1..c5dfeda6 100644 --- a/kal/posix/src/pthread_attr.c +++ b/kal/posix/src/pthread_attr.c @@ -29,11 +29,10 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "pthread_impl.h" #include -#include - -#define PTHREAD_STACK_MIN LOSCFG_BASE_CORE_TSK_MIN_STACK_SIZE - +#include +#include "los_config.h" int pthread_attr_init(pthread_attr_t *attr) { @@ -51,7 +50,7 @@ int pthread_attr_init(pthread_attr_t *attr) attr->stacksize_set = 1; attr->stacksize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - return ENOERR; + return 0; } int pthread_attr_destroy(pthread_attr_t *attr) @@ -61,14 +60,14 @@ int pthread_attr_destroy(pthread_attr_t *attr) } /* Nothing to do here... */ - return ENOERR; + return 0; } int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachState) { if ((attr != NULL) && ((detachState == PTHREAD_CREATE_JOINABLE) || (detachState == PTHREAD_CREATE_DETACHED))) { attr->detachstate = (UINT32)detachState; - return ENOERR; + return 0; } return EINVAL; @@ -82,7 +81,7 @@ int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachState) *detachState = (int)attr->detachstate; - return ENOERR; + return 0; } int pthread_attr_setscope(pthread_attr_t *attr, int scope) @@ -93,7 +92,7 @@ int pthread_attr_setscope(pthread_attr_t *attr, int scope) if (scope == PTHREAD_SCOPE_PROCESS) { attr->scope = (unsigned int)scope; - return ENOERR; + return 0; } if (scope == PTHREAD_SCOPE_SYSTEM) { @@ -111,14 +110,14 @@ int pthread_attr_getscope(const pthread_attr_t *attr, int *scope) *scope = (int)attr->scope; - return ENOERR; + return 0; } int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) { if ((attr != NULL) && ((inherit == PTHREAD_INHERIT_SCHED) || (inherit == PTHREAD_EXPLICIT_SCHED))) { attr->inheritsched = (UINT32)inherit; - return ENOERR; + return 0; } return EINVAL; @@ -132,14 +131,14 @@ int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) *inherit = (int)attr->inheritsched; - return ENOERR; + return 0; } int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) { if ((attr != NULL) && (policy == SCHED_RR)) { attr->schedpolicy = SCHED_RR; - return ENOERR; + return 0; } return EINVAL; @@ -153,20 +152,21 @@ int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) *policy = (int)attr->schedpolicy; - return ENOERR; + return 0; } int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) { if ((attr == NULL) || (param == NULL)) { return EINVAL; - } else if ((param->sched_priority < 0) || (param->sched_priority > OS_TASK_PRIORITY_LOWEST)) { + } else if ((param->sched_priority < LOS_TASK_PRIORITY_HIGHEST) || + (param->sched_priority >= LOS_TASK_PRIORITY_LOWEST)) { return ENOTSUP; } attr->schedparam = *param; - return ENOERR; + return 0; } int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) @@ -177,7 +177,7 @@ int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *p *param = attr->schedparam; - return ENOERR; + return 0; } /* @@ -194,14 +194,14 @@ int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackAddr) attr->stackaddr_set = 1; attr->stackaddr = stackAddr; - return ENOERR; + return 0; } int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackAddr) { if (((attr != NULL) && (stackAddr != NULL)) && attr->stackaddr_set) { *stackAddr = attr->stackaddr; - return ENOERR; + return 0; } return EINVAL; /* Stack address not set, return EINVAL. */ @@ -217,7 +217,7 @@ int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stackSize) attr->stacksize_set = 1; attr->stacksize = stackSize; - return ENOERR; + return 0; } int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stackSize) @@ -229,5 +229,5 @@ int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stackSize) *stackSize = attr->stacksize; - return ENOERR; + return 0; } diff --git a/kal/posix/src/pthread_impl.h b/kal/posix/src/pthread_impl.h new file mode 100644 index 00000000..1ede97de --- /dev/null +++ b/kal/posix/src/pthread_impl.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PTHREAD_IMPL_H_ +#define PTHREAD_IMPL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct __pthread_attr_s pthread_attr_t; +#define __DEFINED_pthread_attr_t + +#ifdef __cplusplus +} +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct __pthread_attr_s { + unsigned int detachstate; + unsigned int schedpolicy; + struct sched_param schedparam; + unsigned int inheritsched; + unsigned int scope; + unsigned int stackaddr_set; + void* stackaddr; + unsigned int stacksize_set; + size_t stacksize; +} pthread_attr_t; + +#ifdef __cplusplus +} +#endif + +#endif // PTHREAD_IMPL_H_ diff --git a/kal/posix/src/pthread_mutex.c b/kal/posix/src/pthread_mutex.c new file mode 100644 index 00000000..98b7ba2d --- /dev/null +++ b/kal/posix/src/pthread_mutex.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "los_compiler.h" +#include "los_mux.h" +#include "errno.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define OS_SYS_NS_PER_MSECOND 1000000 +#define OS_SYS_NS_PER_SECOND 1000000000 + +static inline int MapError(UINT32 err) +{ + switch (err) { + case LOS_OK: + return 0; + case LOS_ERRNO_MUX_PEND_INTERR: + return EPERM; + case LOS_ERRNO_MUX_PEND_IN_LOCK: + return EDEADLK; + case LOS_ERRNO_MUX_PENDED: + case LOS_ERRNO_MUX_UNAVAILABLE: + return EBUSY; + case LOS_ERRNO_MUX_TIMEOUT: + return ETIMEDOUT; + case LOS_ERRNO_MUX_ALL_BUSY: + return EAGAIN; + case LOS_ERRNO_MUX_INVALID: + default: + return EINVAL; + } +} + +/* Initialize mutex. If mutexAttr is NULL, use default attributes. */ +int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexAttr) +{ + UINT32 muxHandle; + UINT32 ret; + + if (mutexAttr != NULL) { + return EOPNOTSUPP; + } + + ret = LOS_MuxCreate(&muxHandle); + if (ret != LOS_OK) { + return MapError(ret); + } + + mutex->magic = _MUX_MAGIC; + mutex->handle = muxHandle; + + return 0; +} + +int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + UINT32 ret; + if (mutex->magic != _MUX_MAGIC) { + return EINVAL; + } + ret = LOS_MuxDelete(mutex->handle); + if (ret != LOS_OK) { + return MapError(ret); + } + mutex->handle = _MUX_INVALID_HANDLE; + return 0; +} + +int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *absTimeout) +{ + UINT32 ret; + UINT32 timeout; + UINT64 timeoutNs; + struct timespec curTime = {0}; + if ((mutex->magic != _MUX_MAGIC) || (absTimeout->tv_nsec < 0) || (absTimeout->tv_nsec >= OS_SYS_NS_PER_SECOND)) { + return EINVAL; + } + if (mutex->handle == _MUX_INVALID_HANDLE) { + ret = LOS_MuxCreate(&mutex->handle); + if (ret != LOS_OK) { + return MapError(ret); + } + } + ret = clock_gettime(CLOCK_REALTIME, &curTime); + if (ret != LOS_OK) { + return EINVAL; + } + timeoutNs = (absTimeout->tv_sec - curTime.tv_sec) * OS_SYS_NS_PER_SECOND + (absTimeout->tv_nsec - curTime.tv_nsec); + if (timeoutNs <= 0) { + return ETIMEDOUT; + } + timeout = (timeoutNs + (OS_SYS_NS_PER_MSECOND - 1)) / OS_SYS_NS_PER_MSECOND; + ret = LOS_MuxPend(mutex->handle, timeout); + return MapError(ret); +} + +/* Lock mutex, waiting for it if necessary. */ +int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + UINT32 ret; + if (mutex->magic != _MUX_MAGIC) { + return EINVAL; + } + if (mutex->handle == _MUX_INVALID_HANDLE) { + ret = LOS_MuxCreate(&mutex->handle); + if (ret != LOS_OK) { + return MapError(ret); + } + } + ret = LOS_MuxPend(mutex->handle, LOS_WAIT_FOREVER); + return MapError(ret); +} + +int pthread_mutex_trylock(pthread_mutex_t *mutex) +{ + UINT32 ret; + if (mutex->magic != _MUX_MAGIC) { + return EINVAL; + } + if (mutex->handle == _MUX_INVALID_HANDLE) { + ret = LOS_MuxCreate(&mutex->handle); + if (ret != LOS_OK) { + return MapError(ret); + } + } + ret = LOS_MuxPend(mutex->handle, 0); + return MapError(ret); +} + +int pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + UINT32 ret; + if (mutex->magic != _MUX_MAGIC) { + return EINVAL; + } + ret = LOS_MuxPost(mutex->handle); + return MapError(ret); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ diff --git a/kal/posix/src/semaphore.c b/kal/posix/src/semaphore.c new file mode 100644 index 00000000..a640df62 --- /dev/null +++ b/kal/posix/src/semaphore.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "los_sem.h" + +#define _SEM_MAGIC 0xEBCFDEA1 + +#define s_magic __val[0] +#define s_handle __val[1] + +static inline int MapError(UINT32 err) +{ + switch (err) { + case LOS_OK: + return 0; + case LOS_ERRNO_SEM_INVALID: + case LOS_ERRNO_SEM_UNAVAILABLE: + return EINVAL; + case LOS_ERRNO_SEM_ALL_BUSY: + return ENOSPC; + case LOS_ERRNO_SEM_OVERFLOW: + return ENOMEM; + case LOS_ERRNO_SEM_PENDED: + return EBUSY; + case LOS_ERRNO_SEM_PEND_IN_LOCK: + return EPERM; + case LOS_ERRNO_SEM_PEND_INTERR: + return EINTR; + case LOS_ERRNO_SEM_TIMEOUT: + return ETIMEDOUT; + default: + return EINVAL; + } +} + +int sem_init(sem_t *sem, int shared, unsigned int value) +{ + UINT32 semHandle = 0; + UINT32 ret; + + (VOID)shared; + if ((sem == NULL) || (value >= OS_SEM_COUNTING_MAX_COUNT)) { + errno = EINVAL; + return -1; + } + + ret = LOS_SemCreate(value, &semHandle); + if (ret != LOS_OK) { + errno = MapError(ret); + return -1; + } + + sem->s_magic = _SEM_MAGIC; + sem->s_handle = (int)semHandle; + + return 0; +} + +int sem_destroy(sem_t *sem) +{ + UINT32 ret; + + if ((sem == NULL) || (sem->s_magic != _SEM_MAGIC)) { + errno = EINVAL; + return -1; + } + + ret = LOS_SemDelete((UINT32)sem->s_handle); + if (ret != LOS_OK) { + errno = MapError(ret); + return -1; + } + return 0; +} + +int sem_wait(sem_t *sem) +{ + UINT32 ret; + + if ((sem == NULL) || (sem->s_magic != _SEM_MAGIC)) { + errno = EINVAL; + return -1; + } + + ret = LOS_SemPend((UINT32)sem->s_handle, LOS_WAIT_FOREVER); + if (ret != LOS_OK) { + errno = MapError(ret); + return -1; + } + return 0; +} + +int sem_post(sem_t *sem) +{ + UINT32 ret; + + if ((sem == NULL) || (sem->s_magic != _SEM_MAGIC)) { + errno = EINVAL; + return -1; + } + + ret = LOS_SemPost((UINT32)sem->s_handle); + if (ret != LOS_OK) { + errno = MapError(ret); + return -1; + } + + return 0; +} diff --git a/kal/posix/src/time.c b/kal/posix/src/time.c index dcdb598d..4a8a5b54 100644 --- a/kal/posix/src/time.c +++ b/kal/posix/src/time.c @@ -29,12 +29,16 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include +#include +#include #include #include -#include -#include +#include "los_debug.h" +#include "los_task.h" +#include "los_swtmr.h" +#include "los_timer.h" +#include "los_context.h" #ifndef STATIC #define STATIC static @@ -45,11 +49,8 @@ #define OS_SYS_US_PER_SECOND 1000000 #define OS_SYS_MS_PER_SECOND 1000 -STATIC INLINE BOOL ValidTimerID(UINT16 swtmrID) -{ - /* check timer id */ - return (swtmrID < LOSCFG_BASE_CORE_SWTMR_LIMIT); -} +/* accumulative time delta from discontinuous modify */ +STATIC struct timespec g_accDeltaFromSet; /* internal functions */ STATIC INLINE BOOL ValidTimeSpec(const struct timespec *tp) @@ -87,19 +88,38 @@ STATIC INLINE VOID OsTick2TimeSpec(struct timespec *tp, UINT32 tick) tp->tv_nsec = (long)(ns % OS_SYS_NS_PER_SECOND); } -int nanosleep(const struct timespec *req, struct timespec *rem) +int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { - UINT64 us = (UINT64)req->tv_sec * OS_SYS_US_PER_SECOND + (req->tv_nsec + OS_SYS_NS_PER_US - 1) / OS_SYS_NS_PER_US; - if (us > 0xFFFFFFFFU) { + UINT64 nseconds; + UINT64 tick; + UINT32 ret; + const UINT32 nsPerTick = OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND; + + if (!ValidTimeSpec(rqtp)) { errno = EINVAL; return -1; } - if (usleep(us) == 0) { - if (rem) { - rem->tv_sec = rem->tv_nsec = 0; + + nseconds = (UINT64)rqtp->tv_sec * OS_SYS_NS_PER_SECOND + rqtp->tv_nsec; + + tick = (nseconds + nsPerTick - 1) / nsPerTick; // Round up for ticks + + if (tick >= UINT32_MAX) { + errno = EINVAL; + return -1; + } + + /* PS: skip the first tick because it is NOT a full tick. */ + ret = LOS_TaskDelay(tick ? (UINT32)(tick + 1) : 0); + if (ret == LOS_OK || ret == LOS_ERRNO_TSK_YIELD_NOT_ENOUGH_TASK) { + if (rmtp) { + rmtp->tv_sec = rmtp->tv_nsec = 0; } return 0; } + + /* sleep in interrupt context or in task sched lock state */ + errno = EPERM; return -1; } @@ -119,7 +139,11 @@ int timer_create(clockid_t clockID, struct sigevent *restrict evp, timer_t *rest } ret = LOS_SwtmrCreate(1, LOS_SWTMR_MODE_ONCE, (SWTMR_PROC_FUNC)evp->sigev_notify_function, - &swtmrID, (UINT32)(UINTPTR)evp->sigev_value.sival_ptr); + &swtmrID, (UINT32)(UINTPTR)evp->sigev_value.sival_ptr +#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1) + , OS_SWTMR_ROUSES_IGNORE, OS_SWTMR_ALIGN_INSENSITIVE +#endif + ); if (ret != LOS_OK) { errno = (ret == LOS_ERRNO_SWTMR_MAXSIZE) ? EAGAIN : EINVAL; return -1; @@ -132,12 +156,6 @@ int timer_create(clockid_t clockID, struct sigevent *restrict evp, timer_t *rest int timer_delete(timer_t timerID) { UINT16 swtmrID = (UINT16)(UINTPTR)timerID; - - if (!ValidTimerID(swtmrID)) { - errno = EINVAL; - return -1; - } - if (LOS_SwtmrDelete(swtmrID) != LOS_OK) { errno = EINVAL; return -1; @@ -150,6 +168,7 @@ int timer_settime(timer_t timerID, int flags, const struct itimerspec *restrict value, struct itimerspec *restrict oldValue) { + UINTPTR intSave; UINT16 swtmrID = (UINT16)(UINTPTR)timerID; SWTMR_CTRL_S *swtmr = NULL; UINT32 interval, expiry, ret; @@ -160,7 +179,7 @@ int timer_settime(timer_t timerID, int flags, return -1; } - if (value == NULL || !ValidTimerID(swtmrID)) { + if (value == NULL) { errno = EINVAL; return -1; } @@ -189,13 +208,11 @@ int timer_settime(timer_t timerID, int flags, return -1; } + intSave = LOS_IntLock(); swtmr = OS_SWT_FROM_SID(swtmrID); - ret = LOS_SwtmrModify(swtmrID, expiry, (interval ? LOS_SWTMR_MODE_PERIOD : LOS_SWTMR_MODE_NO_SELFDELETE), - swtmr->pfnHandler, swtmr->uwArg); - if (ret != LOS_OK) { - errno = EINVAL; - return -1; - } + swtmr->ucMode = (interval ? LOS_SWTMR_MODE_PERIOD : LOS_SWTMR_MODE_NO_SELFDELETE); + swtmr->uwInterval = interval; + LOS_IntRestore(intSave); if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0)) { /* @@ -221,7 +238,7 @@ int timer_gettime(timer_t timerID, struct itimerspec *value) UINT16 swtmrID = (UINT16)(UINTPTR)timerID; UINT32 ret; - if ((value == NULL) || !ValidTimerID(swtmrID)) { + if (value == NULL) { errno = EINVAL; return -1; } @@ -242,13 +259,168 @@ int timer_gettime(timer_t timerID, struct itimerspec *value) int timer_getoverrun(timer_t timerID) { - UINT16 swtmrID = (UINT16)(UINTPTR)timerID; - - if (!ValidTimerID(swtmrID)) { - errno = EINVAL; - return -1; - } + (void)timerID; errno = ENOSYS; return -1; } + +STATIC VOID OsGetHwTime(struct timespec *hwTime) +{ + UINT64 nowNsec; + UINT32 countHigh = 0; + UINT32 countLow = 0; + HalGetCpuCycle(&countHigh, &countLow); + nowNsec = (((UINT64)countHigh * OS_SYS_NS_PER_SECOND / OS_SYS_CLOCK) << 32) + + ((((UINT64)countHigh * OS_SYS_NS_PER_SECOND % OS_SYS_CLOCK) << 32) / OS_SYS_CLOCK) + + ((UINT64)countLow * OS_SYS_NS_PER_SECOND / OS_SYS_CLOCK); + hwTime->tv_sec = nowNsec / OS_SYS_NS_PER_SECOND; + hwTime->tv_nsec = nowNsec % OS_SYS_NS_PER_SECOND; +} + +STATIC VOID OsGetRealTime(struct timespec *realTime) +{ + UINTPTR intSave; + struct timespec hwTime = {0}; + OsGetHwTime(&hwTime); + intSave = LOS_IntLock(); + realTime->tv_nsec = hwTime.tv_nsec + g_accDeltaFromSet.tv_nsec; + realTime->tv_sec = hwTime.tv_sec + g_accDeltaFromSet.tv_sec + (realTime->tv_nsec >= OS_SYS_NS_PER_SECOND); + realTime->tv_nsec %= OS_SYS_NS_PER_SECOND; + LOS_IntRestore(intSave); +} + +STATIC VOID OsSetRealTime(const struct timespec *realTime) +{ + UINTPTR intSave; + struct timespec hwTime = {0}; + OsGetHwTime(&hwTime); + intSave = LOS_IntLock(); + g_accDeltaFromSet.tv_nsec = realTime->tv_nsec - hwTime.tv_nsec; + g_accDeltaFromSet.tv_sec = realTime->tv_sec - hwTime.tv_sec - (g_accDeltaFromSet.tv_nsec < 0); + g_accDeltaFromSet.tv_nsec = (g_accDeltaFromSet.tv_nsec + OS_SYS_NS_PER_SECOND) % OS_SYS_NS_PER_SECOND; + LOS_IntRestore(intSave); +} + +int clock_settime(clockid_t clockID, const struct timespec *tp) +{ + if (!ValidTimeSpec(tp)) { + errno = EINVAL; + return -1; + } + + switch (clockID) { + case CLOCK_REALTIME: + /* we only support the realtime clock currently */ + OsSetRealTime(tp); + return 0; + case CLOCK_MONOTONIC_COARSE: + case CLOCK_REALTIME_COARSE: + case CLOCK_MONOTONIC_RAW: + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_BOOTTIME: + case CLOCK_REALTIME_ALARM: + case CLOCK_BOOTTIME_ALARM: + case CLOCK_SGI_CYCLE: + case CLOCK_TAI: + case CLOCK_THREAD_CPUTIME_ID: + errno = ENOTSUP; + return -1; + case CLOCK_MONOTONIC: + default: + errno = EINVAL; + return -1; + } +} + +int clock_gettime(clockid_t clockID, struct timespec *tp) +{ + if (tp == NULL) { + errno = EINVAL; + return -1; + } + + switch (clockID) { + case CLOCK_MONOTONIC_RAW: + case CLOCK_MONOTONIC: + case CLOCK_MONOTONIC_COARSE: + OsGetHwTime(tp); + return 0; + case CLOCK_REALTIME: + case CLOCK_REALTIME_COARSE: + OsGetRealTime(tp); + return 0; + case CLOCK_THREAD_CPUTIME_ID: + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_BOOTTIME: + case CLOCK_REALTIME_ALARM: + case CLOCK_BOOTTIME_ALARM: + case CLOCK_SGI_CYCLE: + case CLOCK_TAI: + errno = ENOTSUP; + return -1; + default: + errno = EINVAL; + return -1; + } +} + +int clock_getres(clockid_t clockID, struct timespec *tp) +{ + if (tp == NULL) { + errno = EINVAL; + return -1; + } + + switch (clockID) { + case CLOCK_MONOTONIC_RAW: + case CLOCK_MONOTONIC: + case CLOCK_REALTIME: + case CLOCK_MONOTONIC_COARSE: + case CLOCK_REALTIME_COARSE: + tp->tv_nsec = OS_SYS_NS_PER_SECOND / OS_SYS_CLOCK; + tp->tv_sec = 0; + return 0; + case CLOCK_THREAD_CPUTIME_ID: + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_BOOTTIME: + case CLOCK_REALTIME_ALARM: + case CLOCK_BOOTTIME_ALARM: + case CLOCK_SGI_CYCLE: + case CLOCK_TAI: + errno = ENOTSUP; + return -1; + default: + errno = EINVAL; + return -1; + } +} + +int clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, struct timespec *rem) +{ + switch (clk) { + case CLOCK_REALTIME: + if (flags == 0) { + /* we only support the realtime clock currently */ + return nanosleep(req, rem); + } + /* fallthrough */ + case CLOCK_MONOTONIC_COARSE: + case CLOCK_REALTIME_COARSE: + case CLOCK_MONOTONIC_RAW: + case CLOCK_MONOTONIC: + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_BOOTTIME: + case CLOCK_REALTIME_ALARM: + case CLOCK_BOOTTIME_ALARM: + case CLOCK_SGI_CYCLE: + case CLOCK_TAI: + if (flags == 0 || flags == TIMER_ABSTIME) { + return ENOTSUP; + } + /* fallthrough */ + case CLOCK_THREAD_CPUTIME_ID: + default: + return EINVAL; + } +} diff --git a/kernel/include/los_task.h b/kernel/include/los_task.h index 28673c44..3e13c610 100644 --- a/kernel/include/los_task.h +++ b/kernel/include/los_task.h @@ -1611,6 +1611,7 @@ typedef struct { UINT32 eventMask; /**< Event mask */ UINT32 eventMode; /**< Event mode */ VOID *msg; /**< Memory allocated to queues */ + INT32 errorNo; } LosTaskCB; typedef struct {