Hi I'm having a problem finding an answer to the question below. I'm trying to implement an application layer driver on Linux that performs some IO but needs to have some non-blocking interface functions. Essentially, there will only ever be two threads in this environment, Thread A and B.
Consider the following example:
Class Driver
{
void foo()
{
emergency_shutdown = true;
Signal(cond)
}
void thread_loop()
{
Lock(cond)
while (true)
{
if (emergency_shutdown)
{
// Do an atomic IO Operation #1 that could take 5ms
// For example: Send an emergency shutdown packet
emergency_shutdown = false;
}
else
{
// do an atomic IO Operation #2 that could take 100ms
}
Signal(cond)
CondWait(cond, 1000); // 1 second wait.
}
Unlock(cond)
}
}
Class HigherLayer
{
...
powerfail_handler() // Function only has 20ms to run before power is lost
{
// POWER FAIL DETECTED!
// Do some important stuff
Driver::foo() // Force shutdown of device
// Do some other important stuff
// ... Power eventually lost but hopefully we did all the
// important stuff in this function.
}
...
}
In the above example.. Thread A is basically the Driver thread which is running 'thread_loop()' and Thread B is the HigherLayer thread which does a whole bunch of stuff as well as calling powerfail_handler if a powerfail is detected.
The main question is this:
Is it ok for the driver function foo() to call Signal(cond) without Locking cond first? The reason I don't want to Lock cond is because I don't want any possible situation where the powerfail_handler would call foo() and it have to sit around for 100ms waiting for a lock to be released.
I understand the consequences of modifying the 'emergency_shutdown' variable outside of a Lock. They don't worry me too much.
I also understand that there will be some situations that if foo() is called during the 100ms window that IO Operation #2 is being done by Thread A, then my desired IO Operation #1 wont happen (because power will be lost before there's a chance to do it). That's fine too, I have no way around that and just have to live with it, but in that situation, I do NOT want to be blocked on foo() and miss out on doing the 'other important stuff' in Thread B (which is why I don't have a Lock in foo()).
I just want to make sure that if Thread A is Waiting (which should be the case 90% of the time) I want to signal it to stop waiting and do IO Operation #1.
So will the Signal() in foo() work as desired? If not, do I have to have it in a Lock? Also if not, are there any other ways to solve this problem?
Sorry for the wall of text and thanks ahead for your responses.