I have couple questions regarding setting signals to inactive threads using RTX and CMSIS. Please see the example code below:
osThreadId thread_id = osThreadCreate(osThread(thread_body), NULL); /* set thread active */
osThreadTerminate(thread_id); /* set thread inactive */
osSignalSet(thread_id, 1); /* set signal to inactive thread */
osThreadCreate(osThread(thread_body), NULL); /* set same thread active again */
void thread_body (void const * arg) { osSignalWait(1, 0); /* is the signal set? */ }
Questions: 1) The signal is set while the thread is inactive. What is the effect of this? 2) In the thread_body function, will the signal be set?
Thank you
A common way is to let a thread wait for multiple events. So either an "action" event or a "quit" event.
Same can be done when waiting on a mailbox: - set a global flag "please thread x end" - send a dummy mail to the thread - whenever the thread picks up a mail it checks the "end" flag
Another alternative is to have timeout on all wait calls, allowing the individual threads to regularly poll other data before restarting the waits.
Lots of code constructs will be impossible or at least very difficult to read/use if a thread may be killed by outside sources. And other parts of the code will have to have significant internal knowledge about the inner workings of the thread to attempt "garbage collect" of allocated resources and restore of data structures and hardware to well defined states.
How do you draw a state diagram, when some outside force may kick you out of the state diagram at an arbitrary state - or even in the middle of a state-changing action?
How do you expect to ever manage a full coverage analysis of your code validating every single code path, when there is an arbitrary asynchronous action that may hit the individual threads?
Another thing is that an thread priority change may give unexpected new failures depending on if the thread that kills other threads have higher or lower priority than the thread(s) that are about to be killed. How can you graphically depict this and make sure any developer who picks up the code will be able to spot these dangers?
Think about a program using C++ with objects having constructors and destructors. If the OS has preemptive task switching and the thread gets killed after an object has been constructed but before it gets destructed, then the destructor will not be called. How would a developer be able to spot this?
Think about yourself - you want to perform actions based on received stimuli. You wouldn't want some external force to be able to magically teleport you into a different location at arbitrary times without your control. If you are on the toilet and it knocks on the door - do you want to finish your "critical section" or do you want to be forcibly and instantly teleported to the outside of the door?
Per,
Again valid points. I have some thinking to do about my architecture. I would like to say though, that I believe my architecture handles “knocks on the door” just fine. Critical sections are completed and the door is answered. The case I’m talking about is not a knock on the door, it’s a fire. If I’m on the toilet in the middle of a “critical section” and all of a sudden theres a life threatening fire, I’d gladly be magically teleported to a different location and will deal with the clean up later.
Ben
If you are doing a panic stop after getting a sensor error or someone have pressed a stop button, then you could kill all threads. But you then shouldn't expect to be able to recover from that state. So have the panic code rewrite the state of every I/O pin of the chip to turn off power, short-circuits motors as electrical breaks etc and then wait for an operator to reset the device and then potentially on reboot wait for a key lock activation before limping back to "home position" to do a full self-test before you are ready to start up normal operation again.
Any time you kill a thread, you are violating any known/documented state information for that thread and potentially an unknown number of global variables/hardware. And if the kill comes from a thread of same or higher priority so the kill need not happen in a wait function, you might also violate code-generation or logic rules of the programming language or the runtime library.
If you have any plan at all for returning to normal operation without rebooting, then you really shouldn't kill threads but should spend the time/code to teach them how to always respond to ordered thread-stop events.
Think again about that magical teleportation. It would be "safe" if it always teleported you to a known safe state. So you always ended up in a bed at a safe place. If it instead only manages a horizontal translation, and you happened to start from the eight floor of a building, you might end up with a quite long fall when you got teleported into thin air eight floors above the "rallying point". Killing a thread leaves you in an unknown state where you do not know what is needed to recover. It is a "crash out" function, where only a reset has a contractual obligation to return you to a known state.
I have found a complete and elegant solution to the problem of “waking up” a thread that can pend on several different os events - the CMSIS osWait function. If this function were used for pending, it would be simple to send an asynchronous “halt event” to a thread no matter what its pending on, even a timeout. The thread could then handle the event and any necessary cleanup. No terminating of threads required.
Only problem is, the CMSIS osWait function is optional and RTX doesn’t support it. Why doesn’t RTX support osWait? This seems like an extremely useful function. Can it be added?
Thanks,