1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: implementation for mbox, ticks and memory adaptor
15 * Author: none
16 * Create: 2020
17 */
18
19 #include "lwip/opt.h"
20 #include "lwip/debug.h"
21 #include "lwip/def.h"
22 #include "lwip/sys.h"
23 #include "lwip/mem.h"
24 #include "lwip/stats.h"
25
26 #include "los_config.h"
27 #include "arch/sys_arch.h"
28 #include "linux/wait.h"
29 #include "los_sem.h"
30 #include "los_mux.h"
31 #include "string.h"
32 #include "stdlib.h"
33
34 #ifndef UNUSED
35 #define UNUSED(a) ((void)(a))
36 #endif
37
38 #define LWIP_SEM_ID(x) (u32_t)(uintptr_t)((x)->sem)
39
40 #define MBOX_EXPAND_MULTIPLE_SIZE 2
41
42 #if defined(LOSCFG_KERNEL_SMP) && defined(YES) && (LOSCFG_KERNEL_SMP == YES)
43 SPIN_LOCK_INIT(arch_protect_spin);
44 static u32_t lwprot_thread = LOS_ERRNO_TSK_ID_INVALID;
45 static int lwprot_count = 0;
46 #endif /* LOSCFG_KERNEL_SMP == YES */
47
sys_mbox_new_ext(struct sys_mbox ** mb,int size,unsigned char is_auto_expand)48 err_t sys_mbox_new_ext(struct sys_mbox **mb, int size, unsigned char is_auto_expand)
49 {
50 struct sys_mbox *mbox = NULL;
51 int ret;
52
53 if (size <= 0) {
54 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_new: mbox size must bigger than 0\n"));
55 return ERR_VAL;
56 }
57
58 mbox = (struct sys_mbox *)mem_malloc(sizeof(struct sys_mbox));
59 if (mbox == NULL) {
60 goto err_handler;
61 }
62
63 (void)memset_s(mbox, sizeof(struct sys_mbox), 0, sizeof(struct sys_mbox));
64
65 mbox->msgs = (void **)mem_malloc(sizeof(void *) * size);
66 if (mbox->msgs == NULL) {
67 goto err_handler;
68 }
69
70 (void)memset_s(mbox->msgs, (sizeof(void *) * size), 0, (sizeof(void*) * size));
71
72 mbox->mbox_size = size;
73
74 mbox->first = 0;
75 mbox->last = 0;
76 mbox->is_full = 0;
77 mbox->is_empty = 1;
78 mbox->is_autoexpand = is_auto_expand;
79
80 ret = osal_mutex_init(&(mbox->mutex));
81 if (ret != 0) {
82 goto err_handler;
83 }
84
85 ret = osal_wait_init(&(mbox->not_empty));
86 if (ret != 0) {
87 (void)osal_mutex_destroy(&(mbox->mutex));
88 goto err_handler;
89 }
90
91 ret = osal_wait_init(&(mbox->not_full));
92 if (ret != 0) {
93 (void)osal_mutex_destroy(&(mbox->mutex));
94 (void)osal_wait_destroy(&(mbox->not_empty));
95 goto err_handler;
96 }
97
98 SYS_STATS_INC_USED(mbox);
99 *mb = mbox;
100 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_new: mbox created successfully 0x%p\n", (void *)mbox));
101 return ERR_OK;
102
103 err_handler:
104 if (mbox != NULL) {
105 if (mbox->msgs != NULL) {
106 mem_free(mbox->msgs);
107 mbox->msgs = NULL;
108 }
109 mem_free(mbox);
110 }
111 return ERR_MEM;
112 }
113
114 /*-----------------------------------------------------------------------------------*/
sys_mbox_free(struct sys_mbox ** mb)115 void sys_mbox_free(struct sys_mbox **mb)
116 {
117 if ((mb != NULL) && (*mb != SYS_MBOX_NULL)) {
118 struct sys_mbox *mbox = *mb;
119 int ret;
120 SYS_STATS_DEC(mbox.used);
121
122 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_free: going to free mbox 0x%p\n", (void *)mbox));
123
124 ret = osal_mutex_lock(&(mbox->mutex));
125 if (ret != 0) {
126 return;
127 }
128
129 (void)osal_wait_destroy(&(mbox->not_empty));
130 (void)osal_wait_destroy(&(mbox->not_full));
131
132 (void)osal_mutex_unlock(&(mbox->mutex));
133
134 (void)osal_mutex_destroy(&(mbox->mutex));
135
136 mem_free(mbox->msgs);
137 mbox->msgs = NULL;
138 mem_free(mbox);
139 *mb = NULL;
140
141 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_free: freed mbox\n"));
142 }
143 }
144
145 static unsigned char
sys_mbox_auto_expand(struct sys_mbox * mbox)146 sys_mbox_auto_expand(struct sys_mbox *mbox)
147 {
148 unsigned char is_expanded = 0;
149 void **realloc_msgs = NULL;
150 if ((mbox->is_autoexpand == MBOX_AUTO_EXPAND) &&
151 (MBOX_EXPAND_MULTIPLE_SIZE * (u32_t)mbox->mbox_size) <= MAX_MBOX_SIZE) {
152 realloc_msgs = mem_malloc(MBOX_EXPAND_MULTIPLE_SIZE * sizeof(void *) * (u32_t)mbox->mbox_size);
153 if (realloc_msgs != NULL) {
154 /* memcpy_s */
155 if (mbox->first > 0) {
156 (void)memcpy_s(realloc_msgs,
157 sizeof(void *) * (mbox->mbox_size - mbox->first),
158 mbox->msgs + mbox->first,
159 sizeof(void *) * (mbox->mbox_size - mbox->first));
160 (void)memcpy_s(realloc_msgs + (mbox->mbox_size - mbox->first),
161 sizeof(void *) * (mbox->last),
162 mbox->msgs,
163 sizeof(void *) * (mbox->last));
164 } else {
165 (void)memcpy_s(realloc_msgs, sizeof(void *) * mbox->mbox_size,
166 mbox->msgs, sizeof(void *) * mbox->mbox_size);
167 }
168 mem_free(mbox->msgs);
169 mbox->msgs = realloc_msgs;
170 mbox->first = 0;
171 mbox->last = mbox->mbox_size;
172 mbox->mbox_size *= MBOX_EXPAND_MULTIPLE_SIZE;
173 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post : mbox 0x%p is auto expanded\n", (void *)mbox));
174 is_expanded = 1;
175 }
176 }
177 return is_expanded;
178 }
179
lwip_wait_mbox_full_func(struct sys_mbox * mbox)180 int lwip_wait_mbox_full_func(struct sys_mbox *mbox)
181 {
182 int ret;
183 ret = !(mbox->is_full == 1);
184 return ret;
185 }
186
187 /*
188 * Routine: sys_mbox_post
189 *
190 * Description:
191 * Post the "msg" to the mailbox.
192 * Inputs:
193 * sys_mbox_t mbox -- Handle of mailbox
194 * void *msg -- Pointer to data to post
195 */
sys_mbox_post(struct sys_mbox ** mb,void * msg)196 void sys_mbox_post(struct sys_mbox **mb, void *msg)
197 {
198 struct sys_mbox *mbox = NULL;
199 int ret;
200 if ((mb == NULL) || (*mb == NULL)) {
201 return;
202 }
203 mbox = *mb;
204 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox 0x%p msg 0x%p\n", (void *)mbox, (void *)msg));
205
206 ret = osal_mutex_lock(&(mbox->mutex));
207 if (ret != 0) {
208 return;
209 }
210
211 while (mbox->is_full == 1) {
212 (void)osal_mutex_unlock(&(mbox->mutex));
213 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post : mbox 0x%p mbox 0x%p, queue is full\n", (void *)mbox, (void *)msg));
214 ret = osal_wait_interruptible(&(mbox->not_full), (osal_wait_condition_func)lwip_wait_mbox_full_func, mbox);
215 if (ret != 0) {
216 return;
217 }
218 (void)osal_mutex_lock(&(mbox->mutex));
219 }
220
221 mbox->msgs[mbox->last] = msg;
222
223 mbox->last++;
224 if (mbox->last == mbox->mbox_size) {
225 mbox->last = 0;
226 }
227
228 if (mbox->first == mbox->last) {
229 if (sys_mbox_auto_expand(mbox) == 0) {
230 mbox->is_full = 1;
231 }
232 }
233
234 if (mbox->is_empty == 1) {
235 mbox->is_empty = 0;
236 (void)osal_wait_wakeup(&(mbox->not_empty)); /* if signal failed, anyway it will unlock and go out */
237 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post : mbox 0x%p msg 0x%p, signalling not empty\n", (void *)mbox, (void *)msg));
238 }
239 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox 0x%p msg 0%p posted\n", (void *)mbox, (void *)msg));
240 (void)osal_mutex_unlock(&(mbox->mutex));
241 }
242
243 /*
244 * Routine: sys_mbox_trypost
245 *
246 * Description:
247 * Try to post the "msg" to the mailbox. Returns immediately with
248 * error if cannot.
249 * Inputs:
250 * sys_mbox_t mbox -- Handle of mailbox
251 * void *msg -- Pointer to data to post
252 * Outputs:
253 * err_t -- ERR_OK if message posted, else ERR_MEM
254 * if not.
255 */
sys_mbox_trypost(struct sys_mbox ** mb,void * msg)256 err_t sys_mbox_trypost(struct sys_mbox **mb, void *msg)
257 {
258 struct sys_mbox *mbox = NULL;
259 int ret;
260 mbox = *mb;
261
262 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox 0x%p msg 0x%p \n", (void *)mbox, (void *)msg));
263
264 ret = osal_mutex_lock(&(mbox->mutex));
265 if (ret != 0) {
266 return ERR_MEM;
267 }
268
269 if (mbox->is_full == 1) {
270 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost : mbox 0x%p msgx 0x%p,queue is full\n", (void *)mbox, (void *)msg));
271 (void)osal_mutex_unlock(&(mbox->mutex));
272 return ERR_MEM;
273 }
274
275 mbox->msgs[mbox->last] = msg;
276
277 mbox->last = (mbox->mbox_size - 1 - mbox->last) ? (mbox->last + 1) : 0;
278
279 if (mbox->first == mbox->last) {
280 if (sys_mbox_auto_expand(mbox) == 0) {
281 mbox->is_full = 1;
282 }
283 }
284
285 if (mbox->is_empty) {
286 mbox->is_empty = 0;
287 (void)osal_wait_wakeup(&(mbox->not_empty));
288 }
289 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox 0x%p msg 0x%p posted\n", (void *)mbox, (void *)msg));
290 (void)osal_mutex_unlock(&(mbox->mutex));
291 return ERR_OK;
292 }
293
lwip_wait_mbox_empty_func(struct sys_mbox * mbox)294 int lwip_wait_mbox_empty_func(struct sys_mbox *mbox)
295 {
296 int ret;
297 ret = !(mbox->is_empty == 1);
298 return ret;
299 }
300
301 static u32_t
sys_arch_mbox_handler_timeouts(struct sys_mbox * mbox,u32_t timeout,u8_t ignore_timeout)302 sys_arch_mbox_handler_timeouts(struct sys_mbox *mbox, u32_t timeout, u8_t ignore_timeout)
303 {
304 struct timespec tmsp;
305 int ret;
306 #if LWIP_USE_POSIX_COND_WAIT_WITH_ABS_TIMEOUT
307 struct timeval tv;
308 #endif /* LWIP_USE_POSIX_COND_WAIT_WITH_ABS_TIMEOUT */
309 if (mbox->is_empty && ignore_timeout) {
310 return SYS_ARCH_TIMEOUT;
311 }
312
313 while ((mbox->is_empty == 1) && (ignore_timeout == 0)) {
314 if (timeout != 0) {
315 #if LWIP_USE_POSIX_COND_WAIT_WITH_ABS_TIMEOUT
316 gettimeofday(&tv, NULL);
317 tmsp.tv_sec = tv.tv_sec + (timeout / MS_PER_SECOND);
318 tmsp.tv_nsec = (tv.tv_usec * NS_PER_USECOND) + ((timeout % US_PER_MSECOND) * US_PER_MSECOND * NS_PER_USECOND);
319 tmsp.tv_sec += tmsp.tv_nsec / (NS_PER_USECOND * US_PER_MSECOND * MS_PER_SECOND);
320 tmsp.tv_nsec %= (NS_PER_USECOND * US_PER_MSECOND * MS_PER_SECOND);
321 #else
322 tmsp.tv_sec = (timeout / MS_PER_SECOND);
323 tmsp.tv_nsec = ((timeout % US_PER_MSECOND) * US_PER_MSECOND * NS_PER_USECOND);
324 #endif
325 osal_mutex_unlock(&(mbox->mutex));
326 ret = osal_wait_timeout_interruptible(&(mbox->not_empty), (osal_wait_condition_func)lwip_wait_mbox_empty_func,
327 mbox, timeout);
328 osal_mutex_lock(&(mbox->mutex));
329 if (ret == 0) {
330 LWIP_DEBUGF(SYS_DEBUG, ("sys_arch_mbox_fetch: mbox 0x%p,timeout in cond wait\n", (void *)mbox));
331 return SYS_ARCH_TIMEOUT;
332 }
333 } else {
334 LWIP_DEBUGF(SYS_DEBUG, ("sys_arch_mbox_fetch: cond wait\n"));
335 osal_mutex_unlock(&(mbox->mutex));
336 ret = osal_wait_interruptible(&(mbox->not_empty), (osal_wait_condition_func)lwip_wait_mbox_empty_func, mbox);
337 osal_mutex_lock(&(mbox->mutex));
338 if (ret < 0) {
339 return SYS_ARCH_TIMEOUT;
340 }
341 }
342 }
343 return ERR_OK;
344 }
345
sys_arch_mbox_fetch_ext(struct sys_mbox ** mb,void ** msg,u32_t timeout,u8_t ignore_timeout)346 u32_t sys_arch_mbox_fetch_ext(struct sys_mbox **mb, void **msg, u32_t timeout, u8_t ignore_timeout)
347 {
348 struct sys_mbox *mbox = NULL;
349 #if LWIP_USE_POSIX_COND_WAIT_WITH_ABS_TIMEOUT
350 struct timeval tv;
351 #endif /* LWIP_USE_POSIX_COND_WAIT_WITH_ABS_TIMEOUT */
352 int ret;
353 mbox = *mb;
354
355 LWIP_DEBUGF(SYS_DEBUG, ("sys_arch_mbox_fetch: mbox 0x%p msg 0x%p\n", (void *)mbox, (void *)msg));
356
357 /* The mutex lock is quick so we don't bother with the timeout stuff here. */
358 ret = osal_mutex_lock(&(mbox->mutex));
359 if (ret != 0) {
360 return SYS_ARCH_TIMEOUT;
361 }
362 u32_t timeouts = sys_arch_mbox_handler_timeouts(mbox, timeout, ignore_timeout);
363 if (timeouts != ERR_OK) {
364 (void)osal_mutex_unlock(&(mbox->mutex));
365 return SYS_ARCH_TIMEOUT;
366 }
367
368 if (msg != NULL) {
369 *msg = mbox->msgs[mbox->first];
370 LWIP_DEBUGF(SYS_DEBUG, ("sys_arch_mbox_fetch: mbox 0x%p msg 0x%p\n", (void *)mbox, (void *)*msg));
371 } else {
372 LWIP_DEBUGF(SYS_DEBUG, ("sys_arch_mbox_fetch: mbox 0x%p, null msg\n", (void *)mbox));
373 }
374
375 mbox->first = (mbox->mbox_size - 1 - mbox->first) ? (mbox->first + 1) : 0;
376
377 if (mbox->first == mbox->last) {
378 mbox->is_empty = 1;
379 }
380
381 if (mbox->is_full) {
382 mbox->is_full = 0;
383 (void)osal_wait_wakeup(&(mbox->not_full));
384 }
385 LWIP_DEBUGF(SYS_DEBUG, ("sys_arch_mbox_fetch: mbox 0x%p msg 0x%p fetched\n", (void *)mbox, (void *)msg));
386 (void)osal_mutex_unlock(&(mbox->mutex));
387
388 return 0;
389 }
390
391 /*
392 * Routine: sys_init
393 *
394 * Description:
395 * Initialize sys arch
396 */
sys_init(void)397 void sys_init(void)
398 {
399 /* set rand seed to make random sequence diff on every startup */
400 extern VOID LOS_GetCpuCycle(UINT32 *puwCntHi, UINT32 *puwCntLo);
401 u32_t seedhsb, seedlsb;
402 LOS_GetCpuCycle(&seedhsb, &seedlsb);
403 srand(seedlsb);
404 }
405
406
407 /*
408 * Routine: sys_arch_protect
409 *
410 * Description:
411 * This optional function does a "fast" critical region protection and
412 * returns the previous protection level. This function is only called
413 * during very short critical regions. An embedded system which supports
414 * ISR-based drivers might want to implement this function by disabling
415 * interrupts. Task-based systems might want to implement this by using
416 * a mutex or disabling tasking. This function should support recursive
417 * calls from the same task or interrupt. In other words,
418 * sys_arch_protect() could be called while already protected. In
419 * that case the return value indicates that it is already protected.
420 *
421 * sys_arch_protect() is only required if your port is supporting an
422 * OS.
423 * Outputs:
424 * sys_prot_t -- Previous protection level (not used here)
425 */
sys_arch_protect(void)426 sys_prot_t sys_arch_protect(void)
427 {
428 #if defined(LOSCFG_KERNEL_SMP) && defined(YES) && (LOSCFG_KERNEL_SMP == YES)
429 /* Note that we are using spinlock instead of mutex for LiteOS-SMP here:
430 * 1. spinlock is more effective for short critical region protection.
431 * 2. this function is called only in task context, not in interrupt handler.
432 * so it's not needed to disable interrupt.
433 */
434 if (lwprot_thread != LOS_CurTaskIDGet()) {
435 /* We are locking the spinlock where it has not been locked before
436 * or is being locked by another thread */
437 LOS_SpinLock(&arch_protect_spin);
438 lwprot_thread = LOS_CurTaskIDGet();
439 lwprot_count = 1;
440 } else {
441 /* It is already locked by THIS thread */
442 lwprot_count++;
443 }
444 #else
445 LOS_TaskLock();
446 #endif /* LOSCFG_KERNEL_SMP == YES */
447
448 return 0;
449 }
450
451
452 /*
453 * Routine: sys_arch_unprotect
454 *
455 * Description:
456 * This optional function does a "fast" set of critical region
457 * protection to the value specified by pval. See the documentation for
458 * sys_arch_protect() for more information. This function is only
459 * required if your port is supporting an OS.
460 * Inputs:
461 * sys_prot_t -- Previous protection level (not used here)
462 */
sys_arch_unprotect(sys_prot_t pval)463 void sys_arch_unprotect(sys_prot_t pval)
464 {
465 LWIP_UNUSED_ARG(pval);
466 #if defined(LOSCFG_KERNEL_SMP) && defined(YES) && (LOSCFG_KERNEL_SMP == YES)
467 if (lwprot_thread == LOS_CurTaskIDGet()) {
468 lwprot_count--;
469 if (lwprot_count == 0) {
470 lwprot_thread = LOS_ERRNO_TSK_ID_INVALID;
471 LOS_SpinUnlock(&arch_protect_spin);
472 }
473 }
474 #else
475 LOS_TaskUnlock();
476 #endif /* LOSCFG_KERNEL_SMP == YES */
477 }
478
sys_now(void)479 u32_t sys_now(void)
480 {
481 /* Lwip docs mentioned like wraparound is not a problem in this funtion */
482 return (u32_t)((LOS_TickCountGet() * 1000) / LOSCFG_BASE_CORE_TICK_PER_SECOND);
483 }
484
sys_thread_new(const char * name,lwip_thread_fn function,void * arg,int stacksize,int prio)485 sys_thread_t sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio)
486 {
487 TSK_INIT_PARAM_S task;
488 UINT32 taskid, ret;
489 (void)memset_s(&task, sizeof(task), 0, sizeof(task));
490
491 /* Create host Task */
492 task.pfnTaskEntry = (TSK_ENTRY_FUNC)function;
493 task.uwStackSize = 4096; /* 任务栈大小设定为4096 */
494 task.pcName = (char *)name;
495 task.usTaskPrio = prio;
496 task.uwResved = LOS_TASK_STATUS_DETACHED;
497 #ifdef BR_HW_LITEOS_VERSION
498 LOS_TASK_PARAM_INIT_ARG(task, arg);
499 #else
500 task.auwArgs[0] = (UINTPTR)arg;
501 #endif
502 ret = LOS_TaskCreate(&taskid, &task);
503 if (ret != LOS_OK) {
504 LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: LOS_TaskCreate error %u\n", ret));
505 return SYS_ARCH_ERROR;
506 }
507 (void)stacksize;
508 return taskid;
509 }
510
511 #ifdef LWIP_DEBUG
512 /* \brief Displays an error message on assertion
513
514 This function will display an error message on an assertion
515 to the dbg output.
516
517 \param[in] msg Error message to display
518 \param[in] line Line number in file with error
519 \param[in] file Filename with error
520 */
assert_printf(char * msg,int line,char * file)521 void assert_printf(char *msg, int line, char *file)
522 {
523 if (msg != NULL) {
524 LWIP_DEBUGF(LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
525 ("%s:%d in file %s", msg, line, file));
526 return;
527 } else {
528 LWIP_DEBUGF(LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
529 ("LWIP ASSERT"));
530 return;
531 }
532 }
533 #endif /* LWIP_DEBUG */
534
535
536 /*
537 * Routine: sys_sem_new
538 *
539 * Description:
540 * Creates and returns a new semaphore. The "ucCount" argument specifies
541 * the initial state of the semaphore.
542 * NOTE: Currently this routine only creates counts of 1 or 0
543 * Inputs:
544 * sys_sem_t sem -- Handle of semaphore
545 * u8_t count -- Initial count of semaphore
546 * Outputs:
547 * err_t -- ERR_OK if semaphore created
548 */
sys_sem_new(sys_sem_t * sem,u8_t count)549 err_t sys_sem_new(sys_sem_t *sem, u8_t count)
550 {
551 u32_t sem_handle;
552 u32_t ret;
553
554 if (sem == NULL) {
555 return -1;
556 }
557
558 LWIP_ASSERT("in sys_sem_new count exceeds the limit", (count < 0xFF));
559
560 ret = LOS_SemCreate(count, &sem_handle);
561 if (ret != ERR_OK) {
562 return -1;
563 }
564
565 sem->sem = (void *)(uintptr_t)(sem_handle);
566
567 return ERR_OK;
568 }
569
570 /*
571 * Routine: sys_arch_sem_wait
572 *
573 * Description:
574 * Blocks the thread while waiting for the semaphore to be
575 * signaled. If the "timeout" argument is non-zero, the thread should
576 * only be blocked for the specified time (measured in
577 * milliseconds).
578 *
579 * If the timeout argument is non-zero, the return value is the number of
580 * milliseconds spent waiting for the semaphore to be signaled. If the
581 * semaphore wasn't signaled within the specified time, the return value is
582 * SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
583 * (i.e., it was already signaled), the function may return zero.
584 *
585 * Notice that lwIP implements a function with a similar name,
586 * sys_sem_wait(), that uses the sys_arch_sem_wait() function.
587 * Inputs:
588 * sys_sem_t sem -- Semaphore to wait on
589 * u32_t timeout -- Number of milliseconds until timeout
590 * Outputs:
591 * u32_t -- Time elapsed or SYS_ARCH_TIMEOUT.
592 */
sys_arch_sem_wait(sys_sem_t * sem,u32_t timeout)593 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
594 {
595 u32_t retval;
596 u64_t start_tick;
597 u64_t end_tick;
598
599 if ((sem == NULL) || (sem->sem == NULL)) {
600 return SYS_ARCH_ERROR;
601 }
602
603 start_tick = LOS_TickCountGet();
604
605 if (timeout == 0) {
606 timeout = LOS_WAIT_FOREVER;
607 } else {
608 timeout = LOS_MS2Tick(timeout);
609 if (!timeout) {
610 timeout = 1;
611 }
612 }
613 retval = LOS_SemPend(LWIP_SEM_ID(sem), timeout);
614 if (retval == LOS_ERRNO_SEM_TIMEOUT) {
615 return SYS_ARCH_TIMEOUT;
616 }
617 if (retval != ERR_OK) {
618 return SYS_ARCH_ERROR;
619 }
620
621 end_tick = LOS_TickCountGet();
622 /* Here milli second will not come more than 32 bit because timeout received as 32 bit millisecond only */
623 return (u32_t)(((end_tick - start_tick) * 1000) / LOSCFG_BASE_CORE_TICK_PER_SECOND);
624 }
625
626
627 /*
628 * Routine: sys_sem_signal
629 *
630 * Description:
631 * Signals (releases) a semaphore
632 * Inputs:
633 * sys_sem_t sem -- Semaphore to signal
634 */
sys_sem_signal(sys_sem_t * sem)635 void sys_sem_signal(sys_sem_t *sem)
636 {
637 u32_t ret;
638
639 if ((sem == NULL) || (sem->sem == NULL)) {
640 return;
641 }
642
643 ret = LOS_SemPost(LWIP_SEM_ID(sem));
644 LWIP_ASSERT("LOS_SemPost failed", (ret == 0));
645 UNUSED(ret);
646
647 return;
648 }
649
650
651 /*
652 * Routine: sys_sem_free
653 *
654 * Description:
655 * Deallocates a semaphore
656 * Inputs:
657 * sys_sem_t sem -- Semaphore to free
658 */
sys_sem_free(sys_sem_t * sem)659 void sys_sem_free(sys_sem_t *sem)
660 {
661 u32_t ret;
662
663 if ((sem == NULL) || (sem->sem == NULL)) {
664 return;
665 }
666
667 ret = LOS_SemDelete(LWIP_SEM_ID(sem));
668 sem->sem = NULL;
669 LWIP_ASSERT("LOS_SemDelete failed", (ret == 0));
670 UNUSED(ret);
671 return;
672 }
673
674 #if !LWIP_COMPAT_MUTEX
675 /* Create a new mutex
676 * @param mutex pointer to the mutex to create
677 * @return a new mutex */
sys_mutex_new(sys_mutex_t * mutex)678 err_t sys_mutex_new(sys_mutex_t *mutex)
679 {
680 u32_t ret;
681 #ifdef LWIP_LITEOS_A_COMPAT
682 ret = osal_mutex_init(mutex);
683 #else
684 ret = LOS_MuxCreate(mutex);
685 #endif
686 LWIP_ASSERT("sys_mutex_new failed", (ret == LOS_OK));
687 return ret;
688 }
689 /* Lock a mutex
690 * @param mutex the mutex to lock */
sys_mutex_lock(sys_mutex_t * mutex)691 void sys_mutex_lock(sys_mutex_t *mutex)
692 {
693 u32_t ret;
694 #ifdef LWIP_LITEOS_A_COMPAT
695 ret = osal_mutex_lock(mutex);
696 #else
697 ret = LOS_MuxPend(*mutex, LOS_WAIT_FOREVER);
698 #endif
699 LWIP_ASSERT("sys_mutex_lock failed", (ret == LOS_OK));
700 UNUSED(ret);
701 return;
702 }
703 /* Unlock a mutex
704 * @param mutex the mutex to unlock */
sys_mutex_unlock(sys_mutex_t * mutex)705 void sys_mutex_unlock(sys_mutex_t *mutex)
706 {
707 u32_t ret;
708 #ifdef LWIP_LITEOS_A_COMPAT
709 ret = osal_mutex_unlock(mutex);
710 #else
711 ret = LOS_MuxPost(*mutex);
712 #endif
713 LWIP_ASSERT("sys_mutex_unlock failed", (ret == LOS_OK));
714 UNUSED(ret);
715 return;
716 }
717 /* Delete a semaphore
718 * @param mutex the mutex to delete */
sys_mutex_free(sys_mutex_t * mutex)719 void sys_mutex_free(sys_mutex_t *mutex)
720 {
721 u32_t ret;
722 #ifdef LWIP_LITEOS_A_COMPAT
723 ret = osal_mutex_destroy(mutex);
724 #else
725 ret = LOS_MuxDelete(*mutex);
726 #endif
727 LWIP_ASSERT("sys_mutex_free failed", (ret == LOS_OK));
728 UNUSED(ret);
729 return;
730 }
731 #endif
732