return ERR_MEM;
}
- if (sys_mutex_new(&((*mbox)->lock)) != ERR_OK){
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("fail to new *mbox->lock\n"));
- vQueueDelete((*mbox)->os_mbox);
- free(*mbox);
- return ERR_MEM;
- }
-
- (*mbox)->alive = true;
+#if ESP_THREAD_SAFE
+ (*mbox)->owner = NULL;
+#endif
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("new *mbox ok mbox=%p os_mbox=%p mbox_lock=%p\n", *mbox, (*mbox)->os_mbox, (*mbox)->lock));
+ LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("new *mbox ok mbox=%p os_mbox=%p\n", *mbox, (*mbox)->os_mbox));
return ERR_OK;
}
if (*mbox == NULL){
*msg = NULL;
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_arch_mbox_fetch: null mbox\n"));
return -1;
}
- sys_mutex_lock(&(*mbox)->lock);
-
- if (timeout != 0) {
- if (pdTRUE == xQueueReceive((*mbox)->os_mbox, &(*msg), timeout / portTICK_PERIOD_MS)) {
- EndTime = xTaskGetTickCount();
- Elapsed = (EndTime - StartTime) * portTICK_PERIOD_MS;
-
- if (Elapsed == 0) {
- Elapsed = 1;
- }
-
- ulReturn = Elapsed;
- } else { // timed out blocking for message
- *msg = NULL;
- ulReturn = SYS_ARCH_TIMEOUT;
- }
- } else { // block forever for a message.
-
- while (1){
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_arch_mbox_fetch: fetch mbox=%p os_mbox=%p lock=%p\n", mbox, (*mbox)->os_mbox, (*mbox)->lock));
- if (pdTRUE == xQueueReceive((*mbox)->os_mbox, &(*msg), portMAX_DELAY)){
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_arch_mbox_fetch:mbox rx msg=%p\n", (*msg)));
- break;
- }
-
- if ((*mbox)->alive == false){
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_arch_mbox_fetch:mbox not alive\n"));
- *msg = NULL;
- break;
- }
- }
+ if (timeout == 0) {
+ timeout = portMAX_DELAY;
+ } else {
+ timeout = timeout / portTICK_PERIOD_MS;
+ }
+ *msg = NULL;
+ if (pdTRUE == xQueueReceive((*mbox)->os_mbox, &(*msg), timeout)) {
EndTime = xTaskGetTickCount();
Elapsed = (EndTime - StartTime) * portTICK_PERIOD_MS;
}
ulReturn = Elapsed;
+ } else { // timed out blocking for message
+ ulReturn = SYS_ARCH_TIMEOUT;
}
- sys_mutex_unlock(&(*mbox)->lock);
-
return ulReturn ; // return time blocked TBD test
}
}
/*-----------------------------------------------------------------------------------*/
+
+void
+sys_mbox_set_owner(sys_mbox_t *mbox, void* owner)
+{
+ if (mbox && *mbox) {
+ (*mbox)->owner = owner;
+ LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("set mbox=%p owner=%p", *mbox, owner));
+ }
+}
+
/*
Deallocates a mailbox. If there are messages still present in the
mailbox when the mailbox is deallocated, it is an indication of a
void
sys_mbox_free(sys_mbox_t *mbox)
{
-#define MAX_POLL_CNT 100
-#define PER_POLL_DELAY 20
- uint16_t count = 0;
- bool post_null = true;
-
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: set alive false\n"));
- (*mbox)->alive = false;
-
- while ( count++ < MAX_POLL_CNT ){ //ESP32_WORKAROUND
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free:try lock=%d\n", count));
- if (!sys_mutex_trylock( &(*mbox)->lock )){
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free:get lock ok %d\n", count));
- sys_mutex_unlock( &(*mbox)->lock );
- break;
- }
+ uint32_t mbox_message_num = 0;
- if (post_null){
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: post null to mbox\n"));
- if (sys_mbox_trypost( mbox, NULL) != ERR_OK){
- ESP_STATS_DROP_INC(esp.free_mbox_post_fail);
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: post null mbox fail\n"));
+ if ( (NULL == mbox) || (NULL == *mbox) ) {
+ ESP_LOGW(TAG, "WARNING: free null mbox\n");
+ return;
+ }
+
+ mbox_message_num = uxQueueMessagesWaiting((*mbox)->os_mbox);
+
+ LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mbox free: mbox=%p os_mbox=%p owner=%p msg_num=%d\n",
+ *mbox, (*mbox)->os_mbox, (*mbox)->owner, mbox_message_num));
+
+#if ESP_THREAD_SAFE
+ if ((*mbox)->owner) {
+ if (0 == mbox_message_num) {
+ /*
+ * If mbox->owner is not NULL, it indicates the mbox is recvmbox or acceptmbox,
+ * we need to post a NULL message to mbox in case some application tasks are blocked
+ * on this mbox
+ */
+ if (sys_mbox_trypost(mbox, NULL) != ERR_OK) {
+ /* Should never be here because post a message to empty mbox should always be successful */
+ ESP_LOGW(TAG, "WARNING: failed to post NULL msg to mbox\n");
} else {
- post_null = false;
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: post null mbox ok\n"));
+ LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mbox free: post null successfully\n"));
}
}
-
- if (count == (MAX_POLL_CNT-1)){
- ESP_LOGW(TAG, "WARNING: mbox %p had a consumer who never unblocked. Leaking!\n", (*mbox)->os_mbox);
+ (*mbox)->owner = NULL;
+ } else {
+ if (mbox_message_num > 1) {
+ ESP_LOGW(TAG, "WARNING: mbox has %d message, potential memory leaking\n", mbox_message_num);
}
- sys_delay_ms(PER_POLL_DELAY);
- }
- LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free:free mbox\n"));
+ if (mbox_message_num > 0) {
+ LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mbox free: reset mbox queue\n"));
+ xQueueReset((*mbox)->os_mbox);
+ }
- if (uxQueueMessagesWaiting((*mbox)->os_mbox)) {
- xQueueReset((*mbox)->os_mbox);
- /* Line for breakpoint. Should never break here! */
- __asm__ volatile ("nop");
+ /* For recvmbox or acceptmbox, free them in netconn_free() when all sockets' API are returned */
+ vQueueDelete((*mbox)->os_mbox);
+ free(*mbox);
}
-
+#else
vQueueDelete((*mbox)->os_mbox);
- sys_mutex_free(&(*mbox)->lock);
free(*mbox);
+#endif
*mbox = NULL;
}