Skip to content

Commit

Permalink
Use native Windows sempahore to avoid deadlock
Browse files Browse the repository at this point in the history
Replace global semaphore with `host_thread_wait` and `host_thread_kick`
  • Loading branch information
mikee47 committed Jan 25, 2022
1 parent 9be7fdc commit 905e28b
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 15 deletions.
8 changes: 5 additions & 3 deletions Sming/Arch/Host/Components/driver/os_timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
#include <muldiv.h>
#include <cassert>

extern CSemaphore host_main_loop_semaphore;

namespace
{
os_timer_t* timer_list;
Expand Down Expand Up @@ -44,7 +42,11 @@ void os_timer_arm_ticks(os_timer_t* ptimer, uint32_t ticks, bool repeat_flag)
mutex.lock();
timer_insert(hw_timer2_read() + ticks, ptimer);
mutex.unlock();
host_main_loop_semaphore.post();

// Kick main thread (which services timers) if we're due next
if(timer_list == ptimer) {
host_thread_kick();
}
}

void os_timer_arm(struct os_timer_t* ptimer, uint32_t time, bool repeat_flag)
Expand Down
3 changes: 1 addition & 2 deletions Sming/Arch/Host/Components/esp_hal/tasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ bool system_os_post(uint8_t prio, os_signal_t sig, os_param_t par)
return false;
}

extern CSemaphore host_main_loop_semaphore;
host_main_loop_semaphore.post();
host_thread_kick();
return true;
}

Expand Down
10 changes: 3 additions & 7 deletions Sming/Arch/Host/Components/hostlib/startup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@
#include <host_lwip.h>
#endif

CSemaphore host_main_loop_semaphore;

namespace
{
static int exitCode;
Expand All @@ -70,7 +68,7 @@ void host_exit(int code)

host_debug_i("returning %d", code);
exitCode = code;
host_main_loop_semaphore.post();
host_thread_kick();
done = true;

if(exit_count++) {
Expand Down Expand Up @@ -299,10 +297,8 @@ int main(int argc, char* argv[])
break;
}
}
constexpr int SCHED_WAIT{2};
if(due > SCHED_WAIT) {
host_main_loop_semaphore.timedwait((due - SCHED_WAIT) * 1000);
}

host_thread_wait(due);
}

host_debug_i(">> Normal Exit <<\n");
Expand Down
49 changes: 46 additions & 3 deletions Sming/Arch/Host/Components/hostlib/threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,33 @@

CThread::List CThread::list;
unsigned CThread::interrupt_mask;
CBasicMutex* interrupt;

namespace
{
pthread_t mainThread;
CBasicMutex* interrupt;

#ifdef __WIN32

#ifndef __WIN32
/*
* pthread-win32 implements semaphores with a mutex.
* If it's locked when the main thread is susepended then a deadlock occurs when another thread calls sem_post().
* UsE A native Windows semaphores to avoid this issue.
*/
HANDLE host_thread_semaphore;

#else

CSemaphore host_thread_semaphore;
volatile bool mainThreadSignalled;
timer_t signalTimer;
int pauseSignal;
int resumeSignal;

void host_thread_init()
{
}

void signal_handler(int sig)
{
if(sig == pauseSignal) {
Expand Down Expand Up @@ -147,7 +161,10 @@ void CThread::startup(unsigned cpulimit)

mainThread = pthread_self();
interrupt = new CBasicMutex;
#ifndef __WIN32

#ifdef __WIN32
host_thread_semaphore = CreateSemaphore(nullptr, 0, 1024, nullptr);
#else
pauseSignal = SIGRTMIN + 0;
resumeSignal = SIGRTMIN + 1;
signal(pauseSignal, signal_handler);
Expand Down Expand Up @@ -266,3 +283,29 @@ const char* CThread::getCurrentName()

return "";
}

void host_thread_wait(int ms)
{
constexpr int SCHED_WAIT{2};
if(ms >= 0 && ms <= SCHED_WAIT) {
return;
}
#ifdef __WIN32
WaitForSingleObject(host_thread_semaphore, (ms < 0) ? INFINITE : ms - SCHED_WAIT);
#else
if(ms < 0) {
host_thread_semaphore.wait();
} else if(ms > SCHED_WAIT) {
host_thread_semaphore.timedwait((ms - SCHED_WAIT) * 1000);
}
#endif
}

void host_thread_kick()
{
#ifdef __WIN32
ReleaseSemaphore(host_thread_semaphore, 1, nullptr);
#else
host_thread_semaphore.post();
#endif
}
12 changes: 12 additions & 0 deletions Sming/Arch/Host/Components/hostlib/threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,15 @@ class CThread : public LinkedObjectTemplate<CThread>
static List list; ///< All running threads
static unsigned interrupt_mask; ///< Current interrupt level
};

/*
* Called from main loop
* @param ms Time in milliseconds until next schedule timer event,
* negative if no timers have been scheduled.
*/
void host_thread_wait(int ms);

/*
* Cancels wait, e.g. when new event is posted to queue
*/
void host_thread_kick();

0 comments on commit 905e28b

Please sign in to comment.