first submission
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 <errno.h>
|
||||
#include "los_interrupt.h"
|
||||
#include "los_task.h"
|
||||
|
||||
/* the specific errno get or set in interrupt service routine */
|
||||
static int g_isrErrno;
|
||||
|
||||
int *__errno_location(void)
|
||||
{
|
||||
LosTaskCB *runTask = NULL;
|
||||
|
||||
if (OS_INT_INACTIVE) {
|
||||
runTask = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
|
||||
return &runTask->errorNo;
|
||||
} else {
|
||||
return &g_isrErrno;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 <libc.h>
|
||||
#include "libc_config.h"
|
||||
|
||||
/**
|
||||
* get libc version string.
|
||||
* @return libc version string. the format is <major>.<minor>.<patch>[-<platform>[-<desc>]]
|
||||
*/
|
||||
const char *libc_get_version_string(void)
|
||||
{
|
||||
return LIBC_VERSION_STR;
|
||||
}
|
||||
|
||||
/**
|
||||
* get libc version code.
|
||||
* @return libc version code. the format is 0x00XXYYZZ, XX is major version, YY is minor version and ZZ is patch version
|
||||
*/
|
||||
int libc_get_version(void)
|
||||
{
|
||||
return LIBC_VERSION_NUM;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LIBC_CONFIG_H_
|
||||
#define LIBC_CONFIG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef LIBC_VERSION_STR
|
||||
#define LIBC_VERSION_STR "1.0.0-LiteOS_M"
|
||||
#endif
|
||||
|
||||
#ifndef LIBC_VERSION_NUM
|
||||
#define LIBC_VERSION_NUM 0x00010000
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LIBC_CONFIG_H_
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "securec.h"
|
||||
#include "los_config.h"
|
||||
#include "los_memory.h"
|
||||
|
||||
|
||||
void *calloc(size_t nitems, size_t size)
|
||||
{
|
||||
size_t real_size;
|
||||
void *ptr = NULL;
|
||||
|
||||
if (nitems == 0 || size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
real_size = (size_t)(nitems * size);
|
||||
ptr = LOS_MemAlloc(OS_SYS_MEM_ADDR, real_size);
|
||||
if (ptr != NULL) {
|
||||
(void)memset_s(ptr, real_size, 0, real_size);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void free(void *ptr)
|
||||
{
|
||||
if (ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOS_MemFree(OS_SYS_MEM_ADDR, ptr);
|
||||
}
|
||||
|
||||
void *malloc(size_t size)
|
||||
{
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return LOS_MemAlloc(OS_SYS_MEM_ADDR, size);
|
||||
}
|
||||
|
||||
void *zalloc(size_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = LOS_MemAlloc(OS_SYS_MEM_ADDR, size);
|
||||
if (ptr != NULL) {
|
||||
(void)memset_s(ptr, size, 0, size);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *memalign(size_t boundary, size_t size)
|
||||
{
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return LOS_MemAllocAlign(OS_SYS_MEM_ADDR, size, boundary);
|
||||
}
|
||||
|
||||
void *realloc(void *ptr, size_t size)
|
||||
{
|
||||
if (ptr == NULL) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return LOS_MemRealloc(OS_SYS_MEM_ADDR, ptr, size);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,616 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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_impl.h"
|
||||
#include "time_internal.h"
|
||||
|
||||
/* GLOBALS */
|
||||
STATIC struct mqarray g_queueTable[LOSCFG_BASE_IPC_QUEUE_LIMIT];
|
||||
STATIC pthread_mutex_t g_mqueueMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||
|
||||
int MapMqErrno(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;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
return errno;
|
||||
}
|
||||
|
||||
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 (MapMqErrno(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->queue = 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, {0} };
|
||||
|
||||
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) {
|
||||
(VOID)memcpy_s(&defaultAttr, sizeof(struct mq_attr), attr, sizeof(struct mq_attr));
|
||||
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;
|
||||
|
||||
(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 (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 (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_getattr(mqd_t mqd, struct mq_attr *attr)
|
||||
{
|
||||
return mq_getsetattr(mqd, 0, attr);
|
||||
}
|
||||
|
||||
int mq_setattr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old)
|
||||
{
|
||||
return mq_getsetattr(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)
|
||||
{
|
||||
(void)personal;
|
||||
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 (MapMqErrno(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 (MapMqErrno(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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 _MQUEUE_IMPL_H
|
||||
#define _MQUEUE_IMPL_H
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <mqueue.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <securec.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <sys/select.h>
|
||||
#include "los_queue.h"
|
||||
#include "los_memory.h"
|
||||
#include "los_task.h"
|
||||
#include "los_compiler.h"
|
||||
|
||||
#define OS_QUEUE_OPERATE_TYPE(ReadOrWrite, HeadOrTail, PointOrNot) \
|
||||
(((UINT32)(PointOrNot) << 2) | ((UINT32)(HeadOrTail) << 1) | (ReadOrWrite))
|
||||
#define OS_QUEUE_READ_WRITE_GET(type) ((type) & (0x01))
|
||||
#define OS_QUEUE_READ_HEAD (OS_QUEUE_READ | (OS_QUEUE_HEAD << 1))
|
||||
#define OS_QUEUE_READ_TAIL (OS_QUEUE_READ | (OS_QUEUE_TAIL << 1))
|
||||
#define OS_QUEUE_WRITE_HEAD (OS_QUEUE_WRITE | (OS_QUEUE_HEAD << 1))
|
||||
#define OS_QUEUE_WRITE_TAIL (OS_QUEUE_WRITE | (OS_QUEUE_TAIL << 1))
|
||||
#define OS_QUEUE_OPERATE_GET(type) ((type) & (0x03))
|
||||
#define OS_QUEUE_IS_POINT(type) ((type) & (0x04))
|
||||
#define OS_QUEUE_IS_READ(type) (OS_QUEUE_READ_WRITE_GET(type) == OS_QUEUE_READ)
|
||||
#define OS_QUEUE_IS_WRITE(type) (OS_QUEUE_READ_WRITE_GET(type) == OS_QUEUE_WRITE)
|
||||
#define OS_READWRITE_LEN 2
|
||||
|
||||
/**
|
||||
* @ingroup mqueue
|
||||
* Maximum number of messages in a message queue
|
||||
*/
|
||||
#define MQ_MAX_MSG_NUM 16
|
||||
|
||||
/**
|
||||
* @ingroup mqueue
|
||||
* Maximum size of a single message in a message queue
|
||||
*/
|
||||
#define MQ_MAX_MSG_LEN 64
|
||||
|
||||
#define ENOERR 0
|
||||
|
||||
/* CONSTANTS */
|
||||
|
||||
#define MQ_USE_MAGIC 0x89abcdef
|
||||
#define MQ_PRIO_MAX 1
|
||||
|
||||
|
||||
#define FNONBLOCK O_NONBLOCK
|
||||
|
||||
#define QUEUE_SPLIT_BIT 16
|
||||
|
||||
#define SET_QUEUE_ID(count, queueID) (((count) << QUEUE_SPLIT_BIT) | (queueID))
|
||||
|
||||
/**
|
||||
* @ingroup los_queue
|
||||
* get the queue index
|
||||
*/
|
||||
#define GET_QUEUE_INDEX(queueID) ((queueID) & ((1U << QUEUE_SPLIT_BIT) - 1))
|
||||
|
||||
/**
|
||||
* @ingroup los_queue
|
||||
* get the queue count
|
||||
*/
|
||||
#define GET_QUEUE_COUNT(queueID) ((queueID) >> QUEUE_SPLIT_BIT)
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup los_queue
|
||||
* Obtain the head node in a queue doubly linked list.
|
||||
*/
|
||||
#define GET_QUEUE_LIST(ptr) LOS_DL_LIST_ENTRY(ptr, LosQueueCB, readWriteList[OS_QUEUE_WRITE])
|
||||
|
||||
#define STATIC static
|
||||
#define INLINE inline
|
||||
|
||||
typedef union send_receive_t {
|
||||
unsigned oth : 3;
|
||||
unsigned grp : 6;
|
||||
unsigned usr : 9;
|
||||
short data;
|
||||
} mode_s;
|
||||
|
||||
/* TYPE DEFINITIONS */
|
||||
struct mqarray {
|
||||
UINT32 mq_id : 31;
|
||||
UINT32 unlinkflag : 1;
|
||||
char *mq_name;
|
||||
UINT32 unlink_ref;
|
||||
mode_s mode_data; /* mode data of mqueue */
|
||||
uid_t euid; /* euid of mqueue */
|
||||
gid_t egid; /* egid of mqueue */
|
||||
fd_set mq_fdset; /* mqueue sysFd bit map */
|
||||
LosQueueCB *mqcb;
|
||||
struct mqpersonal *mq_personal;
|
||||
};
|
||||
|
||||
struct mqpersonal {
|
||||
struct mqarray *mq_posixdes;
|
||||
struct mqpersonal *mq_next;
|
||||
int mq_flags;
|
||||
int mq_mode; /* Mode of mqueue */
|
||||
UINT32 mq_status;
|
||||
UINT32 mq_refcount;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <securec.h>
|
||||
#include "los_config.h"
|
||||
#include "los_task.h"
|
||||
|
||||
#define PTHREAD_NAMELEN 16
|
||||
|
||||
typedef struct {
|
||||
void *(*startRoutine)(void *);
|
||||
void *param;
|
||||
char name[PTHREAD_NAMELEN];
|
||||
}PthreadData;
|
||||
|
||||
static void *PthreadEntry(UINT32 param)
|
||||
{
|
||||
PthreadData *pthreadData = (PthreadData *)(UINTPTR)param;
|
||||
void *(*startRoutine)(void *) = pthreadData->startRoutine;
|
||||
void *ret = startRoutine(pthreadData->param);
|
||||
free(pthreadData);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int IsPthread(pthread_t thread)
|
||||
{
|
||||
return ((UINT32)thread <= LOSCFG_BASE_CORE_TSK_LIMIT) &&
|
||||
(OS_TCB_FROM_TID((UINT32)thread)->taskEntry == PthreadEntry);
|
||||
}
|
||||
|
||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*startRoutine)(void *), void *arg)
|
||||
{
|
||||
TSK_INIT_PARAM_S taskInitParam = {0};
|
||||
PthreadData *pthreadData = NULL;
|
||||
UINT32 taskID;
|
||||
|
||||
if ((thread == NULL) || (startRoutine == NULL)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
taskInitParam.usTaskPrio = LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO;
|
||||
taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
|
||||
if (attr) {
|
||||
if (attr->detachstate == PTHREAD_CREATE_DETACHED) {
|
||||
return ENOTSUP;
|
||||
}
|
||||
if (attr->stackaddr_set) {
|
||||
return ENOTSUP;
|
||||
}
|
||||
if (attr->stacksize_set) {
|
||||
taskInitParam.uwStackSize = attr->stacksize;
|
||||
}
|
||||
taskInitParam.usTaskPrio = (UINT16)attr->schedparam.sched_priority;
|
||||
}
|
||||
|
||||
pthreadData = (PthreadData *)malloc(sizeof(PthreadData));
|
||||
if (pthreadData == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
pthreadData->startRoutine = startRoutine;
|
||||
pthreadData->param = arg;
|
||||
taskInitParam.pcName = pthreadData->name;
|
||||
taskInitParam.pfnTaskEntry = PthreadEntry;
|
||||
taskInitParam.uwArg = (UINT32)(UINTPTR)pthreadData;
|
||||
|
||||
if (LOS_TaskCreateOnly(&taskID, &taskInitParam) != LOS_OK) {
|
||||
free(pthreadData);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* set pthread default name */
|
||||
(void)sprintf_s(taskInitParam.pcName, PTHREAD_NAMELEN, "pthread%u", taskID);
|
||||
|
||||
(void)LOS_TaskResume(taskID);
|
||||
|
||||
*thread = (pthread_t)taskID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param)
|
||||
{
|
||||
if ((param == NULL) || (param->sched_priority < OS_TASK_PRIORITY_HIGHEST) ||
|
||||
(param->sched_priority >= OS_TASK_PRIORITY_LOWEST) || !IsPthread(thread)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Only support SCHED_RR policy now */
|
||||
if (policy != SCHED_RR) {
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
if (LOS_TaskPriSet((UINT32)thread, (UINT16)param->sched_priority) != LOS_OK) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param)
|
||||
{
|
||||
UINT32 prio;
|
||||
|
||||
if ((policy == NULL) || (param == NULL) || !IsPthread(thread)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
prio = LOS_TaskPriGet((UINT32)thread);
|
||||
if (prio == OS_INVALID) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
*policy = SCHED_RR;
|
||||
param->sched_priority = prio;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pthread_t pthread_self(void)
|
||||
{
|
||||
return (pthread_t)LOS_CurTaskIDGet();
|
||||
}
|
||||
|
||||
int pthread_cancel(pthread_t thread)
|
||||
{
|
||||
if (!IsPthread(thread)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int pthread_join(pthread_t thread, void **retval)
|
||||
{
|
||||
UINT32 taskStatus;
|
||||
|
||||
if (!IsPthread(thread)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (retval) {
|
||||
/* retrieve thread exit code is not supported currently */
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
if (thread == pthread_self()) {
|
||||
return EDEADLK;
|
||||
}
|
||||
|
||||
while (LOS_TaskStatusGet((UINT32)thread, &taskStatus) == LOS_OK) {
|
||||
(void)LOS_TaskDelay(10); /* 10: Waiting for the end of thread execution. */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_detach(pthread_t thread)
|
||||
{
|
||||
if (!IsPthread(thread)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
void pthread_exit(void *retVal)
|
||||
{
|
||||
(void)retVal;
|
||||
LosTaskCB *tcb = OS_TCB_FROM_TID(LOS_CurTaskIDGet());
|
||||
free((PthreadData *)(UINTPTR)tcb->arg);
|
||||
(void)LOS_TaskDelete(LOS_CurTaskIDGet());
|
||||
}
|
||||
|
||||
int pthread_setname_np(pthread_t thread, const char *name)
|
||||
{
|
||||
char *taskName = LOS_TaskNameGet((UINT32)thread);
|
||||
if (taskName == NULL || !IsPthread(thread)) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (strnlen(name, PTHREAD_NAMELEN) >= PTHREAD_NAMELEN) {
|
||||
return ERANGE;
|
||||
}
|
||||
(void)strcpy_s(taskName, PTHREAD_NAMELEN, name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_getname_np(pthread_t thread, char *buf, size_t buflen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
const char *name = LOS_TaskNameGet((UINT32)thread);
|
||||
if (name == NULL || !IsPthread(thread)) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (buflen > strlen(name)) {
|
||||
ret = strcpy_s(buf, buflen, name);
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return ERANGE;
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 <errno.h>
|
||||
#include <limits.h>
|
||||
#include "los_config.h"
|
||||
|
||||
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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_destroy(pthread_attr_t *attr)
|
||||
{
|
||||
if (attr == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Nothing to do here... */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachState)
|
||||
{
|
||||
if ((attr != NULL) && ((detachState == PTHREAD_CREATE_JOINABLE) || (detachState == PTHREAD_CREATE_DETACHED))) {
|
||||
attr->detachstate = (UINT32)detachState;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 0;
|
||||
}
|
||||
|
||||
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 0;
|
||||
}
|
||||
|
||||
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 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
|
||||
{
|
||||
if ((attr != NULL) && ((inherit == PTHREAD_INHERIT_SCHED) || (inherit == PTHREAD_EXPLICIT_SCHED))) {
|
||||
attr->inheritsched = (UINT32)inherit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
|
||||
{
|
||||
if ((attr != NULL) && (policy == SCHED_RR)) {
|
||||
attr->schedpolicy = SCHED_RR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 0;
|
||||
}
|
||||
|
||||
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param)
|
||||
{
|
||||
if ((attr == NULL) || (param == NULL)) {
|
||||
return EINVAL;
|
||||
} else if ((param->sched_priority < LOS_TASK_PRIORITY_HIGHEST) ||
|
||||
(param->sched_priority >= LOS_TASK_PRIORITY_LOWEST)) {
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
attr->schedparam = *param;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param)
|
||||
{
|
||||
if ((attr == NULL) || (param == NULL)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
*param = attr->schedparam;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 0;
|
||||
}
|
||||
|
||||
int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackAddr)
|
||||
{
|
||||
if (((attr != NULL) && (stackAddr != NULL)) && attr->stackaddr_set) {
|
||||
*stackAddr = attr->stackaddr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 0;
|
||||
}
|
||||
|
||||
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 0;
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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_internal.h"
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <securec.h>
|
||||
#include "los_config.h"
|
||||
#include "los_task.h"
|
||||
#include <los_swtmr.h>
|
||||
#include "los_atomic.h"
|
||||
#include "los_event.h"
|
||||
|
||||
typedef struct {
|
||||
volatile INT32 *realValue;
|
||||
INT32 value;
|
||||
UINT32 clearEvent;
|
||||
} EventCond;
|
||||
|
||||
#define INLINE inline
|
||||
|
||||
#define BROADCAST_EVENT 1
|
||||
#define COND_COUNTER_STEP 0x0004U
|
||||
#define COND_FLAGS_MASK 0x0003U
|
||||
#define COND_COUNTER_MASK (~COND_FLAGS_MASK)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
(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);
|
||||
// This should modify to once.
|
||||
(VOID)LOS_EventWrite(&(cond->event), BROADCAST_EVENT);
|
||||
|
||||
return ret;
|
||||
}
|
||||
(VOID)pthread_mutex_unlock(cond->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if ((cond == NULL) || (mutex == NULL) || (absTime == NULL)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (CondInitCheck(cond)) {
|
||||
ret = pthread_cond_init(cond, NULL);
|
||||
if (ret != ENOERR) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
(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__);
|
||||
}
|
||||
|
||||
ret = (INT32)LOS_EventRead(&(cond->event), 0x0f, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, absTicks);
|
||||
|
||||
if (pthread_mutex_lock(mutex) != ENOERR) {
|
||||
PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
ret = ProcessReturnVal(cond, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((cond == NULL) || (mutex == NULL)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (CondInitCheck(cond)) {
|
||||
ret = pthread_cond_init(cond, NULL);
|
||||
if (ret != ENOERR) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
(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__);
|
||||
}
|
||||
ret = (INT32)LOS_EventRead(&(cond->event), 0x0f, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 <time.h>
|
||||
#include "los_compiler.h"
|
||||
#include "los_mux.h"
|
||||
#include "errno.h"
|
||||
|
||||
|
||||
#define OS_SYS_NS_PER_MSECOND 1000000
|
||||
#define OS_SYS_NS_PER_SECOND 1000000000
|
||||
|
||||
static inline int MapError(UINT32 err)
|
||||
{
|
||||
switch (err) {
|
||||
case LOS_OK:
|
||||
return 0;
|
||||
case LOS_ERRNO_MUX_PEND_INTERR:
|
||||
return EPERM;
|
||||
case LOS_ERRNO_MUX_PEND_IN_LOCK:
|
||||
return EDEADLK;
|
||||
case LOS_ERRNO_MUX_PENDED:
|
||||
case LOS_ERRNO_MUX_UNAVAILABLE:
|
||||
return EBUSY;
|
||||
case LOS_ERRNO_MUX_TIMEOUT:
|
||||
return ETIMEDOUT;
|
||||
case LOS_ERRNO_MUX_ALL_BUSY:
|
||||
return EAGAIN;
|
||||
case LOS_ERRNO_MUX_INVALID:
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize mutex. If mutexAttr is NULL, use default attributes. */
|
||||
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexAttr)
|
||||
{
|
||||
UINT32 muxHandle;
|
||||
UINT32 ret;
|
||||
|
||||
if (mutexAttr != NULL) {
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = LOS_MuxCreate(&muxHandle);
|
||||
if (ret != LOS_OK) {
|
||||
return MapError(ret);
|
||||
}
|
||||
|
||||
mutex->magic = _MUX_MAGIC;
|
||||
mutex->handle = muxHandle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_destroy(pthread_mutex_t *mutex)
|
||||
{
|
||||
UINT32 ret;
|
||||
if (mutex->magic != _MUX_MAGIC) {
|
||||
return EINVAL;
|
||||
}
|
||||
ret = LOS_MuxDelete(mutex->handle);
|
||||
if (ret != LOS_OK) {
|
||||
return MapError(ret);
|
||||
}
|
||||
mutex->handle = _MUX_INVALID_HANDLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *absTimeout)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT32 timeout;
|
||||
UINT64 timeoutNs;
|
||||
struct timespec curTime = {0};
|
||||
if ((mutex->magic != _MUX_MAGIC) || (absTimeout->tv_nsec < 0) || (absTimeout->tv_nsec >= OS_SYS_NS_PER_SECOND)) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (mutex->handle == _MUX_INVALID_HANDLE) {
|
||||
ret = LOS_MuxCreate(&mutex->handle);
|
||||
if (ret != LOS_OK) {
|
||||
return MapError(ret);
|
||||
}
|
||||
}
|
||||
ret = clock_gettime(CLOCK_REALTIME, &curTime);
|
||||
if (ret != LOS_OK) {
|
||||
return EINVAL;
|
||||
}
|
||||
timeoutNs = (absTimeout->tv_sec - curTime.tv_sec) * OS_SYS_NS_PER_SECOND + (absTimeout->tv_nsec - curTime.tv_nsec);
|
||||
if (timeoutNs <= 0) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
timeout = (timeoutNs + (OS_SYS_NS_PER_MSECOND - 1)) / OS_SYS_NS_PER_MSECOND;
|
||||
ret = LOS_MuxPend(mutex->handle, timeout);
|
||||
return MapError(ret);
|
||||
}
|
||||
|
||||
/* Lock mutex, waiting for it if necessary. */
|
||||
int pthread_mutex_lock(pthread_mutex_t *mutex)
|
||||
{
|
||||
UINT32 ret;
|
||||
if (mutex->magic != _MUX_MAGIC) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (mutex->handle == _MUX_INVALID_HANDLE) {
|
||||
ret = LOS_MuxCreate(&mutex->handle);
|
||||
if (ret != LOS_OK) {
|
||||
return MapError(ret);
|
||||
}
|
||||
}
|
||||
ret = LOS_MuxPend(mutex->handle, LOS_WAIT_FOREVER);
|
||||
return MapError(ret);
|
||||
}
|
||||
|
||||
int pthread_mutex_trylock(pthread_mutex_t *mutex)
|
||||
{
|
||||
UINT32 ret;
|
||||
if (mutex->magic != _MUX_MAGIC) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (mutex->handle == _MUX_INVALID_HANDLE) {
|
||||
ret = LOS_MuxCreate(&mutex->handle);
|
||||
if (ret != LOS_OK) {
|
||||
return MapError(ret);
|
||||
}
|
||||
}
|
||||
ret = LOS_MuxPend(mutex->handle, 0);
|
||||
return MapError(ret);
|
||||
}
|
||||
|
||||
int pthread_mutex_unlock(pthread_mutex_t *mutex)
|
||||
{
|
||||
UINT32 ret;
|
||||
if (mutex->magic != _MUX_MAGIC) {
|
||||
return EINVAL;
|
||||
}
|
||||
ret = LOS_MuxPost(mutex->handle);
|
||||
return MapError(ret);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 <errno.h>
|
||||
#include "los_sem.h"
|
||||
#include "time_internal.h"
|
||||
|
||||
#define _SEM_MAGIC 0xEBCFDEA1
|
||||
|
||||
#define s_magic __val[0]
|
||||
#define s_handle __val[1]
|
||||
|
||||
static inline int MapError(UINT32 err)
|
||||
{
|
||||
switch (err) {
|
||||
case LOS_OK:
|
||||
return 0;
|
||||
case LOS_ERRNO_SEM_INVALID:
|
||||
case LOS_ERRNO_SEM_UNAVAILABLE:
|
||||
return EINVAL;
|
||||
case LOS_ERRNO_SEM_ALL_BUSY:
|
||||
return ENOSPC;
|
||||
case LOS_ERRNO_SEM_OVERFLOW:
|
||||
return ENOMEM;
|
||||
case LOS_ERRNO_SEM_PENDED:
|
||||
return EBUSY;
|
||||
case LOS_ERRNO_SEM_PEND_IN_LOCK:
|
||||
return EPERM;
|
||||
case LOS_ERRNO_SEM_PEND_INTERR:
|
||||
return EINTR;
|
||||
case LOS_ERRNO_SEM_TIMEOUT:
|
||||
return ETIMEDOUT;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int sem_init(sem_t *sem, int shared, unsigned int value)
|
||||
{
|
||||
UINT32 semHandle = 0;
|
||||
UINT32 ret;
|
||||
|
||||
(VOID)shared;
|
||||
if ((sem == NULL) || (value >= OS_SEM_COUNTING_MAX_COUNT)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = LOS_SemCreate(value, &semHandle);
|
||||
if (ret != LOS_OK) {
|
||||
errno = MapError(ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sem->s_magic = _SEM_MAGIC;
|
||||
sem->s_handle = (int)semHandle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_destroy(sem_t *sem)
|
||||
{
|
||||
UINT32 ret;
|
||||
|
||||
if ((sem == NULL) || (sem->s_magic != _SEM_MAGIC)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = LOS_SemDelete((UINT32)sem->s_handle);
|
||||
if (ret != LOS_OK) {
|
||||
errno = MapError(ret);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_wait(sem_t *sem)
|
||||
{
|
||||
UINT32 ret;
|
||||
|
||||
if ((sem == NULL) || (sem->s_magic != _SEM_MAGIC)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = LOS_SemPend((UINT32)sem->s_handle, LOS_WAIT_FOREVER);
|
||||
if (ret != LOS_OK) {
|
||||
errno = MapError(ret);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_post(sem_t *sem)
|
||||
{
|
||||
UINT32 ret;
|
||||
|
||||
if ((sem == NULL) || (sem->s_magic != _SEM_MAGIC)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = LOS_SemPost((UINT32)sem->s_handle);
|
||||
if (ret != LOS_OK) {
|
||||
errno = MapError(ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long long GetTickTimeFromNow(const struct timespec *absTimeSpec)
|
||||
{
|
||||
struct timespec tsNow = { 0 };
|
||||
long long ns;
|
||||
long long tick;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &tsNow);
|
||||
ns = (absTimeSpec->tv_sec - tsNow.tv_sec) * OS_SYS_NS_PER_SECOND + (absTimeSpec->tv_nsec - tsNow.tv_nsec);
|
||||
|
||||
/* Round up for ticks */
|
||||
tick = (ns * LOSCFG_BASE_CORE_TICK_PER_SECOND + (OS_SYS_NS_PER_SECOND - 1)) / OS_SYS_NS_PER_SECOND;
|
||||
return tick;
|
||||
}
|
||||
|
||||
int sem_timedwait(sem_t *sem, const struct timespec *timeout)
|
||||
{
|
||||
UINT32 ret;
|
||||
long long tickCnt;
|
||||
|
||||
if ((sem == NULL) || (sem->s_magic != _SEM_MAGIC)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ValidTimeSpec(timeout)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tickCnt = GetTickTimeFromNow(timeout);
|
||||
if (tickCnt < 0) {
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tickCnt > LOS_WAIT_FOREVER) {
|
||||
tickCnt = LOS_WAIT_FOREVER;
|
||||
}
|
||||
|
||||
ret = LOS_SemPend((UINT32)sem->s_handle, (UINT32)tickCnt);
|
||||
if (ret != LOS_OK) {
|
||||
errno = MapError(ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_getvalue(sem_t *sem, int *currVal)
|
||||
{
|
||||
UINT32 ret;
|
||||
|
||||
if ((sem == NULL) || (currVal == NULL)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = LOS_SemGetValue(sem->s_handle, currVal);
|
||||
if (ret) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return LOS_OK;
|
||||
}
|
||||
@@ -0,0 +1,663 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include "time_internal.h"
|
||||
#include "los_debug.h"
|
||||
#include "los_task.h"
|
||||
#include "los_swtmr.h"
|
||||
#include "los_tick.h"
|
||||
#include "los_context.h"
|
||||
|
||||
/* accumulative time delta from discontinuous modify */
|
||||
STATIC struct timespec g_accDeltaFromSet;
|
||||
|
||||
STATIC const UINT16 g_daysInMonth[2][13] = {
|
||||
/* Normal years. */
|
||||
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
|
||||
/* Leap years. */
|
||||
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
|
||||
};
|
||||
|
||||
STATIC const UINT8 g_montbl[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
/*
|
||||
* Time zone information, stored in seconds,
|
||||
* negative values indicate the east of UTC,
|
||||
* positive values indicate the west of UTC.
|
||||
*/
|
||||
long timezone = -8 * 60 * 60; // defaults to CST: 8 hours east of the Prime Meridian
|
||||
|
||||
/* internal shared struct tm object for localtime and gmtime */
|
||||
static struct tm g_tm;
|
||||
|
||||
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
|
||||
{
|
||||
UINT64 nseconds;
|
||||
UINT64 tick;
|
||||
UINT32 ret;
|
||||
const UINT32 nsPerTick = OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND;
|
||||
|
||||
if (!ValidTimeSpec(rqtp)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nseconds = (UINT64)rqtp->tv_sec * OS_SYS_NS_PER_SECOND + rqtp->tv_nsec;
|
||||
|
||||
tick = (nseconds + nsPerTick - 1) / nsPerTick; // Round up for ticks
|
||||
|
||||
if (tick >= UINT32_MAX) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* PS: skip the first tick because it is NOT a full tick. */
|
||||
ret = LOS_TaskDelay(tick ? (UINT32)(tick + 1) : 0);
|
||||
if (ret == LOS_OK || ret == LOS_ERRNO_TSK_YIELD_NOT_ENOUGH_TASK) {
|
||||
if (rmtp) {
|
||||
rmtp->tv_sec = rmtp->tv_nsec = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sleep in interrupt context or in task sched lock state */
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int timer_create(clockid_t clockID, struct sigevent *restrict evp, timer_t *restrict timerID)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT32 swtmrID;
|
||||
|
||||
if (!timerID || (clockID != CLOCK_REALTIME)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!evp || evp->sigev_notify != SIGEV_THREAD || evp->sigev_notify_attributes) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = LOS_SwtmrCreate(1, LOS_SWTMR_MODE_ONCE, (SWTMR_PROC_FUNC)evp->sigev_notify_function,
|
||||
&swtmrID, (UINT32)(UINTPTR)evp->sigev_value.sival_ptr
|
||||
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
|
||||
, OS_SWTMR_ROUSES_IGNORE, OS_SWTMR_ALIGN_INSENSITIVE
|
||||
#endif
|
||||
);
|
||||
if (ret != LOS_OK) {
|
||||
errno = (ret == LOS_ERRNO_SWTMR_MAXSIZE) ? EAGAIN : EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*timerID = (timer_t)(UINTPTR)swtmrID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_delete(timer_t timerID)
|
||||
{
|
||||
UINT32 swtmrID = (UINT32)(UINTPTR)timerID;
|
||||
if (LOS_SwtmrDelete(swtmrID) != LOS_OK) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_settime(timer_t timerID, int flags,
|
||||
const struct itimerspec *restrict value,
|
||||
struct itimerspec *restrict oldValue)
|
||||
{
|
||||
UINT32 intSave;
|
||||
UINT32 swtmrID = (UINT32)(UINTPTR)timerID;
|
||||
SWTMR_CTRL_S *swtmr = NULL;
|
||||
UINT32 interval, expiry, ret;
|
||||
|
||||
if (flags != 0) {
|
||||
/* flags not supported currently */
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (value == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ValidTimeSpec(&value->it_value) || !ValidTimeSpec(&value->it_interval)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
expiry = OsTimeSpec2Tick(&value->it_value);
|
||||
interval = OsTimeSpec2Tick(&value->it_interval);
|
||||
|
||||
/* if specified interval, it must be same with expiry due to the limitation of liteos-m */
|
||||
if (interval && interval != expiry) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (oldValue) {
|
||||
(VOID)timer_gettime(timerID, oldValue);
|
||||
}
|
||||
|
||||
ret = LOS_SwtmrStop(swtmrID);
|
||||
if ((ret != LOS_OK) && (ret != LOS_ERRNO_SWTMR_NOT_STARTED)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
intSave = LOS_IntLock();
|
||||
swtmr = OS_SWT_FROM_SID(swtmrID);
|
||||
swtmr->ucMode = (interval ? LOS_SWTMR_MODE_PERIOD : LOS_SWTMR_MODE_NO_SELFDELETE);
|
||||
swtmr->uwInterval = (interval ? interval : expiry);
|
||||
|
||||
LOS_IntRestore(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) != LOS_OK) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_gettime(timer_t timerID, struct itimerspec *value)
|
||||
{
|
||||
UINT32 tick = 0;
|
||||
SWTMR_CTRL_S *swtmr = NULL;
|
||||
UINT32 swtmrID = (UINT32)(UINTPTR)timerID;
|
||||
UINT32 ret;
|
||||
|
||||
if (value == NULL) {
|
||||
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)
|
||||
{
|
||||
(void)timerID;
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
STATIC VOID OsGetHwTime(struct timespec *hwTime)
|
||||
{
|
||||
UINT64 cycle = LOS_SysCycleGet();
|
||||
UINT64 nowNsec = (cycle / OS_SYS_CLOCK) * OS_SYS_NS_PER_SECOND +
|
||||
(cycle % OS_SYS_CLOCK) * OS_SYS_NS_PER_SECOND / OS_SYS_CLOCK;
|
||||
|
||||
hwTime->tv_sec = nowNsec / OS_SYS_NS_PER_SECOND;
|
||||
hwTime->tv_nsec = nowNsec % OS_SYS_NS_PER_SECOND;
|
||||
}
|
||||
|
||||
STATIC VOID OsGetRealTime(struct timespec *realTime)
|
||||
{
|
||||
UINT32 intSave;
|
||||
struct timespec hwTime = {0};
|
||||
OsGetHwTime(&hwTime);
|
||||
intSave = LOS_IntLock();
|
||||
realTime->tv_nsec = hwTime.tv_nsec + g_accDeltaFromSet.tv_nsec;
|
||||
realTime->tv_sec = hwTime.tv_sec + g_accDeltaFromSet.tv_sec + (realTime->tv_nsec >= OS_SYS_NS_PER_SECOND);
|
||||
realTime->tv_nsec %= OS_SYS_NS_PER_SECOND;
|
||||
LOS_IntRestore(intSave);
|
||||
}
|
||||
|
||||
STATIC VOID OsSetRealTime(const struct timespec *realTime)
|
||||
{
|
||||
UINT32 intSave;
|
||||
struct timespec hwTime = {0};
|
||||
OsGetHwTime(&hwTime);
|
||||
intSave = LOS_IntLock();
|
||||
g_accDeltaFromSet.tv_nsec = realTime->tv_nsec - hwTime.tv_nsec;
|
||||
g_accDeltaFromSet.tv_sec = realTime->tv_sec - hwTime.tv_sec - (g_accDeltaFromSet.tv_nsec < 0);
|
||||
g_accDeltaFromSet.tv_nsec = (g_accDeltaFromSet.tv_nsec + OS_SYS_NS_PER_SECOND) % OS_SYS_NS_PER_SECOND;
|
||||
LOS_IntRestore(intSave);
|
||||
}
|
||||
|
||||
int clock_settime(clockid_t clockID, const struct timespec *tp)
|
||||
{
|
||||
if (!ValidTimeSpec(tp)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (clockID) {
|
||||
case CLOCK_REALTIME:
|
||||
/* we only support the realtime clock currently */
|
||||
OsSetRealTime(tp);
|
||||
return 0;
|
||||
case CLOCK_MONOTONIC_COARSE:
|
||||
case CLOCK_REALTIME_COARSE:
|
||||
case CLOCK_MONOTONIC_RAW:
|
||||
case CLOCK_PROCESS_CPUTIME_ID:
|
||||
case CLOCK_BOOTTIME:
|
||||
case CLOCK_REALTIME_ALARM:
|
||||
case CLOCK_BOOTTIME_ALARM:
|
||||
case CLOCK_SGI_CYCLE:
|
||||
case CLOCK_TAI:
|
||||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
case CLOCK_MONOTONIC:
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int clock_gettime(clockid_t clockID, struct timespec *tp)
|
||||
{
|
||||
if (tp == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (clockID) {
|
||||
case CLOCK_MONOTONIC_RAW:
|
||||
case CLOCK_MONOTONIC:
|
||||
case CLOCK_MONOTONIC_COARSE:
|
||||
OsGetHwTime(tp);
|
||||
return 0;
|
||||
case CLOCK_REALTIME:
|
||||
case CLOCK_REALTIME_COARSE:
|
||||
OsGetRealTime(tp);
|
||||
return 0;
|
||||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
case CLOCK_PROCESS_CPUTIME_ID:
|
||||
case CLOCK_BOOTTIME:
|
||||
case CLOCK_REALTIME_ALARM:
|
||||
case CLOCK_BOOTTIME_ALARM:
|
||||
case CLOCK_SGI_CYCLE:
|
||||
case CLOCK_TAI:
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int clock_getres(clockid_t clockID, struct timespec *tp)
|
||||
{
|
||||
if (tp == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (clockID) {
|
||||
case CLOCK_MONOTONIC_RAW:
|
||||
case CLOCK_MONOTONIC:
|
||||
case CLOCK_REALTIME:
|
||||
case CLOCK_MONOTONIC_COARSE:
|
||||
case CLOCK_REALTIME_COARSE:
|
||||
tp->tv_nsec = OS_SYS_NS_PER_SECOND / OS_SYS_CLOCK;
|
||||
tp->tv_sec = 0;
|
||||
return 0;
|
||||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
case CLOCK_PROCESS_CPUTIME_ID:
|
||||
case CLOCK_BOOTTIME:
|
||||
case CLOCK_REALTIME_ALARM:
|
||||
case CLOCK_BOOTTIME_ALARM:
|
||||
case CLOCK_SGI_CYCLE:
|
||||
case CLOCK_TAI:
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, struct timespec *rem)
|
||||
{
|
||||
switch (clk) {
|
||||
case CLOCK_REALTIME:
|
||||
if (flags == 0) {
|
||||
/* we only support the realtime clock currently */
|
||||
return nanosleep(req, rem);
|
||||
}
|
||||
/* fallthrough */
|
||||
case CLOCK_MONOTONIC_COARSE:
|
||||
case CLOCK_REALTIME_COARSE:
|
||||
case CLOCK_MONOTONIC_RAW:
|
||||
case CLOCK_MONOTONIC:
|
||||
case CLOCK_PROCESS_CPUTIME_ID:
|
||||
case CLOCK_BOOTTIME:
|
||||
case CLOCK_REALTIME_ALARM:
|
||||
case CLOCK_BOOTTIME_ALARM:
|
||||
case CLOCK_SGI_CYCLE:
|
||||
case CLOCK_TAI:
|
||||
if (flags == 0 || flags == TIMER_ABSTIME) {
|
||||
return ENOTSUP;
|
||||
}
|
||||
/* fallthrough */
|
||||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
clock_t clock(void)
|
||||
{
|
||||
clock_t clk;
|
||||
struct timespec hwTime;
|
||||
OsGetHwTime(&hwTime);
|
||||
|
||||
clk = hwTime.tv_sec * CLOCKS_PER_SEC;
|
||||
clk += hwTime.tv_nsec / (OS_SYS_NS_PER_SECOND / CLOCKS_PER_SEC);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
time_t time(time_t *timer)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
if (-1 == clock_gettime(CLOCK_REALTIME, &ts)) {
|
||||
return (time_t)-1;
|
||||
}
|
||||
|
||||
if (timer != NULL) {
|
||||
*timer = ts.tv_sec;
|
||||
}
|
||||
return ts.tv_sec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the `struct tm' representation of T,
|
||||
* offset OFFSET seconds east of UTC,
|
||||
* and store year, yday, mon, mday, wday, hour, min, sec into *TP.
|
||||
* Return nonzero if successful.
|
||||
*/
|
||||
static INT32 ConvertSecs2Utc(time_t t, INT32 offset, struct tm *tp)
|
||||
{
|
||||
time_t days;
|
||||
time_t rem;
|
||||
time_t year;
|
||||
time_t month;
|
||||
time_t yearGuess;
|
||||
|
||||
days = t / SECS_PER_DAY;
|
||||
rem = t % SECS_PER_DAY;
|
||||
rem += offset;
|
||||
while (rem < 0) {
|
||||
rem += SECS_PER_DAY;
|
||||
--days;
|
||||
}
|
||||
while (rem >= SECS_PER_DAY) {
|
||||
rem -= SECS_PER_DAY;
|
||||
++days;
|
||||
}
|
||||
tp->tm_hour = rem / SECS_PER_HOUR;
|
||||
rem %= SECS_PER_HOUR;
|
||||
tp->tm_min = rem / SECS_PER_MIN;
|
||||
tp->tm_sec = rem % SECS_PER_MIN;
|
||||
/* January 1, 1970 was a Thursday. */
|
||||
tp->tm_wday = (BEGIN_WEEKDAY + days) % DAYS_PER_WEEK;
|
||||
if (tp->tm_wday < 0) {
|
||||
tp->tm_wday += DAYS_PER_WEEK;
|
||||
}
|
||||
year = EPOCH_YEAR;
|
||||
|
||||
while ((days < 0) ||
|
||||
(days >= (IS_LEAP_YEAR (year) ? DAYS_PER_LEAP_YEAR : DAYS_PER_NORMAL_YEAR))) {
|
||||
/* Guess a corrected year, assuming 365 days per year. */
|
||||
yearGuess = year + days / DAYS_PER_NORMAL_YEAR - (days % DAYS_PER_NORMAL_YEAR < 0);
|
||||
|
||||
/* Adjust days and year to match the guessed year. */
|
||||
days -= ((yearGuess - year) * DAYS_PER_NORMAL_YEAR +
|
||||
LEAPS_THRU_END_OF (yearGuess - 1) -
|
||||
LEAPS_THRU_END_OF (year - 1));
|
||||
year = yearGuess;
|
||||
}
|
||||
tp->tm_year = year - TM_YEAR_BASE;
|
||||
if (tp->tm_year != year - TM_YEAR_BASE) {
|
||||
return 0;
|
||||
}
|
||||
tp->tm_yday = days;
|
||||
const UINT16 *daysInMonth = g_daysInMonth[IS_LEAP_YEAR(year)];
|
||||
/* valid month value is 0-11 */
|
||||
for (month = 11; days < (long int) daysInMonth[month]; --month) {
|
||||
continue;
|
||||
}
|
||||
days -= daysInMonth[month];
|
||||
tp->tm_mon = month;
|
||||
tp->tm_mday = days + 1;
|
||||
tp->__tm_gmtoff = offset;
|
||||
tp->__tm_zone = NULL;
|
||||
tp->tm_isdst = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct tm *gmtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
if ((timep == NULL) || (result == NULL)) {
|
||||
errno = EFAULT;
|
||||
return NULL;
|
||||
}
|
||||
if (!ConvertSecs2Utc(*timep, 0, result)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct tm *gmtime(const time_t *timer)
|
||||
{
|
||||
return gmtime_r(timer, &g_tm);
|
||||
}
|
||||
|
||||
struct tm *localtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
if ((timep == NULL) || (result == NULL)) {
|
||||
errno = EFAULT;
|
||||
return NULL;
|
||||
}
|
||||
if (!ConvertSecs2Utc(*timep, -timezone, result)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct tm *localtime(const time_t *timer)
|
||||
{
|
||||
return localtime_r(timer, &g_tm);
|
||||
}
|
||||
|
||||
static time_t ConvertUtc2Secs(struct tm *tm)
|
||||
{
|
||||
time_t seconds = 0;
|
||||
INT32 month = 0;
|
||||
UINT8 leap = 0;
|
||||
|
||||
INT32 year = (EPOCH_YEAR - TM_YEAR_BASE);
|
||||
while (year < tm->tm_year) {
|
||||
seconds += SECS_PER_NORMAL_YEAR;
|
||||
if (IS_LEAP_YEAR(year + TM_YEAR_BASE)) {
|
||||
seconds += SECS_PER_DAY;
|
||||
}
|
||||
year++;
|
||||
}
|
||||
|
||||
if (IS_LEAP_YEAR(tm->tm_year + TM_YEAR_BASE)) {
|
||||
leap = 1;
|
||||
}
|
||||
while (month < tm->tm_mon) {
|
||||
if ((month == 1) && leap) {
|
||||
seconds += (g_montbl[month] + 1) * SECS_PER_DAY;
|
||||
} else {
|
||||
seconds += g_montbl[month] * SECS_PER_DAY;
|
||||
}
|
||||
month++;
|
||||
}
|
||||
|
||||
seconds += (tm->tm_mday - 1) * SECS_PER_DAY;
|
||||
seconds += tm->tm_hour * SECS_PER_HOUR + tm->tm_min * SECS_PER_MIN + tm->tm_sec;
|
||||
|
||||
seconds -= tm->__tm_gmtoff; // sub time zone to get UTC time
|
||||
return seconds;
|
||||
}
|
||||
|
||||
time_t mktime(struct tm *tmptr)
|
||||
{
|
||||
time_t timeInSeconds;
|
||||
if (tmptr == NULL) {
|
||||
errno = EFAULT;
|
||||
return (time_t)-1;
|
||||
}
|
||||
|
||||
/* tm_isdst is not supported and is ignored */
|
||||
if (tmptr->tm_year < (EPOCH_YEAR - TM_YEAR_BASE) ||
|
||||
tmptr->__tm_gmtoff > (-TIME_ZONE_MIN * SECS_PER_MIN) ||
|
||||
tmptr->__tm_gmtoff < (-TIME_ZONE_MAX * SECS_PER_MIN) ||
|
||||
tmptr->tm_sec > 60 || tmptr->tm_sec < 0 || /* Seconds [0-60] */
|
||||
tmptr->tm_min > 59 || tmptr->tm_min < 0 || /* Minutes [0-59] */
|
||||
tmptr->tm_hour > 23 || tmptr->tm_hour < 0 || /* Hours [0-23] */
|
||||
tmptr->tm_mday > 31 || tmptr->tm_mday < 1 || /* Day of the month [1-31] */
|
||||
tmptr->tm_mon > 11 || tmptr->tm_mon < 0) { /* Month [0-11] */
|
||||
errno = EOVERFLOW;
|
||||
return (time_t)-1;
|
||||
}
|
||||
timeInSeconds = ConvertUtc2Secs(tmptr);
|
||||
/* normalize tm_wday and tm_yday */
|
||||
ConvertSecs2Utc(timeInSeconds, tmptr->__tm_gmtoff, tmptr);
|
||||
return timeInSeconds;
|
||||
}
|
||||
|
||||
int gettimeofday(struct timeval *tv, void *ptz)
|
||||
{
|
||||
struct timespec ts;
|
||||
struct timezone *tz = (struct timezone *)ptz;
|
||||
|
||||
if (tv != NULL) {
|
||||
if (-1 == clock_gettime(CLOCK_REALTIME, &ts)) {
|
||||
return -1;
|
||||
}
|
||||
tv->tv_sec = ts.tv_sec;
|
||||
tv->tv_usec = ts.tv_nsec / OS_SYS_NS_PER_US;
|
||||
}
|
||||
if (tz != NULL) {
|
||||
tz->tz_minuteswest = timezone / SECS_PER_MIN;
|
||||
tz->tz_dsttime = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int settimeofday(const struct timeval *tv, const struct timezone *tz)
|
||||
{
|
||||
struct timespec ts;
|
||||
INT32 rtcTimeZone = timezone;
|
||||
|
||||
if (tv == NULL) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
if (tz != NULL) {
|
||||
if ((tz->tz_minuteswest >= TIME_ZONE_MIN) &&
|
||||
(tz->tz_minuteswest <= TIME_ZONE_MAX)) {
|
||||
rtcTimeZone = tz->tz_minuteswest * SECS_PER_MIN;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tv->tv_usec >= OS_SYS_US_PER_SECOND) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ts.tv_sec = tv->tv_sec;
|
||||
ts.tv_nsec = tv->tv_usec * OS_SYS_NS_PER_US;
|
||||
if (-1 == clock_settime(CLOCK_REALTIME, &ts)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
timezone = rtcTimeZone;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usleep(unsigned useconds)
|
||||
{
|
||||
struct timespec specTime = { 0 };
|
||||
UINT64 nanoseconds = (UINT64)useconds * OS_SYS_NS_PER_US;
|
||||
|
||||
specTime.tv_sec = (time_t)(nanoseconds / OS_SYS_NS_PER_SECOND);
|
||||
specTime.tv_nsec = (long)(nanoseconds % OS_SYS_NS_PER_SECOND);
|
||||
return nanosleep(&specTime, NULL);
|
||||
}
|
||||
|
||||
unsigned sleep(unsigned seconds)
|
||||
{
|
||||
struct timespec specTime = { 0 };
|
||||
UINT64 nanoseconds = (UINT64)seconds * OS_SYS_NS_PER_SECOND;
|
||||
|
||||
specTime.tv_sec = (time_t)(nanoseconds / OS_SYS_NS_PER_SECOND);
|
||||
specTime.tv_nsec = (long)(nanoseconds % OS_SYS_NS_PER_SECOND);
|
||||
return nanosleep(&specTime, NULL);
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020-2021 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 _TIME_IMPL_H
|
||||
#define _TIME_IMPL_H
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include "los_debug.h"
|
||||
#include "los_task.h"
|
||||
#include "los_swtmr.h"
|
||||
#include "los_timer.h"
|
||||
#include "los_context.h"
|
||||
#include "los_compiler.h"
|
||||
|
||||
#define OS_SYS_NS_PER_US 1000
|
||||
#define OS_SYS_NS_PER_SECOND 1000000000
|
||||
#define OS_SYS_US_PER_SECOND 1000000
|
||||
#define OS_SYS_MS_PER_SECOND 1000
|
||||
|
||||
#define TM_YEAR_BASE 1900
|
||||
#define EPOCH_YEAR 1970
|
||||
#define SECS_PER_MIN 60
|
||||
#define MINS_PER_HOUR 60
|
||||
#define SECS_PER_HOUR 3600 /* 60 * 60 */
|
||||
#define SECS_PER_DAY 86400 /* 60 * 60 * 24 */
|
||||
#define SECS_PER_NORMAL_YEAR 31536000 /* 60 * 60 * 24 * 365 */
|
||||
#define DAYS_PER_WEEK 7
|
||||
#define DAYS_PER_NORMAL_YEAR 365
|
||||
#define DAYS_PER_LEAP_YEAR 366
|
||||
#define BEGIN_WEEKDAY 4
|
||||
#define TIME_ZONE_MAX 720 /* UTC-12:00 , the last time zone */
|
||||
#define TIME_ZONE_MIN (-840) /* UTC+14:00 , the first time zone */
|
||||
|
||||
/*
|
||||
* Nonzero if YEAR is a leap year (every 4 years,
|
||||
* except every 100th isn't, and every 400th is).
|
||||
*/
|
||||
#ifndef IS_LEAP_YEAR
|
||||
#define IS_LEAP_YEAR(year) \
|
||||
(((year) % 4 == 0) && (((year) % 100 != 0) || ((year) % 400 == 0)))
|
||||
#endif
|
||||
|
||||
#define DIV(a, b) (((a) / (b)) - ((a) % (b) < 0))
|
||||
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
|
||||
|
||||
/* internal functions */
|
||||
STATIC INLINE BOOL ValidTimeSpec(const struct timespec *tp)
|
||||
{
|
||||
/* Fail a NULL pointer */
|
||||
if (tp == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Fail illegal nanosecond values */
|
||||
if ((tp->tv_nsec < 0) || (tp->tv_nsec >= OS_SYS_NS_PER_SECOND) || (tp->tv_sec < 0)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STATIC INLINE UINT32 OsTimeSpec2Tick(const struct timespec *tp)
|
||||
{
|
||||
UINT64 tick, ns;
|
||||
|
||||
ns = (UINT64)tp->tv_sec * OS_SYS_NS_PER_SECOND + tp->tv_nsec;
|
||||
/* Round up for ticks */
|
||||
tick = (ns * LOSCFG_BASE_CORE_TICK_PER_SECOND + (OS_SYS_NS_PER_SECOND - 1)) / OS_SYS_NS_PER_SECOND;
|
||||
if (tick > LOS_WAIT_FOREVER) {
|
||||
tick = LOS_WAIT_FOREVER;
|
||||
}
|
||||
return (UINT32)tick;
|
||||
}
|
||||
|
||||
STATIC INLINE VOID OsTick2TimeSpec(struct timespec *tp, UINT32 tick)
|
||||
{
|
||||
UINT64 ns = ((UINT64)tick * OS_SYS_NS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND;
|
||||
tp->tv_sec = (time_t)(ns / OS_SYS_NS_PER_SECOND);
|
||||
tp->tv_nsec = (long)(ns % OS_SYS_NS_PER_SECOND);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user