add OpenHarmony 1.0 baseline

This commit is contained in:
wenjun
2020-09-08 10:21:39 +08:00
parent 94f5f466b4
commit 6df931fc98
736 changed files with 111817 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
/*
* 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 "los_mux.h"
#include "los_queue.h"
#include "los_sem.h"
#include "los_task.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
int map_errno(UINT32 err)
{
if (err == LOS_OK) {
return ENOERR;
}
switch (err) {
case LOS_ERRNO_QUEUE_INVALID:
case LOS_ERRNO_QUEUE_WRITE_PTR_NULL:
case LOS_ERRNO_QUEUE_WRITESIZE_ISZERO:
case LOS_ERRNO_QUEUE_SIZE_TOO_BIG:
case LOS_ERRNO_QUEUE_CREAT_PTR_NULL:
case LOS_ERRNO_QUEUE_PARA_ISZERO:
case LOS_ERRNO_QUEUE_WRITE_SIZE_TOO_BIG:
errno = EINVAL;
break;
case LOS_ERRNO_QUEUE_ISFULL:
case LOS_ERRNO_QUEUE_ISEMPTY:
errno = EAGAIN;
break;
case LOS_ERRNO_QUEUE_CREATE_NO_MEMORY:
errno = ENOSPC;
break;
case LOS_ERRNO_QUEUE_TIMEOUT:
errno = ETIMEDOUT;
break;
case LOS_ERRNO_QUEUE_CB_UNAVAILABLE:
errno = ENFILE;
break;
case LOS_ERRNO_QUEUE_READ_IN_INTERRUPT:
case LOS_ERRNO_QUEUE_WRITE_IN_INTERRUPT:
errno = EINTR;
break;
case LOS_ERRNO_TSK_ID_INVALID:
case LOS_ERRNO_TSK_PTR_NULL:
case LOS_ERRNO_TSK_NAME_EMPTY:
case LOS_ERRNO_TSK_ENTRY_NULL:
case LOS_ERRNO_TSK_PRIOR_ERROR:
case LOS_ERRNO_TSK_STKSZ_TOO_LARGE:
case LOS_ERRNO_TSK_STKSZ_TOO_SMALL:
case LOS_ERRNO_TSK_NOT_CREATED:
case LOS_ERRNO_TSK_CPU_AFFINITY_MASK_ERR:
case OS_ERROR:
case LOS_ERRNO_SEM_INVALID:
case LOS_ERRNO_SEM_UNAVAILABLE:
errno = EINVAL;
break;
case LOS_ERRNO_TSK_TCB_UNAVAILABLE:
case LOS_ERRNO_TSK_MP_SYNC_RESOURCE:
case LOS_ERRNO_SEM_ALL_BUSY:
errno = ENOSPC;
break;
case LOS_ERRNO_TSK_NO_MEMORY:
case LOS_ERRNO_SEM_OVERFLOW:
errno = ENOMEM;
break;
case LOS_ERRNO_SEM_PENDED:
case LOS_ERRNO_EVENT_SHOULD_NOT_DESTORY:
errno = EBUSY;
break;
case LOS_ERRNO_SEM_PEND_IN_LOCK:
errno = EPERM;
break;
case LOS_ERRNO_SEM_PEND_INTERR:
errno = EINTR;
break;
case LOS_ERRNO_SEM_TIMEOUT:
errno = ETIMEDOUT;
break;
default:
errno = EINVAL;
break;
}
return errno;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
+49
View File
@@ -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.
*/
#ifndef _HWLITEOS_POSIX_MAP_ERROR_H
#define _HWLITEOS_POSIX_MAP_ERROR_H
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
int map_errno(unsigned int err);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+152
View File
@@ -0,0 +1,152 @@
/*
* 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 "sys/types.h"
#include "unistd.h"
#include "stdio.h"
#include "pthread.h"
#include "sys/utsname.h"
#include "mqueue.h"
#include "semaphore.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/*
* Supply some suitable values for constants that may not be present
* in all configurations.
*/
#define SC_ENABLE 1
#define SC_DISABLE (-1)
#define CONF_CASE_RETURN(name, val) \
case (name): \
return (val)
int uname(struct utsname *name)
{
INT32 ret;
if (name == NULL) {
return -EFAULT;
}
(VOID)strncpy_s(name->sysname, sizeof(name->sysname), KERNEL_NAME, strlen(KERNEL_NAME) + 1);
(VOID)strncpy_s(name->nodename, sizeof(name->nodename), "hisilicon", strlen("hisilicon") + 1);
ret = snprintf_s(name->version, sizeof(name->version), sizeof(name->version) - 1, "%s %u.%u.%u.%u %s %s\n",
KERNEL_NAME, KERNEL_MAJOR, KERNEL_MINOR, KERNEL_PATCH, KERNEL_ITRE, __DATE__, __TIME__);
if (ret < 0) {
return -EIO;
}
name->machine[0] = '\0';
name->domainname[0] = '\0';
return 0;
}
long sysconf(int name)
{
switch (name) {
CONF_CASE_RETURN(_SC_AIO_LISTIO_MAX, SC_DISABLE);
CONF_CASE_RETURN(_SC_AIO_MAX, SC_DISABLE);
CONF_CASE_RETURN(_SC_AIO_PRIO_DELTA_MAX, SC_DISABLE);
CONF_CASE_RETURN(_SC_ARG_MAX, ARG_MAX);
CONF_CASE_RETURN(_SC_ASYNCHRONOUS_IO, SC_DISABLE);
CONF_CASE_RETURN(_SC_CHILD_MAX, CHILD_MAX);
CONF_CASE_RETURN(_SC_CLK_TCK, SYS_CLK_TCK);
CONF_CASE_RETURN(_SC_DELAYTIMER_MAX, DELAYTIMER_MAX);
CONF_CASE_RETURN(_SC_FSYNC, SC_DISABLE);
CONF_CASE_RETURN(_SC_GETGR_R_SIZE_MAX, GETGR_R_SIZE_MAX);
CONF_CASE_RETURN(_SC_GETPW_R_SIZE_MAX, GETPW_R_SIZE_MAX);
CONF_CASE_RETURN(_SC_JOB_CONTROL, SC_DISABLE);
CONF_CASE_RETURN(_SC_LOGIN_NAME_MAX, LOGIN_NAME_MAX);
CONF_CASE_RETURN(_SC_MAPPED_FILES, SC_DISABLE);
CONF_CASE_RETURN(_SC_MEMLOCK, SC_DISABLE);
CONF_CASE_RETURN(_SC_MEMLOCK_RANGE, SC_DISABLE);
CONF_CASE_RETURN(_SC_MEMORY_PROTECTION, SC_DISABLE);
CONF_CASE_RETURN(_SC_MESSAGE_PASSING, SC_DISABLE);
#ifdef LOSCFG_BASE_IPC_QUEUE
CONF_CASE_RETURN(_SC_MQ_OPEN_MAX, MQ_OPEN_MAX);
CONF_CASE_RETURN(_SC_MQ_PRIO_MAX, MQ_PRIO_MAX);
#endif
CONF_CASE_RETURN(_SC_NGROUPS_MAX, NGROUPS_MAX);
CONF_CASE_RETURN(_SC_OPEN_MAX, OPEN_MAX);
CONF_CASE_RETURN(_SC_PAGESIZE, 0x1000);
CONF_CASE_RETURN(_SC_PRIORITIZED_IO, SC_DISABLE);
CONF_CASE_RETURN(_SC_PRIORITY_SCHEDULING, SC_DISABLE);
CONF_CASE_RETURN(_SC_REALTIME_SIGNALS, SC_DISABLE);
CONF_CASE_RETURN(_SC_RTSIG_MAX, RTSIG_MAX);
CONF_CASE_RETURN(_SC_SAVED_IDS, SC_DISABLE);
#ifdef LOSCFG_BASE_IPC_SEM
CONF_CASE_RETURN(_SC_SEMAPHORES, SC_ENABLE);
CONF_CASE_RETURN(_SC_SEM_NSEMS_MAX, SEM_NSEMS_MAX);
CONF_CASE_RETURN(_SC_SEM_VALUE_MAX, SEM_VALUE_MAX);
#endif
CONF_CASE_RETURN(_SC_SHARED_MEMORY_OBJECTS, SC_DISABLE);
CONF_CASE_RETURN(_SC_SIGQUEUE_MAX, SIGQUEUE_MAX);
CONF_CASE_RETURN(_SC_STREAM_MAX, STREAM_MAX);
CONF_CASE_RETURN(_SC_SYNCHRONIZED_IO, SC_DISABLE);
CONF_CASE_RETURN(_SC_THREADS, SC_ENABLE);
CONF_CASE_RETURN(_SC_THREAD_ATTR_STACKADDR, SC_ENABLE);
CONF_CASE_RETURN(_SC_THREAD_ATTR_STACKSIZE, PTHREAD_ATTR_STACKSIZE);
CONF_CASE_RETURN(_SC_THREAD_DESTRUCTOR_ITERATIONS, PTHREAD_DESTRUCTOR_ITERATIONS);
CONF_CASE_RETURN(_SC_THREAD_KEYS_MAX, PTHREAD_KEYS_MAX);
CONF_CASE_RETURN(_SC_THREAD_PRIO_INHERIT, PTHREAD_PRIO_INHERIT);
CONF_CASE_RETURN(_SC_THREAD_PRIO_PROTECT, PTHREAD_PRIO_PROTECT);
CONF_CASE_RETURN(_SC_THREAD_PRIORITY_SCHEDULING, PTHREAD_PRIORITY_SCHEDULING);
CONF_CASE_RETURN(_SC_THREAD_PROCESS_SHARED, PTHREAD_PROCESS_SHARED);
CONF_CASE_RETURN(_SC_THREAD_SAFE_FUNCTIONS, SC_DISABLE);
CONF_CASE_RETURN(_SC_THREAD_STACK_MIN, PTHREAD_STACK_MIN);
CONF_CASE_RETURN(_SC_THREAD_THREADS_MAX, PTHREAD_THREADS_MAX);
CONF_CASE_RETURN(_SC_TIMERS, TIMERS);
CONF_CASE_RETURN(_SC_TIMER_MAX, TIMER_MAX);
CONF_CASE_RETURN(_SC_TTY_NAME_MAX, TTY_NAME_MAX);
CONF_CASE_RETURN(_SC_TZNAME_MAX, TZNAME_MAX);
CONF_CASE_RETURN(_SC_VERSION, POSIX_VERSION);
default:
set_errno(EINVAL);
return -1;
}
}
pid_t getpid(void)
{
return ((LosTaskCB *)(OsCurrTaskGet()))->taskID;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
+610
View File
@@ -0,0 +1,610 @@
/*
* 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 "mqueue.h"
#include "fcntl.h"
#include "pthread.h"
#include "map_error.h"
#include "time_posix.h"
#include "los_memory.h"
#include "los_vm_map.h"
#include "user_copy.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define FNONBLOCK O_NONBLOCK
/* GLOBALS */
STATIC struct mqarray g_queueTable[LOSCFG_BASE_IPC_QUEUE_LIMIT];
STATIC pthread_mutex_t g_mqueueMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
/* LOCAL FUNCTIONS */
STATIC INLINE INT32 MqNameCheck(const CHAR *mqName)
{
if (mqName == NULL) {
errno = EINVAL;
return -1;
}
if (strlen(mqName) == 0) {
errno = EINVAL;
return -1;
}
if (strlen(mqName) > (PATH_MAX - 1)) {
errno = ENAMETOOLONG;
return -1;
}
return 0;
}
STATIC INLINE UINT32 GetMqueueCBByID(UINT32 queueID, LosQueueCB **queueCB)
{
LosQueueCB *tmpQueueCB = NULL;
if (queueCB == NULL) {
errno = EINVAL;
return LOS_ERRNO_QUEUE_READ_PTR_NULL;
}
tmpQueueCB = GET_QUEUE_HANDLE(queueID);
if ((GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) || (tmpQueueCB->queueID != queueID)) {
return LOS_ERRNO_QUEUE_INVALID;
}
*queueCB = tmpQueueCB;
return LOS_OK;
}
STATIC INLINE struct mqarray *GetMqueueCBByName(const CHAR *name)
{
UINT32 index;
UINT32 mylen = strlen(name);
for (index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) {
if ((g_queueTable[index].mq_name == NULL) || (strlen(g_queueTable[index].mq_name) != mylen)) {
continue;
}
if (strncmp(name, (const CHAR *)(g_queueTable[index].mq_name), mylen) == 0) {
return &(g_queueTable[index]);
}
}
return NULL;
}
STATIC INT32 DoMqueueDelete(struct mqarray *mqueueCB)
{
UINT32 ret;
if (mqueueCB->mq_name != NULL) {
LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
mqueueCB->mq_name = NULL;
}
mqueueCB->mqcb = NULL;
ret = LOS_QueueDelete(mqueueCB->mq_id);
switch (ret) {
case LOS_OK:
return 0;
case LOS_ERRNO_QUEUE_NOT_FOUND:
case LOS_ERRNO_QUEUE_NOT_CREATE:
case LOS_ERRNO_QUEUE_IN_TSKUSE:
case LOS_ERRNO_QUEUE_IN_TSKWRITE:
errno = EAGAIN;
return -1;
default:
errno = EINVAL;
return -1;
}
}
STATIC int SaveMqueueName(const CHAR *mqName, struct mqarray *mqueueCB)
{
size_t nameLen;
nameLen = strlen(mqName); /* sys_mq_open has checked name and name length */
mqueueCB->mq_name = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, nameLen + 1);
if (mqueueCB->mq_name == NULL) {
errno = ENOMEM;
return LOS_NOK;
}
if (strncpy_s(mqueueCB->mq_name, (nameLen + 1), mqName, nameLen) != EOK) {
LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
mqueueCB->mq_name = NULL;
errno = EINVAL;
return LOS_NOK;
}
mqueueCB->mq_name[nameLen] = '\0';
return LOS_OK;
}
STATIC struct mqpersonal *DoMqueueCreate(const struct mq_attr *attr, const CHAR *mqName, INT32 openFlag)
{
struct mqarray *mqueueCB = NULL;
UINT32 mqueueID;
UINT32 err = LOS_QueueCreate(NULL, attr->mq_maxmsg, &mqueueID, 0, attr->mq_msgsize);
if (map_errno(err) != ENOERR) {
goto ERROUT;
}
if (g_queueTable[GET_QUEUE_INDEX(mqueueID)].mqcb == NULL) {
mqueueCB = &(g_queueTable[GET_QUEUE_INDEX(mqueueID)]);
mqueueCB->mq_id = mqueueID;
}
if (mqueueCB == NULL) {
errno = EINVAL;
goto ERROUT;
}
if (SaveMqueueName(mqName, mqueueCB) != LOS_OK) {
goto ERROUT;
}
if (GetMqueueCBByID(mqueueCB->mq_id, &(mqueueCB->mqcb)) != LOS_OK) {
errno = ENOSPC;
goto ERROUT;
}
mqueueCB->mq_personal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal));
if (mqueueCB->mq_personal == NULL) {
(VOID)LOS_QueueDelete(mqueueCB->mq_id);
mqueueCB->mqcb->queueHandle = NULL;
mqueueCB->mqcb = NULL;
errno = ENOSPC;
goto ERROUT;
}
mqueueCB->unlinkflag = FALSE;
mqueueCB->mq_personal->mq_status = MQ_USE_MAGIC;
mqueueCB->mq_personal->mq_next = NULL;
mqueueCB->mq_personal->mq_posixdes = mqueueCB;
mqueueCB->mq_personal->mq_flags = (INT32)((UINT32)openFlag | ((UINT32)attr->mq_flags & (UINT32)FNONBLOCK));
return mqueueCB->mq_personal;
ERROUT:
if ((mqueueCB != NULL) && (mqueueCB->mq_name != NULL)) {
LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
mqueueCB->mq_name = NULL;
}
return (struct mqpersonal *)-1;
}
STATIC struct mqpersonal *DoMqueueOpen(struct mqarray *mqueueCB, INT32 openFlag)
{
struct mqpersonal *privateMqPersonal = NULL;
/* already have the same name of g_squeuetable */
if (mqueueCB->unlinkflag == TRUE) {
errno = EINVAL;
goto ERROUT;
}
/* alloc mqprivate and add to mqarray */
privateMqPersonal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal));
if (privateMqPersonal == NULL) {
errno = ENOSPC;
goto ERROUT;
}
privateMqPersonal->mq_next = mqueueCB->mq_personal;
mqueueCB->mq_personal = privateMqPersonal;
privateMqPersonal->mq_posixdes = mqueueCB;
privateMqPersonal->mq_flags = openFlag;
privateMqPersonal->mq_status = MQ_USE_MAGIC;
return privateMqPersonal;
ERROUT:
return (struct mqpersonal *)-1;
}
mqd_t mq_open(const char *mqName, int openFlag, ...)
{
struct mqarray *mqueueCB = NULL;
struct mqpersonal *privateMqPersonal = (struct mqpersonal *)-1;
struct mq_attr *attr = NULL;
struct mq_attr defaultAttr = { 0, MQ_MAX_MSG_NUM, MQ_MAX_MSG_LEN, 0 };
int retVal;
va_list ap;
if (MqNameCheck(mqName) == -1) {
return (mqd_t)-1;
}
(VOID)pthread_mutex_lock(&g_mqueueMutex);
mqueueCB = GetMqueueCBByName(mqName);
if ((UINT32)openFlag & (UINT32)O_CREAT) {
if (mqueueCB != NULL) {
if (((UINT32)openFlag & (UINT32)O_EXCL)) {
errno = EEXIST;
goto OUT;
}
privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag);
} else {
va_start(ap, openFlag);
(VOID)va_arg(ap, int);
attr = va_arg(ap, struct mq_attr *);
va_end(ap);
if (attr != NULL) {
retVal = LOS_ArchCopyFromUser(&defaultAttr, attr, sizeof(struct mq_attr));
if (retVal != 0) {
errno = EFAULT;
goto OUT;
}
if ((defaultAttr.mq_maxmsg < 0) || (defaultAttr.mq_maxmsg > (long int)USHRT_MAX) ||
(defaultAttr.mq_msgsize < 0) || (defaultAttr.mq_msgsize > (long int)(USHRT_MAX - sizeof(UINT32)))) {
errno = EINVAL;
goto OUT;
}
}
privateMqPersonal = DoMqueueCreate(&defaultAttr, mqName, openFlag);
}
} else {
if (mqueueCB == NULL) {
errno = ENOENT;
goto OUT;
}
privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag);
}
OUT:
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
return (mqd_t)privateMqPersonal;
}
int mq_close(mqd_t personal)
{
INT32 ret = 0;
struct mqarray *mqueueCB = NULL;
struct mqpersonal *privateMqPersonal = NULL;
struct mqpersonal *tmp = NULL;
if (!LOS_IsKernelAddressRange(personal, sizeof(struct mqpersonal))) {
errno = EBADF;
return -1;
}
(VOID)pthread_mutex_lock(&g_mqueueMutex);
privateMqPersonal = (struct mqpersonal *)personal;
if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
errno = EBADF;
goto OUT_UNLOCK;
}
mqueueCB = privateMqPersonal->mq_posixdes;
if (mqueueCB->mq_personal == NULL) {
errno = EBADF;
goto OUT_UNLOCK;
}
/* find the personal and remove */
if (mqueueCB->mq_personal == privateMqPersonal) {
mqueueCB->mq_personal = privateMqPersonal->mq_next;
} else {
for (tmp = mqueueCB->mq_personal; tmp->mq_next != NULL; tmp = tmp->mq_next) {
if (tmp->mq_next == privateMqPersonal) {
break;
}
}
if (tmp->mq_next == NULL) {
errno = EBADF;
goto OUT_UNLOCK;
}
tmp->mq_next = privateMqPersonal->mq_next;
}
/* flag no use */
privateMqPersonal->mq_status = 0;
/* free the personal */
ret = LOS_MemFree(OS_SYS_MEM_ADDR, privateMqPersonal);
if (ret != LOS_OK) {
errno = EFAULT;
ret = -1;
goto OUT_UNLOCK;
}
if ((mqueueCB->unlinkflag == TRUE) && (mqueueCB->mq_personal == NULL)) {
ret = DoMqueueDelete(mqueueCB);
}
OUT_UNLOCK:
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
return ret;
}
int OsMqGetAttr(mqd_t personal, struct mq_attr *mqAttr)
{
struct mqarray *mqueueCB = NULL;
struct mqpersonal *privateMqPersonal = NULL;
if (!LOS_IsKernelAddressRange(personal, sizeof(struct mqpersonal))) {
errno = EBADF;
return -1;
}
if (mqAttr == NULL) {
errno = EINVAL;
return -1;
}
(VOID)pthread_mutex_lock(&g_mqueueMutex);
privateMqPersonal = (struct mqpersonal *)personal;
if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
errno = EBADF;
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
return -1;
}
mqueueCB = privateMqPersonal->mq_posixdes;
mqAttr->mq_maxmsg = mqueueCB->mqcb->queueLen;
mqAttr->mq_msgsize = mqueueCB->mqcb->queueSize - sizeof(UINT32);
mqAttr->mq_curmsgs = mqueueCB->mqcb->readWriteableCnt[OS_QUEUE_READ];
mqAttr->mq_flags = privateMqPersonal->mq_flags;
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
return 0;
}
int OsMqSetAttr(mqd_t personal, const struct mq_attr *mqSetAttr, struct mq_attr *mqOldAttr)
{
struct mqpersonal *privateMqPersonal = NULL;
if (!LOS_IsKernelAddressRange(personal, sizeof(struct mqpersonal))) {
errno = EBADF;
return -1;
}
if (mqSetAttr == NULL) {
errno = EINVAL;
return -1;
}
(VOID)pthread_mutex_lock(&g_mqueueMutex);
privateMqPersonal = (struct mqpersonal *)personal;
if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
errno = EBADF;
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
return -1;
}
if (mqOldAttr != NULL) {
(VOID)OsMqGetAttr((mqd_t)privateMqPersonal, mqOldAttr);
}
privateMqPersonal->mq_flags = (INT32)((UINT32)privateMqPersonal->mq_flags & (UINT32)(~FNONBLOCK)); /* clear */
if (((UINT32)mqSetAttr->mq_flags & (UINT32)FNONBLOCK) == (UINT32)FNONBLOCK) {
privateMqPersonal->mq_flags = (INT32)((UINT32)privateMqPersonal->mq_flags | (UINT32)FNONBLOCK);
}
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
return 0;
}
int mq_getsetattr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old)
{
if (new == NULL) {
return OsMqGetAttr(mqd, old);
}
return OsMqSetAttr(mqd, new, old);
}
int mq_unlink(const char *mqName)
{
INT32 ret = 0;
struct mqarray *mqueueCB = NULL;
if (MqNameCheck(mqName) == -1) {
return -1;
}
(VOID)pthread_mutex_lock(&g_mqueueMutex);
mqueueCB = GetMqueueCBByName(mqName);
if (mqueueCB == NULL) {
errno = ENOENT;
goto ERROUT_UNLOCK;
}
if (mqueueCB->mq_personal != NULL) {
mqueueCB->unlinkflag = TRUE;
} else {
ret = DoMqueueDelete(mqueueCB);
}
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
return ret;
ERROUT_UNLOCK:
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
return -1;
}
STATIC INT32 ConvertTimeout(long flags, const struct timespec *absTimeout, UINT64 *ticks)
{
if ((UINT32)flags & (UINT32)FNONBLOCK) {
*ticks = LOS_NO_WAIT;
return 0;
}
if (absTimeout == NULL) {
*ticks = LOS_WAIT_FOREVER;
return 0;
}
if (!ValidTimeSpec(absTimeout)) {
errno = EINVAL;
return -1;
}
*ticks = OsTimeSpec2Tick(absTimeout);
return 0;
}
STATIC INLINE BOOL MqParamCheck(mqd_t personal, const char *msg, size_t msgLen)
{
if (!LOS_IsKernelAddressRange(personal, sizeof(struct mqpersonal))) {
errno = EBADF;
return FALSE;
}
if ((msg == NULL) || (msgLen == 0)) {
errno = EINVAL;
return FALSE;
}
return TRUE;
}
#define OS_MQ_GOTO_ERROUT_UNLOCK_IF(expr, errcode) \
if (expr) { \
errno = errcode; \
goto ERROUT_UNLOCK; \
}
#define OS_MQ_GOTO_ERROUT_IF(expr, errcode) \
if (expr) { \
errno = errcode; \
goto ERROUT; \
}
int mq_timedsend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio,
const struct timespec *absTimeout)
{
UINT32 mqueueID, err;
UINT64 absTicks;
struct mqarray *mqueueCB = NULL;
struct mqpersonal *privateMqPersonal = NULL;
OS_MQ_GOTO_ERROUT_IF(!MqParamCheck(personal, msg, msgLen), errno);
OS_MQ_GOTO_ERROUT_IF(msgPrio > (MQ_PRIO_MAX - 1), EINVAL);
(VOID)pthread_mutex_lock(&g_mqueueMutex);
privateMqPersonal = (struct mqpersonal *)personal;
OS_MQ_GOTO_ERROUT_UNLOCK_IF(privateMqPersonal->mq_status != MQ_USE_MAGIC, EBADF);
mqueueCB = privateMqPersonal->mq_posixdes;
OS_MQ_GOTO_ERROUT_UNLOCK_IF(msgLen > (size_t)(mqueueCB->mqcb->queueSize - sizeof(UINT32)), EMSGSIZE);
OS_MQ_GOTO_ERROUT_UNLOCK_IF((((UINT32)privateMqPersonal->mq_flags & (UINT32)O_WRONLY) != (UINT32)O_WRONLY) &&
(((UINT32)privateMqPersonal->mq_flags & (UINT32)O_RDWR) != (UINT32)O_RDWR),
EBADF);
OS_MQ_GOTO_ERROUT_UNLOCK_IF(ConvertTimeout(privateMqPersonal->mq_flags, absTimeout, &absTicks) == -1, errno);
mqueueID = mqueueCB->mq_id;
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
err = LOS_QueueWriteCopy(mqueueID, (VOID *)msg, (UINT32)msgLen, (UINT32)absTicks);
if (map_errno(err) != ENOERR) {
goto ERROUT;
}
return 0;
ERROUT_UNLOCK:
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
ERROUT:
return -1;
}
ssize_t mq_timedreceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio,
const struct timespec *absTimeout)
{
UINT32 mqueueID, err;
UINT32 receiveLen;
UINT64 absTicks;
struct mqarray *mqueueCB = NULL;
struct mqpersonal *privateMqPersonal = NULL;
if (!MqParamCheck(personal, msg, msgLen)) {
goto ERROUT;
}
if (msgPrio != NULL) {
*msgPrio = 0;
}
(VOID)pthread_mutex_lock(&g_mqueueMutex);
privateMqPersonal = (struct mqpersonal *)personal;
if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
errno = EBADF;
goto ERROUT_UNLOCK;
}
mqueueCB = privateMqPersonal->mq_posixdes;
if (msgLen < (size_t)(mqueueCB->mqcb->queueSize - sizeof(UINT32))) {
errno = EMSGSIZE;
goto ERROUT_UNLOCK;
}
if (((UINT32)privateMqPersonal->mq_flags & (UINT32)O_WRONLY) == (UINT32)O_WRONLY) {
errno = EBADF;
goto ERROUT_UNLOCK;
}
if (ConvertTimeout(privateMqPersonal->mq_flags, absTimeout, &absTicks) == -1) {
goto ERROUT_UNLOCK;
}
receiveLen = msgLen;
mqueueID = mqueueCB->mq_id;
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
err = LOS_QueueReadCopy(mqueueID, (VOID *)msg, &receiveLen, (UINT32)absTicks);
if (map_errno(err) == ENOERR) {
return (ssize_t)receiveLen;
} else {
goto ERROUT;
}
ERROUT_UNLOCK:
(VOID)pthread_mutex_unlock(&g_mqueueMutex);
ERROUT:
return -1;
}
/* not support the prio */
int mq_send(mqd_t personal, const char *msg_ptr, size_t msg_len, unsigned int msg_prio)
{
return mq_timedsend(personal, msg_ptr, msg_len, msg_prio, NULL);
}
ssize_t mq_receive(mqd_t personal, char *msg_ptr, size_t msg_len, unsigned int *msg_prio)
{
return mq_timedreceive(personal, msg_ptr, msg_len, msg_prio, NULL);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
+59
View File
@@ -0,0 +1,59 @@
/*
* 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 "los_typedef.h"
#include "los_memory.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
int posix_memalign(void **memAddr, size_t alignment, size_t size)
{
if ((alignment == 0) || ((alignment & (alignment - 1)) != 0) || ((alignment % sizeof(void *)) != 0)) {
return EINVAL;
}
*memAddr = LOS_MemAllocAlign(OS_SYS_MEM_ADDR, size, alignment);
if (*memAddr == NULL) {
return ENOMEM;
}
return ENOERR;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
+87
View File
@@ -0,0 +1,87 @@
/*
* 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 _HWLITEOS_POSIX_PPRIVATE_H
#define _HWLITEOS_POSIX_PPRIVATE_H
#include "los_process.h"
#include "pthread.h"
#include "sys/types.h"
#include "los_sem_pri.h"
#include "los_task_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define PTHREAD_DATA_NAME_MAX 20
/*
* Thread control data structure
* Per-thread information needed by POSIX
*/
typedef struct {
pthread_attr_t attr; /* Current thread attributes */
pthread_t id; /* My thread ID */
LosTaskCB *task; /* pointer to Huawei LiteOS thread object */
CHAR name[PTHREAD_DATA_NAME_MAX]; /* name string for debugging */
UINT8 state; /* Thread state */
UINT8 cancelstate; /* Cancel state of thread */
volatile UINT8 canceltype; /* Cancel type of thread */
volatile UINT8 canceled; /* pending cancel flag */
struct pthread_cleanup_buffer *cancelbuffer; /* stack of cleanup buffers */
UINT32 freestack; /* stack malloced, must be freed */
UINT32 stackmem; /* base of stack memory area only valid if freestack == true */
VOID **thread_data; /* Per-thread data table pointer */
} _pthread_data;
/*
* Values for the state field. These are solely concerned with the
* states visible to POSIX. The thread's run state is stored in the
* struct _pthread_data about thread object.
* Note: numerical order here is important, do not rearrange.
*/
#define PTHREAD_STATE_FREE 0 /* This structure is free for reuse */
#define PTHREAD_STATE_DETACHED 1 /* The thread is running but detached */
#define PTHREAD_STATE_RUNNING 2 /* The thread is running and will wait to join when it exits */
#define PTHREAD_STATE_JOIN 3 /* The thread has exited and is waiting to be joined */
#define PTHREAD_STATE_EXITED 4 /* The thread has exited and is ready to be reaped */
#define PTHREAD_STATE_ALRDY_JOIN 5 /* The thread state is in join */
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+817
View File
@@ -0,0 +1,817 @@
/*
* 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 "pprivate.h"
#include "pthread.h"
#include "sched.h"
#include "stdio.h"
#include "map_error.h"
#include "los_process_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/*
* Array of pthread control structures. A pthread_t object is
* "just" an index into this array.
*/
STATIC _pthread_data g_pthreadData[LOSCFG_BASE_CORE_TSK_LIMIT + 1];
/* Count of number of threads that have exited and not been reaped. */
STATIC INT32 g_pthreadsExited = 0;
/* this is to protect the pthread data */
STATIC pthread_mutex_t g_pthreadsDataMutex = PTHREAD_MUTEX_INITIALIZER;
/* pointed to by PTHREAD_CANCELED */
UINTPTR g_pthreadCanceledDummyVar;
/*
* Private version of pthread_self() that returns a pointer to our internal
* control structure.
*/
_pthread_data *pthread_get_self_data(void)
{
UINT32 runningTaskPID = ((LosTaskCB *)(OsCurrTaskGet()))->taskID;
_pthread_data *data = &g_pthreadData[runningTaskPID];
return data;
}
_pthread_data *pthread_get_data(pthread_t id)
{
_pthread_data *data = NULL;
if (OS_TID_CHECK_INVALID(id)) {
return NULL;
}
data = &g_pthreadData[id];
/* Check that this is a valid entry */
if ((data->state == PTHREAD_STATE_FREE) || (data->state == PTHREAD_STATE_EXITED)) {
return NULL;
}
/* Check that the entry matches the id */
if (data->id != id) {
return NULL;
}
/* Return the pointer */
return data;
}
/*
* Check whether there is a cancel pending and if so, whether
* cancellations are enabled. We do it in this order to reduce the
* number of tests in the common case - when no cancellations are
* pending. We make this inline so it can be called directly below for speed
*/
STATIC INT32 CheckForCancel(VOID)
{
_pthread_data *self = pthread_get_self_data();
if (self->canceled && (self->cancelstate == PTHREAD_CANCEL_ENABLE)) {
return 1;
}
return 0;
}
STATIC VOID ProcessUnusedStatusTask(_pthread_data *data)
{
data->state = PTHREAD_STATE_FREE;
(VOID)memset_s(data, sizeof(_pthread_data), 0, sizeof(_pthread_data));
}
/*
* This function is called to tidy up and dispose of any threads that have
* exited. This work must be done from a thread other than the one exiting.
* Note: this function must be called with pthread_mutex locked.
*/
STATIC VOID PthreadReap(VOID)
{
UINT32 i;
_pthread_data *data = NULL;
/*
* Loop over the thread table looking for exited threads. The
* g_pthreadsExited counter springs us out of this once we have
* found them all (and keeps us out if there are none to do).
*/
for (i = 0; g_pthreadsExited && (i < g_taskMaxNum); i++) {
data = &g_pthreadData[i];
if (data->state == PTHREAD_STATE_EXITED) {
/* the Huawei LiteOS not delete the dead TCB,so need to delete the TCB */
(VOID)LOS_TaskDelete(data->task->taskID);
if (data->task->taskStatus & OS_TASK_STATUS_UNUSED) {
ProcessUnusedStatusTask(data);
g_pthreadsExited--;
}
}
}
}
STATIC VOID SetPthreadAttr(const _pthread_data *self, const pthread_attr_t *attr, pthread_attr_t *outAttr)
{
/*
* Set use_attr to the set of attributes we are going to
* actually use. Either those passed in, or the default set.
*/
if (attr == NULL) {
(VOID)pthread_attr_init(outAttr);
} else {
(VOID)memcpy_s(outAttr, sizeof(pthread_attr_t), attr, sizeof(pthread_attr_t));
}
/*
* If the stack size is not valid, we can assume that it is at
* least PTHREAD_STACK_MIN bytes.
*/
if (!outAttr->stacksize_set) {
outAttr->stacksize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
}
if (outAttr->inheritsched == PTHREAD_INHERIT_SCHED) {
if (self->task == NULL) {
outAttr->schedparam.sched_priority = ((LosTaskCB *)(OsCurrTaskGet()))->priority;
} else {
outAttr->schedpolicy = self->attr.schedpolicy;
outAttr->schedparam = self->attr.schedparam;
outAttr->scope = self->attr.scope;
}
}
}
STATIC VOID SetPthreadDataAttr(const pthread_attr_t *userAttr, const pthread_t threadID,
LosTaskCB *taskCB, _pthread_data *created)
{
created->attr = *userAttr;
created->id = threadID;
created->task = taskCB;
created->state = (userAttr->detachstate == PTHREAD_CREATE_JOINABLE) ?
PTHREAD_STATE_RUNNING : PTHREAD_STATE_DETACHED;
/* need to confirmation */
created->cancelstate = PTHREAD_CANCEL_ENABLE;
created->canceltype = PTHREAD_CANCEL_DEFERRED;
created->cancelbuffer = NULL;
created->canceled = 0;
created->freestack = 0; /* no use default : 0 */
created->stackmem = taskCB->topOfStack;
created->thread_data = NULL;
}
STATIC UINT32 InitPthreadData(pthread_t threadID, pthread_attr_t *userAttr,
const CHAR name[], size_t len)
{
errno_t err;
UINT32 ret = LOS_OK;
LosTaskCB *taskCB = OS_TCB_FROM_TID(threadID);
_pthread_data *created = &g_pthreadData[threadID];
err = strncpy_s(created->name, sizeof(created->name), name, len);
if (err != EOK) {
PRINT_ERR("%s: %d, err: %d\n", __FUNCTION__, __LINE__, err);
return LOS_NOK;
}
userAttr->stacksize = taskCB->stackSize;
err = memcpy_s(taskCB->taskName, OS_TCB_NAME_LEN, created->name, strlen(created->name));
if (err != EOK) {
PRINT_ERR("%s: %d, err: %d\n", __FUNCTION__, __LINE__, err);
taskCB->taskName[0] = '\0';
return LOS_NOK;
}
#if (LOSCFG_KERNEL_SMP == YES)
if (userAttr->cpuset.__bits[0] > 0) {
taskCB->cpuAffiMask = (UINT16)userAttr->cpuset.__bits[0];
}
#endif
SetPthreadDataAttr(userAttr, threadID, taskCB, created);
return ret;
}
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*startRoutine)(void *), void *arg)
{
pthread_attr_t userAttr;
UINT32 ret;
CHAR name[PTHREAD_DATA_NAME_MAX];
STATIC UINT16 pthreadNumber = 1;
TSK_INIT_PARAM_S taskInitParam = {0};
UINT32 taskHandle;
_pthread_data *self = pthread_get_self_data();
if ((thread == NULL) || (startRoutine == NULL)) {
return EINVAL;
}
SetPthreadAttr(self, attr, &userAttr);
(VOID)memset_s(name, sizeof(name), 0, sizeof(name));
(VOID)snprintf_s(name, sizeof(name), sizeof(name) - 1, "pth%02d", pthreadNumber);
pthreadNumber++;
taskInitParam.pcName = name;
taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)startRoutine;
taskInitParam.auwArgs[0] = (UINTPTR)arg;
taskInitParam.usTaskPrio = (UINT16)userAttr.schedparam.sched_priority;
taskInitParam.uwStackSize = userAttr.stacksize;
if (OsProcessIsUserMode(OsCurrProcessGet())) {
taskInitParam.processID = OsGetKernelInitProcessID();
} else {
taskInitParam.processID = OsCurrProcessGet()->processID;
}
if (userAttr.detachstate == PTHREAD_CREATE_DETACHED) {
taskInitParam.uwResved = LOS_TASK_STATUS_DETACHED;
} else {
/* Set the pthread default joinable */
taskInitParam.uwResved = 0;
}
PthreadReap();
ret = LOS_TaskCreateOnly(&taskHandle, &taskInitParam);
if (ret == LOS_OK) {
*thread = (pthread_t)taskHandle;
ret = InitPthreadData(*thread, &userAttr, name, PTHREAD_DATA_NAME_MAX);
if (ret != LOS_OK) {
goto ERROR_OUT_WITH_TASK;
}
(VOID)LOS_SetTaskScheduler(taskHandle, SCHED_RR, taskInitParam.usTaskPrio);
}
if (ret == LOS_OK) {
return ENOERR;
} else {
goto ERROR_OUT;
}
ERROR_OUT_WITH_TASK:
(VOID)LOS_TaskDelete(taskHandle);
ERROR_OUT:
*thread = (pthread_t)-1;
return map_errno(ret);
}
void pthread_exit(void *retVal)
{
_pthread_data *self = pthread_get_self_data();
UINT32 intSave;
if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, (int *)0) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
if (pthread_mutex_lock(&g_pthreadsDataMutex) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
self->task->joinRetval = retVal;
/*
* If we are already detached, go to EXITED state, otherwise
* go into JOIN state.
*/
if (self->state == PTHREAD_STATE_DETACHED) {
self->state = PTHREAD_STATE_EXITED;
g_pthreadsExited++;
} else {
self->state = PTHREAD_STATE_JOIN;
}
if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
SCHEDULER_LOCK(intSave);
/* If the thread is the highest thread,it can't schedule in LOS_SemPost. */
OsTaskJoinPostUnsafe(self->task);
if (self->task->taskStatus & OS_TASK_STATUS_RUNNING) {
OsSchedResched();
}
SCHEDULER_UNLOCK(intSave);
}
STATIC INT32 ProcessByJoinState(_pthread_data *joined)
{
UINT32 intSave;
INT32 err = 0;
UINT32 ret;
switch (joined->state) {
case PTHREAD_STATE_RUNNING:
/* The thread is still running, we must wait for it. */
SCHEDULER_LOCK(intSave);
ret = OsTaskJoinPendUnsafe(joined->task);
SCHEDULER_UNLOCK(intSave);
if (ret != LOS_OK) {
err = (INT32)ret;
break;
}
joined->state = PTHREAD_STATE_ALRDY_JOIN;
break;
/*
* The thread has become unjoinable while we waited, so we
* fall through to complain.
*/
case PTHREAD_STATE_FREE:
case PTHREAD_STATE_DETACHED:
case PTHREAD_STATE_EXITED:
/* None of these may be joined. */
err = EINVAL;
break;
case PTHREAD_STATE_ALRDY_JOIN:
err = EINVAL;
break;
case PTHREAD_STATE_JOIN:
break;
default:
PRINT_ERR("state: %u is not supported\n", (UINT32)joined->state);
break;
}
return err;
}
int pthread_join(pthread_t thread, void **retVal)
{
INT32 err;
UINT8 status;
_pthread_data *self = NULL;
_pthread_data *joined = NULL;
/* Check for cancellation first. */
pthread_testcancel();
/* Dispose of any dead threads */
(VOID)pthread_mutex_lock(&g_pthreadsDataMutex);
PthreadReap();
(VOID)pthread_mutex_unlock(&g_pthreadsDataMutex);
self = pthread_get_self_data();
joined = pthread_get_data(thread);
if (joined == NULL) {
return ESRCH;
}
status = joined->state;
if (joined == self) {
return EDEADLK;
}
err = ProcessByJoinState(joined);
(VOID)pthread_mutex_lock(&g_pthreadsDataMutex);
if (!err) {
/*
* Here, we know that joinee is a thread that has exited and is
* ready to be joined.
*/
if (retVal != NULL) {
/* Get the retVal */
*retVal = joined->task->joinRetval;
}
/* Set state to exited. */
joined->state = PTHREAD_STATE_EXITED;
g_pthreadsExited++;
/* Dispose of any dead threads */
PthreadReap();
} else {
joined->state = status;
}
(VOID)pthread_mutex_unlock(&g_pthreadsDataMutex);
/* Check for cancellation before returning */
pthread_testcancel();
return err;
}
/*
* Set the detachstate of the thread to "detached". The thread then does not
* need to be joined and its resources will be freed when it exits.
*/
int pthread_detach(pthread_t thread)
{
int ret = 0;
UINT32 intSave;
_pthread_data *detached = NULL;
if (pthread_mutex_lock(&g_pthreadsDataMutex) != ENOERR) {
ret = ESRCH;
}
detached = pthread_get_data(thread);
if (detached == NULL) {
ret = ESRCH; /* No such thread */
} else if (detached->state == PTHREAD_STATE_DETACHED) {
ret = EINVAL; /* Already detached! */
} else if (detached->state == PTHREAD_STATE_JOIN) {
detached->state = PTHREAD_STATE_EXITED;
g_pthreadsExited++;
} else {
/* Set state to detached and kick any joinees to make them return. */
SCHEDULER_LOCK(intSave);
if (!(detached->task->taskStatus & OS_TASK_STATUS_EXIT)) {
ret = OsTaskSetDeatchUnsafe(detached->task);
if (ret == ESRCH) {
ret = LOS_OK;
} else if (ret == LOS_OK) {
detached->state = PTHREAD_STATE_DETACHED;
}
} else {
detached->state = PTHREAD_STATE_EXITED;
g_pthreadsExited++;
}
SCHEDULER_UNLOCK(intSave);
}
/* Dispose of any dead threads */
PthreadReap();
if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) {
ret = ESRCH;
}
return ret;
}
int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param)
{
_pthread_data *data = NULL;
int ret;
if ((param == NULL) || (param->sched_priority > OS_TASK_PRIORITY_LOWEST)) {
return EINVAL;
}
if (policy != SCHED_RR) {
return EINVAL;
}
/* The parameters seem OK, change the thread. */
ret = pthread_mutex_lock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
data = pthread_get_data(thread);
if (data == NULL) {
ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
return ESRCH;
}
/* Only support one policy now */
data->attr.schedpolicy = SCHED_RR;
data->attr.schedparam = *param;
ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
(VOID)LOS_TaskPriSet((UINT32)thread, (UINT16)param->sched_priority);
return ENOERR;
}
int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param)
{
_pthread_data *data = NULL;
int ret;
if ((policy == NULL) || (param == NULL)) {
return EINVAL;
}
ret = pthread_mutex_lock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
data = pthread_get_data(thread);
if (data == NULL) {
goto ERR_OUT;
}
*policy = data->attr.schedpolicy;
*param = data->attr.schedparam;
ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
return ret;
ERR_OUT:
ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
return ESRCH;
}
/* Call initRoutine just the once per control variable. */
int pthread_once(pthread_once_t *onceControl, void (*initRoutine)(void))
{
pthread_once_t old;
int ret;
if ((onceControl == NULL) || (initRoutine == NULL)) {
return EINVAL;
}
/* Do a test and set on the onceControl object. */
ret = pthread_mutex_lock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
old = *onceControl;
*onceControl = 1;
ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
/* If the onceControl was zero, call the initRoutine(). */
if (!old) {
initRoutine();
}
return ENOERR;
}
/* Thread specific data */
int pthread_key_create(pthread_key_t *key, void (*destructor)(void *))
{
(VOID)key;
(VOID)destructor;
PRINT_ERR("[%s] is not support.\n", __FUNCTION__);
return 0;
}
/* Store the pointer value in the thread-specific data slot addressed by the key. */
int pthread_setspecific(pthread_key_t key, const void *pointer)
{
(VOID)key;
(VOID)pointer;
PRINT_ERR("[%s] is not support.\n", __FUNCTION__);
return 0;
}
/* Retrieve the pointer value in the thread-specific data slot addressed by the key. */
void *pthread_getspecific(pthread_key_t key)
{
(VOID)key;
PRINT_ERR("[%s] is not support.\n", __FUNCTION__);
return NULL;
}
/*
* Set cancel state of current thread to ENABLE or DISABLE.
* Returns old state in *oldState.
*/
int pthread_setcancelstate(int state, int *oldState)
{
_pthread_data *self = NULL;
int ret;
if ((state != PTHREAD_CANCEL_ENABLE) && (state != PTHREAD_CANCEL_DISABLE)) {
return EINVAL;
}
ret = pthread_mutex_lock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
self = pthread_get_self_data();
if (oldState != NULL) {
*oldState = self->cancelstate;
}
self->cancelstate = (UINT8)state;
ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
return ENOERR;
}
/*
* Set cancel type of current thread to ASYNCHRONOUS or DEFERRED.
* Returns old type in *oldType.
*/
int pthread_setcanceltype(int type, int *oldType)
{
_pthread_data *self = NULL;
int ret;
if ((type != PTHREAD_CANCEL_ASYNCHRONOUS) && (type != PTHREAD_CANCEL_DEFERRED)) {
return EINVAL;
}
ret = pthread_mutex_lock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
self = pthread_get_self_data();
if (oldType != NULL) {
*oldType = self->canceltype;
}
self->canceltype = (UINT8)type;
ret = pthread_mutex_unlock(&g_pthreadsDataMutex);
if (ret != ENOERR) {
return ret;
}
return ENOERR;
}
STATIC UINT32 DoPthreadCancel(_pthread_data *data)
{
UINT32 ret = LOS_OK;
UINT32 intSave;
LOS_TaskLock();
data->canceled = 0;
if ((data->task->taskStatus & OS_TASK_STATUS_EXIT) || (LOS_TaskSuspend(data->task->taskID) != ENOERR)) {
ret = LOS_NOK;
goto OUT;
}
if (data->task->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
SCHEDULER_LOCK(intSave);
OsTaskJoinPostUnsafe(data->task);
SCHEDULER_UNLOCK(intSave);
g_pthreadCanceledDummyVar = (UINTPTR)PTHREAD_CANCELED;
data->task->joinRetval = (VOID *)g_pthreadCanceledDummyVar;
} else if (data->state && !(data->task->taskStatus & OS_TASK_STATUS_UNUSED)) {
data->state = PTHREAD_STATE_EXITED;
g_pthreadsExited++;
PthreadReap();
} else {
ret = LOS_NOK;
}
OUT:
LOS_TaskUnlock();
return ret;
}
int pthread_cancel(pthread_t thread)
{
_pthread_data *data = NULL;
if (pthread_mutex_lock(&g_pthreadsDataMutex) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
data = pthread_get_data(thread);
if (data == NULL) {
if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
return ESRCH;
}
data->canceled = 1;
if ((data->cancelstate == PTHREAD_CANCEL_ENABLE) &&
(data->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(data) == LOS_NOK) {
goto ERROR_OUT;
}
}
/*
* Otherwise the thread has cancellation disabled, in which case
* it is up to the thread to enable cancellation
*/
if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
return ENOERR;
ERROR_OUT:
if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
return ESRCH;
}
/*
* Test for a pending cancellation for the current thread and terminate
* the thread if there is one.
*/
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);
}
}
/* Get current thread id. */
pthread_t pthread_self(void)
{
_pthread_data *data = pthread_get_self_data();
return data->id;
}
/* Compare two thread identifiers. */
int pthread_equal(pthread_t thread1, pthread_t thread2)
{
return thread1 == thread2;
}
void pthread_cleanup_push_inner(struct pthread_cleanup_buffer *buffer,
void (*routine)(void *), void *arg)
{
(VOID)buffer;
(VOID)routine;
(VOID)arg;
PRINT_ERR("[%s] is not support.\n", __FUNCTION__);
return;
}
void pthread_cleanup_pop_inner(struct pthread_cleanup_buffer *buffer, int execute)
{
(VOID)buffer;
(VOID)execute;
PRINT_ERR("[%s] is not support.\n", __FUNCTION__);
return;
}
/*
* Set the cpu affinity mask for the thread
*/
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t* cpuset)
{
INT32 ret = sched_setaffinity(thread, cpusetsize, cpuset);
if (ret == -1) {
return errno;
} else {
return ENOERR;
}
}
/*
* Get the cpu affinity mask from the thread
*/
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t* cpuset)
{
INT32 ret = sched_getaffinity(thread, cpusetsize, cpuset);
if (ret == -1) {
return errno;
} else {
return ENOERR;
}
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
+287
View File
@@ -0,0 +1,287 @@
/*
* 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 "pthread.h"
#include "pprivate.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
int pthread_attr_init(pthread_attr_t *attr)
{
if (attr == NULL) {
return EINVAL;
}
attr->detachstate = PTHREAD_CREATE_JOINABLE;
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->stackaddr_set = 0;
attr->stackaddr = NULL;
attr->stacksize_set = 1;
attr->stacksize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
#if (LOSCFG_KERNEL_SMP == YES)
attr->cpuset.__bits[0] = 0;
#endif
return ENOERR;
}
int pthread_attr_destroy(pthread_attr_t *attr)
{
if (attr == NULL) {
return EINVAL;
}
/* Nothing to do here... */
return ENOERR;
}
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 EINVAL;
}
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachState)
{
if ((attr == NULL) || (detachState == NULL)) {
return EINVAL;
}
*detachState = (int)attr->detachstate;
return ENOERR;
}
int pthread_attr_setscope(pthread_attr_t *attr, int scope)
{
if (attr == NULL) {
return EINVAL;
}
if (scope == PTHREAD_SCOPE_PROCESS) {
attr->scope = (unsigned int)scope;
return ENOERR;
}
if (scope == PTHREAD_SCOPE_SYSTEM) {
return ENOTSUP;
}
return EINVAL;
}
int pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
{
if ((attr == NULL) || (scope == NULL)) {
return EINVAL;
}
*scope = (int)attr->scope;
return ENOERR;
}
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 EINVAL;
}
int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
{
if ((attr == NULL) || (inherit == NULL)) {
return EINVAL;
}
*inherit = (int)attr->inheritsched;
return ENOERR;
}
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
{
if ((attr != NULL) && (policy == SCHED_RR)) {
attr->schedpolicy = SCHED_RR;
return ENOERR;
}
return EINVAL;
}
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
{
if ((attr == NULL) || (policy == NULL)) {
return EINVAL;
}
*policy = (int)attr->schedpolicy;
return ENOERR;
}
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)) {
return ENOTSUP;
}
attr->schedparam = *param;
return ENOERR;
}
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param)
{
if ((attr == NULL) || (param == NULL)) {
return EINVAL;
}
*param = attr->schedparam;
return ENOERR;
}
/*
* Set starting address of stack. Whether this is at the start or end of
* the memory block allocated for the stack depends on whether the stack
* grows up or down.
*/
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackAddr)
{
if (attr == NULL) {
return EINVAL;
}
attr->stackaddr_set = 1;
attr->stackaddr = stackAddr;
return ENOERR;
}
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 EINVAL; /* Stack address not set, return EINVAL. */
}
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stackSize)
{
/* Reject inadequate stack sizes */
if ((attr == NULL) || (stackSize < PTHREAD_STACK_MIN)) {
return EINVAL;
}
attr->stacksize_set = 1;
attr->stacksize = stackSize;
return ENOERR;
}
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. */
if ((attr == NULL) || (stackSize == NULL) || (!attr->stacksize_set)) {
return EINVAL;
}
*stackSize = attr->stacksize;
return ENOERR;
}
/*
* Set the cpu affinity mask
*/
int pthread_attr_setaffinity_np(pthread_attr_t* attr, size_t cpusetsize, const cpu_set_t* cpuset)
{
#if (LOSCFG_KERNEL_SMP == YES)
if (attr == NULL) {
return EINVAL;
}
if ((cpuset == NULL) || (cpusetsize == 0)) {
attr->cpuset.__bits[0] = 0;
return ENOERR;
}
if ((cpusetsize != sizeof(cpu_set_t)) || (cpuset->__bits[0] > LOSCFG_KERNEL_CPU_MASK)) {
return EINVAL;
}
attr->cpuset = *cpuset;
#endif
return ENOERR;
}
/*
* Get the cpu affinity mask
*/
int pthread_attr_getaffinity_np(const pthread_attr_t* attr, size_t cpusetsize, cpu_set_t* cpuset)
{
#if (LOSCFG_KERNEL_SMP == YES)
if ((attr == NULL) || (cpuset == NULL) || (cpusetsize != sizeof(cpu_set_t))) {
return EINVAL;
}
*cpuset = attr->cpuset;
#endif
return ENOERR;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
+358
View File
@@ -0,0 +1,358 @@
/*
* 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 "pprivate.h"
#include "pthread.h"
#include "stdlib.h"
#include "time_posix.h"
#include "los_atomic.h"
#include "los_event_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define BROADCAST_EVENT 1
#define COND_COUNTER_STEP 0x0004U
#define COND_FLAGS_MASK 0x0003U
#define COND_COUNTER_MASK (~COND_FLAGS_MASK)
STATIC INLINE INT32 CondInitCheck(const pthread_cond_t *cond)
{
if ((cond->event.stEventList.pstPrev == NULL) &&
(cond->event.stEventList.pstNext == NULL)) {
return 1;
}
return 0;
}
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) {
return EINVAL;
}
return 0;
}
int pthread_condattr_init(pthread_condattr_t *attr)
{
if (attr == NULL) {
return EINVAL;
}
return 0;
}
int pthread_cond_destroy(pthread_cond_t *cond)
{
if (cond == NULL) {
return EINVAL;
}
if (CondInitCheck(cond)) {
return ENOERR;
}
if (LOS_EventDestroy(&cond->event) != LOS_OK) {
return EBUSY;
}
if (pthread_mutex_destroy(cond->mutex) != ENOERR) {
PRINT_ERR("%s mutex destroy fail!\n", __FUNCTION__);
return EINVAL;
}
free(cond->mutex);
cond->mutex = NULL;
return ENOERR;
}
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
{
int ret = ENOERR;
if (cond == NULL) {
return EINVAL;
}
(VOID)attr;
(VOID)LOS_EventInit(&(cond->event));
cond->mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
if (cond->mutex == NULL) {
return ENOMEM;
}
(VOID)pthread_mutex_init(cond->mutex, NULL);
cond->value = 0;
(VOID)pthread_mutex_lock(cond->mutex);
cond->count = 0;
(VOID)pthread_mutex_unlock(cond->mutex);
return ret;
}
STATIC VOID PthreadCondValueModify(pthread_cond_t *cond)
{
UINT32 flags = ((UINT32)cond->value & COND_FLAGS_MASK);
INT32 oldVal, newVal;
while (true) {
oldVal = cond->value;
newVal = (INT32)(((UINT32)(oldVal - COND_COUNTER_STEP) & COND_COUNTER_MASK) | flags);
if (LOS_AtomicCmpXchg32bits(&cond->value, newVal, oldVal) == 0) {
break;
}
}
}
int pthread_cond_broadcast(pthread_cond_t *cond)
{
int ret = ENOERR;
if (cond == NULL) {
return EINVAL;
}
(VOID)pthread_mutex_lock(cond->mutex);
if (cond->count > 0) {
cond->count = 0;
(VOID)pthread_mutex_unlock(cond->mutex);
PthreadCondValueModify(cond);
(VOID)LOS_EventWrite(&(cond->event), BROADCAST_EVENT);
return ret;
}
(VOID)pthread_mutex_unlock(cond->mutex);
return ret;
}
int pthread_cond_signal(pthread_cond_t *cond)
{
int ret = ENOERR;
if (cond == NULL) {
return EINVAL;
}
(VOID)pthread_mutex_lock(cond->mutex);
if (cond->count > 0) {
cond->count--;
(VOID)pthread_mutex_unlock(cond->mutex);
PthreadCondValueModify(cond);
(VOID)OsEventWriteOnce(&(cond->event), 0x01);
return ret;
}
(VOID)pthread_mutex_unlock(cond->mutex);
return ret;
}
STATIC INT32 PthreadCondWaitSub(pthread_cond_t *cond, INT32 value, UINT32 ticks)
{
EventCond eventCond = { &cond->value, value, ~0x01U };
/*
* When the scheduling lock is held:
* (1) value is not equal to cond->value, clear the event message and
* do not block the current thread, because other threads is calling pthread_cond_broadcast or
* pthread_cond_signal to modify cond->value and wake up the current thread,
* and others threads will block on the scheduling lock until the current thread releases
* the scheduling lock.
* (2) value is equal to cond->value, block the current thread
* and wait to be awakened by other threads.
*/
return (int)OsEventReadWithCond(&eventCond, &(cond->event), 0x0fU,
LOS_WAITMODE_OR | LOS_WAITMODE_CLR, ticks);
}
STATIC VOID PthreadCountSub(pthread_cond_t *cond)
{
(VOID)pthread_mutex_lock(cond->mutex);
if (cond->count > 0) {
cond->count--;
}
(VOID)pthread_mutex_unlock(cond->mutex);
}
STATIC INT32 ProcessReturnVal(pthread_cond_t *cond, INT32 val)
{
INT32 ret;
switch (val) {
/* 0: event does not occur */
case 0:
case BROADCAST_EVENT:
ret = ENOERR;
break;
case LOS_ERRNO_EVENT_READ_TIMEOUT:
PthreadCountSub(cond);
ret = ETIMEDOUT;
break;
default:
PthreadCountSub(cond);
ret = EINVAL;
break;
}
return ret;
}
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
const struct timespec *absTime)
{
UINT32 absTicks;
INT32 ret;
INT32 oldValue;
pthread_testcancel();
if ((cond == NULL) || (mutex == NULL) || (absTime == NULL)) {
return EINVAL;
}
if (CondInitCheck(cond)) {
ret = pthread_cond_init(cond, NULL);
if (ret != ENOERR) {
return ret;
}
}
oldValue = cond->value;
(VOID)pthread_mutex_lock(cond->mutex);
cond->count++;
(VOID)pthread_mutex_unlock(cond->mutex);
if ((absTime->tv_sec == 0) && (absTime->tv_nsec == 0)) {
return ETIMEDOUT;
}
if (!ValidTimeSpec(absTime)) {
return EINVAL;
}
absTicks = OsTimeSpec2Tick(absTime);
if (pthread_mutex_unlock(mutex) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
#ifndef LOSCFG_ARCH_CORTEX_M7
ret = PthreadCondWaitSub(cond, oldValue, absTicks);
#else
ret = (INT32)LOS_EventRead(&(cond->event), 0x0f, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, absTicks);
#endif
if (pthread_mutex_lock(mutex) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
ret = ProcessReturnVal(cond, ret);
pthread_testcancel();
return ret;
}
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{
int ret;
int oldValue;
if ((cond == NULL) || (mutex == NULL)) {
return EINVAL;
}
if (CondInitCheck(cond)) {
ret = pthread_cond_init(cond, NULL);
if (ret != ENOERR) {
return ret;
}
}
oldValue = cond->value;
(VOID)pthread_mutex_lock(cond->mutex);
cond->count++;
(VOID)pthread_mutex_unlock(cond->mutex);
if (pthread_mutex_unlock(mutex) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
#ifndef LOSCFG_ARCH_CORTEX_M7
ret = PthreadCondWaitSub(cond, oldValue, LOS_WAIT_FOREVER);
#else
ret = (INT32)LOS_EventRead(&(cond->event), 0x0f, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
#endif
if (pthread_mutex_lock(mutex) != ENOERR) {
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
}
switch (ret) {
/* 0: event does not occur */
case 0:
case BROADCAST_EVENT:
ret = ENOERR;
break;
default:
PthreadCountSub(cond);
ret = EINVAL;
break;
}
return ret;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
+146
View File
@@ -0,0 +1,146 @@
/*
* 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 "pthread.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
int pthread_mutexattr_init(pthread_mutexattr_t *attr)
{
unsigned int ret = LOS_MuxAttrInit(attr);
if (ret != LOS_OK) {
return (int)ret;
}
#if defined POSIX_MUTEX_DEFAULT_INHERIT
attr->protocol = PTHREAD_PRIO_INHERIT;
#elif defined POSIX_MUTEX_DEFAULT_PROTECT
attr->protocol = PTHREAD_PRIO_PROTECT;
#else
attr->protocol = PTHREAD_PRIO_NONE;
#endif
attr->type = PTHREAD_MUTEX_NORMAL;
return LOS_OK;
}
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
{
return LOS_MuxAttrDestroy(attr);
}
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol)
{
return LOS_MuxAttrSetProtocol(attr, protocol);
}
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol)
{
return LOS_MuxAttrGetProtocol(attr, protocol);
}
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling)
{
return LOS_MuxAttrSetPrioceiling(attr, prioceiling);
}
int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *prioceiling)
{
return LOS_MuxAttrGetPrioceiling(attr, prioceiling);
}
int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *oldPrioceiling)
{
return LOS_MuxSetPrioceiling(mutex, prioceiling, oldPrioceiling);
}
int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex, int *prioceiling)
{
return LOS_MuxGetPrioceiling(mutex, prioceiling);
}
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *outType)
{
return LOS_MuxAttrGetType(attr, outType);
}
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
{
return LOS_MuxAttrSetType(attr, type);
}
/* Initialize mutex. If mutexAttr is NULL, use default attributes. */
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexAttr)
{
unsigned int ret = LOS_MuxInit(mutex, mutexAttr);
if ((ret == LOS_OK) && (mutexAttr == NULL)) {
#if defined POSIX_MUTEX_DEFAULT_INHERIT
mutex->attr.protocol = PTHREAD_PRIO_INHERIT;
#elif defined POSIX_MUTEX_DEFAULT_PROTECT
mutex->attr.protocol = PTHREAD_PRIO_PROTECT;
#else
mutex->attr.protocol = PTHREAD_PRIO_NONE;
#endif
mutex->attr.type = PTHREAD_MUTEX_NORMAL;
}
return (int)ret;
}
int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
return LOS_MuxDestroy(mutex);
}
/* Lock mutex, waiting for it if necessary. */
int pthread_mutex_lock(pthread_mutex_t *mutex)
{
return LOS_MuxLock(mutex, LOS_WAIT_FOREVER);
}
int pthread_mutex_trylock(pthread_mutex_t *mutex)
{
return LOS_MuxTrylock(mutex);
}
int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
return LOS_MuxUnlock(mutex);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
+150
View File
@@ -0,0 +1,150 @@
/*
* 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 "sched.h"
#include "map_error.h"
#include "sys/types.h"
#include "unistd.h"
#include "los_task_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
int sched_get_priority_min(int policy)
{
if (policy != SCHED_RR) {
errno = EINVAL;
return -1;
}
return OS_TASK_PRIORITY_HIGHEST;
}
int sched_get_priority_max(int policy)
{
if (policy != SCHED_RR) {
errno = EINVAL;
return -1;
}
return OS_TASK_PRIORITY_LOWEST;
}
/*
* This API is Linux-specific, not conforming to POSIX.
*/
int sched_setaffinity(pid_t pid, size_t set_size, const cpu_set_t* set)
{
#if (LOSCFG_KERNEL_SMP == YES)
UINT32 taskID = (UINT32)pid;
UINT32 ret;
if ((set == NULL) || (set_size != sizeof(cpu_set_t)) || (set->__bits[0] > LOSCFG_KERNEL_CPU_MASK)) {
errno = EINVAL;
return -1;
}
if (taskID == 0) {
taskID = LOS_CurTaskIDGet();
if (taskID == LOS_ERRNO_TSK_ID_INVALID) {
errno = EINVAL;
return -1;
}
}
ret = LOS_TaskCpuAffiSet(taskID, (UINT16)set->__bits[0]);
if (ret != LOS_OK) {
errno = map_errno(ret);
return -1;
}
#endif
return 0;
}
/*
* This API is Linux-specific, not conforming to POSIX.
*/
int sched_getaffinity(pid_t pid, size_t set_size, cpu_set_t* set)
{
#if (LOSCFG_KERNEL_SMP == YES)
UINT32 taskID = (UINT32)pid;
UINT16 cpuAffiMask;
if ((set == NULL) || (set_size != sizeof(cpu_set_t))) {
errno = EINVAL;
return -1;
}
if (taskID == 0) {
taskID = LOS_CurTaskIDGet();
if (taskID == LOS_ERRNO_TSK_ID_INVALID) {
errno = EINVAL;
return -1;
}
}
cpuAffiMask = LOS_TaskCpuAffiGet(taskID);
if (cpuAffiMask == 0) {
errno = EINVAL;
return -1;
}
set->__bits[0] = cpuAffiMask;
#endif
return 0;
}
int __sched_cpucount(size_t set_size, const cpu_set_t* set)
{
INT32 count = 0;
UINT32 i;
if ((set_size != sizeof(cpu_set_t)) || (set == NULL)) {
return 0;
}
for (i = 0; i < set_size / sizeof(__CPU_BITTYPE); i++) {
count += __builtin_popcountl(set->__bits[i]);
}
return count;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
+204
View File
@@ -0,0 +1,204 @@
/*
* 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 "semaphore.h"
#include "sys/types.h"
#include "map_error.h"
#include "time_posix.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/* Initialize semaphore to value, shared is not supported in Huawei LiteOS. */
int sem_init(sem_t *sem, int shared, unsigned int value)
{
UINT32 semHandle = 0;
UINT32 ret;
(VOID)shared;
if ((sem == NULL) || (value > OS_SEM_COUNT_MAX)) {
errno = EINVAL;
return -1;
}
ret = LOS_SemCreate(value, &semHandle);
if (map_errno(ret) != ENOERR) {
return -1;
}
sem->sem = GET_SEM(semHandle);
return 0;
}
int sem_destroy(sem_t *sem)
{
UINT32 ret;
if ((sem == NULL) || (sem->sem == NULL)) {
errno = EINVAL;
return -1;
}
ret = LOS_SemDelete(sem->sem->semID);
if (map_errno(ret) != ENOERR) {
return -1;
}
return 0;
}
/* Decrement value if >0 or wait for a post. */
int sem_wait(sem_t *sem)
{
UINT32 ret;
if ((sem == NULL) || (sem->sem == NULL)) {
errno = EINVAL;
return -1;
}
ret = LOS_SemPend(sem->sem->semID, LOS_WAIT_FOREVER);
if (map_errno(ret) == ENOERR) {
return 0;
} else {
return -1;
}
}
/* Decrement value if >0, return -1 if not. */
int sem_trywait(sem_t *sem)
{
UINT32 ret;
if ((sem == NULL) || (sem->sem == NULL)) {
errno = EINVAL;
return -1;
}
ret = LOS_SemPend(sem->sem->semID, LOS_NO_WAIT);
if (map_errno(ret) == ENOERR) {
return 0;
} else {
if ((errno != EINVAL) || (ret == LOS_ERRNO_SEM_UNAVAILABLE)) {
errno = EAGAIN;
}
return -1;
}
}
int sem_timedwait(sem_t *sem, const struct timespec *timeout)
{
UINT32 ret;
UINT32 tickCnt;
if ((sem == NULL) || (sem->sem == NULL)) {
errno = EINVAL;
return -1;
}
if (!ValidTimeSpec(timeout)) {
errno = EINVAL;
return -1;
}
tickCnt = OsTimeSpec2Tick(timeout);
ret = LOS_SemPend(sem->sem->semID, tickCnt);
if (map_errno(ret) == ENOERR) {
return 0;
} else {
return -1;
}
}
int sem_post(sem_t *sem)
{
UINT32 ret;
if ((sem == NULL) || (sem->sem == NULL)) {
errno = EINVAL;
return -1;
}
ret = LOS_SemPost(sem->sem->semID);
if (map_errno(ret) != ENOERR) {
return -1;
}
return 0;
}
int sem_getvalue(sem_t *sem, int *currVal)
{
INT32 val;
if ((sem == NULL) || (currVal == NULL)) {
errno = EINVAL;
return -1;
}
val = sem->sem->semCount;
if (val < 0) {
val = 0;
}
*currVal = val;
return 0;
}
sem_t *sem_open(const char *name, int openFlag, ...)
{
(VOID)name;
(VOID)openFlag;
errno = ENOSYS;
return NULL;
}
int sem_close(sem_t *sem)
{
(VOID)sem;
errno = ENOSYS;
return -1;
}
int sem_unlink(const char *name)
{
(VOID)name;
errno = ENOSYS;
return -1;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
+188
View File
@@ -0,0 +1,188 @@
/*
* 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 <los_config.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#ifdef LOSCFG_NET_LWIP_SACK
#include <lwip/sockets.h>
#if !LWIP_COMPAT_SOCKETS
#define CHECK_NULL_PTR(ptr) do { if (ptr == NULL) { set_errno(EFAULT); return -1; } } while (0)
int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
return lwip_accept(s, addr, addrlen);
}
int bind(int s, const struct sockaddr *name, socklen_t namelen)
{
CHECK_NULL_PTR(name);
if (namelen < sizeof(*name)) {
set_errno(EINVAL);
return -1;
}
return lwip_bind(s, name, namelen);
}
int shutdown(int s, int how)
{
return lwip_shutdown(s, how);
}
int getpeername(int s, struct sockaddr *name, socklen_t *namelen)
{
CHECK_NULL_PTR(name);
CHECK_NULL_PTR(namelen);
return lwip_getpeername(s, name, namelen);
}
int getsockname(int s, struct sockaddr *name, socklen_t *namelen)
{
CHECK_NULL_PTR(name);
CHECK_NULL_PTR(namelen);
return lwip_getsockname(s, name, namelen);
}
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
{
return lwip_getsockopt(s, level, optname, optval, optlen);
}
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
{
return lwip_setsockopt(s, level, optname, optval, optlen);
}
int closesocket(int s)
{
return lwip_close(s);
}
int connect(int s, const struct sockaddr *name, socklen_t namelen)
{
CHECK_NULL_PTR(name);
if (namelen < sizeof(*name)) {
set_errno(EINVAL);
return -1;
}
return lwip_connect(s, name, namelen);
}
int listen(int s, int backlog)
{
return lwip_listen(s, backlog);
}
ssize_t recv(int s, void *mem, size_t len, int flags)
{
CHECK_NULL_PTR(mem);
return lwip_recv(s, mem, len, flags);
}
ssize_t recvfrom(int s, void *mem, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen)
{
CHECK_NULL_PTR(mem);
return lwip_recvfrom(s, mem, len, flags, from, fromlen);
}
ssize_t recvmsg(int s, struct msghdr *message, int flags)
{
CHECK_NULL_PTR(message);
if (message->msg_iovlen) {
CHECK_NULL_PTR(message->msg_iov);
}
return lwip_recvmsg(s, message, flags);
}
ssize_t send(int s, const void *dataptr, size_t size, int flags)
{
CHECK_NULL_PTR(dataptr);
return lwip_send(s, dataptr, size, flags);
}
ssize_t sendmsg(int s, const struct msghdr *message, int flags)
{
return lwip_sendmsg(s, message, flags);
}
ssize_t sendto(int s, const void *dataptr, size_t size, int flags,
const struct sockaddr *to, socklen_t tolen)
{
CHECK_NULL_PTR(dataptr);
if (to && tolen < sizeof(*to)) {
set_errno(EINVAL);
return -1;
}
return lwip_sendto(s, dataptr, size, flags, to, tolen);
}
int socket(int domain, int type, int protocol)
{
return lwip_socket(domain, type, protocol);
}
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
{
return lwip_inet_ntop(af, src, dst, size);
}
int inet_pton(int af, const char *src, void *dst)
{
return lwip_inet_pton(af, src, dst);
}
#ifndef LWIP_INET_ADDR_FUNC
in_addr_t inet_addr(const char* cp)
{
return ipaddr_addr(cp);
}
#endif
#ifndef LWIP_INET_ATON_FUNC
int inet_aton(const char* cp, struct in_addr* inp)
{
return ip4addr_aton(cp, (ip4_addr_t*)inp);
}
#endif
#ifndef LWIP_INET_NTOA_FUNC
char* inet_ntoa(struct in_addr in)
{
return ip4addr_ntoa((const ip4_addr_t*)&(in));
}
#endif
#endif /* !LWIP_COMPAT_SOCKETS */
#endif /* LOSCFG_NET_LWIP_SACK */
+984
View File
@@ -0,0 +1,984 @@
/*
* 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 "time.h"
#include "asm/hal_platform_ints.h"
#include "stdint.h"
#include "stdio.h"
#include "sys/times.h"
#include "time_posix.h"
#include "unistd.h"
#ifdef LOSCFG_SECURITY_CAPABILITY
#include "capability_api.h"
#endif
#include "los_signal.h"
#ifdef LOSCFG_KERNEL_VDSO
#include "los_vdso.h"
#endif
#ifdef LOSCFG_SECURITY_VID
#include "vid_api.h"
#endif
#include "user_copy.h"
#include "los_process_pri.h"
#include "los_swtmr_pri.h"
#include "los_sys_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/*
* Do a time package defined return. This requires the error code
* to be placed in errno, and if it is non-zero, -1 returned as the
* result of the function. This also gives us a place to put any
* generic tidyup handling needed for things like signal delivery and
* cancellation.
*/
#define TIME_RETURN(err) do { \
INT32 retVal = 0; \
if ((err) != 0) { \
retVal = -1; \
errno = (err); \
} \
return retVal; \
} while (0)
#ifdef LOSCFG_AARCH64
/*
* This two structures originally did't exit,
* they added by liteos to support 64bit interfaces on 32bit platform,
* in 64bit platform, timeval64 define to timeval which is platform adaptive.
*/
#define timeval64 timeval
#define timespec64 timespec
#endif
STATIC INLINE BOOL ValidTimeval(const struct timeval *tv)
{
/* Fail a NULL pointer */
if (tv == NULL) {
return FALSE;
}
/* Fail illegal microseconds values */
if ((tv->tv_usec < 0) || (tv->tv_usec >= OS_SYS_US_PER_SECOND) || (tv->tv_sec < 0)) {
return FALSE;
}
return TRUE;
}
STATIC INLINE BOOL ValidTimeval64(const struct timeval64 *tv)
{
/* Fail a NULL pointer */
if (tv == NULL) {
return FALSE;
}
/* Fail illegal microseconds values */
if ((tv->tv_usec < 0) || (tv->tv_usec >= OS_SYS_US_PER_SECOND) || (tv->tv_sec < 0)) {
return FALSE;
}
return TRUE;
}
STATIC INLINE BOOL ValidTimerID(UINT16 swtmrID)
{
/* check timer id */
if (swtmrID >= OS_SWTMR_MAX_TIMERID) {
return FALSE;
}
/* check owner of this timer */
if (OS_SWT_FROM_SID(swtmrID)->uwOwnerPid != LOS_GetCurrProcessID()) {
return FALSE;
}
return TRUE;
}
STATIC SPIN_LOCK_INIT(g_timeSpin);
STATIC long long g_adjTimeLeft; /* absolute value of adjtime */
STATIC INT32 g_adjDirection; /* 1, speed up; 0, slow down; */
/* Adjust pacement, nanoseconds per SCHED_CLOCK_INTETRVAL_TICKS ticks */
STATIC const long long g_adjPacement = (((LOSCFG_BASE_CORE_ADJ_PER_SECOND * SCHED_CLOCK_INTETRVAL_TICKS) /
LOSCFG_BASE_CORE_TICK_PER_SECOND) * OS_SYS_NS_PER_US);
/* accumulative time delta from continuous modify, such as adjtime */
STATIC struct timespec64 g_accDeltaFromAdj;
/* accumulative time delta from discontinuous modify, such as settimeofday */
STATIC struct timespec64 g_accDeltaFromSet;
VOID OsAdjTime(VOID)
{
UINT32 intSave;
LOS_SpinLockSave(&g_timeSpin, &intSave);
if (!g_adjTimeLeft) {
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
return;
}
if (g_adjTimeLeft > g_adjPacement) {
if (g_adjDirection) {
if ((g_accDeltaFromAdj.tv_nsec + g_adjPacement) >= OS_SYS_NS_PER_SECOND) {
g_accDeltaFromAdj.tv_sec++;
g_accDeltaFromAdj.tv_nsec = (g_accDeltaFromAdj.tv_nsec + g_adjPacement) % OS_SYS_NS_PER_SECOND;
} else {
g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec + g_adjPacement;
}
} else {
if ((g_accDeltaFromAdj.tv_nsec - g_adjPacement) < 0) {
g_accDeltaFromAdj.tv_sec--;
g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec - g_adjPacement + OS_SYS_NS_PER_SECOND;
} else {
g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec - g_adjPacement;
}
}
g_adjTimeLeft -= g_adjPacement;
} else {
if (g_adjDirection) {
if ((g_accDeltaFromAdj.tv_nsec + g_adjTimeLeft) >= OS_SYS_NS_PER_SECOND) {
g_accDeltaFromAdj.tv_sec++;
g_accDeltaFromAdj.tv_nsec = (g_accDeltaFromAdj.tv_nsec + g_adjTimeLeft) % OS_SYS_NS_PER_SECOND;
} else {
g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec + g_adjTimeLeft;
}
} else {
if ((g_accDeltaFromAdj.tv_nsec - g_adjTimeLeft) < 0) {
g_accDeltaFromAdj.tv_sec--;
g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec - g_adjTimeLeft + OS_SYS_NS_PER_SECOND;
} else {
g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec - g_adjTimeLeft;
}
}
g_adjTimeLeft = 0;
}
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
return;
}
/*
* Function: adjtime
* Description: correct the time to synchronize the system clock.
* Input: delta - The amount of time by which the clock is to be adjusted.
* Output: oldDelta - the amount of time remaining from any previous adjustment that has not yet been completed.
* Return: On success, returns 0. On failure, -1 is returned, and errno is set to indicate the error.
*/
int adjtime(const struct timeval *delta, struct timeval *oldDelta)
{
UINT32 intSave;
LOS_SpinLockSave(&g_timeSpin, &intSave);
/* return the amount of time remaining from any previous adjustment that has not yet been completed. */
if (oldDelta != NULL) {
if (g_adjDirection == 1) {
oldDelta->tv_sec = g_adjTimeLeft / OS_SYS_NS_PER_SECOND;
oldDelta->tv_usec = (g_adjTimeLeft % OS_SYS_NS_PER_SECOND) / OS_SYS_NS_PER_US;
} else {
oldDelta->tv_sec = -(g_adjTimeLeft / OS_SYS_NS_PER_SECOND);
oldDelta->tv_usec = -((g_adjTimeLeft % OS_SYS_NS_PER_SECOND) / OS_SYS_NS_PER_US);
}
}
if ((delta == NULL) || ((delta->tv_sec == 0) && (delta->tv_usec == 0))) {
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
return 0;
}
if ((delta->tv_usec > OS_SYS_US_PER_SECOND) || (delta->tv_usec < -OS_SYS_US_PER_SECOND)) {
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
TIME_RETURN(EINVAL);
}
/*
* 2: in the glibc implementation, delta must be less than or equal to (INT_MAX / 1000000 - 2) and
* greater than or equal to (INT_MIN / 1000000 + 2)
*/
if ((delta->tv_sec < (INT_MIN / OS_SYS_US_PER_SECOND + 2)) ||
(delta->tv_sec > (INT_MAX / OS_SYS_US_PER_SECOND + 2))) {
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
TIME_RETURN(EINVAL);
}
g_adjTimeLeft = (INT64)delta->tv_sec * OS_SYS_NS_PER_SECOND + delta->tv_usec * OS_SYS_NS_PER_US;
if (g_adjTimeLeft > 0) {
g_adjDirection = 1;
} else {
g_adjDirection = 0;
g_adjTimeLeft = -g_adjTimeLeft;
}
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
return 0;
}
STATIC INLINE struct timespec64 OsTimeSpecAdd(const struct timespec64 t1, const struct timespec64 t2)
{
struct timespec64 ret = {0};
ret.tv_sec = t1.tv_sec + t2.tv_sec;
ret.tv_nsec = t1.tv_nsec + t2.tv_nsec;
if (ret.tv_nsec >= OS_SYS_NS_PER_SECOND) {
ret.tv_sec += 1;
ret.tv_nsec -= OS_SYS_NS_PER_SECOND;
} else if (ret.tv_nsec < 0L) {
ret.tv_sec -= 1;
ret.tv_nsec += OS_SYS_NS_PER_SECOND;
}
return ret;
}
STATIC INLINE struct timespec64 OsTimeSpecSub(const struct timespec64 t1, const struct timespec64 t2)
{
struct timespec64 ret = {0};
ret.tv_sec = t1.tv_sec - t2.tv_sec;
ret.tv_nsec = t1.tv_nsec - t2.tv_nsec;
if (ret.tv_nsec < 0) {
ret.tv_sec -= 1;
ret.tv_nsec += OS_SYS_NS_PER_SECOND;
}
return ret;
}
STATIC VOID OsGetHwTime(struct timespec64 *hwTime)
{
UINT64 nowNsec;
nowNsec = hi_sched_clock();
hwTime->tv_sec = nowNsec / OS_SYS_NS_PER_SECOND;
hwTime->tv_nsec = nowNsec - hwTime->tv_sec * OS_SYS_NS_PER_SECOND;
}
STATIC INT32 OsSetTimeOfDay(const struct timeval64 *tv, const struct timezone *tz)
{
UINT32 intSave;
struct timespec64 setTime = {0};
struct timespec64 hwTime = {0};
struct timespec64 realTime = {0};
struct timespec64 tmp = {0};
#ifdef LOSCFG_SECURITY_CAPABILITY
if (!IsCapPermit(CAP_SET_TIMEOFDAY)) {
TIME_RETURN(EPERM);
}
#endif
(VOID)tz;
OsGetHwTime(&hwTime);
setTime.tv_sec = tv->tv_sec;
setTime.tv_nsec = tv->tv_usec * OS_SYS_NS_PER_US;
LOS_SpinLockSave(&g_timeSpin, &intSave);
/* stop on-going continuous adjusement */
if (g_adjTimeLeft) {
g_adjTimeLeft = 0;
}
realTime = OsTimeSpecAdd(hwTime, g_accDeltaFromAdj);
realTime = OsTimeSpecAdd(realTime, g_accDeltaFromSet);
tmp = OsTimeSpecSub(setTime, realTime);
g_accDeltaFromSet = OsTimeSpecAdd(g_accDeltaFromSet, tmp);
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
return 0;
}
int settimeofday(const struct timeval *tv, const struct timezone *tz)
{
struct timeval64 stTimeVal64 = {0};
if (!ValidTimeval(tv)) {
TIME_RETURN(EINVAL);
}
stTimeVal64.tv_sec = tv->tv_sec;
stTimeVal64.tv_usec = tv->tv_usec;
return OsSetTimeOfDay(&stTimeVal64, tz);
}
#ifndef LOSCFG_AARCH64
int settimeofday64(const struct timeval64 *tv, const struct timezone *tz)
{
if (!ValidTimeval64(tv)) {
TIME_RETURN(EINVAL);
}
return OsSetTimeOfDay(tv, tz);
}
#endif
int setlocalseconds(int seconds)
{
struct timeval tv = {0};
tv.tv_sec = seconds;
tv.tv_usec = 0;
return settimeofday(&tv, NULL);
}
STATIC INT32 OsGetTimeOfDay(struct timeval64 *tv, struct timezone *tz)
{
UINT32 intSave;
(VOID)tz;
struct timespec64 hwTime = {0};
struct timespec64 realTime = {0};
OsGetHwTime(&hwTime);
LOS_SpinLockSave(&g_timeSpin, &intSave);
realTime = OsTimeSpecAdd(hwTime, g_accDeltaFromAdj);
realTime = OsTimeSpecAdd(realTime, g_accDeltaFromSet);
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
tv->tv_sec = realTime.tv_sec;
tv->tv_usec = realTime.tv_nsec / OS_SYS_NS_PER_US;
if (tv->tv_sec < 0) {
TIME_RETURN(EINVAL);
}
return 0;
}
#ifndef LOSCFG_AARCH64
int gettimeofday64(struct timeval64 *tv, struct timezone *tz)
{
if (tv == NULL) {
TIME_RETURN(EINVAL);
}
return OsGetTimeOfDay(tv, tz);
}
#endif
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
struct timeval64 stTimeVal64 = {0};
if (tv == NULL) {
TIME_RETURN(EINVAL);
}
if (OsGetTimeOfDay(&stTimeVal64, tz) == -1) {
return -1;
}
#ifdef LOSCFG_AARCH64
tv->tv_sec = stTimeVal64.tv_sec;
tv->tv_usec = stTimeVal64.tv_usec;
#else
if (stTimeVal64.tv_sec > (long long)LONG_MAX) {
return -1;
}
tv->tv_sec = (time_t)stTimeVal64.tv_sec;
tv->tv_usec = (suseconds_t)stTimeVal64.tv_usec;
#endif
return 0;
}
int clock_settime(clockid_t clockID, const struct timespec *tp)
{
struct timeval tv = {0};
switch (clockID) {
case CLOCK_REALTIME:
/* we only support the realtime clock currently */
break;
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:
TIME_RETURN(ENOTSUP);
case CLOCK_MONOTONIC:
default:
TIME_RETURN(EINVAL);
}
if (!ValidTimeSpec(tp)) {
TIME_RETURN(EINVAL);
}
#ifdef LOSCFG_SECURITY_CAPABILITY
if (!IsCapPermit(CAP_CLOCK_SETTIME)) {
TIME_RETURN(EPERM);
}
#endif
tv.tv_sec = tp->tv_sec;
tv.tv_usec = tp->tv_nsec / OS_SYS_NS_PER_US;
return settimeofday(&tv, NULL);
}
int clock_gettime(clockid_t clockID, struct timespec *tp)
{
UINT32 intSave;
struct timespec64 tmp = {0};
struct timespec64 hwTime = {0};
if ((clockID > MAX_CLOCKS) || (clockID < CLOCK_REALTIME)) {
goto ERROUT;
}
if (tp == NULL) {
goto ERROUT;
}
OsGetHwTime(&hwTime);
switch (clockID) {
case CLOCK_MONOTONIC_RAW:
tp->tv_sec = hwTime.tv_sec;
tp->tv_nsec = hwTime.tv_nsec;
break;
case CLOCK_MONOTONIC:
LOS_SpinLockSave(&g_timeSpin, &intSave);
tmp = OsTimeSpecAdd(hwTime, g_accDeltaFromAdj);
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
tp->tv_sec = tmp.tv_sec;
tp->tv_nsec = tmp.tv_nsec;
break;
case CLOCK_REALTIME:
LOS_SpinLockSave(&g_timeSpin, &intSave);
tmp = OsTimeSpecAdd(hwTime, g_accDeltaFromAdj);
tmp = OsTimeSpecAdd(tmp, g_accDeltaFromSet);
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
tp->tv_sec = tmp.tv_sec;
tp->tv_nsec = tmp.tv_nsec;
break;
case CLOCK_MONOTONIC_COARSE:
case CLOCK_REALTIME_COARSE:
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:
TIME_RETURN(ENOTSUP);
default:
goto ERROUT;
}
return 0;
ERROUT:
TIME_RETURN(EINVAL);
}
int clock_getres(clockid_t clockID, struct timespec *tp)
{
if (tp == NULL) {
TIME_RETURN(EINVAL);
}
switch (clockID) {
case CLOCK_MONOTONIC_RAW:
case CLOCK_MONOTONIC:
case CLOCK_REALTIME:
/* the accessable rtc resolution */
tp->tv_nsec = OS_SYS_NS_PER_US; /* the precision of clock_gettime is 1us */
tp->tv_sec = 0;
break;
case CLOCK_MONOTONIC_COARSE:
case CLOCK_REALTIME_COARSE:
/* the clock coarse resolution, supported by vdso.
* the precision of clock_gettime is 1tick */
tp->tv_nsec = OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND;
tp->tv_sec = 0;
break;
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:
TIME_RETURN(ENOTSUP);
default:
TIME_RETURN(EINVAL);
}
TIME_RETURN(0);
}
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) {
TIME_RETURN(ENOTSUP);
}
/* fallthrough */
case CLOCK_THREAD_CPUTIME_ID:
default:
TIME_RETURN(EINVAL);
}
TIME_RETURN(0);
}
typedef struct {
int sigev_signo;
UINT32 pid;
union sigval sigev_value;
} swtmr_proc_arg;
static VOID SwtmrProc(UINTPTR tmrArg)
{
int sig;
pid_t pid;
siginfo_t info;
swtmr_proc_arg *arg = (swtmr_proc_arg *)tmrArg;
if (arg == NULL) {
return;
}
sig = arg->sigev_signo + 1;
pid = arg->pid;
/* Make sure that the para is valid */
if (!GOOD_SIGNO(sig) || pid <= 0) {
return;
}
if (OS_PID_CHECK_INVALID(pid)) {
return;
}
/* Create the siginfo structure */
info.si_signo = sig;
info.si_code = SI_TIMER;
info.si_value.sival_ptr = arg->sigev_value.sival_ptr;
/* Send the signal */
OsDispatch(pid, &info, OS_USER_KILL_PERMISSION);
return;
}
int timer_create(clockid_t clockID, struct sigevent *evp, timer_t *timerID)
{
UINT32 ret;
UINT16 swtmrID;
swtmr_proc_arg *arg = NULL;
int signo;
#ifdef LOSCFG_SECURITY_VID
UINT16 vid;
#endif
if ((clockID != CLOCK_REALTIME) || (timerID == NULL)) {
errno = EINVAL;
return -1;
}
signo = evp ? evp->sigev_signo : SIGALRM;
if (signo > SIGRTMAX || signo < 1) {
errno = EINVAL;
return -1;
}
if (evp && (evp->sigev_notify != SIGEV_SIGNAL && evp->sigev_notify != SIGEV_THREAD_ID)) {
errno = ENOTSUP;
return -1;
}
arg = (swtmr_proc_arg *)malloc(sizeof(swtmr_proc_arg));
if (arg == NULL) {
errno = ENOMEM;
return -1;
}
arg->sigev_signo = signo - 1;
arg->pid = LOS_GetCurrProcessID();
arg->sigev_value.sival_ptr = evp ? evp->sigev_value.sival_ptr : NULL;
ret = LOS_SwtmrCreate(1, LOS_SWTMR_MODE_ONCE, SwtmrProc, &swtmrID, (UINTPTR)arg);
if (ret != LOS_OK) {
errno = (ret == LOS_ERRNO_SWTMR_MAXSIZE) ? EAGAIN : EINVAL;
free(arg);
return -1;
}
#ifdef LOSCFG_SECURITY_VID
vid = AddNodeByRid(swtmrID);
if (vid == MAX_INVALID_TIMER_VID) {
free(arg);
(VOID)LOS_SwtmrDelete(swtmrID);
return -1;
}
swtmrID = vid;
#endif
*timerID = (timer_t)(UINTPTR)swtmrID;
return 0;
}
int timer_delete(timer_t timerID)
{
UINT16 swtmrID = (UINT16)(UINTPTR)timerID;
VOID *arg = NULL;
#ifdef LOSCFG_SECURITY_VID
swtmrID = GetRidByVid(swtmrID);
#endif
if (OS_INT_ACTIVE || !ValidTimerID(swtmrID)) {
goto ERROUT;
}
arg = (VOID *)OS_SWT_FROM_SID(swtmrID)->uwArg;
if (LOS_SwtmrDelete(swtmrID)) {
goto ERROUT;
}
if (arg != NULL) {
free(arg);
}
#ifdef LOSCFG_SECURITY_VID
RemoveNodeByVid((UINT16)(UINTPTR)timerID);
#endif
return 0;
ERROUT:
errno = EINVAL;
return -1;
}
int timer_settime(timer_t timerID, int flags,
const struct itimerspec *value, /* new value */
struct itimerspec *oldValue) /* old value to return, always 0 */
{
UINT16 swtmrID = (UINT16)(UINTPTR)timerID;
SWTMR_CTRL_S *swtmr = NULL;
UINT32 interval, expiry, ret;
UINT32 intSave;
if (flags != 0) {
/* flags not supported currently */
errno = ENOSYS;
return -1;
}
#ifdef LOSCFG_SECURITY_VID
swtmrID = GetRidByVid(swtmrID);
#endif
if ((value == NULL) || OS_INT_ACTIVE || !ValidTimerID(swtmrID)) {
errno = EINVAL;
return -1;
}
if (!ValidTimeSpec(&value->it_value) || !ValidTimeSpec(&value->it_interval)) {
errno = EINVAL;
return -1;
}
if (oldValue) {
(VOID)timer_gettime(timerID, oldValue);
}
swtmr = OS_SWT_FROM_SID(swtmrID);
ret = LOS_SwtmrStop(swtmr->usTimerID);
if ((ret != LOS_OK) && (ret != LOS_ERRNO_SWTMR_NOT_STARTED)) {
errno = EINVAL;
return -1;
}
expiry = OsTimeSpec2Tick(&value->it_value);
interval = OsTimeSpec2Tick(&value->it_interval);
LOS_SpinLockSave(&g_swtmrSpin, &intSave);
swtmr->ucMode = interval ? LOS_SWTMR_MODE_OPP : LOS_SWTMR_MODE_NO_SELFDELETE;
swtmr->uwExpiry = expiry + !!expiry; // PS: skip the first tick because it is NOT a full tick.
swtmr->uwInterval = interval;
swtmr->ucOverrun = 0;
LOS_SpinUnlockRestore(&g_swtmrSpin, intSave);
if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0)) {
/*
* 1) when expiry is 0, means timer should be stopped.
* 2) If timer is ticking, stopping timer is already done before.
* 3) If timer is created but not ticking, return 0 as well.
*/
return 0;
}
if (LOS_SwtmrStart(swtmr->usTimerID)) {
errno = EINVAL;
return -1;
}
return 0;
}
int timer_gettime(timer_t timerID, struct itimerspec *value)
{
UINT32 tick = 0;
SWTMR_CTRL_S *swtmr = NULL;
UINT16 swtmrID = (UINT16)(UINTPTR)timerID;
UINT32 ret;
#ifdef LOSCFG_SECURITY_VID
swtmrID = GetRidByVid(swtmrID);
#endif
if ((value == NULL) || !ValidTimerID(swtmrID)) {
errno = EINVAL;
return -1;
}
swtmr = OS_SWT_FROM_SID(swtmrID);
/* get expire time */
ret = LOS_SwtmrTimeGet(swtmr->usTimerID, &tick);
if ((ret != LOS_OK) && (ret != LOS_ERRNO_SWTMR_NOT_STARTED)) {
errno = EINVAL;
return -1;
}
OsTick2TimeSpec(&value->it_value, tick);
OsTick2TimeSpec(&value->it_interval, (swtmr->ucMode == LOS_SWTMR_MODE_ONCE) ? 0 : swtmr->uwInterval);
return 0;
}
int timer_getoverrun(timer_t timerID)
{
UINT16 swtmrID = (UINT16)(UINTPTR)timerID;
SWTMR_CTRL_S *swtmr = NULL;
INT32 overRun;
#ifdef LOSCFG_SECURITY_VID
swtmrID = GetRidByVid(swtmrID);
#endif
if (!ValidTimerID(swtmrID)) {
errno = EINVAL;
return -1;
}
swtmr = OS_SWT_FROM_SID(swtmrID);
if (swtmr->usTimerID >= OS_SWTMR_MAX_TIMERID) {
errno = EINVAL;
return -1;
}
overRun = (INT32)(swtmr->ucOverrun);
return (overRun > DELAYTIMER_MAX) ? DELAYTIMER_MAX : overRun;
}
STATIC INT32 DoNanoSleep(UINT64 nseconds)
{
UINT64 tick;
UINT32 ret;
const UINT32 nsPerTick = OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND;
tick = (nseconds + nsPerTick - 1) / nsPerTick; // Round up for ticks
/* PS: skip the first tick because it is NOT a full tick. */
ret = LOS_TaskDelay((tick >= UINT32_MAX) ? UINT32_MAX : (tick ? ((UINT32)tick + 1) : 0));
if (ret == LOS_OK || ret == LOS_ERRNO_TSK_YIELD_NOT_ENOUGH_TASK) {
return 0;
}
return -1;
}
int usleep(unsigned useconds)
{
return DoNanoSleep((UINT64)useconds * OS_SYS_NS_PER_US);
}
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
{
UINT64 nseconds;
INT32 ret = -1;
(VOID)rmtp;
/* expire time */
if (!ValidTimeSpec(rqtp)) {
errno = EINVAL;
return ret;
}
nseconds = (UINT64)rqtp->tv_sec * OS_SYS_NS_PER_SECOND + rqtp->tv_nsec;
return DoNanoSleep(nseconds);
}
unsigned int sleep(unsigned int seconds)
{
return DoNanoSleep((UINT64)seconds * OS_SYS_NS_PER_SECOND);
}
double difftime(time_t time2, time_t time1)
{
return (double)(time2 - time1);
}
clock_t clock(VOID)
{
clock_t clockMsec;
UINT64 nowNsec;
nowNsec = hi_sched_clock();
clockMsec = (clock_t)(nowNsec / OS_SYS_NS_PER_MS);
return clockMsec;
}
clock_t times(struct tms *buf)
{
clock_t clockTick;
clockTick = LOS_TickCountGet();
if (buf != NULL) {
buf->tms_cstime = clockTick;
buf->tms_cutime = clockTick;
buf->tms_stime = clockTick;
buf->tms_utime = clockTick;
}
return clockTick;
}
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
{
LosTaskCB *taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
struct itimerspec spec;
struct itimerspec ospec;
int ret = LOS_OK;
/* we only support the realtime clock timer currently */
if (which != ITIMER_REAL || !value) {
set_errno(EINVAL);
return -1;
}
LOS_TaskLock();
if (processCB->timerID == (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID) {
ret = timer_create(CLOCK_REALTIME, NULL, &processCB->timerID);
if (ret != LOS_OK) {
LOS_TaskUnlock();
return ret;
}
}
LOS_TaskUnlock();
TIMEVAL_TO_TIMESPEC(&value->it_value, &spec.it_value);
TIMEVAL_TO_TIMESPEC(&value->it_interval, &spec.it_interval);
ret = timer_settime(processCB->timerID, 0, &spec, ovalue ? &ospec : NULL);
if (ret == LOS_OK && ovalue) {
TIMESPEC_TO_TIMEVAL(&ovalue->it_value, &ospec.it_value);
TIMESPEC_TO_TIMEVAL(&ovalue->it_interval, &ospec.it_interval);
}
return ret;
}
int getitimer(int which, struct itimerval *value)
{
LosTaskCB *taskCB = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
struct itimerspec spec = {};
int ret = LOS_OK;
/* we only support the realtime clock timer currently */
if (which != ITIMER_REAL || !value) {
set_errno(EINVAL);
return -1;
}
if (processCB->timerID != (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID) {
ret = timer_gettime(processCB->timerID, &spec);
}
if (ret == LOS_OK) {
TIMESPEC_TO_TIMEVAL(&value->it_value, &spec.it_value);
TIMESPEC_TO_TIMEVAL(&value->it_interval, &spec.it_interval);
}
return ret;
}
#ifdef LOSCFG_KERNEL_VDSO
VOID OsGetVdsoTime(VdsoDataPage *vdsoDataPage)
{
UINT32 intSave;
struct timespec64 tmp = {0};
struct timespec64 hwTime = {0};
if (vdsoDataPage == NULL) {
return;
}
OsGetHwTime(&hwTime);
LOS_SpinLockSave(&g_timeSpin, &intSave);
tmp = OsTimeSpecAdd(hwTime, g_accDeltaFromAdj);
vdsoDataPage->monoTimeSec = tmp.tv_sec;
vdsoDataPage->monoTimeNsec = tmp.tv_nsec;
tmp = OsTimeSpecAdd(tmp, g_accDeltaFromSet);
vdsoDataPage->realTimeSec = tmp.tv_sec;
vdsoDataPage->realTimeNsec = tmp.tv_nsec;
LOS_SpinUnlockRestore(&g_timeSpin, intSave);
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */