add OpenHarmony 1.0 baseline
This commit is contained in:
Executable
+122
@@ -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 */
|
||||
Executable
+49
@@ -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
|
||||
Executable
+152
@@ -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 */
|
||||
Executable
+610
@@ -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 */
|
||||
Executable
+59
@@ -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 */
|
||||
Executable
+87
@@ -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
|
||||
Executable
+817
@@ -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 */
|
||||
Executable
+287
@@ -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 */
|
||||
Executable
+358
@@ -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 */
|
||||
Executable
+146
@@ -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 */
|
||||
Executable
+150
@@ -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 */
|
||||
Executable
+204
@@ -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 */
|
||||
Executable
+188
@@ -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 */
|
||||
Executable
+984
@@ -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 */
|
||||
Reference in New Issue
Block a user