1
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
41
42
54
55
60
61
68
69
74
75
82
83
88
89
95
96
97
98
105
106
107
108
109
110
111
112
116
117
122
123
124
125
126
131
132
133
134
135
136
137
138
139
140
141
142
143
144
150
151
158
159
160
161
162
163
182
183
184
185
186
191
192
197
198
205
206
207
208
209
213
214
215
216
221
222
223
224
225
226
232
233
239
240
247
248
249
250
251
252
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
306
307
321
322
323
324
325
332
333
334
335
336
337
338
341
342
346
347
348
349
350
351
356
357
358
359
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
390
391
392
393
394
395
396
399
400
401
402
403
407
408
409
410
415
416
417
418
419
420
421
422
427
428
432
433
438
439
443
444
451
452
460
461
466
467
472
473
476
477
478
479
480
481
484
485
486
487
488
489
490
491
492
493
497
498
502
503
504
505
506
507
508
509
513
514
515
520
521
522
523
524
525
526
534
535
536
540
541
542
543
544
545
546
547
548
549
551
553
558
566
567
569
570
571
572
/* ... */
#include <pthread.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/mem.h"
#include "lwip/stats.h"
#include "arch/sys_arch.h"
#include "arch/vfs_lwip.h"
#include "esp_log.h"
#include "esp_compiler.h"14 includes
static const char* TAG = "lwip_arch";
static sys_mutex_t g_lwip_protect_mutex = NULL;
static pthread_key_t sys_thread_sem_key;
static void sys_thread_sem_free(void* data);
#if !LWIP_COMPAT_MUTEX
/* ... */
err_t
sys_mutex_new(sys_mutex_t *pxMutex)
{
*pxMutex = xSemaphoreCreateMutex();
if (*pxMutex == NULL) {
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mutex_new: out of mem\r\n"));
return ERR_MEM;
}{...}
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mutex_new: m=%p\n", *pxMutex));
return ERR_OK;
}{ ... }
/* ... */
void
sys_mutex_lock(sys_mutex_t *pxMutex)
{
BaseType_t ret = xSemaphoreTake(*pxMutex, portMAX_DELAY);
LWIP_ASSERT("failed to take the mutex", ret == pdTRUE);
(void)ret;
}{ ... }
/* ... */
void
sys_mutex_unlock(sys_mutex_t *pxMutex)
{
BaseType_t ret = xSemaphoreGive(*pxMutex);
LWIP_ASSERT("failed to give the mutex", ret == pdTRUE);
(void)ret;
}{ ... }
/* ... */
void
sys_mutex_free(sys_mutex_t *pxMutex)
{
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mutex_free: m=%p\n", *pxMutex));
vSemaphoreDelete(*pxMutex);
*pxMutex = NULL;
}{ ... }
/* ... */#endif
/* ... */
err_t
sys_sem_new(sys_sem_t *sem, u8_t count)
{
LWIP_ASSERT("initial_count invalid (neither 0 nor 1)",
(count == 0) || (count == 1));
*sem = xSemaphoreCreateBinary();
if (*sem == NULL) {
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_sem_new: out of mem\r\n"));
return ERR_MEM;
}{...}
if (count == 1) {
BaseType_t ret = xSemaphoreGive(*sem);
LWIP_ASSERT("sys_sem_new: initial give failed", ret == pdTRUE);
(void)ret;
}{...}
return ERR_OK;
}{ ... }
/* ... */
void
sys_sem_signal(sys_sem_t *sem)
{
BaseType_t ret = xSemaphoreGive(*sem);
LWIP_ASSERT("sys_sem_signal: sane return value",
(ret == pdTRUE) || (ret == errQUEUE_FULL));
(void)ret;
}{ ... }
int
sys_sem_signal_isr(sys_sem_t *sem)
{
BaseType_t woken = pdFALSE;
xSemaphoreGiveFromISR(*sem, &woken);
return woken == pdTRUE;
}{ ... }
/* ... */
u32_t
sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
{
BaseType_t ret;
if (!timeout) {
ret = xSemaphoreTake(*sem, portMAX_DELAY);
LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
}{...} else {
/* ... */
TickType_t timeout_ticks = ((timeout + portTICK_PERIOD_MS - 1) / portTICK_PERIOD_MS) + 1;
ret = xSemaphoreTake(*sem, timeout_ticks);
if (ret == errQUEUE_EMPTY) {
return SYS_ARCH_TIMEOUT;
}{...}
LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
}{...}
return 0;
}{ ... }
/* ... */
void
sys_sem_free(sys_sem_t *sem)
{
vSemaphoreDelete(*sem);
*sem = NULL;
}{ ... }
/* ... */
err_t
sys_mbox_new(sys_mbox_t *mbox, int size)
{
*mbox = mem_malloc(sizeof(struct sys_mbox_s));
if (*mbox == NULL){
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("fail to new *mbox\n"));
return ERR_MEM;
}{...}
(*mbox)->os_mbox = xQueueCreate(size, sizeof(void *));
if ((*mbox)->os_mbox == NULL) {
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("fail to new (*mbox)->os_mbox\n"));
free(*mbox);
return ERR_MEM;
}{...}
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("new *mbox ok mbox=%p os_mbox=%p\n", *mbox, (*mbox)->os_mbox));
return ERR_OK;
}{ ... }
/* ... */
void
sys_mbox_post(sys_mbox_t *mbox, void *msg)
{
BaseType_t ret = xQueueSendToBack((*mbox)->os_mbox, &msg, portMAX_DELAY);
LWIP_ASSERT("mbox post failed", ret == pdTRUE);
(void)ret;
}{ ... }
/* ... */
err_t
sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
{
err_t xReturn;
if (xQueueSend((*mbox)->os_mbox, &msg, 0) == pdTRUE) {
xReturn = ERR_OK;
}{...} else {
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("trypost mbox=%p fail\n", (*mbox)->os_mbox));
xReturn = ERR_MEM;
}{...}
return xReturn;
}{ ... }
/* ... */
err_t
sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg)
{
BaseType_t ret;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
ret = xQueueSendFromISR((*mbox)->os_mbox, &msg, &xHigherPriorityTaskWoken);
if (ret == pdTRUE) {
if (xHigherPriorityTaskWoken == pdTRUE) {
return ERR_NEED_SCHED;
}{...}
return ERR_OK;
}{...} else {
LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
return ERR_MEM;
}{...}
}{ ... }
/* ... */
u32_t
sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
{
BaseType_t ret;
void *msg_dummy;
if (msg == NULL) {
msg = &msg_dummy;
}{...}
if (timeout == 0) {
ret = xQueueReceive((*mbox)->os_mbox, &(*msg), portMAX_DELAY);
LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
}{...} else {
TickType_t timeout_ticks = timeout / portTICK_PERIOD_MS;
ret = xQueueReceive((*mbox)->os_mbox, &(*msg), timeout_ticks);
if (ret == errQUEUE_EMPTY) {
*msg = NULL;
return SYS_ARCH_TIMEOUT;
}{...}
LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
}{...}
return 0;
}{ ... }
/* ... */
u32_t
sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
{
BaseType_t ret;
void *msg_dummy;
if (msg == NULL) {
msg = &msg_dummy;
}{...}
ret = xQueueReceive((*mbox)->os_mbox, &(*msg), 0);
if (ret == errQUEUE_EMPTY) {
*msg = NULL;
return SYS_MBOX_EMPTY;
}{...}
LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
return 0;
}{ ... }
/* ... */
void
sys_mbox_free(sys_mbox_t *mbox)
{
if ((NULL == mbox) || (NULL == *mbox)) {
return;
}{...}
UBaseType_t msgs_waiting = uxQueueMessagesWaiting((*mbox)->os_mbox);
LWIP_ASSERT("mbox quence not empty", msgs_waiting == 0);
vQueueDelete((*mbox)->os_mbox);
free(*mbox);
*mbox = NULL;
(void)msgs_waiting;
}{ ... }
/* ... */
sys_thread_t
sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
{
TaskHandle_t rtos_task;
BaseType_t ret;
/* ... */
ret = xTaskCreatePinnedToCore(thread, name, stacksize, arg, prio, &rtos_task,
CONFIG_LWIP_TCPIP_TASK_AFFINITY);
LWIP_DEBUGF(TCPIP_DEBUG, ("new lwip task : %" U32_F ", prio:%d,stack:%d\n",
(u32_t)rtos_task, prio, stacksize));
if (ret != pdTRUE) {
return NULL;
}{...}
return (sys_thread_t)rtos_task;
}{ ... }
/* ... */
void
sys_init(void)
{
if (!g_lwip_protect_mutex) {
if (ERR_OK != sys_mutex_new(&g_lwip_protect_mutex)) {
ESP_LOGE(TAG, "sys_init: failed to init lwip protect mutex");
}{...}
}{...}
pthread_key_create(&sys_thread_sem_key, sys_thread_sem_free);
esp_vfs_lwip_sockets_register();
}{ ... }
/* ... */
u32_t
sys_jiffies(void)
{
return xTaskGetTickCount();
}{ ... }
/* ... */
u32_t
sys_now(void)
{
return xTaskGetTickCount() * portTICK_PERIOD_MS;
}{ ... }
/* ... */
sys_prot_t
sys_arch_protect(void)
{
if (unlikely(!g_lwip_protect_mutex)) {
sys_mutex_new(&g_lwip_protect_mutex);
}{...}
sys_mutex_lock(&g_lwip_protect_mutex);
return (sys_prot_t) 1;
}{ ... }
/* ... */
void
sys_arch_unprotect(sys_prot_t pval)
{
LWIP_UNUSED_ARG(pval);
sys_mutex_unlock(&g_lwip_protect_mutex);
}{ ... }
/* ... */
sys_sem_t*
sys_thread_sem_get(void)
{
sys_sem_t *sem = pthread_getspecific(sys_thread_sem_key);
if (!sem) {
sem = sys_thread_sem_init();
}{...}
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sem_get s=%p\n", sem));
return sem;
}{ ... }
static void
sys_thread_sem_free(void* data)
{
sys_sem_t *sem = (sys_sem_t*)(data);
if (sem && *sem){
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sem del, sem=%p\n", *sem));
vSemaphoreDelete(*sem);
}{...}
if (sem) {
LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sem pointer del, sem_p=%p\n", sem));
free(sem);
}{...}
}{...}
sys_sem_t*
sys_thread_sem_init(void)
{
sys_sem_t *sem = (sys_sem_t*)mem_malloc(sizeof(sys_sem_t*));
if (!sem){
ESP_LOGE(TAG, "thread_sem_init: out of memory");
return 0;
}{...}
*sem = xSemaphoreCreateBinary();
if (!(*sem)){
free(sem);
ESP_LOGE(TAG, "thread_sem_init: out of memory");
return 0;
}{...}
pthread_setspecific(sys_thread_sem_key, sem);
return sem;
}{ ... }
void
sys_thread_sem_deinit(void)
{
sys_sem_t *sem = pthread_getspecific(sys_thread_sem_key);
if (sem != NULL) {
sys_thread_sem_free(sem);
pthread_setspecific(sys_thread_sem_key, NULL);
}{...}
}{ ... }
void
sys_delay_ms(uint32_t ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}{ ... }
bool
sys_thread_tcpip(sys_thread_core_lock_t type)
{
static sys_thread_t lwip_task = NULL;
#if LWIP_TCPIP_CORE_LOCKING
static sys_thread_t core_lock_holder = NULL;
#endif
switch (type) {
default:
return false;...
case LWIP_CORE_IS_TCPIP_INITIALIZED:
return lwip_task != NULL;...
case LWIP_CORE_MARK_TCPIP_TASK:
LWIP_ASSERT("LWIP_CORE_MARK_TCPIP_TASK: lwip_task == NULL", (lwip_task == NULL));
lwip_task = (sys_thread_t) xTaskGetCurrentTaskHandle();
return true;
#if LWIP_TCPIP_CORE_LOCKING...
case LWIP_CORE_LOCK_QUERY_HOLDER:
return lwip_task ? core_lock_holder == (sys_thread_t) xTaskGetCurrentTaskHandle() : true;...
case LWIP_CORE_LOCK_MARK_HOLDER:
core_lock_holder = (sys_thread_t) xTaskGetCurrentTaskHandle();
return true;...
case LWIP_CORE_LOCK_UNMARK_HOLDER:
core_lock_holder = NULL;
return true;/* ... */
#else
case LWIP_CORE_LOCK_QUERY_HOLDER:
return lwip_task == NULL || lwip_task == (sys_thread_t) xTaskGetCurrentTaskHandle();/* ... */
#endif
}{...}
return true;
}{ ... }