Resuming the thread after schedule() - linux-kernel

Another newbie question:
In the following code, what if the thread is preempted after calling 'set_current_state' but before 'schedule' is called. When the code is scheduled again, does it start from 'schedule' call and is removed from the run queue? Or the 'schedule' call is ignored this time and starts from the set_current_state(TASK_RUNNING) statement?
{
...
set_current_state(TASK_INTERRUPTIBLE); /* suppose thread is preempted just after this function call */
schedule();
set_current_state(TASK_RUNNING);
...
}

Here's (more or less) what will happen if involuntary preemption happens after the first line and before the second:
The scheduler will run (scheduler() function from sched.c) - since this is what being preempted mean.
Since your task is marked as not runnable, the scheduler will remove it from the run queue and will pick another task.
Now your task will not be scheduled until something external will mark it as runnable again. This might happen due to a signal sent to the task or, assuming the task is queued in a wait queue, due to the event the wake queue belongs to happening, but something external MUST mark the task as runnable again or it will never be scheduled. This is why if you look at the wait queue code, it first put the task on the wait queue and only then does something similar to your code.
When your task is marked as runnable, at some point the scheduler will pick it and will context switch into the task code.
Then the schedule() function will get called. In all likelihood, the scheduler is going to pick the same task yet again, since it has just been picked by it as most eligible for running and it is not likely that this have changed.
On the way back from the scheduler, the last set_current_state will basically be a no op, since the task by this time is already marked as runnable in this scenario.

Related

Does async task gets killed before its completion if so what happens to life cycle of calling activity when async task is stopped?

I have an Activity A which has a task that needs to be performed in background. So i'm sending the task to async. What happens to activity life cycle when the
myAsyncTask.cancel(true)
is called i.e async task is killed.
According to Android Developers to stop AsyncTask,
A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
and for "what will happen to life cycle of calling activity" i dont know much, you can see here for life cycle of an activity, but as the async task is performed in background the activity will continue to work, but after stopping the asynctask according to documentation found in android studio
The default implementation simply invokes onCancelled() and ignores the result. If you write your own implementation, do not call super.onCancelled(result).
you can do your own implemetation of how to handle after stoping from async task, and after this may be the activity life cycle will be resumed and work normally.
I am not confirmed about this, but let me know if i am wrong somewhere.

beanstalkd allowing one job to be reserved twice

I have a beanstalkd instance with two workers picking jobs from one tube.
I've noticed that occasionally one of the workers will reserve a job that has already been reserved (and being worked on) by the other worker.
I know there aren't duplicate jobs in the queue.
Why does beanstalkd allow the same job to be reserved twice?
It sounds to me that you didn't implemented the protocol properly. You need to handle DEADLINE_SOON, and do TOUCH.
What does DEADLINE_SOON mean?
DEADLINE_SOON is a response to a reserve command indicating that you have a job reserved whose deadline is real soon (current safety margin is approximately 1 second).
If you are frequently receiving DEADLINE_SOON errors on reserve, you should probably consider increasing the TTR on your jobs as it generally indicates you aren’t completing them in time. It may also be that you are failing to delete tasks when you have completed them.
See the mailing list discussion for more information.
How does TTR work?
TTR only applies to a job at the moment it becomes reserved. At that event, a timer (called “time-left” in the job stats) starts counting down from the job’s TTR.
If the timer reaches zero, the job gets put back in the ready queue.
If the job is buried, deleted, or released before the timer runs out, the timer ceases to exist.
If the job is touch"ed before the timer reaches zero, the timer starts over counting down from TTR.
The "touch" command
Allows a worker to request more time to work on a job.
This is useful for jobs that potentially take a long time, but you still want
the benefits of a TTR pulling a job away from an unresponsive worker. A worker
may periodically tell the server that it's still alive and processing a job
(e.g. it may do this on DEADLINE_SOON). The command postpones the auto
release of a reserved job until TTR seconds from when the command is issued.
The jobs take longer to run than the TTR, so it was being returned back to the queue and picked up by the other worker.
I now set a larger TTR on the job.

Who is the calling thread of the callback function set by CreateTimerQueueTimer()?

