/* 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. */ 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; } 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")); } else { post_null = false; LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: post null mbox ok\n")); } } if (count == (MAX_POLL_CNT-1)){ ESP_LOGW(TAG, "WARNING: mbox %p had a consumer who never unblocked. Leaking!\n", (*mbox)->os_mbox); } sys_delay_ms(PER_POLL_DELAY); } LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free:free mbox\n")); if (uxQueueMessagesWaiting((*mbox)->os_mbox)) { xQueueReset((*mbox)->os_mbox); /* Line for breakpoint. Should never break here! */ __asm__ volatile ("nop"); }
error_code sys_lwmutex_trylock(ppu_thread& ppu, vm::ptr<sys_lwmutex_t> lwmutex) { sysPrxForUser.trace("sys_lwmutex_trylock(lwmutex=*0x%x)", lwmutex); if (g_cfg.core.hle_lwmutex) { return sys_mutex_trylock(ppu, lwmutex->sleep_queue); } const be_t<u32> tid(ppu.id); // try to lock lightweight mutex const be_t<u32> old_owner = lwmutex->vars.owner.compare_and_swap(lwmutex_free, tid); if (old_owner == lwmutex_free) { // locking succeeded return CELL_OK; } if (old_owner == tid) { // recursive locking if ((lwmutex->attribute & SYS_SYNC_RECURSIVE) == 0) { // if not recursive return CELL_EDEADLK; } if (lwmutex->recursive_count == -1) { // if recursion limit reached return CELL_EKRESOURCE; } // recursive locking succeeded lwmutex->recursive_count++; _mm_mfence(); return CELL_OK; } if (old_owner == lwmutex_dead) { // invalid or deleted mutex return CELL_EINVAL; } if (old_owner == lwmutex_reserved) { // should be locked by the syscall const error_code res = _sys_lwmutex_trylock(lwmutex->sleep_queue); if (res == CELL_OK) { // locking succeeded auto old = lwmutex->vars.owner.exchange(tid); if (old != lwmutex_reserved) { fmt::throw_exception("Locking failed (lwmutex=*0x%x, owner=0x%x)" HERE, lwmutex, old); } } return res; } // locked by another thread return not_an_error(CELL_EBUSY); }