2

i have passed through this post and i noticed that in Clifford's answer he said that we shouldn't use mutex in an interrupt, i know that in an interrupt we have to avoid too much instructions and delays ext... but am not very clear about the reasons could anyone clarify me for which reason we have to avoid this?

In case that we want establish a synchronous communication between 2 interrupt driven threads what are the other mecahnism to use if using mutex is not allowed?

Community
  • 1
  • 1
fedi
  • 368
  • 3
  • 7
  • 18
  • 2
    It's nonsense. Mutexes are a perfectly reasonable synchronization primitive to use in interrupts. Of course, you do need to ensure that a thread that holds the mutex can't be interrupted and run a handler that tries to acquire that same mutex! But writing interrupt handlers isn't for newbies anyway. Almost every modern operating system you can think of that supports multiple cores uses mutexes in its interrupt handlers. (Many mutex implementations cannot be used from user-space signal handlers. But that's an implementation limitation, not a general rule about mutexes as a concept.) – David Schwartz Jan 26 '16 at 10:50
  • 3
    When a thread attempts to get a mutex that is not available, the thread typically suspends to wait for the mutex. How do you expect an interupt handler to suspend and wait for a mutex to become available? – kkrambo Jan 26 '16 at 12:00
  • 1
    You must not make system calls that may block in an interrupt-handler. Interrupt-handlers don't have any thread context to block and if you get an error message you will be lucky. A BSOD or kernel panic fail is more likely. – Martin James Jan 26 '16 at 12:14
  • On a simple embedded tasker, a likely result is that the system gets totally deadlocked with interrupts disabled, ie. it's dead. – Martin James Jan 26 '16 at 12:16
  • 1
    @DavidSchwartz : The question is about hardware interrupt handlers, not about deferred interrupt handler threads. The original post referred to relates to Atmel ATMegaAVR, and so one would assume a very simple RTOS scheduler. The scheduler does not run until the interrupt context is exited, so if the interrupt blocks, the scheduler won't ever run. In the context of that question the statement is not "nonsense", and I am pretty sure that is generally true also - certainly for hard-realtime systems. – Clifford Jan 26 '16 at 19:16
  • @kkrambo It depends on the platform. One way is that the CPU is halted until an inter-processor interrupt resumes it. Obviously, you have to ensure that the code that holds the mutex can't be interrupted by an interrupt handler that attempts to acquire the mutex. That's usually done by disabling interrupts while non-interrupt code holds the mutex. – David Schwartz Jan 26 '16 at 19:46
  • @Clifford I read the question as an example of taking a comment that may make sense in a very specific context and assuming that it's a rule of general applicability. – David Schwartz Jan 26 '16 at 19:47
  • 2
    @DavidSchwartz : Indeed. The question was asked in a comment, I advised that a question should be posted. In doing so, any context is lost and we do not know what kind of system or OS this might apply to. Your response might however have been more measured that "nonsense". It might in fact be useful for you to post an answer with examples of situations where it is valid and OS's that support it. – Clifford Jan 26 '16 at 19:54

4 Answers4

5

The original question you cite refers to code on an Atmel ATMegaAVR - a simple 8 mit microcontroller. In that context, one can assume that the mutex machanism is part of a simple RTOS.

In such a system, there is a thread context and an interrupt context. Interrupts are invoked by the hardware, while threads are scheduler by the RTOS scheduler. Now when an interrupt occurs, any thread will be immediately pre-empted; the interrupt must run to completion and can only be preempted by a higher priority interrupt (where nested interrupts are supported). All pending interrupts will run to completion before the scheduler can run.

Blocking on a mutex (or indeed any blocking kernel object) is a secheduling event. If you were to make any blocking call in an interrupt, the scheduler will never run. In prectice an RTOS would either ignore the blocking call, raise an exception, or enter a terminal error handler.

Some OS's such as SMX, Velocity or even WinCE have somewhat more complex interrupt architectures and support variety of deferred interrupt handler. Deferred interrupt handlers are run-to-completion scheduled from an interrupt but running outside of the interrupt context; the rules for blocking in such handlers may differ, but you would need to refer to the specific OS documentation. Without deferred interrupt handlers, the usual solution is to have a thread wait on a some blocking object such as a semaphore, and have the interrupt itself do little more that cause the object to unblock (such as giving a semaphore for example).