I guess it's the thread, say A, on which the timer was created. But I can't figure out how exactly the callback function is called. Assume the timer expires, and then what happens? Does this happen when this thread gets its time slice? And if this is the case, I think the function should be called by the scheduler or what before the context is finally switched to A, then can I say A is the caller?
Thanks.
The timer callback can also be called by a pool thread, a thread that specifically manages timers or in the context of the creating thread, (the creating thread is designed to accept and process an 'Asynchronous Procedure Call'). The flag paramters in CTQT() control the action upon timer expiry.
If the timer event is called by a pool thread or timer-manager thread, that thread will become ready upon expiry and, when there is a core available to run it, it will make the callback 'immediately' within its own context. The thread that created the timer could, if it wished, wait on a synchro object, (event or semaphore), that could be signaled by the timer callback, (ie. normal inter-thread comms).
The timer callback can only be executed in the context of the thread that created it if that thread is in a position to execute the callback when it receives some sort of signal. In the case of these timers, an APC is QUEUED to the creating thread and, if that thread is blocked on one of the 'alertable' wait calls, it will become ready immediately, will run when there is a core available to run it. After the APC has run, the wait call will return. If the wait call is not SleepEx(), it will return WAIT_IO_COMPLETION - a result that is usually ignored. If the thread is not waiting when the APC is queued up, it will not be executed until the thread makes the next wait call, (obviously - since the thread must be off doing something else:).
'And if this is the case, I think the function should be called by the scheduler or what before the context is finally switched to A, then can I say A is the caller?' NO!

function posted to boost::asio::io_service::strand not executed

I am using boost::asio in a quite complex scenario and I am experiencing a problem where a method posted to a boost::asio::io_service::strand object is not executed although several worker threads on the io_service are running and idle.
As I said, the scenario is very complex, I'm still trying to develop a reasonably small repro scenario. But the conditions are as follows:
one io_service is running and has a work-object assigned to it
4 worker threads are assigned to the io_service (called io_service::run on each)
several strand objects are used to post numerous different tasks
in some of the tasks that are executed via the strands, new tasks are posted to the strand
The whole system works well and stable, except for one situation:
When calling the destructor of one of the classes, it posts the abort handler to the strand (to initiate aborting in sync with the other taks) and then waits until abort is done.
Every once in a while it now happens, that the abort handler is never executed (destructor is called from an invocation of another strand object).
I assume the problem is that the strand waits for executing the handler on the same thread that it has been posted. And since this thread is waiting for the abort handler to be executed the program deadlocks.
My questions now:
- is my assumption correct?
- is there any way to avoid this situation?
- how would you approach that problem (having several async tasks running and need to abort them synchronously)
Thanx a lot for your help!
m.

Does a thread waiting on Windows Events need to get scheduled on CPU to wake up from sleeping?

It is best to describe my question in an example:
We create a Windows Event handle by CreateEvent, with manualReset as FALSE.
We create 4 threads. Ensure that they all start running and waiting on the above event by WaitForSingleObject.
In the main thread, in a for loop, we signal this event 4 times, by SetEvent. such as:
for (int i = 0; i < 4; ++i) ::SetEvent(event);
My question is, can we say that all these 4 threads will certainly be waken up from waiting on this event?
According to my understanding of Windows Event, the answer is YES. Because when the event is set, there is always a thread waiting for it.
However, I read on MSDN that "Setting an event that is already set has no effect". Since the waiting threads probably do not get a chance to run while main thread setting event in the loop. Can they still be notified and reset the event to nonsignaled? If the event is not reset, the following SetEvent in the loop is obviously useless.
Or the OS kernel knows which thread should be notified when an event is set, and reset this event immediately if there is a waiting thread. So the waiting thread does not need to be schedule to reset the event to nonsignaled?
Any clarification or references are welcome. Thanks.
Because when the event is set, there is always a thread waiting for it.
No, you don't know that. A thread may indefinitely suspended for some reason just before the NtWaitForSingleObject system call.
Since the waiting threads probably do not get a chance to run while main thread setting event in the loop.
If a thread is waiting for an object, it doesn't run at all - that's the whole point of being able to block on a synchronization object.
Can they still be notified and reset the event to nonsignaled? If the event is not reset, the following SetEvent in the loop is obviously useless.
The thread that sets the event is the one that resets the signal state back to 0, not the thread that gets woken up. Of course, if there's no thread waiting the signal state won't be reset.
Or the OS kernel knows which thread should be notified when an event is set, and reset this event immediately if there is a waiting thread.
Yes, the kernel does know. Every dispatcher object has a wait list, and when a thread waits on an object it pushes a wait block onto that list.
In a word? No.
There's no guarantee that each and every call to Set() will signal a waiting thread. MSDN describes this behavior as follows:
There is no guarantee that every call
to the Set method will release a
thread from an EventWaitHandle whose
reset mode is
EventResetMode::AutoReset. If two
calls are too close together, so that
the second call occurs before a thread
has been released, only one thread is
released. It is as if the second call
did not happen. Also, if Set is called
when there are no threads waiting and
the EventWaitHandle is already
signaled, the call has no effect.
(Source)
If you want to ensure that a specific number of threads will be signaled, you should use a more suitable kind of synchronization primitive, such as a Semaphore.
When you do SetEvent(event), since your manual reset is set as false for the event, any thread (windows doesnt specify any preferences) from one of the four would get passed the waitforsingleobject() and on the subsequent calls the other 3 threads would randomly be selected since your event is autoreset after releasing every thread.
If you're trying to imply the threads are re-entrant, the threads getting released every time would again be one out of four randomly by OSes choice.

Resources