diff --git a/kal/libc/musl/malloc.c b/kal/libc/musl/malloc.c index 434cba04..96ad102d 100644 --- a/kal/libc/musl/malloc.c +++ b/kal/libc/musl/malloc.c @@ -29,6 +29,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "securec.h" #include "los_config.h" #include "los_memory.h" @@ -39,7 +40,7 @@ void *calloc(size_t nitems, size_t size) size_t real_size; void *ptr = NULL; - if (nitems == 0 || size == 0) { + if ((nitems == 0) || (size == 0) || (nitems > (UINT32_MAX / size))) { return NULL; } diff --git a/kal/libc/newlib/BUILD.gn b/kal/libc/newlib/BUILD.gn index 4e4efc7d..27639840 100644 --- a/kal/libc/newlib/BUILD.gn +++ b/kal/libc/newlib/BUILD.gn @@ -40,7 +40,6 @@ kernel_module(module_name) { "porting/src/network/ntohl.c", "porting/src/network/ntohs.c", "porting/src/other_adapt.c", - "porting/src/pthread.c", "porting/src/time.c", ] configs += [ "$LITEOSTOPDIR:warn_config" ] diff --git a/kal/libc/newlib/porting/include/sys/_pthreadtypes.h b/kal/libc/newlib/porting/include/sys/_pthreadtypes.h index e864aa79..bb60f027 100644 --- a/kal/libc/newlib/porting/include/sys/_pthreadtypes.h +++ b/kal/libc/newlib/porting/include/sys/_pthreadtypes.h @@ -57,6 +57,7 @@ #undef _PTHREAD_ONCE_INIT #undef PTHREAD_STACK_MIN +#undef PTHREAD_MUTEX_DEFAULT #include "los_config.h" #define PTHREAD_STACK_MIN LOSCFG_BASE_CORE_TSK_MIN_STACK_SIZE @@ -76,17 +77,18 @@ typedef struct { } pthread_attr_t; #include "los_list.h" -typedef struct { unsigned int magic; unsigned int handle; } pthread_mutex_t; - typedef struct { unsigned type; } pthread_mutexattr_t; +typedef struct { unsigned int magic; unsigned int handle; pthread_mutexattr_t stAttr;} pthread_mutex_t; #define _MUX_MAGIC 0xEBCFDEA0 #define _MUX_INVALID_HANDLE 0xEEEEEEEF +#define PTHREAD_MUTEX_DEFAULT 0 -#define _PTHREAD_MUTEX_INITIALIZER { _MUX_MAGIC, _MUX_INVALID_HANDLE } +#define PTHREAD_MUTEXATTR_INITIALIZER { PTHREAD_MUTEX_RECURSIVE } +#define _PTHREAD_MUTEX_INITIALIZER { _MUX_MAGIC, _MUX_INVALID_HANDLE, PTHREAD_MUTEXATTR_INITIALIZER } #ifdef _GNU_SOURCE -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP { _MUX_MAGIC, _MUX_INVALID_HANDLE } +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP { _MUX_MAGIC, _MUX_INVALID_HANDLE, PTHREAD_MUTEXATTR_INITIALIZER } #endif #include "los_event.h" diff --git a/kal/libc/newlib/porting/include/sys/features.h b/kal/libc/newlib/porting/include/sys/features.h index d5444864..c6a58858 100644 --- a/kal/libc/newlib/porting/include/sys/features.h +++ b/kal/libc/newlib/porting/include/sys/features.h @@ -49,6 +49,7 @@ #define _POSIX_TIMEOUTS #define _POSIX_THREAD_PRIORITY_SCHEDULING #define _UNIX98_THREAD_MUTEX_ATTRIBUTES +#define _POSIX_THREAD_PROCESS_SHARED #include_next diff --git a/kal/libc/newlib/porting/src/pthread.c b/kal/libc/newlib/porting/src/pthread.c deleted file mode 100755 index ed3d4ce7..00000000 --- a/kal/libc/newlib/porting/src/pthread.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2022-2022 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 - -int pthread_equal(pthread_t __t1, pthread_t __t2) -{ - return (int)(__t1 == __t2); -} diff --git a/kal/posix/src/mqueue.c b/kal/posix/src/mqueue.c index 54f59a3c..03da4d3d 100644 --- a/kal/posix/src/mqueue.c +++ b/kal/posix/src/mqueue.c @@ -312,7 +312,7 @@ OUT: int mq_close(mqd_t personal) { - INT32 ret = 0; + INT32 ret = -1; struct mqarray *mqueueCB = NULL; struct mqpersonal *privateMqPersonal = NULL; struct mqpersonal *tmp = NULL; @@ -425,7 +425,7 @@ int OsMqSetAttr(mqd_t personal, const struct mq_attr *mqSetAttr, struct mq_attr return 0; } -int mq_getsetattr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) +static int MqGetSetAttr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) { if (new == NULL) { return OsMqGetAttr(mqd, old); @@ -439,7 +439,7 @@ int mq_getattr(mqd_t mqd, struct mq_attr *attr) errno = EBADF; return -1; } - return mq_getsetattr(mqd, 0, attr); + return MqGetSetAttr(mqd, NULL, attr); } int mq_setattr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) @@ -452,7 +452,7 @@ int mq_setattr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) errno = EINVAL; return -1; } - return mq_getsetattr(mqd, new, old); + return MqGetSetAttr(mqd, new, old); } int mq_unlink(const char *mqName) @@ -472,7 +472,9 @@ int mq_unlink(const char *mqName) } if (mqueueCB->mq_personal != NULL) { + errno = EINTR; mqueueCB->unlinkflag = TRUE; + goto ERROUT_UNLOCK; } else { ret = DoMqueueDelete(mqueueCB); } diff --git a/kal/posix/src/pthread.c b/kal/posix/src/pthread.c index 837c8dec..1ea26b2f 100644 --- a/kal/posix/src/pthread.c +++ b/kal/posix/src/pthread.c @@ -37,12 +37,14 @@ #include #include "los_config.h" #include "los_task.h" +#include "los_debug.h" #define PTHREAD_DEFAULT_NAME "pthread" #define PTHREAD_DEFAULT_NAME_LEN 8 #define PTHREAD_NAMELEN 16 #define PTHREAD_KEY_UNUSED 0 #define PTHREAD_KEY_USED 1 +#define PTHREAD_TASK_INVAILD 0 typedef void (*PthreadKeyDtor)(void *); typedef struct { @@ -59,6 +61,9 @@ typedef struct { char name[PTHREAD_NAMELEN]; uintptr_t *key; LOS_DL_LIST threadList; + unsigned char cancelState; + unsigned char cancelType; + unsigned char canceled; } PthreadData; static void PthreadExitKeyDtor(PthreadData *pthreadData); @@ -69,6 +74,7 @@ static void *PthreadEntry(UINT32 param) void *(*startRoutine)(void *) = pthreadData->startRoutine; void *ret = startRoutine(pthreadData->param); pthread_exit(ret); + return ret; } @@ -121,6 +127,9 @@ static int PthreadCreateAttrInit(const pthread_attr_t *attr, void *(*startRoutin return error; } + pthreadData->cancelState = PTHREAD_CANCEL_ENABLE; + pthreadData->cancelType = PTHREAD_CANCEL_DEFERRED; + pthreadData->canceled = 0; pthreadData->startRoutine = startRoutine; pthreadData->param = arg; pthreadData->key = NULL; @@ -130,6 +139,23 @@ static int PthreadCreateAttrInit(const pthread_attr_t *attr, void *(*startRoutin if (threadAttr->detachstate != PTHREAD_CREATE_DETACHED) { taskInitParam->uwResved = LOS_TASK_ATTR_JOINABLE; } + + return 0; +} + +static int CheckForCancel(void) +{ + UINT32 intSave; + LosTaskCB *tcb = NULL; + + intSave = LOS_IntLock(); + tcb = OS_TCB_FROM_TID(LOS_CurTaskIDGet()); + PthreadData *pthreadData = (PthreadData *)(UINTPTR)tcb->arg; + if ((pthreadData->canceled) && (pthreadData->cancelState == PTHREAD_CANCEL_ENABLE)) { + LOS_IntRestore(intSave); + return 1; + } + LOS_IntRestore(intSave); return 0; } @@ -167,6 +193,7 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr, (void)LOS_TaskResume(taskID); *thread = (pthread_t)taskID; + return 0; } @@ -189,6 +216,94 @@ int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param return 0; } +int pthread_setschedprio(pthread_t thread, int prio) +{ + if (LOS_TaskPriSet((UINT32)thread, (UINT16)prio) != LOS_OK) { + return EINVAL; + } + + return 0; +} + +int pthread_once(pthread_once_t *onceControl, void (*initRoutine)(void)) +{ + UINT32 intSave; + pthread_once_t old; + + if ((onceControl == NULL) || (initRoutine == NULL)) { + return EINVAL; + } + intSave = LOS_IntLock(); + old = *onceControl; + *onceControl = 1; + LOS_IntRestore(intSave); + + if (!old) { + initRoutine(); + } + + return 0; +} + +int pthread_equal(pthread_t thread1, pthread_t thread2) +{ + return (int)(thread1 == thread2); +} + +int pthread_setcancelstate(int state, int *oldState) +{ + UINT32 intSave; + LosTaskCB *tcb = NULL; + PthreadData *pthreadData = NULL; + if ((state != PTHREAD_CANCEL_ENABLE) && (state != PTHREAD_CANCEL_DISABLE)) { + return EINVAL; + } + + intSave = LOS_IntLock(); + tcb = OS_TCB_FROM_TID(LOS_CurTaskIDGet()); + pthreadData = (PthreadData *)(UINTPTR)tcb->arg; + if (pthreadData == NULL) { + LOS_IntRestore(intSave); + return EINVAL; + } + + if (oldState != NULL) { + *oldState = pthreadData->cancelState; + } + pthreadData->cancelState = (UINT8)state; + LOS_IntRestore(intSave); + + return 0; +} + +int pthread_setcanceltype(int type, int *oldType) +{ + UINT32 intSave; + LosTaskCB *tcb = NULL; + PthreadData *pthreadData = NULL; + + if ((type != PTHREAD_CANCEL_ASYNCHRONOUS) && (type != PTHREAD_CANCEL_DEFERRED)) { + return EINVAL; + } + + intSave = LOS_IntLock(); + tcb = OS_TCB_FROM_TID(LOS_CurTaskIDGet()); + pthreadData = (PthreadData *)(UINTPTR)tcb->arg; + if (pthreadData == NULL) { + LOS_IntRestore(intSave); + return EINVAL; + } + + if (oldType != NULL) { + *oldType = pthreadData->cancelType; + } + + pthreadData->cancelType = (UINT8)type; + LOS_IntRestore(intSave); + + return 0; +} + int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param) { UINT32 prio; @@ -204,6 +319,7 @@ int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *par *policy = SCHED_RR; param->sched_priority = prio; + return 0; } @@ -212,21 +328,81 @@ pthread_t pthread_self(void) return (pthread_t)LOS_CurTaskIDGet(); } +STATIC UINT32 DoPthreadCancel(LosTaskCB *task) +{ + UINT32 ret = LOS_OK; + PthreadData *pthreadData = NULL; + + LOS_TaskLock(); + pthreadData = (PthreadData *)(UINTPTR)task->arg; + pthreadData->canceled = 0; + if ((task->taskStatus == PTHREAD_TASK_INVAILD) || (LOS_TaskSuspend(task->taskID) != LOS_OK)) { + ret = LOS_NOK; + goto OUT; + } + free((VOID *)(UINTPTR)task->arg); + task->arg = (UINT32)(UINTPTR)NULL; + (void)LOS_TaskDelete(task->taskID); + +OUT: + LOS_TaskUnlock(); + return ret; +} + int pthread_cancel(pthread_t thread) { + UINT32 intSave; + LosTaskCB *tcb = NULL; + PthreadData *pthreadData = NULL; if (!IsPthread(thread)) { return EINVAL; } + intSave = LOS_IntLock(); + tcb = OS_TCB_FROM_TID((UINT32)thread); + pthreadData = (PthreadData *)(UINTPTR)tcb->arg; + pthreadData->canceled = 1; + if ((pthreadData->cancelState == PTHREAD_CANCEL_ENABLE) && + (pthreadData->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS)) { + /* + * If the thread has cancellation enabled, and it is in + * asynchronous mode, suspend it and set corresponding thread's status. + * We also release the thread out of any current wait to make it wake up. + */ + if (DoPthreadCancel(tcb) == LOS_NOK) { + LOS_IntRestore(intSave); + return ESRCH; + } + } + LOS_IntRestore(intSave); - return ENOSYS; + return 0; +} + +void pthread_testcancel(void) +{ + if (CheckForCancel()) { + /* + * If we have cancellation enabled, and there is a cancellation + * pending, then go ahead and do the deed. + * Exit now with special retVal. pthread_exit() calls the + * cancellation handlers implicitly. + */ + pthread_exit((void *)PTHREAD_CANCELED); + } } int pthread_join(pthread_t thread, void **retval) { UINTPTR result; + UINT32 ret = LOS_TaskJoin((UINT32)thread, &result); if (ret == LOS_ERRNO_TSK_NOT_JOIN_SELF) { return EDEADLK; + } else if ((ret == LOS_ERRNO_TSK_NOT_CREATED) || + (ret == LOS_ERRNO_TSK_OPERATE_IDLE) || + (ret == LOS_ERRNO_TSK_ID_INVALID) || + (ret == LOS_ERRNO_TSK_SUSPEND_SWTMR_NOT_ALLOWED)) { + return ESRCH; } else if (ret != LOS_OK) { return EINVAL; } @@ -234,6 +410,7 @@ int pthread_join(pthread_t thread, void **retval) if (retval != NULL) { *retval = (VOID *)result; } + return 0; } @@ -256,7 +433,10 @@ void pthread_exit(void *retVal) LosTaskCB *tcb = OS_TCB_FROM_TID(LOS_CurTaskIDGet()); tcb->joinRetval = (UINTPTR)retVal; PthreadData *pthreadData = (PthreadData *)(UINTPTR)tcb->arg; - + if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0) { + PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); + } + if (pthreadData->key != NULL) { PthreadExitKeyDtor(pthreadData); } @@ -298,6 +478,7 @@ int pthread_setname_np(pthread_t thread, const char *name) return EINVAL; } LOS_IntRestore(intSave); + return 0; } @@ -315,6 +496,7 @@ int pthread_getname_np(pthread_t thread, char *buf, size_t buflen) return 0; } } + return ERANGE; } @@ -373,6 +555,7 @@ int pthread_key_create(pthread_key_t *k, void (*dtor)(void *)) LOS_IntRestore(intSave); *k = count; + return 0; } @@ -406,6 +589,7 @@ int pthread_key_delete(pthread_key_t k) g_pthreadKeyData[k].flag = PTHREAD_KEY_UNUSED; g_pthreadkeyCount--; LOS_IntRestore(intSave); + return 0; } @@ -446,6 +630,7 @@ int pthread_setspecific(pthread_key_t k, const void *x) pthreadData->key[k] = (uintptr_t)x; LOS_IntRestore(intSave); + return 0; } @@ -473,6 +658,7 @@ void *pthread_getspecific(pthread_key_t k) key = (void *)pthreadData->key[k]; LOS_IntRestore(intSave); + return key; } diff --git a/kal/posix/src/pthread_attr.c b/kal/posix/src/pthread_attr.c index 3caf5ea8..f924f541 100644 --- a/kal/posix/src/pthread_attr.c +++ b/kal/posix/src/pthread_attr.c @@ -29,10 +29,12 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "pthread.h" #include +#include #include +#include "pthread.h" #include "los_config.h" +#include "los_debug.h" int pthread_attr_init(pthread_attr_t *attr) { @@ -44,7 +46,7 @@ int pthread_attr_init(pthread_attr_t *attr) attr->schedpolicy = SCHED_RR; attr->schedparam.sched_priority = LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO; attr->inheritsched = PTHREAD_INHERIT_SCHED; - attr->scope = PTHREAD_SCOPE_PROCESS; + attr->scope = PTHREAD_SCOPE_SYSTEM; attr->stackaddr_set = 0; attr->stackaddr = NULL; attr->stacksize_set = 1; @@ -59,7 +61,8 @@ int pthread_attr_destroy(pthread_attr_t *attr) return EINVAL; } - /* Nothing to do here... */ + (void)memset_s(attr, sizeof(pthread_attr_t), 0, sizeof(pthread_attr_t)); + return 0; } @@ -90,12 +93,12 @@ int pthread_attr_setscope(pthread_attr_t *attr, int scope) return EINVAL; } - if (scope == PTHREAD_SCOPE_PROCESS) { + if (scope == PTHREAD_SCOPE_SYSTEM) { attr->scope = (unsigned int)scope; return 0; } - if (scope == PTHREAD_SCOPE_SYSTEM) { + if (scope == PTHREAD_SCOPE_PROCESS) { return ENOTSUP; } @@ -220,6 +223,28 @@ int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stackSize) return 0; } +int pthread_attr_setstack(pthread_attr_t *attr, void *stackAddr, size_t stackSize) +{ + (void)attr; + (void)stackAddr; + (void)stackSize; + PRINT_ERR("%s: Don't support the pthread stack func currently!\n", __FUNCTION__); + errno = ENOSYS; + + return -1; +} + +int pthread_attr_getstack(const pthread_attr_t *attr, void **stackAddr, size_t *stackSize) +{ + (void)attr; + (void)stackAddr; + (void)stackSize; + PRINT_ERR("%s: Don't support the pthread stack func currently!\n", __FUNCTION__); + errno = ENOSYS; + + return -1; +} + int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stackSize) { /* Reject attempts to get a stack size when one has not been set. */ diff --git a/kal/posix/src/pthread_cond.c b/kal/posix/src/pthread_cond.c index 9e2ca660..b5a230b0 100644 --- a/kal/posix/src/pthread_cond.c +++ b/kal/posix/src/pthread_cond.c @@ -29,7 +29,6 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "time_internal.h" #include #include #include @@ -37,9 +36,11 @@ #include #include "los_config.h" #include "los_task.h" -#include +#include "los_swtmr.h" +#include "time_internal.h" #include "los_atomic.h" #include "los_event.h" +#include "los_mux.h" typedef struct { volatile INT32 *realValue; @@ -54,6 +55,31 @@ typedef struct { #define COND_FLAGS_MASK 0x0003U #define COND_COUNTER_MASK (~COND_FLAGS_MASK) +int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *shared) +{ + if ((attr == NULL) || (shared == NULL)) { + return EINVAL; + } + + *shared = PTHREAD_PROCESS_PRIVATE; + + return 0; +} + +int pthread_condattr_setpshared(pthread_condattr_t *attr, int shared) +{ + (VOID)attr; + if ((shared != PTHREAD_PROCESS_PRIVATE) && (shared != PTHREAD_PROCESS_SHARED)) { + return EINVAL; + } + + if (shared != PTHREAD_PROCESS_PRIVATE) { + return ENOSYS; + } + + return 0; +} + int pthread_condattr_destroy(pthread_condattr_t *attr) { if (attr == NULL) { @@ -61,6 +87,19 @@ int pthread_condattr_destroy(pthread_condattr_t *attr) } (VOID)memset_s(attr, sizeof(pthread_condattr_t), 0, sizeof(pthread_condattr_t)); + attr->clock = INT32_MAX; + + return 0; +} + +int pthread_condattr_getclock(const pthread_condattr_t *attr, clockid_t *clock) +{ + if ((attr == NULL) || (clock == NULL)) { + return -1; + } + + *clock = attr->clock; + return 0; } @@ -71,6 +110,7 @@ int pthread_condattr_init(pthread_condattr_t *attr) } attr->clock = CLOCK_REALTIME; + return 0; } @@ -86,6 +126,7 @@ int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clk) } attr->clock = clk; + return 0; } @@ -95,6 +136,7 @@ STATIC INLINE INT32 CondInitCheck(const pthread_cond_t *cond) (cond->event.stEventList.pstNext == NULL)) { return 1; } + return 0; } @@ -149,6 +191,7 @@ int pthread_cond_destroy(pthread_cond_t *cond) } free(cond->mutex); cond->mutex = NULL; + return 0; } @@ -222,6 +265,7 @@ STATIC INT32 ProcessReturnVal(pthread_cond_t *cond, INT32 val) ret = EINVAL; break; } + return ret; } @@ -230,15 +274,17 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, { INT32 ret; UINT64 absTicks; - const UINT32 nsPerTick = OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND; - struct timespec tp; - UINT64 nseconds; - UINT64 currTime; - - if ((cond == NULL) || (mutex == NULL) || (ts == NULL)) { + LosMuxCB *muxPosted = NULL; + pthread_testcancel(); + if ((cond == NULL) || (mutex == NULL) || (ts == NULL) || (mutex->magic != _MUX_MAGIC)) { return EINVAL; } + muxPosted = GET_MUX(mutex->handle); + if ((mutex->stAttr.type == PTHREAD_MUTEX_ERRORCHECK) && (g_losTask.runTask != muxPosted->owner)) { + return EPERM; + } + if (CondInitCheck(cond)) { ret = pthread_cond_init(cond, NULL); if (ret != 0) { @@ -250,17 +296,11 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, cond->count++; (VOID)pthread_mutex_unlock(cond->mutex); - if (!ValidTimeSpec(ts)) { - return EINVAL; + ret = OsGetTickTimeFromNow(ts, cond->clock, &absTicks); + if (ret != 0) { + return ret; } - clock_gettime(cond->clock, &tp); - currTime = (UINT64)tp.tv_sec * OS_SYS_NS_PER_SECOND + tp.tv_nsec; - nseconds = (UINT64)ts->tv_sec * OS_SYS_NS_PER_SECOND + ts->tv_nsec; - if (currTime >= nseconds) { - return ETIMEDOUT; - } - absTicks = ((nseconds - currTime) + nsPerTick - 1) / nsPerTick + 1; if (absTicks >= UINT32_MAX) { return EINVAL; } @@ -277,6 +317,8 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, } ret = ProcessReturnVal(cond, ret); + pthread_testcancel(); + return ret; } diff --git a/kal/posix/src/pthread_mutex.c b/kal/posix/src/pthread_mutex.c index a2459d94..8adfe96a 100644 --- a/kal/posix/src/pthread_mutex.c +++ b/kal/posix/src/pthread_mutex.c @@ -35,8 +35,12 @@ #include "los_compiler.h" #include "los_mux.h" #include "errno.h" +#include "los_mux.h" +#include "los_debug.h" +#include "los_hook.h" +#include "los_sched.h" - +#define MUTEXATTR_TYPE_MASK 0x0FU #define OS_SYS_NS_PER_MSECOND 1000000 #define OS_SYS_NS_PER_SECOND 1000000000 @@ -68,7 +72,28 @@ int pthread_mutexattr_init(pthread_mutexattr_t *mutexAttr) return EINVAL; } - mutexAttr->type = PTHREAD_MUTEX_RECURSIVE; + mutexAttr->type = PTHREAD_MUTEX_DEFAULT; + + return 0; +} + +int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *outType) +{ + INT32 type; + + if ((attr == NULL) || (outType == NULL)) { + return EINVAL; + } + + type = (INT32)(attr->type & MUTEXATTR_TYPE_MASK); + if ((type != PTHREAD_MUTEX_NORMAL) && + (type != PTHREAD_MUTEX_RECURSIVE) && + (type != PTHREAD_MUTEX_ERRORCHECK)) { + return EINVAL; + } + + *outType = type; + return 0; } @@ -83,12 +108,8 @@ int pthread_mutexattr_settype(pthread_mutexattr_t *mutexAttr, int type) ((unsigned)type != PTHREAD_MUTEX_ERRORCHECK)) { return EINVAL; } + mutexAttr->type = (UINT8)((mutexAttr->type & ~MUTEXATTR_TYPE_MASK) | (UINT32)type); - if ((unsigned)type != PTHREAD_MUTEX_RECURSIVE) { - return EOPNOTSUPP; - } - - mutexAttr->type = PTHREAD_MUTEX_RECURSIVE; return 0; } @@ -99,17 +120,25 @@ int pthread_mutexattr_destroy(pthread_mutexattr_t *mutexAttr) } (VOID)memset_s(mutexAttr, sizeof(pthread_mutexattr_t), 0, sizeof(pthread_mutexattr_t)); + return 0; } /* Initialize mutex. If mutexAttr is NULL, use default attributes. */ int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexAttr) { + pthread_mutexattr_t useAttr; UINT32 muxHandle; UINT32 ret; - if ((mutexAttr != NULL) && (mutexAttr->type != PTHREAD_MUTEX_RECURSIVE)) { - return EOPNOTSUPP; + if (mutex == NULL) { + return EINVAL; + } + + if (mutexAttr == NULL) { + (VOID)pthread_mutexattr_init(&useAttr); + } else { + useAttr = *mutexAttr; } ret = LOS_MuxCreate(&muxHandle); @@ -117,6 +146,7 @@ int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexA return MapError(ret); } + mutex->stAttr = useAttr; mutex->magic = _MUX_MAGIC; mutex->handle = muxHandle; @@ -126,7 +156,7 @@ int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexA int pthread_mutex_destroy(pthread_mutex_t *mutex) { UINT32 ret; - if (mutex->magic != _MUX_MAGIC) { + if ((mutex == NULL) || (mutex->magic != _MUX_MAGIC)) { return EINVAL; } ret = LOS_MuxDelete(mutex->handle); @@ -135,16 +165,172 @@ int pthread_mutex_destroy(pthread_mutex_t *mutex) } mutex->handle = _MUX_INVALID_HANDLE; mutex->magic = 0; + return 0; } +STATIC UINT32 CheckMutexAttr(const pthread_mutexattr_t *attr) +{ + if ((attr->type != PTHREAD_MUTEX_NORMAL) && + (attr->type != PTHREAD_MUTEX_RECURSIVE) && + (attr->type != PTHREAD_MUTEX_ERRORCHECK)) { + return LOS_NOK; + } + + return LOS_OK; +} + +STATIC UINT32 MuxPreCheck(const pthread_mutex_t *mutex, const LosTaskCB *runTask) +{ + if ((mutex == NULL) || (mutex->magic != _MUX_MAGIC) || + ((mutex->handle != _MUX_INVALID_HANDLE) && (mutex->handle >= (UINT32)LOSCFG_BASE_IPC_MUX_LIMIT))) { + return EINVAL; + } + + if (OS_INT_ACTIVE) { + return EPERM; + } + /* DO NOT recommend to use blocking API in system tasks */ + if ((runTask != NULL) && (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK)) { + PRINT_DEBUG("Warning: DO NOT recommend to use %s in system tasks.\n", __FUNCTION__); + } + + if (CheckMutexAttr(&mutex->stAttr) != LOS_OK) { + return EINVAL; + } + + return 0; +} + +STATIC UINT32 MuxPendForPosix(pthread_mutex_t *mutex, UINT32 timeout) +{ + UINT32 intSave; + LosMuxCB *muxPended = NULL; + UINT32 retErr; + LosTaskCB *runningTask = NULL; + UINT32 muxHandle = mutex->handle; + + muxPended = GET_MUX(muxHandle); + intSave = LOS_IntLock(); + + if (muxPended->muxStat == OS_MUX_UNUSED) { + LOS_IntRestore(intSave); + OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID); + } + + runningTask = (LosTaskCB *)g_losTask.runTask; + if (muxPended->muxCount == 0) { + muxPended->muxCount++; + muxPended->owner = runningTask; + muxPended->priority = runningTask->priority; + LOS_IntRestore(intSave); + OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended, timeout); + return LOS_OK; + } + + if ((muxPended->owner == runningTask) && (mutex->stAttr.type == PTHREAD_MUTEX_RECURSIVE)) { + muxPended->muxCount++; + LOS_IntRestore(intSave); + OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended, timeout); + return LOS_OK; + } + + if (!timeout) { + LOS_IntRestore(intSave); + OS_RETURN_ERROR(LOS_ERRNO_MUX_UNAVAILABLE); + } + + runningTask->taskMux = (VOID *)muxPended; + + if (muxPended->owner->priority > runningTask->priority) { + (VOID)OsSchedModifyTaskSchedParam(muxPended->owner, runningTask->priority); + } + + OsSchedTaskWait(&muxPended->muxList, timeout); + + LOS_IntRestore(intSave); + OsHookCall(LOS_HOOK_TYPE_MUX_PEND, muxPended, timeout); + LOS_Schedule(); + + intSave = LOS_IntLock(); + if (runningTask->taskStatus & OS_TASK_STATUS_TIMEOUT) { + runningTask->taskStatus &= (~OS_TASK_STATUS_TIMEOUT); + retErr = LOS_ERRNO_MUX_TIMEOUT; + LOS_IntRestore(intSave); + OS_RETURN_ERROR(retErr); + } + + LOS_IntRestore(intSave); + return LOS_OK; +} + +STATIC UINT32 MuxPostForPosix(pthread_mutex_t *mutex) +{ + UINT32 intSave; + LosMuxCB *muxPosted = NULL; + LosTaskCB *resumedTask = NULL; + LosTaskCB *runningTask = NULL; + UINT32 muxHandle = mutex->handle; + + muxPosted = GET_MUX(muxHandle); + intSave = LOS_IntLock(); + + if (muxPosted->muxStat == OS_MUX_UNUSED) { + LOS_IntRestore(intSave); + OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID); + } + + runningTask = (LosTaskCB *)g_losTask.runTask; + if ((muxPosted->muxCount == 0) || (muxPosted->owner != runningTask)) { + LOS_IntRestore(intSave); + OS_RETURN_ERROR(LOS_ERRNO_MUX_INVALID); + } + + if ((--(muxPosted->muxCount) != 0) && (mutex->stAttr.type == PTHREAD_MUTEX_RECURSIVE)) { + LOS_IntRestore(intSave); + OsHookCall(LOS_HOOK_TYPE_MUX_POST, muxPosted); + return LOS_OK; + } + + if ((muxPosted->owner->priority) != muxPosted->priority) { + (VOID)OsSchedModifyTaskSchedParam(muxPosted->owner, muxPosted->priority); + } + + if (!LOS_ListEmpty(&muxPosted->muxList)) { + resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(muxPosted->muxList))); + + muxPosted->muxCount = 1; + muxPosted->owner = resumedTask; + muxPosted->priority = resumedTask->priority; + resumedTask->taskMux = NULL; + + OsSchedTaskWake(resumedTask); + + LOS_IntRestore(intSave); + OsHookCall(LOS_HOOK_TYPE_MUX_POST, muxPosted); + LOS_Schedule(); + } else { + muxPosted->owner = NULL; + LOS_IntRestore(intSave); + } + + return LOS_OK; +} + 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)) { + LosMuxCB *muxPended = NULL; + + ret = MuxPreCheck(mutex, OS_TCB_FROM_TID(LOS_CurTaskIDGet())); + if (ret != 0) { + return (INT32)ret; + } + + if ((absTimeout == NULL) || (absTimeout->tv_nsec < 0) || (absTimeout->tv_nsec >= OS_SYS_NS_PER_SECOND)) { return EINVAL; } if (mutex->handle == _MUX_INVALID_HANDLE) { @@ -152,6 +338,13 @@ int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *absTi if (ret != LOS_OK) { return MapError(ret); } + } else { + muxPended = GET_MUX(mutex->handle); + if ((mutex->stAttr.type == PTHREAD_MUTEX_ERRORCHECK) && + (muxPended->muxCount != 0) && + (muxPended->owner == OS_TCB_FROM_TID(LOS_CurTaskIDGet()))) { + return EDEADLK; + } } ret = clock_gettime(CLOCK_REALTIME, &curTime); if (ret != LOS_OK) { @@ -162,7 +355,8 @@ int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *absTi return ETIMEDOUT; } timeout = (timeoutNs + (OS_SYS_NS_PER_MSECOND - 1)) / OS_SYS_NS_PER_MSECOND; - ret = LOS_MuxPend(mutex->handle, timeout); + ret = MuxPendForPosix(mutex, timeout); + return MapError(ret); } @@ -170,42 +364,72 @@ int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *absTi int pthread_mutex_lock(pthread_mutex_t *mutex) { UINT32 ret; - if (mutex->magic != _MUX_MAGIC) { - return EINVAL; + LosMuxCB *muxPended = NULL; + LosTaskCB *runTask = OS_TCB_FROM_TID(LOS_CurTaskIDGet()); + + ret = MuxPreCheck(mutex, runTask); + if (ret != 0) { + return (INT32)ret; } + if (mutex->handle == _MUX_INVALID_HANDLE) { ret = LOS_MuxCreate(&mutex->handle); if (ret != LOS_OK) { return MapError(ret); } + } else { + muxPended = GET_MUX(mutex->handle); + if ((mutex->stAttr.type == PTHREAD_MUTEX_ERRORCHECK) && + (muxPended->muxCount != 0) && + (muxPended->owner == runTask)) { + return EDEADLK; + } } - ret = LOS_MuxPend(mutex->handle, LOS_WAIT_FOREVER); + ret = MuxPendForPosix(mutex, LOS_WAIT_FOREVER); + return MapError(ret); } int pthread_mutex_trylock(pthread_mutex_t *mutex) { UINT32 ret; - if (mutex->magic != _MUX_MAGIC) { - return EINVAL; + LosMuxCB *muxPended = NULL; + + ret = MuxPreCheck(mutex, OS_TCB_FROM_TID(LOS_CurTaskIDGet())); + if (ret != 0) { + return (INT32)ret; } + if (mutex->handle == _MUX_INVALID_HANDLE) { ret = LOS_MuxCreate(&mutex->handle); if (ret != LOS_OK) { return MapError(ret); } + } else { + muxPended = GET_MUX(mutex->handle); + if ((mutex->stAttr.type != PTHREAD_MUTEX_RECURSIVE) && (muxPended->muxCount != 0)) { + return EBUSY; + } } - ret = LOS_MuxPend(mutex->handle, 0); + ret = MuxPendForPosix(mutex, 0); + return MapError(ret); } int pthread_mutex_unlock(pthread_mutex_t *mutex) { UINT32 ret; - if (mutex->magic != _MUX_MAGIC) { + ret = MuxPreCheck(mutex, OS_TCB_FROM_TID(LOS_CurTaskIDGet())); + if (ret != 0) { + return (INT32)ret; + } + + if (mutex->handle == _MUX_INVALID_HANDLE) { return EINVAL; } - ret = LOS_MuxPost(mutex->handle); + + ret = MuxPostForPosix(mutex); + return MapError(ret); } diff --git a/kal/posix/src/semaphore.c b/kal/posix/src/semaphore.c index 3fd73696..c74a4044 100644 --- a/kal/posix/src/semaphore.c +++ b/kal/posix/src/semaphore.c @@ -102,6 +102,7 @@ int sem_destroy(sem_t *sem) errno = MapError(ret); return -1; } + return 0; } @@ -119,6 +120,7 @@ int sem_wait(sem_t *sem) errno = MapError(ret); return -1; } + return 0; } @@ -140,38 +142,37 @@ int sem_post(sem_t *sem) return 0; } -static long long GetTickTimeFromNow(const struct timespec *absTimeSpec) +int sem_trywait(sem_t *sem) { - struct timespec tsNow = { 0 }; - long long ns; - long long tick; + UINT32 ret; - clock_gettime(CLOCK_REALTIME, &tsNow); - ns = (absTimeSpec->tv_sec - tsNow.tv_sec) * OS_SYS_NS_PER_SECOND + (absTimeSpec->tv_nsec - tsNow.tv_nsec); + if ((sem == NULL) || (sem->s_magic != _SEM_MAGIC)) { + errno = EINVAL; + return -1; + } - /* Round up for ticks */ - tick = (ns * LOSCFG_BASE_CORE_TICK_PER_SECOND + (OS_SYS_NS_PER_SECOND - 1)) / OS_SYS_NS_PER_SECOND; - return tick; + ret = LOS_SemPend((UINT32)sem->s_handle, LOS_NO_WAIT); + if (ret != LOS_OK) { + errno = MapError(ret); + return -1; + } + + return 0; } int sem_timedwait(sem_t *sem, const struct timespec *timeout) { UINT32 ret; - long long tickCnt; + UINT64 tickCnt; if ((sem == NULL) || (sem->s_magic != (int)_SEM_MAGIC)) { errno = EINVAL; return -1; } - if (!ValidTimeSpec(timeout)) { - errno = EINVAL; - return -1; - } - - tickCnt = GetTickTimeFromNow(timeout); - if (tickCnt < 0) { - errno = ETIMEDOUT; + ret = OsGetTickTimeFromNow(timeout, CLOCK_REALTIME, &tickCnt); + if (ret != 0) { + errno = (INT32)ret; return -1; } @@ -192,7 +193,7 @@ int sem_getvalue(sem_t *sem, int *currVal) { UINT32 ret; - if ((sem == NULL) || (currVal == NULL)) { + if ((sem == NULL) || (sem->s_magic != _SEM_MAGIC)|| (currVal == NULL)) { errno = EINVAL; return -1; } diff --git a/kal/posix/src/time.c b/kal/posix/src/time.c index 7d2d7294..7d183703 100644 --- a/kal/posix/src/time.c +++ b/kal/posix/src/time.c @@ -43,6 +43,9 @@ #include "los_tick.h" #include "los_context.h" #include "los_interrupt.h" +#include "sys/times.h" + +#define DELAYTIMER_MAX 0x7FFFFFFFF /* accumulative time delta from discontinuous modify */ STATIC struct timespec g_accDeltaFromSet; @@ -96,7 +99,7 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) } /* sleep in interrupt context or in task sched lock state */ - errno = EPERM; + errno = EINTR; return -1; } @@ -105,12 +108,12 @@ int timer_create(clockid_t clockID, struct sigevent *restrict evp, timer_t *rest UINT32 ret; UINT32 swtmrID; - if (!timerID || (clockID != CLOCK_REALTIME)) { + if (!timerID || (clockID != CLOCK_REALTIME) || !evp) { errno = EINVAL; return -1; } - if (!evp || evp->sigev_notify != SIGEV_THREAD || evp->sigev_notify_attributes) { + if ((evp->sigev_notify != SIGEV_THREAD) || evp->sigev_notify_attributes) { errno = ENOTSUP; return -1; } @@ -152,7 +155,7 @@ int timer_settime(timer_t timerID, int flags, if (flags != 0) { /* flags not supported currently */ - errno = ENOSYS; + errno = ENOTSUP; return -1; } @@ -190,6 +193,7 @@ int timer_settime(timer_t timerID, int flags, swtmr->ucMode = (interval ? LOS_SWTMR_MODE_PERIOD : LOS_SWTMR_MODE_NO_SELFDELETE); swtmr->uwInterval = (interval ? interval : expiry); + swtmr->ucOverrun = 0; LOS_IntRestore(intSave); if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0)) { @@ -229,7 +233,9 @@ int timer_gettime(timer_t timerID, struct itimerspec *value) errno = EINVAL; return -1; } - + if (ret == LOS_ERRNO_SWTMR_NOT_STARTED) { + tick = 0; + } OsTick2TimeSpec(&value->it_value, tick); OsTick2TimeSpec(&value->it_interval, (swtmr->ucMode == LOS_SWTMR_MODE_ONCE) ? 0 : swtmr->uwInterval); return 0; @@ -237,10 +243,13 @@ int timer_gettime(timer_t timerID, struct itimerspec *value) int timer_getoverrun(timer_t timerID) { - (void)timerID; + SWTMR_CTRL_S *swtmr = NULL; + swtmr = OS_SWT_FROM_SID((UINT32)(UINTPTR)timerID); - errno = ENOSYS; - return -1; + if ((swtmr->ucOverrun) >= (UINT8)DELAYTIMER_MAX) { + return (INT32)DELAYTIMER_MAX; + } + return (int)swtmr->ucOverrun; } STATIC VOID OsGetHwTime(struct timespec *hwTime) @@ -696,3 +705,17 @@ unsigned sleep(unsigned seconds) specTime.tv_nsec = (long)(nanoseconds % OS_SYS_NS_PER_SECOND); return nanosleep(&specTime, NULL); } + +clock_t times(struct tms *tms) +{ + clock_t clockTick = (clock_t)LOS_TickCountGet(); + + if (tms != NULL) { + tms->tms_cstime = clockTick; + tms->tms_cutime = clockTick; + tms->tms_stime = clockTick; + tms->tms_utime = clockTick; + } + return clockTick; +} + diff --git a/kal/posix/src/time_internal.h b/kal/posix/src/time_internal.h index a8fc596f..1c57bc94 100644 --- a/kal/posix/src/time_internal.h +++ b/kal/posix/src/time_internal.h @@ -111,5 +111,27 @@ STATIC INLINE VOID OsTick2TimeSpec(struct timespec *tp, UINT32 tick) tp->tv_sec = (time_t)(ns / OS_SYS_NS_PER_SECOND); tp->tv_nsec = (long)(ns % OS_SYS_NS_PER_SECOND); } + +STATIC INLINE INT32 OsGetTickTimeFromNow(const struct timespec *ts, clockid_t clockId, UINT64 *absTicks) +{ + struct timespec tp; + UINT64 nseconds; + UINT64 currTime; + const UINT32 nsPerTick = OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND; + + if (!ValidTimeSpec(ts)) { + return EINVAL; + } + + clock_gettime(clockId, &tp); + currTime = (UINT64)tp.tv_sec * OS_SYS_NS_PER_SECOND + tp.tv_nsec; + nseconds = (UINT64)ts->tv_sec * OS_SYS_NS_PER_SECOND + ts->tv_nsec; + if (currTime >= nseconds) { + return ETIMEDOUT; + } + *absTicks = ((nseconds - currTime) + nsPerTick - 1) / nsPerTick + 1; + + return 0; +} #endif diff --git a/kernel/include/los_swtmr.h b/kernel/include/los_swtmr.h index 2fdc5dd4..8a472dff 100644 --- a/kernel/include/los_swtmr.h +++ b/kernel/include/los_swtmr.h @@ -271,6 +271,7 @@ typedef struct tagSwTmrCtrl { struct tagSwTmrCtrl *pstNext; /* Pointer to the next software timer */ UINT8 ucState; /* Software timer state */ UINT8 ucMode; /* Software timer mode */ + UINT8 ucOverrun; /* Times that a software timer repeats timing */ #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1) UINT8 ucRouses; /* wake up enable */ UINT8 ucSensitive; /* align enable */ diff --git a/kernel/src/los_swtmr.c b/kernel/src/los_swtmr.c index 3717d1fb..b2f9394e 100644 --- a/kernel/src/los_swtmr.c +++ b/kernel/src/los_swtmr.c @@ -273,6 +273,7 @@ LITE_OS_SEC_TEXT VOID OsSwtmrStop(SWTMR_CTRL_S *swtmr) OsDeleteSortLink(&swtmr->stSortList); swtmr->ucState = OS_SWTMR_STATUS_CREATED; + swtmr->ucOverrun = 0; OsSchedUpdateExpireTime(OsGetCurrSchedTimeCycle()); #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1) g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned = 0; @@ -289,6 +290,7 @@ STATIC VOID OsSwtmrTimeoutHandle(UINT64 currTime, SWTMR_CTRL_S *swtmr) (VOID)LOS_QueueWriteCopy(g_swtmrHandlerQueue, &swtmrHandler, sizeof(SwtmrHandlerItem), LOS_NO_WAIT); if (swtmr->ucMode == LOS_SWTMR_MODE_PERIOD) { + swtmr->ucOverrun++; OsSwtmrStart(currTime, swtmr); } else if (swtmr->ucMode == LOS_SWTMR_MODE_NO_SELFDELETE) { swtmr->ucState = OS_SWTMR_STATUS_CREATED; @@ -492,6 +494,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval, swtmr->ucSensitive = sensitive; #endif swtmr->ucState = OS_SWTMR_STATUS_CREATED; + swtmr->ucOverrun = 0; *swtmrId = swtmr->usTimerID; SET_SORTLIST_VALUE(&swtmr->stSortList, OS_SORT_LINK_INVALID_TIME); OsHookCall(LOS_HOOK_TYPE_SWTMR_CREATE, swtmr); diff --git a/testsuites/unittest/posix/src/pthread/pthread_cond_func_test.c b/testsuites/unittest/posix/src/pthread/pthread_cond_func_test.c index 4fac2873..ce08df7e 100644 --- a/testsuites/unittest/posix/src/pthread/pthread_cond_func_test.c +++ b/testsuites/unittest/posix/src/pthread/pthread_cond_func_test.c @@ -41,6 +41,9 @@ #define TASK_PRIO_TEST LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO #define OS_TSK_TEST_STACK_SIZE 0x1000 +#define PTHREAD_TASK_DELAY 10 + +static INT32 g_pthreadSem = 0; static UINT32 g_testCount; /** @@ -251,7 +254,7 @@ LITE_TEST_CASE(PthreadFuncTestSuite, testPthread004, Function | MediumTest | Lev ICUNIT_ASSERT_EQUAL(g_testCount, 1, g_testCount); ret = pthread_join(newTh, NULL); - ICUNIT_ASSERT_EQUAL(ret, EINVAL, ret); + ICUNIT_ASSERT_EQUAL(ret, ESRCH, ret); return LOS_OK; }; @@ -645,4 +648,343 @@ LITE_TEST_CASE(PthreadFuncTestSuite, testPthread008, Function | MediumTest | Lev return LOS_OK; }; +static VOID *pthread_prio_f01(void *argument) +{ + g_testCount++; + ICUNIT_ASSERT_EQUAL(g_testCount, (UINT32)argument, g_testCount); + return NULL; +} + +/** + * @tc.number : SUB_KERNEL_PTHREAD_OPERATION_009 + * @tc.name : event operation for set priority + * @tc.desc : [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PthreadFuncTestSuite, testPthread009, Function | MediumTest | Level1) +{ + pthread_attr_t attr; + pthread_t thread[TEST_THREAD_COUNT]; + struct sched_param schedParam = { 0 }; + UINT32 ret; + UINT32 i = 0; + g_testCount = 0; + ret = pthread_attr_init(&attr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setstacksize(&attr, OS_TSK_TEST_STACK_SIZE); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + schedParam.sched_priority = TASK_PRIO_TEST + 1; + ret = pthread_attr_setschedparam(&attr, &schedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + for (i = 0; i < TEST_THREAD_COUNT; i++) { + ret = pthread_create(&thread[i], &attr, pthread_prio_f01, TEST_THREAD_COUNT - i); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + } + + for (i = 0; i < TEST_THREAD_COUNT; i++) { + ret = pthread_setschedprio(thread[i], TASK_PRIO_TEST + TEST_THREAD_COUNT - i); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + } + + for (i = 0; i < TEST_THREAD_COUNT; i++) { + ret = pthread_join(thread[i], NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + } + + return LOS_OK; +}; + +static VOID pthread_once_f01(void) +{ + g_testCount++; + ICUNIT_ASSERT_EQUAL(g_testCount, 1, g_testCount); +} + +/** + * @tc.number : SUB_KERNEL_PTHREAD_OPERATION_010 + * @tc.name : event operation for pthread_once + * @tc.desc : [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PthreadFuncTestSuite, testPthread010, Function | MediumTest | Level1) +{ + pthread_attr_t attr; + pthread_t thread[TEST_THREAD_COUNT]; + struct sched_param schedParam = { 0 }; + UINT32 ret; + UINT32 i = 0; + pthread_once_t onceControl = 0; + g_testCount = 0; + ret = pthread_attr_init(&attr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setstacksize(&attr, OS_TSK_TEST_STACK_SIZE); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + schedParam.sched_priority = TASK_PRIO_TEST + 1; + ret = pthread_attr_setschedparam(&attr, &schedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + for (i = 0; i < TEST_THREAD_COUNT; i++) { + ret = pthread_once(&onceControl, pthread_once_f01); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + } + ICUNIT_ASSERT_EQUAL(g_testCount, 1, g_testCount); + + return LOS_OK; +}; + +static VOID *pthread_cancel_f01(void *argument) +{ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + while (1) { + g_testCount++; + ICUNIT_ASSERT_EQUAL(g_testCount, 1, g_testCount); + LOS_TaskDelay(PTHREAD_TASK_DELAY); + } + + return NULL; +} + +/** + * @tc.number : SUB_KERNEL_PTHREAD_OPERATION_011 + * @tc.name : event operation for pthread_cancel + * @tc.desc : [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PthreadFuncTestSuite, testPthread011, Function | MediumTest | Level1) +{ + pthread_attr_t attr; + pthread_t thread; + struct sched_param schedParam = { 0 }; + UINT32 ret; + pthread_once_t onceControl = 0; + g_testCount = 0; + ret = pthread_attr_init(&attr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setstacksize(&attr, OS_TSK_TEST_STACK_SIZE); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + schedParam.sched_priority = TASK_PRIO_TEST - 1; + ret = pthread_attr_setschedparam(&attr, &schedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_create(&thread, &attr, pthread_cancel_f01, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_cancel(thread); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ICUNIT_ASSERT_EQUAL(g_testCount, 1, g_testCount); + + return LOS_OK; +}; + +static VOID *pthread_testcancel_f01(void *argument) +{ + INT32 ret = 0; + + ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + ICUNIT_TRACK_EQUAL(ret, 0, ret); + + ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + g_testCount = 1; + g_pthreadSem = 1; + while (g_pthreadSem == 1) { + LOS_TaskDelay(PTHREAD_TASK_DELAY); + } + + LOS_TaskDelay(PTHREAD_TASK_DELAY); + pthread_testcancel(); + g_testCount = -1; + + return NULL; +} + +/** + * @tc.number : SUB_KERNEL_PTHREAD_OPERATION_012 + * @tc.name : event operation for testcancel + * @tc.desc : [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PthreadFuncTestSuite, testPthread012, Function | MediumTest | Level1) +{ + pthread_attr_t attr; + pthread_t thread; + struct sched_param schedParam = { 0 }; + UINT32 ret; + pthread_once_t onceControl = 0; + + g_testCount = 0; + g_pthreadSem = 0; + + ret = pthread_attr_init(&attr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setstacksize(&attr, OS_TSK_TEST_STACK_SIZE); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + schedParam.sched_priority = TASK_PRIO_TEST - 1; + ret = pthread_attr_setschedparam(&attr, &schedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_create(&thread, &attr, pthread_testcancel_f01, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + while (g_pthreadSem == 0) { + LOS_TaskDelay(PTHREAD_TASK_DELAY); + } + + ret = pthread_cancel(thread); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + g_pthreadSem = 0; + + ret = pthread_join(thread, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(g_testCount, 1, g_testCount); + + return LOS_OK; +}; + +/** + * @tc.number : SUB_KERNEL_PTHREAD_OPERATION_013 + * @tc.name : event operation for set/get clock + * @tc.desc : [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PthreadFuncTestSuite, testPthread013, Function | MediumTest | Level1) +{ + INT32 ret; + clockid_t clk; + const int invalidClock = -100; + pthread_condattr_t condattr; + ret = pthread_condattr_init(&condattr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_condattr_getclock(&condattr, &clk); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(clk, 0, clk); + + ret = pthread_condattr_setclock(&condattr, 0); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ret = pthread_condattr_getclock(&condattr, &clk); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(clk, 0, clk); + + struct timespec ts = {0}; + ret = clock_getres(CLOCK_MONOTONIC, &ts); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ret = pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ret = pthread_condattr_getclock(&condattr, &clk); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(clk, CLOCK_MONOTONIC, clk); + + ret = pthread_condattr_setclock(&condattr, invalidClock); + ICUNIT_ASSERT_EQUAL(ret, EINVAL, ret); + + return 0; +} + +/** + * @tc.number : SUB_KERNEL_PTHREAD_OPERATION_014 + * @tc.name : event operation for setpshared + * @tc.desc : [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PthreadFuncTestSuite, testPthread014, Function | MediumTest | Level1) +{ + INT32 ret; + pthread_condattr_t attr; + + /* Initialize a cond attributes object */ + ret = pthread_condattr_init(&attr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + /* Set 'pshared' to INVALID_PSHARED_VALUE. */ + ret = pthread_condattr_setpshared(&attr, (-100)); + ICUNIT_ASSERT_EQUAL(ret, EINVAL, ret); + + /* Destroy the cond attributes object */ + ret = pthread_condattr_destroy(&attr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + return 0; +} + +/** + * @tc.number : SUB_KERNEL_PTHREAD_OPERATION_015 + * @tc.name : event operation for getpshared + * @tc.desc : [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PthreadFuncTestSuite, testPthread015, Function | MediumTest | Level1) +{ + INT32 ret; + INT32 pshared; + pthread_condattr_t attr; + + /* Initialize a cond attributes object */ + ret = pthread_condattr_init(&attr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + /* Set 'pshared' to INVALID_PSHARED_VALUE. */ + ret = pthread_condattr_getpshared(&attr, &pshared); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_ASSERT_EQUAL(pshared, PTHREAD_PROCESS_PRIVATE, pshared); + + /* Destroy the cond attributes object */ + ret = pthread_condattr_destroy(&attr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + return 0; +} + +/** + * @tc.number : SUB_KERNEL_PTHREAD_OPERATION_016 + * @tc.name : event operation for get/set mutex attr + * @tc.desc : [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PthreadFuncTestSuite, testPthread016, Function | MediumTest | Level1) +{ + pthread_mutexattr_t mutex_attr; + int mutex_type; + int ret; + pthread_mutexattr_init(&mutex_attr); + ret = pthread_mutexattr_settype(NULL, PTHREAD_MUTEX_ERRORCHECK); + if (ret == 0) + { + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + } + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); + pthread_mutexattr_gettype(&mutex_attr, &mutex_type); + if (mutex_type != PTHREAD_MUTEX_ERRORCHECK) { + ICUNIT_ASSERT_EQUAL(mutex_type, 0, mutex_type); + } + ret = pthread_mutexattr_gettype(NULL, &mutex_type); + if (ret == 0) { + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + } + mutex_attr.type = 3; + ret = pthread_mutexattr_gettype(&mutex_attr, &mutex_type); + if (ret == 0) { + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + } + return LOS_OK; +} + RUN_TEST_SUITE(PthreadFuncTestSuite); + diff --git a/testsuites/unittest/posix/src/semaphore/semaphore_func_test.c b/testsuites/unittest/posix/src/semaphore/semaphore_func_test.c index 9dc767b6..4a97149b 100644 --- a/testsuites/unittest/posix/src/semaphore/semaphore_func_test.c +++ b/testsuites/unittest/posix/src/semaphore/semaphore_func_test.c @@ -214,6 +214,33 @@ LITE_TEST_CASE(PosixSemaphoreFuncTestSuite, testIpcSem_Timedwait003, Function | TEST_ASSERT_EQUAL_INT(errno, EINVAL); } +/* * + * @tc.number SUB_KERNEL_IPC_SEM_TIMEDWAIT_004 + * @tc.name sem_trywait get semaphore success + * @tc.desc [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PosixSemaphoreFuncTestSuite, testIpcSem_Trywait004, Function | MediumTest | Level3) +{ + sem_t sem; + int val; + int ret; + + ret = sem_init(&sem, 0, 1); + TEST_ASSERT_EQUAL_INT(0, ret); + + ret = sem_trywait(&sem); + TEST_ASSERT_EQUAL_INT(0, ret); + + ret = sem_getvalue(&sem, &val); + TEST_ASSERT_EQUAL_INT(0, ret); + + if (val <= 0) { + sem_destroy(&sem); + return LOS_OK; + } else { + TEST_ASSERT_EQUAL_INT(0, ret); + } +} RUN_TEST_SUITE(PosixSemaphoreFuncTestSuite); @@ -223,6 +250,7 @@ void PosixSemaphoreFuncTest() RUN_ONE_TESTCASE(testIpcSem_Timedwait001); RUN_ONE_TESTCASE(testIpcSem_Timedwait002); RUN_ONE_TESTCASE(testIpcSem_Timedwait003); + RUN_ONE_TESTCASE(testIpcSem_Trywait004); return; } \ No newline at end of file diff --git a/testsuites/unittest/posix/src/stdlib/strtol_test.c b/testsuites/unittest/posix/src/stdlib/strtol_test.c index 3f8d1303..c1a5eefb 100644 --- a/testsuites/unittest/posix/src/stdlib/strtol_test.c +++ b/testsuites/unittest/posix/src/stdlib/strtol_test.c @@ -265,13 +265,13 @@ LITE_TEST_CASE(PosixStdlibStrtolTest, testStdlibStrtol011, Function | MediumTest char nPtr[] = "12 1.5"; char *endPtr = NULL; long ret = strtol(nPtr, &endPtr, 65); - if (ret == 67) { + if (ret == 0) { LOG("[DEMO] posix stdlib test case 11:strtol(base=65) ret:%ld, %s, endPtr:%s ok.\n", ret, endPtr, endPtr); } else { LOG("[DEMO] posix stdlib test case 11:strtol(base=65) ret:%ld, %s fail.\n", ret, endPtr); } - TEST_ASSERT_EQUAL_INT32(67, ret); - TEST_ASSERT_EQUAL_STRING(endPtr, " 1.5"); + TEST_ASSERT_EQUAL_INT32(0, ret); + TEST_ASSERT_EQUAL_STRING(endPtr, "12 1.5"); } LITE_TEST_CASE(PosixStdlibStrtolTest, testStdlibStrtol012, Function | MediumTest | Level1) diff --git a/testsuites/unittest/posix/src/stdlib/strtoul_test.c b/testsuites/unittest/posix/src/stdlib/strtoul_test.c index 1d196c6d..92018763 100644 --- a/testsuites/unittest/posix/src/stdlib/strtoul_test.c +++ b/testsuites/unittest/posix/src/stdlib/strtoul_test.c @@ -191,13 +191,13 @@ LITE_TEST_CASE(PosixStdlibStrtoulTest, testStdlibStrtoul007, Function | MediumTe char nPtr[] = " 12.34"; char *endPtr = NULL; unsigned long ret = strtoul(nPtr, &endPtr, 65); - if (ret == 67UL) { + if (ret == 0UL) { LOG("[DEMO] posix stdlib test case 7:strtoul(base=65) ret:%lu,%s, endPtr:%s ok.\n", ret, nPtr, endPtr); } else { LOG("[DEMO] posix stdlib test case 7:strtoul(base=65) ret:%lu,%s fail.\n", ret, endPtr); } - TEST_ASSERT_EQUAL_UINT32(67UL, ret); - TEST_ASSERT_EQUAL_STRING(endPtr, ".34"); + TEST_ASSERT_EQUAL_UINT32(0UL, ret); + TEST_ASSERT_EQUAL_STRING(endPtr, " 12.34"); } /* * diff --git a/testsuites/unittest/posix/src/stdlib/strtoull_test.c b/testsuites/unittest/posix/src/stdlib/strtoull_test.c index 0d327d39..3297f80f 100644 --- a/testsuites/unittest/posix/src/stdlib/strtoull_test.c +++ b/testsuites/unittest/posix/src/stdlib/strtoull_test.c @@ -153,13 +153,13 @@ LITE_TEST_CASE(PosixStdlibStrtoullTest, testStdlibStrtoull005, Function | Medium char nPtr[] = " 1.6"; char *endPtr = NULL; unsigned long long ret = strtoull(nPtr, &endPtr, 65); - if (ret == 1ULL) { + if (ret == 0ULL) { LOG("[DEMO] posix stdlib test case 5:strtoull(base=65) ret:%llu,%s, endPtr:%s ok.\n", ret, nPtr, endPtr); } else { LOG("[DEMO] posix stdlib test case 5:strtoull(base=65) ret:%llu,%s fail.\n", ret, nPtr); } - TEST_ASSERT_TRUE(ret == 1ULL); - TEST_ASSERT_EQUAL_STRING(endPtr, ".6"); + TEST_ASSERT_TRUE(ret == 0ULL); + TEST_ASSERT_EQUAL_STRING(endPtr, " 1.6"); } /* *