mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-22 13:33:40 +00:00
[host] app: fix app state race in lgmpTimer thread
While resuming from hibernation lgmpTimer may transition app.state to APP_STATE_REINIT_LGMP. Sometimes the transition is lost if the app_main processing loop also changes app.state simultaneously. This seems to occur frequently with the hibernation use case. Separate lgmp timer state into its own enum. Move resulting app.state transitions to the app_main loop so they are serialized.
This commit is contained in:
parent
e25492a3a3
commit
b9b31093de
@ -69,10 +69,16 @@ enum AppState
|
|||||||
APP_STATE_RUNNING,
|
APP_STATE_RUNNING,
|
||||||
APP_STATE_IDLE,
|
APP_STATE_IDLE,
|
||||||
APP_STATE_TRANSITION_TO_IDLE,
|
APP_STATE_TRANSITION_TO_IDLE,
|
||||||
APP_STATE_REINIT_LGMP,
|
|
||||||
APP_STATE_SHUTDOWN
|
APP_STATE_SHUTDOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LGMPTimerState
|
||||||
|
{
|
||||||
|
LGMP_TIMER_STATE_OK,
|
||||||
|
LGMP_TIMER_STATE_CORRUPTED,
|
||||||
|
LGMP_TIMER_STATE_FAULTED
|
||||||
|
};
|
||||||
|
|
||||||
struct app
|
struct app
|
||||||
{
|
{
|
||||||
int exitcode;
|
int exitcode;
|
||||||
@ -105,7 +111,8 @@ struct app
|
|||||||
CaptureInterface * iface;
|
CaptureInterface * iface;
|
||||||
bool captureStarted;
|
bool captureStarted;
|
||||||
|
|
||||||
enum AppState state, lastState;
|
enum AppState state;
|
||||||
|
enum LGMPTimerState lgmpTimerState;
|
||||||
LGTimer * lgmpTimer;
|
LGTimer * lgmpTimer;
|
||||||
LGThread * frameThread;
|
LGThread * frameThread;
|
||||||
bool threadsStarted;
|
bool threadsStarted;
|
||||||
@ -162,8 +169,7 @@ inline static void setAppState(enum AppState state)
|
|||||||
{
|
{
|
||||||
if (app.state == APP_STATE_SHUTDOWN)
|
if (app.state == APP_STATE_SHUTDOWN)
|
||||||
return;
|
return;
|
||||||
app.lastState = app.state;
|
app.state = state;
|
||||||
app.state = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lgmpTimer(void * opaque)
|
static bool lgmpTimer(void * opaque)
|
||||||
@ -176,12 +182,12 @@ static bool lgmpTimer(void * opaque)
|
|||||||
{
|
{
|
||||||
DEBUG_ERROR("LGMP reported the shared memory has been corrrupted, "
|
DEBUG_ERROR("LGMP reported the shared memory has been corrrupted, "
|
||||||
"attempting to recover");
|
"attempting to recover");
|
||||||
setAppState(APP_STATE_REINIT_LGMP);
|
atomic_store(&app.lgmpTimerState, LGMP_TIMER_STATE_CORRUPTED);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_ERROR("lgmpHostProcess Failed: %s", lgmpStatusString(status));
|
DEBUG_ERROR("lgmpHostProcess Failed: %s", lgmpStatusString(status));
|
||||||
setAppState(APP_STATE_SHUTDOWN);
|
atomic_store(&app.lgmpTimerState, LGMP_TIMER_STATE_FAULTED);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,6 +791,7 @@ static bool lgmpSetup(struct IVSHMEM * shmDev)
|
|||||||
app.frameBuffer[i] = (FrameBuffer *)(((uint8_t*)app.frame[i]) + alignOffset);
|
app.frameBuffer[i] = (FrameBuffer *)(((uint8_t*)app.frame[i]) + alignOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_store(&app.lgmpTimerState, LGMP_TIMER_STATE_OK);
|
||||||
if (!lgCreateTimer(10, lgmpTimer, NULL, &app.lgmpTimer))
|
if (!lgCreateTimer(10, lgmpTimer, NULL, &app.lgmpTimer))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create the LGMP timer");
|
DEBUG_ERROR("Failed to create the LGMP timer");
|
||||||
@ -811,8 +818,7 @@ int app_main(int argc, char * argv[])
|
|||||||
// make sure rng is actually seeded for LGMP
|
// make sure rng is actually seeded for LGMP
|
||||||
srand((unsigned)time(NULL));
|
srand((unsigned)time(NULL));
|
||||||
|
|
||||||
app.lastState = APP_STATE_RUNNING;
|
app.state = APP_STATE_RUNNING;
|
||||||
app.state = APP_STATE_RUNNING;
|
|
||||||
ivshmemOptionsInit();
|
ivshmemOptionsInit();
|
||||||
|
|
||||||
// register capture interface options
|
// register capture interface options
|
||||||
@ -954,16 +960,25 @@ int app_main(int argc, char * argv[])
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
switch(app.state)
|
switch(atomic_load(&app.lgmpTimerState))
|
||||||
{
|
{
|
||||||
case APP_STATE_REINIT_LGMP:
|
case LGMP_TIMER_STATE_OK:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LGMP_TIMER_STATE_CORRUPTED:
|
||||||
DEBUG_INFO("Performing LGMP reinitialization");
|
DEBUG_INFO("Performing LGMP reinitialization");
|
||||||
lgmpShutdown();
|
lgmpShutdown();
|
||||||
setAppState(app.lastState);
|
|
||||||
if (!lgmpSetup(&shmDev))
|
if (!lgmpSetup(&shmDev))
|
||||||
goto fail_lgmp;
|
goto fail_lgmp;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LGMP_TIMER_STATE_FAULTED:
|
||||||
|
setAppState(APP_STATE_SHUTDOWN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(app.state)
|
||||||
|
{
|
||||||
case APP_STATE_IDLE:
|
case APP_STATE_IDLE:
|
||||||
// if there are no clients subscribed, just remain idle
|
// if there are no clients subscribed, just remain idle
|
||||||
if (!lgmpHostQueueHasSubs(app.pointerQueue) &&
|
if (!lgmpHostQueueHasSubs(app.pointerQueue) &&
|
||||||
|
Loading…
Reference in New Issue
Block a user