Task state when mutex and/or semaphore not acquired - rtos

I have basic understanding of rtos and task states.
My query is when a task is unable to acquire mutex, in which particular state the task is moved to?
Also if task is unable to acquire binary semaphore, in which particular state the task is moved?
I am aware of SUSPEND and WAIT state. But not sure in mutex and semaphore case. I want to know the detailed understanding.

Typically a RTOS can have it own implementation. But generally there is mutex wait queue handled by the scheduler, when the task is unable to acquire a mutex it goes into the mutex wait queue.

Related

What happens to a process and/or thread while it waits on a mutex?

When a process and/or thread waits on mutex in which state the process and/or thread is? Is it in WAIT or READY or some other state? I tried to search the answer over the web but could not find a clear, definitive answer, maybe there isn't one or maybe there is, to find out that I am posting this question here.
tl;dr: Nothing happens when it is waiting; it is simply a kernel data structure.
Without loss of generality, all operating systems have some sort of model where a unit of execution (task) moves between the states : Ready, Running, Waiting. This Task has a data structure associated with it, where its state and registers (among other things) are recorded.
When a task moves from Ready to Running, its saved registers are loaded on a cpu, and it continues execution from its last saved state. Initially, its saved registers are set to reasonable values for the program to start.
From Running to Waiting or Ready, its registers are stored in its task data structure, and this structure is placed on either a list of Ready or Waiting tasks.
From Waiting to Ready, the task data structure is removed from the Waiting list and appended to the Ready list.
When a task tries to acquire a mutex that is unavailable, it moves from Running (how else could it try to get the mutex) to Waiting. If the mutex was available, it remains Running, and the mutex becomes unavailable.
When a task releases a mutex, and another task is Waiting for that mutex, the Waiting task becomes Ready, and acquires the mutex. If many tasks are Waiting, one is chosen to acquire the mutex and become Ready, the rest remain Waiting.
This is a very abstract description; real systems are complicated by both a plurality of synchronization mechanisms (mailbox, queue, semaphore, pipe, ...), a desire to optimise the various paths, and the utilization of multiple CPUs.

In pthread_cond_wait() , why it unlock the mutex when it makes caller sleep?

I am currently learning OS with Operating Systems : Three Easy Pieces
And it introduces pthread_cond_wait() function, which makes caller of it sleep.
And It said, it unlock the mutex right after it is called and then makes caller sleep.
I have no idea why it unlock the mutex after it is called. Why is that?
Please help me understand for this reason.
Thank you.
If it left the mutex locked while the caller slept, then no other thread would be able to acquire the mutex until after pthread_cond_wait() returned and the caller woke up and explicitly unlocked the mutex. That behavior would be difficult to work with, since if the mutex is also being used to serialize access to some data, then no other thread would be able to safely read or write that data while the first thread was asleep (since if it did so without locking the mutex, that would introduce a race condition, and if it tried to lock the mutex, the program would deadlock).
A thread calls pthread_cond_wait() when needs to wait for the value of some shared state to change. That shared state must be protected by a mutex, and pthread_cond_wait() must unlock the mutex so another thread has the opportunity to acquire the mutex and modify the shared state - otherwise, you would have a deadlock.
The thread must hold the mutex when it calls pthread_cond_wait(), because otherwise another thread would have the opportunity to acquire the mutex and change the shared state before the waiting thread sleeps - this is a "missed wakeup".

Semaphore when using a pre-emptive kernel

I know what a binary semaphore is: it is a flag when is set to 1 by an ISR of an interrupt.
But what is a semaphore when we are using a pre-emptive kernel, say FreeRTOS? Is it the same as binary semaphore?
it is a flag when is set to 1 by an ISR of an interrupt.
That is neither a complete nor accurate description of a semaphore. What you have described is merely a flag. A semaphore is a synchronisation object; there are three forms provided by a typical RTOS:
Binary Semaphore
Counting Sempahore
Mutual Exclusion Semaphore (Mutex)
In the case of a binary semaphore, there are two operations give and take. A task taking a semaphore will block (i.e. suspend execution and allow other lower or equal priority threads to run threads to run) until some other thread or interrupt handler gives the semaphore. Binary semaphores are used to signal between threads and from ISRs to threads. They are often used to implement deferred interrupt handlers, so that an ISR can ve bery short, and the handler benefit from RTOS mechanisms that are not allowed in an ISR (anything that blocks or suspends execution).
Multiple threads may block on a single semaphore, but only one of those tasks will respond take the semaphore. Some RTOS have a flush operation (VxWorks for example) that puts all threads waiting on a semaphore in the ready state simultaneously - in which case they will run according to the priority scheduling scheme.
A Counting Semaphore is similar to a Binary Semaphore, except that it can be given multiple times, and tasks may take the semaphore without blocking until the count is zero.
A Mutex is used for resource locking. It is possible to use a binary semaphore for this, but a mutex provides features that make this safer. The operations on a mutex are lock and unlock. When a thread locks a mutex, and another task attempts to lock the same mutex, the second (and any subsequent) task blocks until the first task unlocks it. This can be used to prevent more than one thread accessing a resource (memory or I/O) simultaneously. A thread may lock a mutex multiple times; a count is maintained, so that it must be unlocked an equal number of times before the lock is released. This allows a thread to nest locks.
A special feature of a mutex is that if a thread with the lock is a lower priority that a task requesting the lock, then the lower priority task is boosted to the priority of the higher in order to prevent a priority inversion where a middle priority task may preempt the low priority task with the lock increasing the length of time the higher priority task must wait this rendering the scheduling non-deterministic.
The above descriptions are typical; specific RTOS implementations may differ. For example FreeRTOS distinguishes between a mutex and a recursive mutex, the latter supporting the nestability feature; while the first is marginally more efficient where nesting is not needed.
Semaphores are not just flags, or counts. They support send and wait operations. A user-space thread can wait on a semaphore without unnecessary and unwanted polling and be made ready/running 'immediately' when another thread, or an appropriately-designed driver/ISR, sends a unit.
By 'appropriately-designed driver/ISR', I mean one that can perform a send() operation and then exit via the OS scheduler whenever it needs to set a waiting thread ready/running.
Such a mechanism is vitally important on preemptive kernels because it allows them to achieve very good I/O performance without wasting time, CPU cycles and memory-bandwidth on polling. Non-preemptive systems are hopelessly slow, latency-ridden and wasteful at I/O and this is why they are essentially no longer used and why we put up with all the synchro/locking/queueing etc issues.

