10d163575Sopenharmony_ci/*
20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
30d163575Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
40d163575Sopenharmony_ci *
50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
60d163575Sopenharmony_ci * are permitted provided that the following conditions are met:
70d163575Sopenharmony_ci *
80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
90d163575Sopenharmony_ci *    conditions and the following disclaimer.
100d163575Sopenharmony_ci *
110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
120d163575Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
130d163575Sopenharmony_ci *    provided with the distribution.
140d163575Sopenharmony_ci *
150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
160d163575Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
170d163575Sopenharmony_ci *    permission.
180d163575Sopenharmony_ci *
190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
300d163575Sopenharmony_ci */
310d163575Sopenharmony_ci
320d163575Sopenharmony_ci#include <arch/sys_arch.h>
330d163575Sopenharmony_ci#include <lwip/sys.h>
340d163575Sopenharmony_ci#include <lwip/debug.h>
350d163575Sopenharmony_ci#include <los_task.h>
360d163575Sopenharmony_ci#include <los_sys_pri.h>
370d163575Sopenharmony_ci#include <los_tick.h>
380d163575Sopenharmony_ci#include <los_queue.h>
390d163575Sopenharmony_ci#include <los_sem.h>
400d163575Sopenharmony_ci#include <los_mux.h>
410d163575Sopenharmony_ci#include <los_spinlock.h>
420d163575Sopenharmony_ci
430d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_SMP
440d163575Sopenharmony_ciSPIN_LOCK_INIT(arch_protect_spin);
450d163575Sopenharmony_cistatic u32_t lwprot_thread = LOS_ERRNO_TSK_ID_INVALID;
460d163575Sopenharmony_cistatic int lwprot_count = 0;
470d163575Sopenharmony_ci#endif /* LOSCFG_KERNEL_SMP */
480d163575Sopenharmony_ci
490d163575Sopenharmony_ci#define ROUND_UP_DIV(val, div) (((val) + (div) - 1) / (div))
500d163575Sopenharmony_ci
510d163575Sopenharmony_ci/**
520d163575Sopenharmony_ci * Thread and System misc
530d163575Sopenharmony_ci */
540d163575Sopenharmony_ci
550d163575Sopenharmony_cisys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stackSize, int prio)
560d163575Sopenharmony_ci{
570d163575Sopenharmony_ci    UINT32 taskID = LOS_ERRNO_TSK_ID_INVALID;
580d163575Sopenharmony_ci    UINT32 ret;
590d163575Sopenharmony_ci    TSK_INIT_PARAM_S task = {0};
600d163575Sopenharmony_ci
610d163575Sopenharmony_ci    /* Create host Task */
620d163575Sopenharmony_ci    task.pfnTaskEntry = (TSK_ENTRY_FUNC)thread;
630d163575Sopenharmony_ci    task.uwStackSize = stackSize;
640d163575Sopenharmony_ci    task.pcName = (char *)name;
650d163575Sopenharmony_ci    task.usTaskPrio = prio;
660d163575Sopenharmony_ci    task.auwArgs[0] = (UINTPTR)arg;
670d163575Sopenharmony_ci    task.uwResved = LOS_TASK_STATUS_DETACHED;
680d163575Sopenharmony_ci    ret = LOS_TaskCreate(&taskID, &task);
690d163575Sopenharmony_ci    if (ret != LOS_OK) {
700d163575Sopenharmony_ci        LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: LOS_TaskCreate error %u\n", ret));
710d163575Sopenharmony_ci        return -1;
720d163575Sopenharmony_ci    }
730d163575Sopenharmony_ci
740d163575Sopenharmony_ci    return taskID;
750d163575Sopenharmony_ci}
760d163575Sopenharmony_ci
770d163575Sopenharmony_civoid sys_init(void)
780d163575Sopenharmony_ci{
790d163575Sopenharmony_ci    /* set rand seed to make random sequence diff on every startup */
800d163575Sopenharmony_ci    UINT32 seedhsb, seedlsb;
810d163575Sopenharmony_ci    LOS_GetCpuCycle(&seedhsb, &seedlsb);
820d163575Sopenharmony_ci    srand(seedlsb);
830d163575Sopenharmony_ci}
840d163575Sopenharmony_ci
850d163575Sopenharmony_ciu32_t sys_now(void)
860d163575Sopenharmony_ci{
870d163575Sopenharmony_ci    /* Lwip docs mentioned like wraparound is not a problem in this function */
880d163575Sopenharmony_ci    return (u32_t)((LOS_TickCountGet() * OS_SYS_MS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND);
890d163575Sopenharmony_ci}
900d163575Sopenharmony_ci
910d163575Sopenharmony_ci#if (LWIP_CHKSUM_ALGORITHM == 4) /* version #4, asm based */
920d163575Sopenharmony_ci#include "in_cksum.h"
930d163575Sopenharmony_ciu16_t lwip_standard_chksum(const void *dataptr, int len)
940d163575Sopenharmony_ci{
950d163575Sopenharmony_ci    return ~(u16_t)(in_cksum(dataptr, len));
960d163575Sopenharmony_ci}
970d163575Sopenharmony_ci#endif
980d163575Sopenharmony_ci
990d163575Sopenharmony_ci
1000d163575Sopenharmony_ci/**
1010d163575Sopenharmony_ci * Protector
1020d163575Sopenharmony_ci */
1030d163575Sopenharmony_ci
1040d163575Sopenharmony_cisys_prot_t sys_arch_protect(void)
1050d163575Sopenharmony_ci{
1060d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_SMP
1070d163575Sopenharmony_ci    /* Note that we are using spinlock instead of mutex for LiteOS-SMP here:
1080d163575Sopenharmony_ci     * 1. spinlock is more effective for short critical region protection.
1090d163575Sopenharmony_ci     * 2. this function is called only in task context, not in interrupt handler.
1100d163575Sopenharmony_ci     *    so it's not needed to disable interrupt.
1110d163575Sopenharmony_ci     */
1120d163575Sopenharmony_ci    if (lwprot_thread != LOS_CurTaskIDGet()) {
1130d163575Sopenharmony_ci        /* We are locking the spinlock where it has not been locked before
1140d163575Sopenharmony_ci         * or is being locked by another thread */
1150d163575Sopenharmony_ci        LOS_SpinLock(&arch_protect_spin);
1160d163575Sopenharmony_ci        lwprot_thread = LOS_CurTaskIDGet();
1170d163575Sopenharmony_ci        lwprot_count = 1;
1180d163575Sopenharmony_ci    } else {
1190d163575Sopenharmony_ci        /* It is already locked by THIS thread */
1200d163575Sopenharmony_ci        lwprot_count++;
1210d163575Sopenharmony_ci    }
1220d163575Sopenharmony_ci#else
1230d163575Sopenharmony_ci    LOS_TaskLock();
1240d163575Sopenharmony_ci#endif /* LOSCFG_KERNEL_SMP */
1250d163575Sopenharmony_ci    return 0; /* return value is unused */
1260d163575Sopenharmony_ci}
1270d163575Sopenharmony_ci
1280d163575Sopenharmony_civoid sys_arch_unprotect(sys_prot_t pval)
1290d163575Sopenharmony_ci{
1300d163575Sopenharmony_ci    LWIP_UNUSED_ARG(pval);
1310d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_SMP
1320d163575Sopenharmony_ci    if (lwprot_thread == LOS_CurTaskIDGet()) {
1330d163575Sopenharmony_ci        lwprot_count--;
1340d163575Sopenharmony_ci        if (lwprot_count == 0) {
1350d163575Sopenharmony_ci            lwprot_thread = LOS_ERRNO_TSK_ID_INVALID;
1360d163575Sopenharmony_ci            LOS_SpinUnlock(&arch_protect_spin);
1370d163575Sopenharmony_ci        }
1380d163575Sopenharmony_ci    }
1390d163575Sopenharmony_ci#else
1400d163575Sopenharmony_ci    LOS_TaskUnlock();
1410d163575Sopenharmony_ci#endif /* LOSCFG_KERNEL_SMP */
1420d163575Sopenharmony_ci}
1430d163575Sopenharmony_ci
1440d163575Sopenharmony_ci
1450d163575Sopenharmony_ci/**
1460d163575Sopenharmony_ci * MessageBox
1470d163575Sopenharmony_ci */
1480d163575Sopenharmony_ci
1490d163575Sopenharmony_cierr_t sys_mbox_new(sys_mbox_t *mbox, int size)
1500d163575Sopenharmony_ci{
1510d163575Sopenharmony_ci    CHAR qName[] = "lwIP";
1520d163575Sopenharmony_ci    UINT32 ret = LOS_QueueCreate(qName, (UINT16)size, mbox, 0, sizeof(void *));
1530d163575Sopenharmony_ci    switch (ret) {
1540d163575Sopenharmony_ci        case LOS_OK:
1550d163575Sopenharmony_ci            return ERR_OK;
1560d163575Sopenharmony_ci        case LOS_ERRNO_QUEUE_CB_UNAVAILABLE:
1570d163575Sopenharmony_ci        case LOS_ERRNO_QUEUE_CREATE_NO_MEMORY:
1580d163575Sopenharmony_ci            return ERR_MEM;
1590d163575Sopenharmony_ci        default:
1600d163575Sopenharmony_ci            break;
1610d163575Sopenharmony_ci    }
1620d163575Sopenharmony_ci    LWIP_DEBUGF(SYS_DEBUG, ("%s: LOS_QueueCreate error %u\n", __FUNCTION__, ret));
1630d163575Sopenharmony_ci    return ERR_ARG;
1640d163575Sopenharmony_ci}
1650d163575Sopenharmony_ci
1660d163575Sopenharmony_civoid sys_mbox_post(sys_mbox_t *mbox, void *msg)
1670d163575Sopenharmony_ci{
1680d163575Sopenharmony_ci    /* Caution: the second parameter is NOT &msg */
1690d163575Sopenharmony_ci    UINT32 ret = LOS_QueueWrite(*mbox, msg, sizeof(char *), LOS_WAIT_FOREVER);
1700d163575Sopenharmony_ci    if (ret != LOS_OK) {
1710d163575Sopenharmony_ci        LWIP_DEBUGF(SYS_DEBUG, ("%s: LOS_QueueWrite error %u\n", __FUNCTION__, ret));
1720d163575Sopenharmony_ci    }
1730d163575Sopenharmony_ci}
1740d163575Sopenharmony_ci
1750d163575Sopenharmony_cierr_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
1760d163575Sopenharmony_ci{
1770d163575Sopenharmony_ci    /* Caution: the second parameter is NOT &msg */
1780d163575Sopenharmony_ci    UINT32 ret = LOS_QueueWrite(*mbox, msg, sizeof(char *), 0);
1790d163575Sopenharmony_ci    switch (ret) {
1800d163575Sopenharmony_ci        case LOS_OK:
1810d163575Sopenharmony_ci            return ERR_OK;
1820d163575Sopenharmony_ci        case LOS_ERRNO_QUEUE_ISFULL:
1830d163575Sopenharmony_ci            return ERR_MEM;
1840d163575Sopenharmony_ci        default:
1850d163575Sopenharmony_ci            break;
1860d163575Sopenharmony_ci    }
1870d163575Sopenharmony_ci    LWIP_DEBUGF(SYS_DEBUG, ("%s: LOS_QueueWrite error %u\n", __FUNCTION__, ret));
1880d163575Sopenharmony_ci    return ERR_ARG;
1890d163575Sopenharmony_ci}
1900d163575Sopenharmony_ci
1910d163575Sopenharmony_cierr_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg);
1920d163575Sopenharmony_ci
1930d163575Sopenharmony_ciu32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeoutMs)
1940d163575Sopenharmony_ci{
1950d163575Sopenharmony_ci    void *ignore = 0; /* if msg==NULL, the fetched msg should be dropped */
1960d163575Sopenharmony_ci    UINT64 tick = ROUND_UP_DIV((UINT64)timeoutMs * LOSCFG_BASE_CORE_TICK_PER_SECOND, OS_SYS_MS_PER_SECOND);
1970d163575Sopenharmony_ci    UINT32 ret = LOS_QueueRead(*mbox, msg ? msg : &ignore, sizeof(void *), tick ? (UINT32)tick : LOS_WAIT_FOREVER);
1980d163575Sopenharmony_ci    switch (ret) {
1990d163575Sopenharmony_ci        case LOS_OK:
2000d163575Sopenharmony_ci            return ERR_OK;
2010d163575Sopenharmony_ci        case LOS_ERRNO_QUEUE_ISEMPTY:
2020d163575Sopenharmony_ci        case LOS_ERRNO_QUEUE_TIMEOUT:
2030d163575Sopenharmony_ci            return SYS_ARCH_TIMEOUT;
2040d163575Sopenharmony_ci        default:
2050d163575Sopenharmony_ci            break;
2060d163575Sopenharmony_ci    }
2070d163575Sopenharmony_ci    LWIP_DEBUGF(SYS_DEBUG, ("%s: LOS_QueueRead error %u\n", __FUNCTION__, ret));
2080d163575Sopenharmony_ci    return SYS_ARCH_TIMEOUT; /* Errors should be treated as timeout */
2090d163575Sopenharmony_ci}
2100d163575Sopenharmony_ci
2110d163575Sopenharmony_ciu32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
2120d163575Sopenharmony_ci{
2130d163575Sopenharmony_ci    void *ignore = 0; /* if msg==NULL, the fetched msg should be dropped */
2140d163575Sopenharmony_ci    UINT32 ret = LOS_QueueRead(*mbox, msg ? msg : &ignore, sizeof(void *), 0);
2150d163575Sopenharmony_ci    switch (ret) {
2160d163575Sopenharmony_ci        case LOS_OK:
2170d163575Sopenharmony_ci            return ERR_OK;
2180d163575Sopenharmony_ci        case LOS_ERRNO_QUEUE_ISEMPTY:
2190d163575Sopenharmony_ci            return SYS_MBOX_EMPTY;
2200d163575Sopenharmony_ci        case LOS_ERRNO_QUEUE_TIMEOUT:
2210d163575Sopenharmony_ci            return SYS_ARCH_TIMEOUT;
2220d163575Sopenharmony_ci        default:
2230d163575Sopenharmony_ci            break;
2240d163575Sopenharmony_ci    }
2250d163575Sopenharmony_ci    LWIP_DEBUGF(SYS_DEBUG, ("%s: LOS_QueueRead error %u\n", __FUNCTION__, ret));
2260d163575Sopenharmony_ci    return SYS_MBOX_EMPTY; /* Errors should be treated as timeout */
2270d163575Sopenharmony_ci}
2280d163575Sopenharmony_ci
2290d163575Sopenharmony_civoid sys_mbox_free(sys_mbox_t *mbox)
2300d163575Sopenharmony_ci{
2310d163575Sopenharmony_ci    (void)LOS_QueueDelete(*mbox);
2320d163575Sopenharmony_ci}
2330d163575Sopenharmony_ci
2340d163575Sopenharmony_ciint sys_mbox_valid(sys_mbox_t *mbox)
2350d163575Sopenharmony_ci{
2360d163575Sopenharmony_ci    QUEUE_INFO_S queueInfo;
2370d163575Sopenharmony_ci    return LOS_OK == LOS_QueueInfoGet(*mbox, &queueInfo);
2380d163575Sopenharmony_ci}
2390d163575Sopenharmony_ci
2400d163575Sopenharmony_civoid sys_mbox_set_invalid(sys_mbox_t *mbox)
2410d163575Sopenharmony_ci{
2420d163575Sopenharmony_ci    *mbox = LOSCFG_BASE_IPC_QUEUE_LIMIT;
2430d163575Sopenharmony_ci}
2440d163575Sopenharmony_ci
2450d163575Sopenharmony_ci
2460d163575Sopenharmony_ci/**
2470d163575Sopenharmony_ci * Semaphore
2480d163575Sopenharmony_ci */
2490d163575Sopenharmony_ci
2500d163575Sopenharmony_cierr_t sys_sem_new(sys_sem_t *sem, u8_t count)
2510d163575Sopenharmony_ci{
2520d163575Sopenharmony_ci    UINT32 ret = LOS_SemCreate(count, sem);
2530d163575Sopenharmony_ci    if (ret != LOS_OK) {
2540d163575Sopenharmony_ci        return ERR_ARG;
2550d163575Sopenharmony_ci    }
2560d163575Sopenharmony_ci
2570d163575Sopenharmony_ci    return ERR_OK;
2580d163575Sopenharmony_ci}
2590d163575Sopenharmony_ci
2600d163575Sopenharmony_civoid sys_sem_signal(sys_sem_t *sem)
2610d163575Sopenharmony_ci{
2620d163575Sopenharmony_ci    (void)LOS_SemPost(*sem);
2630d163575Sopenharmony_ci}
2640d163575Sopenharmony_ci
2650d163575Sopenharmony_ciu32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeoutMs)
2660d163575Sopenharmony_ci{
2670d163575Sopenharmony_ci    UINT64 tick = ROUND_UP_DIV((UINT64)timeoutMs * LOSCFG_BASE_CORE_TICK_PER_SECOND, OS_SYS_MS_PER_SECOND);
2680d163575Sopenharmony_ci    UINT32 ret = LOS_SemPend(*sem, tick ? (UINT32)tick : LOS_WAIT_FOREVER); // timeoutMs 0 means wait forever
2690d163575Sopenharmony_ci    switch (ret) {
2700d163575Sopenharmony_ci        case LOS_OK:
2710d163575Sopenharmony_ci            return ERR_OK;
2720d163575Sopenharmony_ci        case LOS_ERRNO_SEM_TIMEOUT:
2730d163575Sopenharmony_ci            return SYS_ARCH_TIMEOUT;
2740d163575Sopenharmony_ci        default:
2750d163575Sopenharmony_ci            break;
2760d163575Sopenharmony_ci    }
2770d163575Sopenharmony_ci    LWIP_DEBUGF(SYS_DEBUG, ("%s: LOS_SemPend error %u\n", __FUNCTION__, ret));
2780d163575Sopenharmony_ci    return SYS_ARCH_TIMEOUT; /* Errors should be treated as timeout */
2790d163575Sopenharmony_ci}
2800d163575Sopenharmony_ci
2810d163575Sopenharmony_civoid sys_sem_free(sys_sem_t *sem)
2820d163575Sopenharmony_ci{
2830d163575Sopenharmony_ci    (void)LOS_SemDelete(*sem);
2840d163575Sopenharmony_ci}
2850d163575Sopenharmony_ci
2860d163575Sopenharmony_ciint sys_sem_valid(sys_sem_t *sem)
2870d163575Sopenharmony_ci{
2880d163575Sopenharmony_ci    return *sem != LOSCFG_BASE_IPC_SEM_LIMIT;
2890d163575Sopenharmony_ci}
2900d163575Sopenharmony_ci
2910d163575Sopenharmony_civoid sys_sem_set_invalid(sys_sem_t *sem)
2920d163575Sopenharmony_ci{
2930d163575Sopenharmony_ci    *sem = LOSCFG_BASE_IPC_SEM_LIMIT;
2940d163575Sopenharmony_ci}
2950d163575Sopenharmony_ci
2960d163575Sopenharmony_ci
2970d163575Sopenharmony_ci/**
2980d163575Sopenharmony_ci * Mutex
2990d163575Sopenharmony_ci */
3000d163575Sopenharmony_ci
3010d163575Sopenharmony_cierr_t sys_mutex_new(sys_mutex_t *mutex)
3020d163575Sopenharmony_ci{
3030d163575Sopenharmony_ci    UINT32 ret = LOS_MuxInit(mutex, NULL);
3040d163575Sopenharmony_ci    if (ret != LOS_OK) {
3050d163575Sopenharmony_ci        return ERR_ARG;
3060d163575Sopenharmony_ci    }
3070d163575Sopenharmony_ci
3080d163575Sopenharmony_ci    return ERR_OK;
3090d163575Sopenharmony_ci}
3100d163575Sopenharmony_ci
3110d163575Sopenharmony_civoid sys_mutex_lock(sys_mutex_t *mutex)
3120d163575Sopenharmony_ci{
3130d163575Sopenharmony_ci    (void)LOS_MuxLock(mutex, LOS_WAIT_FOREVER);
3140d163575Sopenharmony_ci}
3150d163575Sopenharmony_ci
3160d163575Sopenharmony_civoid sys_mutex_unlock(sys_mutex_t *mutex)
3170d163575Sopenharmony_ci{
3180d163575Sopenharmony_ci    (void)LOS_MuxUnlock(mutex);
3190d163575Sopenharmony_ci}
3200d163575Sopenharmony_ci
3210d163575Sopenharmony_civoid sys_mutex_free(sys_mutex_t *mutex)
3220d163575Sopenharmony_ci{
3230d163575Sopenharmony_ci    (void)LOS_MuxDestroy(mutex);
3240d163575Sopenharmony_ci}
3250d163575Sopenharmony_ci
3260d163575Sopenharmony_ciint sys_mutex_valid(sys_mutex_t *mutex)
3270d163575Sopenharmony_ci{
3280d163575Sopenharmony_ci    return LOS_MuxIsValid(mutex);
3290d163575Sopenharmony_ci}
3300d163575Sopenharmony_ci
3310d163575Sopenharmony_civoid sys_mutex_set_invalid(sys_mutex_t *mutex)
3320d163575Sopenharmony_ci{
3330d163575Sopenharmony_ci    (void)LOS_MuxDestroy(mutex);
3340d163575Sopenharmony_ci}
335