Multi-processor/core and parallel processing systems are another issue altogether, such systems are way beyond the scope of the question where the original comment was made, and beyond my experience - my comment may not apply in such a system, but there are no doubt additional complexities and considerations in any case

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • thank you i get the point now, so to conclude i have to use semaphores to signal that an event has occure, and you're right blocking a thread is better than blocking an interrupt handler since thread can be interrupted by the RTOS – fedi Jan 26 '16 at 21:20
2

A mutex is typically used to ensure that a resource is used by only one user at any given time.

  • When a thread needs to use a resource it attempts to get the mutex first to ensure the resource is available. If the mutex is not available then the thread typically blocks to wait for the mutex to become available.

  • While a thread owns the mutex, it prevents other threads from obtaining the mutex and interfering with its use of the resource. Higher priority threads are often the concern here because those are the threads that may preempt the mutex owner.

  • The RTOS kernel assigns ownership of the mutex to a particular thread and typically only the mutex owner can release the mutex.

Now lets imagine this from an interrupt handler's point of view.

  • If an interrupt handler attempts to get a mutex that is not available, what should it do? The interrupt handler cannot block like the thread (the kernel is not equipped to push the context of an interrupt handler or switch to a thread from an interrupt handler).

  • If the interrupt handler obtains the mutex, what higher priority code is there that could interrupt the interrupt handler and attempt to use the mutex? Is the interrupt handler going to release the mutex before completing?

  • How does the kernel assign ownership of the mutex to an interrupt handler? An interrupt handler is not a thread. If the interrupt handler does not release the mutex then how will the kernel validate that the mutex is being released by the owner?

So maybe you have answers for all those questions. Maybe the you can guarantee that the interrupt handler runs only when the mutex is available or that the interrupt handler will not block on the mutex. Or maybe you're trying to protect the resource access from an even higher priority nested interrupt handler that also wants to use the resource. And maybe your kernel doesn't have any hangup with assigning ownership or restricting who releases the mutex. I guess if you've got all these questions answered then maybe you have a case for using a mutex within an interrupt handler.

