mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-16 03:18:54 +00:00
786 lines
21 KiB
C
786 lines
21 KiB
C
/*
|
|
* Copyright (C) 2019-2020 Alibaba Group Holding Limited
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
|
* 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. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
|
*
|
|
* This file is part of the lwIP TCP/IP stack.
|
|
*
|
|
* Author: Adam Dunkels <adam@sics.se>
|
|
*
|
|
*/
|
|
|
|
/* system includes */
|
|
#include <aos/kernel.h>
|
|
#include <aos/list.h>
|
|
#include <aos/aos.h>
|
|
/* lwIP includes. */
|
|
#include "lwip/debug.h"
|
|
#include "lwip/def.h"
|
|
#include "lwip/sys.h"
|
|
#include "lwip/mem.h"
|
|
#include "arch/sys_arch.h"
|
|
#include <aos/aos.h>
|
|
#include <k_api.h>
|
|
|
|
static aos_mutex_t sys_arch_mutex;
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Creates a new semaphore.
|
|
* @param sem sem struct pointer
|
|
* @param count
|
|
* @return 0 OK
|
|
* -1 ERR
|
|
*/
|
|
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
|
|
{
|
|
err_t ret = ERR_MEM;
|
|
int stat = aos_sem_new(sem, count);
|
|
|
|
if (stat == 0) {
|
|
ret = ERR_OK;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Deallocates a semaphore.
|
|
* @param sem sem struct
|
|
* @return null
|
|
*/
|
|
void sys_sem_free(sys_sem_t *sem)
|
|
{
|
|
if ((sem != NULL)) {
|
|
aos_sem_free(sem);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Signals a semaphore.
|
|
* @param sem sem struct pointer
|
|
* @return null
|
|
*/
|
|
void sys_sem_signal(sys_sem_t *sem)
|
|
{
|
|
aos_sem_signal(sem);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Blocks the thread while waiting for the semaphore to be
|
|
signaled. If the "timeout" argument is non-zero, the thread should
|
|
only be blocked for the specified time (measured in
|
|
milliseconds).
|
|
|
|
If the timeout argument is non-zero, the return value is the number of
|
|
milliseconds spent waiting for the semaphore to be signaled. If the
|
|
semaphore wasn't signaled within the specified time, the return value is
|
|
SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
|
|
(i.e., it was already signaled), the function may return zero.
|
|
|
|
Notice that lwIP implements a function with a similar name,
|
|
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
|
|
* @param sem sem struct pointer
|
|
* @param timeout
|
|
* @return has been waited time
|
|
*/
|
|
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
|
|
{
|
|
u32_t begin_ms, end_ms, elapsed_ms;
|
|
u32_t ret;
|
|
|
|
if (sem == NULL) {
|
|
return SYS_ARCH_TIMEOUT;
|
|
}
|
|
|
|
begin_ms = sys_now();
|
|
|
|
if (timeout != 0UL) {
|
|
ret = aos_sem_wait(sem, timeout);
|
|
|
|
if (ret == 0) {
|
|
end_ms = sys_now();
|
|
|
|
elapsed_ms = end_ms - begin_ms;
|
|
|
|
ret = elapsed_ms;
|
|
} else {
|
|
ret = SYS_ARCH_TIMEOUT;
|
|
}
|
|
} else {
|
|
while (!(aos_sem_wait(sem, AOS_WAIT_FOREVER) == 0));
|
|
|
|
end_ms = sys_now();
|
|
|
|
elapsed_ms = end_ms - begin_ms;
|
|
|
|
if (elapsed_ms == 0UL) {
|
|
elapsed_ms = 1UL;
|
|
}
|
|
|
|
ret = elapsed_ms;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifndef LWIP_MAILBOX_QUEUE
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Creates an empty mailbox for maximum "size" elements.
|
|
* @param mb mbox struct pointer
|
|
* @param size
|
|
* @return 0 OK
|
|
* -1 ERR
|
|
*/
|
|
err_t sys_mbox_new(sys_mbox_t *mb, int size)
|
|
{
|
|
struct sys_mbox *mbox;
|
|
LWIP_UNUSED_ARG(size);
|
|
|
|
mbox = (struct sys_mbox *)malloc(sizeof(struct sys_mbox));
|
|
|
|
if (mbox == NULL) {
|
|
return ERR_MEM;
|
|
}
|
|
|
|
memset(mbox, 0, sizeof(struct sys_mbox));
|
|
|
|
mbox->first = mbox->last = 0;
|
|
sys_sem_new(&mbox->not_empty, 0);
|
|
sys_sem_new(&mbox->not_full, 0);
|
|
sys_sem_new(&mbox->mutex, 1);
|
|
mbox->wait_send = 0;
|
|
|
|
*mb = mbox;
|
|
return ERR_OK;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Deallocates a mailbox. If there are messages still present in the
|
|
mailbox when the mailbox is deallocated, it is an indication of a
|
|
programming error in lwIP and the developer should be notified.
|
|
* @param mb mbox struct pointer
|
|
* @return null
|
|
*/
|
|
void sys_mbox_free(sys_mbox_t *mb)
|
|
{
|
|
if ((mb != NULL) && (*mb != SYS_MBOX_NULL)) {
|
|
struct sys_mbox *mbox = *mb;
|
|
|
|
sys_arch_sem_wait(&mbox->mutex, 0);
|
|
|
|
sys_sem_free(&mbox->not_empty);
|
|
sys_sem_free(&mbox->not_full);
|
|
sys_sem_free(&mbox->mutex);
|
|
/* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
|
|
free(mbox);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Posts the "msg" to the mailbox. This function have to block until the "msg" is really posted.
|
|
* @param mb mbox struct pointer
|
|
* @param msg for mailbox to post
|
|
* @return null
|
|
*/
|
|
void sys_mbox_post(sys_mbox_t *mb, void *msg)
|
|
{
|
|
u8_t first;
|
|
struct sys_mbox *mbox;
|
|
LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
|
|
mbox = *mb;
|
|
|
|
sys_arch_sem_wait(&mbox->mutex, 0);
|
|
|
|
LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg));
|
|
|
|
while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
|
|
mbox->wait_send++;
|
|
sys_sem_signal(&mbox->mutex);
|
|
sys_arch_sem_wait(&mbox->not_full, 0);
|
|
sys_arch_sem_wait(&mbox->mutex, 0);
|
|
mbox->wait_send--;
|
|
}
|
|
|
|
mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
|
|
|
|
if (mbox->last == mbox->first) {
|
|
first = 1;
|
|
} else {
|
|
first = 0;
|
|
}
|
|
|
|
mbox->last++;
|
|
|
|
if (first) {
|
|
sys_sem_signal(&mbox->not_empty);
|
|
}
|
|
|
|
sys_sem_signal(&mbox->mutex);
|
|
}
|
|
|
|
/**
|
|
* @brief Try to post the "msg" to the mailbox. Returns ERR_MEM if this one is full, else, ERR_OK if the "msg" is posted.
|
|
* @param mb mbox struct pointer
|
|
* @param msg for mailbox to post
|
|
* @return 0 OK
|
|
* -1 ERR
|
|
*/
|
|
err_t sys_mbox_trypost(sys_mbox_t *mb, void *msg)
|
|
{
|
|
u8_t first;
|
|
struct sys_mbox *mbox;
|
|
LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
|
|
mbox = *mb;
|
|
|
|
sys_arch_sem_wait(&mbox->mutex, 0);
|
|
|
|
LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
|
|
(void *)mbox, (void *)msg));
|
|
|
|
if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
|
|
sys_sem_signal(&mbox->mutex);
|
|
return ERR_MEM;
|
|
}
|
|
|
|
mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
|
|
|
|
if (mbox->last == mbox->first) {
|
|
first = 1;
|
|
} else {
|
|
first = 0;
|
|
}
|
|
|
|
mbox->last++;
|
|
|
|
if (first) {
|
|
sys_sem_signal(&mbox->not_empty);
|
|
}
|
|
|
|
sys_sem_signal(&mbox->mutex);
|
|
return ERR_OK;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/*
|
|
@brief Blocks the thread until a message arrives in the mailbox, but does
|
|
not block the thread longer than "timeout" milliseconds (similar to
|
|
the sys_arch_sem_wait() function). The "msg" argument is a result
|
|
parameter that is set by the function (i.e., by doing "*msg =
|
|
ptr"). The "msg" parameter maybe NULL to indicate that the message
|
|
should be dropped.
|
|
|
|
The return values are the same as for the sys_arch_sem_wait() function:
|
|
Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
|
|
timeout.
|
|
|
|
Note that a function with a similar name, sys_mbox_fetch(), is
|
|
implemented by lwIP.
|
|
* @param mb mbox struct pointer
|
|
* @param msg for mailbox to post
|
|
* @param timeout fetch msg in time
|
|
* @return time has wait
|
|
*/
|
|
u32_t sys_arch_mbox_fetch(sys_mbox_t *mb, void **msg, u32_t timeout)
|
|
{
|
|
u32_t time_needed = 0;
|
|
struct sys_mbox *mbox;
|
|
LWIP_ASSERT("invalid mbox", (mb != NULL));
|
|
mbox = *mb;
|
|
|
|
/* The mutex lock is quick so we don't bother with the timeout
|
|
stuff here. */
|
|
sys_arch_sem_wait(&mbox->mutex, 0);
|
|
|
|
while (mbox->first == mbox->last) {
|
|
sys_sem_signal(&mbox->mutex);
|
|
|
|
/* We block while waiting for a mail to arrive in the mailbox. We
|
|
must be prepared to timeout. */
|
|
if (timeout != 0) {
|
|
time_needed = sys_arch_sem_wait(&mbox->not_empty, timeout);
|
|
|
|
if (time_needed == SYS_ARCH_TIMEOUT) {
|
|
return SYS_ARCH_TIMEOUT;
|
|
}
|
|
} else {
|
|
sys_arch_sem_wait(&mbox->not_empty, 0);
|
|
}
|
|
|
|
sys_arch_sem_wait(&mbox->mutex, 0);
|
|
}
|
|
|
|
if (msg != NULL) {
|
|
LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg));
|
|
*msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
|
|
} else {
|
|
LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox));
|
|
}
|
|
|
|
mbox->first++;
|
|
|
|
if (mbox->wait_send) {
|
|
sys_sem_signal(&mbox->not_full);
|
|
}
|
|
|
|
sys_sem_signal(&mbox->mutex);
|
|
|
|
return time_needed;
|
|
}
|
|
|
|
/**
|
|
* @brief similar to sys_arch_mbox_fetch, however if a message is not present in the mailbox,
|
|
it immediately returns with the code SYS_MBOX_EMPTY.
|
|
* @param mb mbox struct pointer
|
|
* @param msg for mailbox to post
|
|
* @return 0 OK
|
|
* -1 ERR
|
|
*/
|
|
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mb, void **msg)
|
|
{
|
|
struct sys_mbox *mbox;
|
|
LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
|
|
mbox = *mb;
|
|
|
|
sys_arch_sem_wait(&mbox->mutex, 0);
|
|
|
|
if (mbox->first == mbox->last) {
|
|
sys_sem_signal(&mbox->mutex);
|
|
return SYS_MBOX_EMPTY;
|
|
}
|
|
|
|
if (msg != NULL) {
|
|
LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg));
|
|
*msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
|
|
} else {
|
|
LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox));
|
|
}
|
|
|
|
mbox->first++;
|
|
|
|
if (mbox->wait_send) {
|
|
sys_sem_signal(&mbox->not_full);
|
|
}
|
|
|
|
sys_sem_signal(&mbox->mutex);
|
|
|
|
return 0;
|
|
}
|
|
#else
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Creates an empty mailbox for maximum "size" elements.
|
|
* @param mb mbox struct pointer
|
|
* @param size
|
|
* @return 0 OK
|
|
* -1 ERR
|
|
*/
|
|
err_t sys_mbox_new(sys_mbox_t *mb, int size)
|
|
{
|
|
void *msg_start;
|
|
err_t ret = ERR_MEM;
|
|
|
|
msg_start = (void *)malloc(size * sizeof(void *));
|
|
|
|
if (msg_start == NULL) {
|
|
return ERR_MEM;
|
|
}
|
|
|
|
int stat = aos_queue_new(mb, msg_start, size * sizeof(void *), sizeof(void *));
|
|
|
|
if (stat == 0) {
|
|
ret = ERR_OK;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Deallocates a mailbox. If there are messages still present in the
|
|
mailbox when the mailbox is deallocated, it is an indication of a
|
|
programming error in lwIP and the developer should be notified.
|
|
* @param mb mbox struct pointer
|
|
* @return null
|
|
*/
|
|
void sys_mbox_free(sys_mbox_t *mb)
|
|
{
|
|
void *start;
|
|
|
|
if ((mb != NULL)) {
|
|
start = aos_queue_buf_ptr(mb);
|
|
|
|
if (start != NULL) {
|
|
free(start);
|
|
}
|
|
|
|
aos_queue_free(mb);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Posts the "msg" to the mailbox. This function have to block until the "msg" is really posted.
|
|
* @param mb mbox struct pointer
|
|
* @param msg for mailbox to post
|
|
* @return null
|
|
*/
|
|
void sys_mbox_post(sys_mbox_t *mb, void *msg)
|
|
{
|
|
int rc, cnt = 0;
|
|
|
|
//FIXME:
|
|
for (;;) {
|
|
rc = aos_queue_send(mb, &msg, sizeof(void *));
|
|
if (rc == 0) {
|
|
break;
|
|
} else {
|
|
if (cnt++ % 50 == 0)
|
|
printf("tcp ip post send fail, queue may be full, cnt = %d, rc = %d, mb = %p\n", cnt, rc, mb);
|
|
aos_msleep(20);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Try to post the "msg" to the mailbox. Returns ERR_MEM if this one is full, else, ERR_OK if the "msg" is posted.
|
|
* @param mb mbox struct pointer
|
|
* @param msg for mailbox to post
|
|
* @return 0 OK
|
|
* -1 ERR
|
|
*/
|
|
err_t sys_mbox_trypost(sys_mbox_t *mb, void *msg)
|
|
{
|
|
if (aos_queue_send(mb, &msg, sizeof(void *)) != 0) {
|
|
return ERR_MEM;
|
|
} else {
|
|
return ERR_OK;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/*
|
|
@brief Blocks the thread until a message arrives in the mailbox, but does
|
|
not block the thread longer than "timeout" milliseconds (similar to
|
|
the sys_arch_sem_wait() function). The "msg" argument is a result
|
|
parameter that is set by the function (i.e., by doing "*msg =
|
|
ptr"). The "msg" parameter maybe NULL to indicate that the message
|
|
should be dropped.
|
|
|
|
The return values are the same as for the sys_arch_sem_wait() function:
|
|
Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
|
|
timeout.
|
|
|
|
Note that a function with a similar name, sys_mbox_fetch(), is
|
|
implemented by lwIP.
|
|
* @param mb mbox struct pointer
|
|
* @param msg for mailbox to post
|
|
* @param timeout fetch msg in time
|
|
* @return time has wait
|
|
*/
|
|
u32_t sys_arch_mbox_fetch(sys_mbox_t *mb, void **msg, u32_t timeout)
|
|
{
|
|
size_t len;
|
|
u32_t ret;
|
|
u32_t begin_ms, end_ms, elapsed_ms;
|
|
|
|
if (mb == NULL) {
|
|
return SYS_ARCH_TIMEOUT;
|
|
}
|
|
|
|
begin_ms = sys_now();
|
|
|
|
if (timeout != 0UL) {
|
|
|
|
if (aos_queue_recv(mb, timeout, msg, &len) == 0) {
|
|
end_ms = sys_now();
|
|
elapsed_ms = end_ms - begin_ms;
|
|
ret = elapsed_ms;
|
|
} else {
|
|
ret = SYS_ARCH_TIMEOUT;
|
|
}
|
|
} else {
|
|
while (aos_queue_recv(mb, AOS_WAIT_FOREVER, msg, &len) != 0);
|
|
|
|
end_ms = sys_now();
|
|
elapsed_ms = end_ms - begin_ms;
|
|
|
|
if (elapsed_ms == 0UL) {
|
|
elapsed_ms = 1UL;
|
|
}
|
|
|
|
ret = elapsed_ms;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief similar to sys_arch_mbox_fetch, however if a message is not present in the mailbox,
|
|
it immediately returns with the code SYS_MBOX_EMPTY.
|
|
* @param mb mbox struct pointer
|
|
* @param msg for mailbox to post
|
|
* @return 0 OK
|
|
* -1 ERR
|
|
*/
|
|
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mb, void **msg)
|
|
{
|
|
size_t len;
|
|
|
|
if (aos_queue_recv(mb, 0u, msg, &len) != 0) {
|
|
return SYS_MBOX_EMPTY;
|
|
} else {
|
|
return ERR_OK;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief Create a new mutex
|
|
* @param mutex pointer to the mutex to create
|
|
* @return status of create new mutex
|
|
* 0 OK
|
|
* -1 ERR
|
|
*/
|
|
err_t sys_mutex_new(sys_mutex_t *mutex)
|
|
{
|
|
err_t ret = ERR_MEM;
|
|
int stat = aos_mutex_new(mutex);
|
|
|
|
if (stat == 0) {
|
|
ret = ERR_OK;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Lock a mutex
|
|
* @param mutex the mutex to lock
|
|
* @return null
|
|
*/
|
|
void sys_mutex_lock(sys_mutex_t *mutex)
|
|
{
|
|
aos_mutex_lock(mutex, AOS_WAIT_FOREVER);
|
|
}
|
|
|
|
/**
|
|
* @brief Unlock a mutex
|
|
* @param mutex the mutex to lock
|
|
* @return null
|
|
*/
|
|
void sys_mutex_unlock(sys_mutex_t *mutex)
|
|
{
|
|
aos_mutex_unlock(mutex);
|
|
}
|
|
|
|
/**
|
|
* @brief Delete a mutex
|
|
* @param mutex the mutex to lock
|
|
* @return null
|
|
**/
|
|
void sys_mutex_free(sys_mutex_t *mutex)
|
|
{
|
|
if ((mutex != NULL)) {
|
|
aos_mutex_free(mutex);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief This optional function returns the current time in seconds (don't care for wraparound,
|
|
* this is only used for time diffs).
|
|
* @param null
|
|
* @return the current time
|
|
*/
|
|
u32_t sys_now(void)
|
|
{
|
|
return aos_now_ms();
|
|
}
|
|
|
|
/**
|
|
* Ticks/jiffies since power up.
|
|
*/
|
|
u32_t sys_jiffies(void)
|
|
{
|
|
return aos_now();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief Starts a new thread with priority "prio" that will begin its execution in the
|
|
* function "thread()". The "arg" argument will be passed as an argument to the
|
|
* thread() function. The id of the new thread is returned. Both the id and
|
|
* the priority are system dependent.
|
|
* @param name thread name
|
|
* @param thread thread function
|
|
* @param arg thread arg
|
|
* @param stacksize thread stacksize
|
|
* @param prio thread prio
|
|
* @return the status of create new thread
|
|
* 0 OK
|
|
* -1 ERR
|
|
*/
|
|
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
|
|
{
|
|
aos_task_t task;
|
|
|
|
int stat = aos_task_new_ext(&task, name, thread, arg, stacksize, prio);
|
|
|
|
if (stat != 0) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if SYS_LIGHTWEIGHT_PROT
|
|
/*
|
|
This optional function does a "fast" critical region protection and returns
|
|
the previous protection level. This function is only called during very short
|
|
critical regions. An embedded system which supports ISR-based drivers might
|
|
want to implement this function by disabling interrupts. Task-based systems
|
|
might want to implement this by using a mutex or disabling tasking. This
|
|
function should support recursive calls from the same task or interrupt. In
|
|
other words, sys_arch_protect() could be called while already protected. In
|
|
that case the return value indicates that it is already protected.
|
|
|
|
sys_arch_protect() is only required if your port is supporting an operating
|
|
system.
|
|
*/
|
|
sys_prot_t sys_arch_protect(void)
|
|
{
|
|
aos_mutex_lock(&sys_arch_mutex, AOS_WAIT_FOREVER);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
This optional function does a "fast" set of critical region protection to the
|
|
value specified by pval. See the documentation for sys_arch_protect() for
|
|
more information. This function is only required if your port is supporting
|
|
an operating system.
|
|
*/
|
|
void sys_arch_unprotect(sys_prot_t pval)
|
|
{
|
|
LWIP_UNUSED_ARG(pval);
|
|
|
|
aos_mutex_unlock(&sys_arch_mutex);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief Prints an assertion messages and aborts execution.
|
|
* @param null
|
|
* @return null
|
|
*/
|
|
void sys_arch_assert(const char *f, const int l)
|
|
{
|
|
printf("LWIP Assert %s:%d\n", f, l);
|
|
fflush(NULL);
|
|
abort();
|
|
}
|
|
|
|
/**
|
|
* @brief Is called to initialize the sys_arch layer.
|
|
* @param null
|
|
* @return null
|
|
*/
|
|
void sys_init(void)
|
|
{
|
|
if (!aos_mutex_is_valid(&sys_arch_mutex))
|
|
aos_mutex_new(&sys_arch_mutex);
|
|
}
|
|
|
|
#if LWIP_NETCONN_SEM_PER_THREAD
|
|
#ifndef LWIP_USER_INFO_POS
|
|
#define LWIP_USER_INFO_POS 0
|
|
#endif
|
|
#include <k_api.h>
|
|
// need RHINO_CONFIG_TASK_INFO_NUM > 3
|
|
typedef struct _sys_sem_cb {
|
|
slist_t next;
|
|
void *task_hdl;
|
|
sys_sem_t *sys_sem;
|
|
} sys_sem_cb_t;
|
|
|
|
/*
|
|
* get per thread semphore
|
|
*/
|
|
sys_sem_t* sys_thread_sem_get(void)
|
|
{
|
|
return krhino_cur_task_get()->user_info[LWIP_USER_INFO_POS];
|
|
}
|
|
|
|
sys_sem_t* sys_thread_sem_init(void)
|
|
{
|
|
sys_sem_t *sem;
|
|
int ret;
|
|
|
|
sem = aos_malloc_check(sizeof(sys_sem_t));
|
|
ret = sys_sem_new(sem, 0);
|
|
aos_check(!ret, ERR_MEM);
|
|
|
|
return sem;
|
|
}
|
|
|
|
void sys_thread_sem_deinit(void)
|
|
{
|
|
// sched suspend here, because sys_sem_free will core_sched and cause mem leak
|
|
aos_kernel_sched_suspend();
|
|
sys_sem_t *sem = krhino_cur_task_get()->user_info[LWIP_USER_INFO_POS];
|
|
|
|
sys_sem_free(sem);
|
|
|
|
aos_free(sem);
|
|
aos_kernel_sched_resume();
|
|
}
|
|
|
|
void krhino_task_create_hook_lwip_thread_sem(ktask_t *task)
|
|
{
|
|
task->user_info[LWIP_USER_INFO_POS] = sys_thread_sem_init();
|
|
}
|
|
|
|
void krhino_task_del_hook_lwip_thread_sem(ktask_t *task, res_free_t *arg)
|
|
{
|
|
// sched suspend here, because sys_sem_free will core_sched and cause mem leak
|
|
aos_kernel_sched_suspend();
|
|
sys_sem_t *sem = task->user_info[LWIP_USER_INFO_POS];
|
|
|
|
sys_sem_free(sem);
|
|
|
|
aos_free(sem);
|
|
aos_kernel_sched_resume();
|
|
}
|
|
#endif
|