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 ?
Kernel preemption is an important feature among mainstream OS kernels. It allows that a kernel thread can be preempted by another kernel thread by performing context switch.
The kernel allows a thread to be preempted by a more favored thread, even when a system call is executing. This capability provides better system responsiveness for large multi-user systems. Because system calls can be preempted, access to global data must be serialized.
A system call is a way for programs to interact with the operating system. A computer program makes a system call when it makes a request to the operating system's kernel. System call provides the services of the operating system to the user programs via Application Program Interface(API).
Under Linux, user-space programs have always been preemptible : the kernel interrupts user-space programs to switch to other threads, using the regular clock tick. So, the kernel doesn't wait for user-space programs to explicitly release the processor (which is the case in cooperative multitasking).
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.
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.
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()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With