How is a process waken up if slept in interruptible state? - linux

The kernel code can explicitly put the process to sleep if it's waiting for some task to occur. Now, if the task is put in TASK_INTERRUPTIBLE state, it can wake either by explicit wake up call or by receiving a signal.
Let's say another process issued a signal to a process which is in the wait queue and in TASK_INTERRUPTIBLE state, it will put the process into TASK_RUNNING and the signal will be handled when the process is scheduled next. Is this correct?
An explicit wake up call by other process can also be used to wake up the slept processes. I am wondering how could another process know when the condition became true for the slept process to wake up? Suppose a disk i/o is to be completed and so the process is put to sleep. How could another process know that the i/o is completed? Or is it done by kernel threads?
What am I missing?

It is up to the code that entered the interruptible state to detect the interruption and take appropriate action when it wakes. That might involve the code that is currently handling the user operation completing it with a -ERESTARTSYS error that will be intercepted and dealt with before the system call returns to user mode.
The code that has completed some I/O can just issue a "wake up" to the queue it is responsible for without caring whether there is any task on the queue to be woken up, or the exact condition the task is waiting for.
The task that is woken up needs to decide what to do, and that could include repeating the wait if the the condition it is waiting for had not been satisfied.

Related

Does sleep() wake up a process by sending some signal at the end of waiting?

APUE says about sleep()
This function sleep() causes the calling process to be suspended
until either
The amount of wall clock time specified by seconds has elapsed.
A signal is caught by the process and the signal handler returns.
Does the first case work by sending some specific signal to the process itself? If yes, what is the signal?
alarm() can send signal SIGALARM to the calling process after a specific time period, which is why I wonder if sleep() work in the same way.
Does sleep() change the state of the calling process to the same state as sigsuspend() changes to? Which process state(s) do the two functions change to?
Is it correct that a suspended process can only be waken by a signal? That is the reason why I have the question.
Thanks.
Linux kernel has absolutely no needs in using user signals for change the state of the process. So, a signal emitting is performed only for meet a requirement on a user library's function.
As documentation for sleep function doesn't say that any signal is emitted after the end of the sleep, so the kernel doesn't use signals in that case.
Is it correct that a suspended process can only be waken by a signal?
Yes, user code may awoke sleeping process only by sending signal to it. This is true for most non-runnable process states too.

Do I need to check for my threads exiting?

I have an embedded application, running as a single process on Linux.
I use sigaction() to catch problems, such as segmentation fault, etc.
The process has a few threads, all of which, like the app, should run forever.
My question is whether (and how) I should detect if one of the threads dies.
Would a seg fault in a thread be caught by the application’s sigaction() handler?
I was thinking of using pthread_cleanup_push/pop, but this page says “If any thread within a process calls exit, _Exit, or _exit, then the entire process terminates”, so I wonder if a thread dying would be caught at the process level …
It is not a must that you need to check whether the child thread is completed.
If you have a need of doing something after the child thread completes its processing you can call thread_join() from the main thread, so that it will wait till the child threads completes execution and you can do the rest after this. If you are using thread_exit in the main thread it will get terminated once it is done, leaving the spawned threads to continue execution. The process will get killed only after all the threads completes execution.
If you want to check the status of the spawned threads you can use a flag to detect whether it is running or not. Check this link for more details
How do you query a pthread to see if it is still running?

Transition from Wait queue to run queue

When a process calls wait_event_interruptible the process goes to sleep(assuming the condition is satisfied and there are no pending signals) the scheduler removes the process from the run queue to the wait queue.
When there is wake_up call how exactly and who removes the process from wait queue and keeps it in the run queue?
Thaks
The "wake_up call" is a system call done by another thread/process/task (some kernels put state on thread rather than process) with the thread/process/task to wake up in parameter. Because the system call is an interrupt (int $0x80 on Linux, until it was recently replaced by sysenter which is basically the same), thus entering the kernel, the scheduler will be called and the requested thred/process/task will be poped out the blocked queue and pushed into the ready queue. If this thread/process/task has the highest priority, it will eventually run when returning from the interrupt, therefore going directly from the blocked state to the running state.

