• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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