But perhaps what you really need is a semaphore instead. One common application of a semaphore is to signal an event. Semaphores are very often used this way within interrupt handlers. The interrupt handler posts or sets the semaphore to signal that an event has occurred. The threads pend on the semaphore to wait for the event condition. (A semaphore doesn't have that ownership restriction that a mutex has.) Event signalling semaphores is one common way to establish synchronous communication between 2 interrupt driven threads.

kkrambo
  • 6,643
  • 1
  • 17
  • 30
  • These questions are all trivial to answer and pretty much all modern operating systems answer them with no difficulty. Roughly: 1, it can either spin or halt the CPU until an inter-processor interrupt resumes it. 2, of course the interrupt handler releases the mutex before completing. 3, the kernel doesn't need to track ownership, it's the job of the code that acquires and releases the mutex to do that. Kernel services don't provide the user friendliness that user space does and even POSIX user-space mutexes have no guarantee that anyone validates whether the mutex is released by the owner. – David Schwartz Jan 26 '16 at 19:50
  • And say you do use a semaphore to let the interrupt handler communicate to higher level code that there's some information it needs to process. How do you protect the container that holds that information without a mutex or something similar? – David Schwartz Jan 26 '16 at 19:52
  • @DavidSchwartz you use a queue with appropriately-updated indices/pointers. Load the 'in' pointer, store the data/buffer in the queue at 'in' position, store the 'in' pointer and only then signal the semaphore. – Martin James Jan 26 '16 at 20:15
  • @MartinJames Great. How do you protect those pointers from being changed while they're read? Maybe a mutex? – David Schwartz Jan 26 '16 at 20:32
  • Does not matter. As long as only one thread reads, and only one handler writes, and the pointers/indices are modded, and data stored, in the right order, all will be fine. The thread is guaranteed to safely find, and deque, one item from teh queue for every time it is woken up by a semaphore unit:) The thread that reads has no need to inspect, or modify, any of the pointer/index vars written by the handler. All it needs to do is keep its own queue pointer and, when signaled, dequeue something and move on its own pointer. – Martin James Jan 26 '16 at 20:46
  • @MartinJames You're avoiding my question rather than answering it. Why are you doing that? Do you want to create clutter or confusion? It's already bad enough that a completely wrong answer is here, obscuring someone pointing out what's wrong with it in the comments is needed too? What if any number of CPUs might run the interrupt handler or run the code that interacts with the interrupt handler? The issue is not whether you can you find some clever way to avoid the obvious solution of a mutex but that the obvious solution that people actually use is a mutex. – David Schwartz Jan 26 '16 at 20:47
  • It is beyond argument that the requirements for a multi-core architecture are more restrictive than single-core systems. If we go there, I would have closed the questinos as too broad:) – Martin James Jan 26 '16 at 20:53
  • @MartinJames This answer is completely wrong. It doesn't answer the question asked and instead asks a bunch of questions with trivial, obvious answers as if they were arguments against a very common, and very sensible, design. – David Schwartz Jan 26 '16 at 20:56
  • It's also beyond argument that you must not use a mutex in an interrupt handler. This answer explains why. If some OS implementation uses critical sections protected other means that may be used in an interrupt-handler, and describes that as a 'mutex', then fine, but a classic mutex will not work safely. 'In case that we want establish a synchronous communication between 2 interrupt driven threads what are the other mechanism to use' is answered by suggesting a semaphore, a synchro object that may be used for inter-thread comms as well as comms from an interrupt-handler. – Martin James Jan 26 '16 at 21:16
  • This answer is written from the perspective of an RTOS running on an embedded system such as an ATMega microcontroller. It points out the complications of using a mutex from within an interrupt handler in this environment and it provides an alternative. That's exactly what the questioner asked for. – kkrambo Jan 26 '16 at 21:19
  • So say you're writing the interrupt handler for a network interface. In the send logic, you need to get the next packet to send from a queue that's shared with higher-level, non-interrupt code that holds such packets. You don't use a mutex to protect the queue structures? – David Schwartz Jan 26 '16 at 21:36
  • 1
    No, because a mutex will not work safely. The mutex is fine for arbitrating between two threads, eg. to allow only one at a time to access a tx queue in order to enqueue data for sending, but the mutex cannot be used to manage interaction with the interrupt-handler code that directly responds to the TX_EMPTY, TXFIFO_EMPTY. or whatever it's called, hardware interrupt because that code can not and must not block. – Martin James Jan 26 '16 at 21:48
  • @MartinJames The term "critical section" means a piece of code protected by a mutex. It's also the name one particular OS (Windows) uses for one of its mutex implementations. A "mutex" is any control structure that allows one and only one flow of execution to take ownership of something at a time. – David Schwartz Jan 27 '16 at 16:03
  • @MartinJames That code can and must block if, for example, another thread is accessing the queue at the same time (except in the special case where you use a lock-free collection, which is not common). The blocking can take the form of either spinning or halting the CPU until an inter-CPU interrupt wakes it. I'm honestly starting to wonder -- have you ever written, or even looked at, an interrupt handler for a modern OS? – David Schwartz Jan 27 '16 at 16:04
  • @DavidSchwartz "The term "critical section" means a piece of code protected by a mutex." At least in single core micros, a "critical section" implies nothing can interrupt it. It's usually implemented by disabling interrupts, not by involving the RTOS with a mutex. Most micro controller RTOSes barf if you try to wait on a mutex in interrupt context. – Russ Schultz Jan 27 '16 at 16:34
  • I agree, you can also use the term "critical section" to mean code that cannot be interrupted. The meanings are almost equivalent. Effectively, on a single core system, disabling interrupts is a mutex implementation. But even most embedded systems large enough to have operating systems at all aren't single core these days, so this may be a dying technique. – David Schwartz Jan 27 '16 at 16:36
  • Disabling interrupts is not equivalent to a mutex. You can mutex protect a piece of hardware that one thread is pending on IO completion, yet allow other threads to operate and only pend when they attempt access the same hardware (or even fail with EBUSY). You also can't block interrupts if you expect the interrupt handler to signal completion... – Russ Schultz Jan 27 '16 at 17:10
  • @RussSchultz The same logic applies to both. You can't hold a mutex and wait for any operation that requires the mutex in order to take place. You can't disable interrupts and wait for any operation that requires an interrupt in order to take place. When you convert a single core OS to multi-core, code that disables interrupts often changes to code that acquires a mutex. Interrupt code that interacts with code that disables interrupts instead takes a mutex. (Assuming you can't/don't optimize to a lockless collection.) – David Schwartz Jan 27 '16 at 18:15
