I have not seen any good answers there. All suggestions were far more complicated than necessary.
Normally, an interrupt handler should do only a very simple thing: it should insert an action item in an agenda queue (i.e. "to do" queue) that is monitored by a kernel thread and it should acknowledge the interrupt handling to the peripheral that has signaled it.
On older CPUs the interrupt handler might also need to do something to ensure that the corresponding kernel thread wakes up, but on better CPUs just writing the queue should automatically wake up a thread that monitors it.
The content of the queue and the write index in it are modified only by the interrupt handler, so no locks are needed for the queue. The kernel thread only reads the content of the queue and it only modifies its own read index.
If the interrupt handler finds that the queue is full (by comparing the indices), one of two policies can be applied, either the last interrupt is ignored or the previous interrupt is overwritten, therefore it will be ignored. Such events should not normally happen.
If the kernel thread modifies the read index during the handling of an interrupt, this is harmless. In the worst case, the interrupt handler may believe that the queue is full even if one position has just been freed. This leads to ignoring one interrupt. With a big enough queue, this should not happen. If the interrupt handler modifies the write index while the kernel thread examines the queue, this is harmless, because in the worst case the kernel thread will believe that the queue is empty when an item has just been added, so it will wait for the next item to be added in the queue. When the kernel thread finds a non-empty queue, it will execute all the requested actions, until the queue is empty.
In most interrupt handlers you do not need anything else than such a queue, which does not require locks.
In very rare cases one may have the need to modify the behavior of the interrupt handlers while they are running, which can be done using static configuration variables that are modified by the kernel using atomic instructions, e.g. atomic bit set or atomic bit clear instructions.
https://users.rust-lang.org/t/sharing-state-between-cores-an...
Normally, an interrupt handler should do only a very simple thing: it should insert an action item in an agenda queue (i.e. "to do" queue) that is monitored by a kernel thread and it should acknowledge the interrupt handling to the peripheral that has signaled it.
On older CPUs the interrupt handler might also need to do something to ensure that the corresponding kernel thread wakes up, but on better CPUs just writing the queue should automatically wake up a thread that monitors it.
The content of the queue and the write index in it are modified only by the interrupt handler, so no locks are needed for the queue. The kernel thread only reads the content of the queue and it only modifies its own read index.
If the interrupt handler finds that the queue is full (by comparing the indices), one of two policies can be applied, either the last interrupt is ignored or the previous interrupt is overwritten, therefore it will be ignored. Such events should not normally happen.
If the kernel thread modifies the read index during the handling of an interrupt, this is harmless. In the worst case, the interrupt handler may believe that the queue is full even if one position has just been freed. This leads to ignoring one interrupt. With a big enough queue, this should not happen. If the interrupt handler modifies the write index while the kernel thread examines the queue, this is harmless, because in the worst case the kernel thread will believe that the queue is empty when an item has just been added, so it will wait for the next item to be added in the queue. When the kernel thread finds a non-empty queue, it will execute all the requested actions, until the queue is empty.
In most interrupt handlers you do not need anything else than such a queue, which does not require locks.
In very rare cases one may have the need to modify the behavior of the interrupt handlers while they are running, which can be done using static configuration variables that are modified by the kernel using atomic instructions, e.g. atomic bit set or atomic bit clear instructions.