Why a mutex cannot be released from an ISR

Vxworks states that mutual exculsion semaphores : Cannot be given inside ISR, while the condition is vaild for binary and counting semaphore.
I am not able to understand the reason out the same.
Thanks,
Zaks.
Remember that a Mutex must first be acquired/taken then released/given.
In addition, the task that acquires the mutex owns it. This prevents another task from releasing a mutex it doesn't own.
With that being the case, it becomes clear that since an ISR cannot acquire a mutex (or any semaphore for that matter - it's a blocking operation), then it follows that it can't give the mutex.
It is quite possible for an ISR to do give a Binary or Counting semaphore to signal a task that something happens. But mutexes are always a take/give pair.
To clarify a point. In VxWorks, the ISR context is not the same as the context of a task!
The following scenario is invalid:
Task A ISR
semTake(mutex)
....
semGive(mutex)
Task A owns the mutex. When the ISR runs, it executes in a totaly different context. Most current processors have a separate ISR stack. Since Task A owns the mutex, how could the ISR give it up? In fact, what guarantee do you have that the ISR will fire while A has the mutex.
Even assuming you "could" give a mutex in an ISR, how would you handle the following scenario:
Task A Task B ISR
semTake(mutex)
...
<context switch happens>
<B runs>
semGive(mutex)
Task A gets switched out due to a call unrelated to the mutex, and Task B runs. The ISR now executes while B was running. Would it still be valid for the ISR to be given?
Regardless of all this, the simple fact is that a mutex is always used in a pair of Get/Set. I fail to see a use case where you would have an isolated semGive.
Is there a specific situation you have in mind that would require a semGive from an ISR context?
Mutexes should not be used from an interrupt because:
They include a priority inheritance mechanism which only makes sense if the mutex is given and taken from a task, not an interrupt.
An interrupt cannot block to wait for a resource that is guarded by a mutex to become available
https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html

Who schedules the scheduler in OS - Isn't it a chicken and egg scenario?

Who schedules the scheduler?
Which is the first task created and how is this first task created? Isn't any resource or memory required for it? isn't like a chicken and egg scenario?
Isn't scheduler a task? Does it get the CPU at the end of each time slice to check which task needs to be given CPU?
Are there any good links which makes a person think and understand deeply all these concepts rather than spilling out some theory which needs to be byhearted?
The scheduler is scheduled by
an (external) event such as an interrupt, (disk done, mouse click, timer tick)
or an internal event (such as the completion of a thread, the signalling by a thread that it needs to wait for something, or the signalling of a thread that it has released a resource, or a trap caused by a thread doing something illegal like division by zero)
In short, it is triggered by any event that might require that the set of tasks to be run and/or the priorities of those tasks to be reevaluated. The scheduler decides which task(s) run next, and passes control to the next task.
Typically, this "scheduling" of the scheduler is caused by the code associated with a hardware interrupt, or code associated with a system call.
While you can think of the scheduler as being a real thread, in practice it doesn't need to be implemented that way... because it is executed with higher priority than any other task. Sophisticated OSes may in fact set aside a special thread that is the scheduler, and mark it busy when the scheduler gets control. That makes it pretty, but the bogus thread isn't scheduled by the scheduler
One can have multiple schedulers: the highest priority one (e.g., the one we just described), and other schedulers which really are threads, and are run like other user tasks. Such lower priority schedulers tend to be used to manage actions which occur at much longer intervals, such as background jobs.
it is usually invoked periodically by a timed CPU interrupt