0

The term "mutex" is often defined both as being the simplest form of synchronization between execution contexts, and also as being a construct that will not only check whether a resource is available, but wait for it to become available if it isn't, acquiring it as soon as it becomes available. These definitions are inconsistent, since the simplest forms of synchronization merely involve testing whether one has been granted ownership of a resource, and don't provide any in-built mechanism to wait for it if it isn't.

It is almost never proper to have code within an interrupt handler that waits for a resource to become available, unless the only things that could hold the resource would be higher-priority interrupts or hardware that will spontaneously release it. If the term "mutex" is only used to describe such constructs, then there would be very few cases where one could properly use a mutex within an interrupt handler. If, however, one uses the term "mutex" more broadly to refer to the simplest structures that will ensure that a piece of code that accesses a resource can only execute at times when no other piece of code anywhere in the universe will be accessing that resource, then the use of such constructs within interrupts is often not only proper, but required.

supercat
  • 77,689
  • 9
  • 166
  • 211
-4

While there might be unusual cases where there's some problem with using a mutex in an interrupt handler, it's quite common practice and there's nothing wrong with it.

It really only makes sense on systems with more than one core. With just a single core (and no hyper-threading), the mutex would never do anything anyway. If the core is running code that acquires a mutex that interrupt code can acquire, interrupts (or the subset of them that matter) are disabled anyway. So with just one core, the mutex would never see any contention.

However, with multiple cores, it's common to use mutexes to protect structures that communicate between interrupt and non-interrupt code. So long as you know what you're doing, and you have to if you're going to write interrupt handlers, there's nothing wrong with it.

How the mutex blocks and unblocks is heavily implementation dependent. It can put the CPU to sleep and be woken by an inter-process interrupt. It can spin the CPU in some CPU-specific way.

Note that a totally unrelated concept that is often confused with this is using user-space mutexes in user-space signal handlers. That's a completely different question.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Thank you for the answer, but here am not talking about multi core system, even though it's a multi core system i think that using a semaphore within the interrupt handler is better than using a mutex, in fact interrupt handlers are usually used to signal that an event has occured and the semaphores are the best mechanism that handle this. – fedi Jan 26 '16 at 21:27
  • @fedi A semaphore is not "better" than a mutex, they solve different problems. For example, say you use a semaphore to alert some other piece of code that the interrupt handler has new data for it to process. You have to protect the container that holds that data, and the interrupt handler may run on multiple cores or may run concurrently with other code that accesses that container. Sure, a semaphore is a good way to notify, but it's not a solution to protecting data from conflicting access. – David Schwartz Jan 26 '16 at 21:32
  • @fedi Take a typical case, say an interrupt handler for a network card. You have a shared data structure that holds the packets you're going to send. You get an interrupt. You need to get the next packet to send from a collection shared with higher-level code that queues packets to send. You use a semaphore? – David Schwartz Jan 26 '16 at 21:34
  • @ David Schwatrz, in this case i use a semaphore to notify a high priority thread that protect data, within the thread i use mutex, the main purpose is always to avoid long delays inside an interrupt handler – fedi Jan 27 '16 at 07:05
  • @fedi If you use a mutex in the thread, you also have to use a mutex in the interrupt handler. A mutex only protects data if both the code that reads and writes the data hold the mutex when they access it. – David Schwartz Jan 27 '16 at 16:02
  • 1
    I disagree that it is common or that the cases where it cannot be used are unusual. It is far from unusual in an RTOS and every RTOS I have ever used explicitly disallow a mutex in an interrupt - because it would not work. You have perhaps made the mistake of assuming that the domain you work in the most often is also the most common domain. I would suggest that the vast majority of embedded systems are single core 8, 16 or 32 bit, sub 200MHz, no MMU, <512Kb on-ship ROM/RAM, and a large number of those systems will have no OS at all. – Clifford Jan 27 '16 at 21:44