Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Real-time operating system
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==Intertask communication and resource sharing== A multitasking operating system like [[Unix]] is poor at real-time tasks. The scheduler gives the highest priority to jobs with the lowest demand on the computer, so there is no way to ensure that a time-critical job will have access to enough resources. Multitasking systems must manage sharing data and hardware resources among multiple tasks. It is usually unsafe for two tasks to access the same specific data or hardware resource simultaneously.<ref name="phraner1984fall">{{Cite magazine |last=Phraner |first=Ralph A. |date=Fall 1984 |url=https://archive.org/stream/byte-magazine-1984-09/1984_09_BYTE_09-09_Guide_to_the_IBM_PCs#page/n61/mode/2up |title=The Future of Unix on the IBM PC |magazine=[[Byte (magazine)|Byte]] |pages=59β64}}</ref> There are three common approaches to resolve this problem: ===Temporarily masking/disabling interrupts=== General-purpose operating systems usually do not allow user programs to mask (disable) [[interrupt]]s, because the user program could control the CPU for as long as it is made to. Some modern CPUs do not allow [[user mode]] code to disable interrupts as such control is considered a key operating system resource. Many embedded systems and RTOSs, however, allow the application itself to run in [[kernel mode]] for greater [[system call]] efficiency and also to permit the application to have greater control of the operating environment without requiring OS intervention. On single-processor systems, an application running in kernel mode and masking interrupts is the lowest overhead method to prevent simultaneous access to a shared resource. While interrupts are masked and the current task does not make a blocking OS call, the current task has ''exclusive'' use of the CPU since no other task or interrupt can take control, so the [[critical section]] is protected. When the task exits its critical section, it must unmask interrupts; pending interrupts, if any, will then execute. Temporarily masking interrupts should only be done when the longest path through the critical section is shorter than the desired maximum [[interrupt latency]]. Typically this method of protection is used only when the critical section is just a few instructions and contains no loops. This method is ideal for protecting hardware bit-mapped registers when the bits are controlled by different tasks. ===Mutexes=== When the shared resource must be reserved without blocking all other tasks (such as waiting for Flash memory to be written), it is better to use mechanisms also available on general-purpose operating systems, such as a [[mutex]] and OS-supervised interprocess messaging. Such mechanisms involve system calls, and usually invoke the OS's dispatcher code on exit, so they typically take hundreds of CPU instructions to execute, while masking interrupts may take as few as one instruction on some processors. A (non-recursive) mutex is either '''locked''' or unlocked. When a task has locked the mutex, all other tasks must wait for the mutex to be unlocked by its '' owner'' - the original thread. A task may set a timeout on its wait for a mutex. There are several well-known problems with mutex based designs such as [[priority inversion]] and [[deadlock (computer science)|deadlock]]s. In [[priority inversion]] a high priority task waits because a low priority task has a mutex, but the lower priority task is not given CPU time to finish its work. A typical solution is to have the task that owns a mutex 'inherit' the priority of the highest waiting task. But this simple approach gets more complex when there are multiple levels of waiting: task ''A'' waits for a mutex locked by task ''B'', which waits for a mutex locked by task ''C''. Handling multiple levels of inheritance causes other code to run in high priority context and thus can cause starvation of medium-priority threads. In a [[deadlock (computer science)|deadlock]], two or more tasks lock mutex without timeouts and then wait forever for the other task's mutex, creating a cyclic dependency. The simplest deadlock scenario occurs when two tasks alternately lock two mutex, but in the opposite order. Deadlock is prevented by careful design. ===Message passing=== The other approach to resource sharing is for tasks to send messages in an organized [[message passing]] scheme. In this paradigm, the resource is managed directly by only one task. When another task wants to interrogate or manipulate the resource, it sends a message to the managing task. Although their real-time behavior is less crisp than [[Semaphore (programming)|semaphore]] systems, simple message-based systems avoid most protocol deadlock hazards, and are generally better-behaved than semaphore systems. However, problems like those of semaphores are possible. Priority inversion can occur when a task is working on a low-priority message and ignores a higher-priority message (or a message originating indirectly from a high priority task) in its incoming message queue. Protocol deadlocks can occur when two or more tasks wait for each other to send response messages.
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)