I am reading "Linux device drivers 3rd edition", the chapter about concurrrency and race conditions. There is an example I don't completely understand; they are talking about the a common pattern in kernel programming, when one needs to initiate activity (fo rexample, new kernel thread or user process, request for existing process, or hardware based action) outside of the current thread, wait for that activity to complete. The example of not very effective solution开发者_C百科 is:
struct semaphore sem;
init_MUTEX_LOCKED(&sem);
start_external_task(&sem);
down(&sem);
Then they suggest the external task to call up(&sem) when its work is done.
I don't understand why can't we do it this way:
struct semaphore sem;
down(&sem);
start_external_task(&sem);
Why is is necessary to create mutex in locked state and then acquire the mutex after the task has been started?
Looking forward to hearing from you! Thanks.
When you call down(), your thread will block until another thread signals the semaphore. Since the other thread is not yet started, the thread will block indefinitely. That's why you need to start the thread first, and then call down() to block until the thread finishes.
If the thread finishes before you call down(), that's ok, because the semaphore will be signaled and down() will simply clear the signal and return.
In first example down(&sem) will wait for external_task to call up(&sem) and effectively pause main thread until task completion. In your code down() will lock main thread forever since there is no task yet to call up()
The call:
init_MUTEX_LOCKED(&sem);
Creates a new semaphore in "mutex mode" initialised to 0. This means that a call to down()
will block. A corresponding call:
init_MUTEX(&sem);
Would create a semaphore initialised to 1.
In the first example you initialise the semaphore to 0, you create your external_task and you call down()
blocking until your task calls up()
.
In the second example you don't initialise your semaphore, call down()
blocking execution, and have no external_task running which can call up()
to unblock you. The call to create external_task is thus never reached.
Incidentally, the process of initialising the semaphore with init_MUTEX_LOCKED has been removed in kernel version 2.6.37.
精彩评论