views:

136

answers:

3

I'm running 2 threads ( assume they are pthreads for the moment) . Thread_1() makes a user-defined API call which ultimately does some work in the kernel . Thread_2() is totally in user-space.

My question is : Can Thread_2() start executing by pre-empting Thread_1() while the API call is in progress , the control is somewhere inside the kernel ? If not , why , and if I want this scenario to occur ( for any reasons ) , what do I have to do ?

+8  A: 

Calls to the kernel are considered to be either blocking or nonblocking. A blocking call (such as waiting for data to read from a network socket) can certainly be preempted with no action required on your part. Other threads will continue to run. Nonblocking kernel calls can be considered to be very fast and in practical terms it won't matter if you can actually preempt them or not.

Generally, when writing multithreaded code, you concentrate on how those threads interact with each other, and leave their interaction with the kernel up to the kernel to manage. It's designed to do a pretty good job.

Greg Hewgill
Well , in this case , I'm writing a test for the API and the test plans involves analyzing what happens when there is a HW interrupt (can be initiated from Thread_2() while being in user-space) in the midst the API's execution . So , ideally I'd like Thread_1(_ to be able to yield in the midst of the API's execution , give control to Thread_2() (starting a sequence which would lead to a HW interrupt) , coming back to Thread_1() and resume execution - if the API can hold its own/save state etc while the HW interrupt actually hits it , then all is well !
shan23
You might want to see the alternative approach I was thinking in this http://stackoverflow.com/questions/1885903/how-to-call-a-c-function-from-random-places-inside-another-function . You can skip it though - all the info is right here in this question ! :)
shan23
+7  A: 

That depends on the kernel. Classically kernels did not allow preemption (except at specific points when it would sleep a thread). But newer kernels have starting enabling preemption within the kernel itself.

Linux supports a preemptible kernel when it is built with CONFIG_PREEMPT. From the kernel documentation:

This option reduces the latency of the kernel by making all kernel code (that is not executing in a critical section) preemptible. This allows reaction to interactive events by permitting a low priority process to be preempted involuntarily even if it is in kernel mode executing a system call and would otherwise not be about to reach a natural preemption point. This allows applications to run more 'smoothly' even when the system is under load, at the cost of slightly lower throughput and a slight runtime overhead to kernel code.

Select this if you are building a kernel for a desktop or embedded system with latency requirements in the milliseconds range.

R Samuel Klatchko
+3  A: 

If you are asking whether a blocking kernel call like an fread() which requires disk IO can be pre-empted, then yes.

More specifically a blocking call will basically put Thread_1 to sleep while waiting for whatever it's waiting for. If Thread_1 is asleep then Thread_2 will be scheduled to run (unless there's something of higher priority waiting to run).

Edit: If you want a way to be "fairly confident" that Thread_1 is performing a blocking call, make Thread_2 lower priority than Thread_1 (so that it generally doesn't run unless Thread_1 is blocked) and when it runs, it elevates its priority to a higher level than Thread_1 until the hardware interrupt has been delivered, at which point it lowers its priority and calls sched_yield().

Artelius
Actually this assumes that your threads are kernel-managed. And some kernels may vary.
Artelius
Can you clarify - the difference between kernel-managed and non-kernel managed ? What variations exist ?
shan23
Non-kernel-managed threads are seen by the kernel as a single process. The process internally (without kernel support) schedules its various threads. Usually if one of these threads blocks, the whole process is seen as blocked by the kernel and hence no threads run. If the threads are kernel-managed, most kernels will run other threads if one thread blocks. You can run a simple test where one thread calls a syscall repeatedly and another yields repeatedly. If the yielding thread gets any runtime it means the syscall is a pre-emption point.
Artelius
Is there an API which I can call to determine what kind of thread has been created - mananaged / non-managed ?
shan23
This is simply a property of your operating system and threading library. Desktop/server OSes support kernel-managed threads, whilst some embedded OSes do not, because user-managed threads have less overhead.
Artelius