Interrupt while placing process on the waiting queue

Suppose there is a process that is trying to enter the critical region but since it is occupied by some other process, the current process has to wait for it. So, at the time when the process is getting added to the waiting queue of the semaphore, suppose an interrupt comes (ex- battery finished), then what will happen to that process and the waiting queue?
I think that since the battery has finished so this interrupt will have the highest priority and so the context of the process which was placing the process on the waiting queue would be saved and interrupt service routine for this routing will be executed.
And then it will return to the process that was placing the process on the queue.
Please give some hints/suggestions for this question.
This is very hardware / OS dependant, however a few thoughts:
As has been mentioned in the comments, a ‘battery finished’ interrupt may be considered as a special case, simply because the machine may turn off without taking any action, in which case the processes + queue will disappear. In general however, assuming a non-fatal interrupt and an OS that suspends / resumes correctly, I think it’s unlikely there will be any noticeable impact to the execution of either process.
In a multi-core setup, the process may not be immediately suspended. The interrupt could be handled by a different core and neither of the processes you’ve mentioned would be any the wiser.
In a pre-emptive multitasking OS there's also no guarantee that the process adding to the queue would be resumed immediately after the interrupt, the scheduler could decide to activate the process currently in the critical section or another process entirely. What would happen when the process adding itself to the semaphore wait queue resumed would depend on how far through adding it was, how the queue has been implemented and what state the semaphore was in. It may be that it never gets on to the wait queue because it detects that the other process has already woken up and left the critical section, or it may be that it completes adding itself to the queue and suspends as if nothing had happened…
In a single core/processor machine with a cooperative multitasking OS, I think the scenario you’ve described in your question is quite likely, with the executing process being suspended to handle the interrupt and then resumed afterwards until it finished adding itself to the queue and yielded.
It depends on the implementation, but conceptually the same operating process should be performing both the addition of the process to the wait queue and the management of the interrupts, so your process being moved to wait would instead be treated as interrupted from the wait queue.
For Java, see the API for Thread.interrupt()
Interrupts this thread.
Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.
If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.
If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.
If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.
If none of the previous conditions hold then this thread's interrupt status will be set.
Interrupting a thread that is not alive need not have any effect.

Mechanics of Condition.Signal()

If I had threads as below
void thread(){
while() {
lock.acquire();
if(condition not true)
{
Cond.wait()
}
// blah blah
Cond.Signal();
lock.release();
}
}
Well I guess my main question is that whether the signalling thread continues running for a while after cond.signal() or immediately gives up the CPU?. I would like it in some cases not to release the lock before the woken up thread finishes execution and in some other cases it may be beneficial to release the lock immediately after signalling, without waiting for the other woken thread to finish.
I understand that if there are any threads waiting on the condition then they get woken up on Cond.signal(). But what do you mean by woekn up - put on the ready queue or does the scheduler make sure that it runs immediately?.
and what about the signalling thread.. does it go to sleep on the same condtion upon signalling? .. so then some other thread has to wake it up to make it release the lock?.
This is in large part dependent on your environment (OS, library, language...) and how the synchronisation primitives are implemented. Since you haven't specified any I'll just give a general answer.
When putting a thread to sleep, most environment will choose to remove it from the scheduler's ready queue and the thread will give up its remaining CPU time. When woken up, the thread is simply placed back into the ready queue and will resume execution the next time the scheduler selects it from the queue.
It's also possible that the thread will do some active waiting (spinning) instead of being removed from the scheduler's ready queue. In this case, the thread will resume execution right away. Note that since a thread can still be run out of CPU of time while spinning, it might have to wait to be rescheduled before waking up. This is a useful strategy if your critical sections are very small and you don't want to pay for the scheduling overheads.
A hybrid approach would be to do a small amount of active waiting before removing the thread from the scheduler's ready queue.
As for the signaling thread, unless specified explicitly by your environment (I can't of any reasons but you never know), I wouldn't expect a call to signal() to block in a way that you have to wake it up. Signal() might have to synchronize itself with other threads calling signal() but those are implementation details and you shouldn't have to do anything about it.

Resources