What is the impact of spinlock between two threads on uniprocessor system - linux-kernel

List item
What happens when we use spinlock on uniprocessor system with two threads running.

The thread in a spinlock would wait spinning until its execution is interrupted by a timer interrupt. As the kernel handles the interrupt, it calls the scheduler, which might decide the timeslice of the thread has expired and schedule the second thread.

Related

Interrupt scheduling and handling in linux

let's say we are getting 100 interrupts from Net device, 50 interrupts from USB, 25 interrupts from SPI device, 25 interrupts from I2c.
It is coming in sequence as follows
5Net - 4USB - 2SPI -2I2C and the same sequence follows.
The top-level handler can dispatch a device-specific handler to service the interrupt
Now the processor will interrupt the running task as soon as it gets the Net device's interrupt. On completing the Top half of Net device's INterrupt handler, it has to execute the top half of USB and SPI and I2C.
And the same sequence will be followed after completing the 1st set of sequence . When the interrupted task will wake again? Do the interrupted task wait until all the 100 interrupt are serviced by their respective device specific handlers?. How the Interrupts are shared to different cores in case multi-core systems as hundreds of thousands of interrupts will have to be serviced?
As far as I know when executing Interrupt handler the processor will be in interrupt context so that there wont be any context switching. As different ISR will have to service hundreds of thousands of Interrupts, do the processor will always be in interrupt context?
When the interrupted task will wake again?
When interrupts are cleared and the scheduler decides to give this task processor time.
Do the interrupted task wait until all the 100 interrupt are serviced by their respective device specific handlers?
You described only 4 IRQs sources (some net device, usb, spi, i2c). So if all IRQ lines are high and enabled, than the cpus which handle these irqs will switch to specific interrupt handlers. If the interrupt is still triggered after the handler, then the cpu servicing it will branch again and again to the interrupt handler until the interrupt is cleared. On multi-cpu system with 5 cpus, 4 may execute interrupt handlers for your devices simultaneously, while the other one will execute your task. So your task may not be interrupted at all. Or it may wait forever for the cpu, on a single cpu system when the interrupt handler is badly written and never clears the IRQ line.
How the Interrupts are shared to different cores in case multi-core systems as lakhs of interrupts will have to be serviced?
I think it is best explained here: multi-core CPU interrupts .
As different ISR will have to service lakhs of Interrupt, do the processor will always be in interrupt context?
It will stay in interrupt context until the IRQ is enabled and IRQ is triggered. You can just disable the IRQ line and return the cpu to the scheduler, if you need.

OS thread scheduling and cpu usage relations

As I know, for threads scheduling, Linux implements a fair scheduler and Windows implements the Round-robin (RR) schedulers: each thread has a time slice for its execution (correct me if I'm wrong).
I wonder, is the CPU usage related to the thread scheduling?
For example: there are 2 threads executing at the same time, and the time slice for system is 15ms. The cpu has only 1 core.
Thread A needs 10ms to finish the job and then sleep 5ms, run in a loop.
Thread B needs 5ms to finish the job and then sleep 10ms, also in a loop.
Will the CPU usage be 100%?
How is the thread scheduled? Will thread A use up all its time and then schedule out?
One More Scenario:
If I got a thread A running, that is then blocked by some condition (e.g network). Will the CPU at 100% affect the wakeup time of this thread? For example, a thread B may be running in this time window, will the thread A be preempted by the OS?
As i know that Linux implements a fair scheduler and Windows System
implements the Round-robin (RR) schedulers for threads scheduling,
Both Linux and Windows use priority-based, preemptive thread schedulers. Fairness matters but it's not, strictly speaking, the objective. Exactly how these scheduler work depends on the version and the flavor (client vs. server) of the system. Generally, thread schedulers are designed to maximize responsiveness and alleviate scheduling hazards such as inversion and starvation. Although some scheduling decisions are made in a round-robin fashion, there are situations in which the scheduler may insert the preempted thread at the front of the queue rather than at the back.
each thread has a time slice for its execution.
The time slice (or quantum) is really more like a guideline than a rule. It's important to understand that a time slice is divisible and it equals some variable number of clock cycles. The scheduler charges CPU usage in terms of clock cycles, not time slices. A thread may run for more than a time slice (e.g., a time slice and a half). A thread may also voluntarily relinquish the rest of its time slice. This is possible because the only way for a thread to relinquish its time slice is by performing a system call (sleep, yield, acquire lock, request synchronous I/O). All of these are privileged operations that cannot be performed in user-mode (otherwise, a thread can go to sleep without telling the OS!). The scheduler can change the state of the thread from "ready" to "waiting" and schedule some other ready thread to run. If a thread relinquishes the rest of its time slice, it will not be compensated the next time it is scheduled to run.
One particularly interesting case is when a hardware interrupt occurs while a thread is running. In this case, the processor will automatically switch to the interrupt handler, forcibly preempting the thread even if its time slice has not finished yet. In this case, the thread will not be charged for the time it takes to handle the interrupt. Note that the interrupt handler would be indeed utilizing the CPU. By the way, the overhead of context switching itself is also not charged towards any time slice. Moreover, on Windows, the fact that a thread is running in user-mode or kernel-mode by itself does not have an impact on its priority or time slice. On Linux, the scheduler is invoked at specific places in the kernel to avoid starvation (kernel preemption implemented in Linux 2.5+).
So the CPU usage will be 100%? And how is the thread scheduled? Will
thread A use up all its time and then schedule out?
It's easy to answer these questions now. When a thread goes to sleep, the other gets scheduled. Note that this happens even if the threads have different priorities.
If i got a thread running, and blocked by some
condition(e.g network). Will the CPU 100% will affect the wakeup time
of this thread? For example, another thread may running in its time
window and will not schedule out by the OS?
Linux and Windows schedulers implement techniques to enable threads that are waiting on I/O operations to "wake up quickly" and get higher chances of being scheduled soon. For example, on Windows, the priority of a thread waiting on an I/O operation may be boosted a bit when the I/O operation completes. This means that it can preempt another running thread before finishing its time slice, even if both threads had the same priorities initially. When a boosted-priority thread wakes up, its original priority is restored.
So the CPU usage will be 100%?
Ideally speaking, the answer would be yes and by ideally I mean , you are not considering the time wasted in doing performing a context switch. Practically , the CPU utilization is increased by keeping it busy all of the time but still there is some amount of time that is wasted in doing a context switch(the time it takes to switch from one process or thread to another).
But I would say that in your case the time constraints of both threads are aligned perfectly to have maximum CPU utilization.
And how is the thread scheduled? Will thread A use up all its time and
then schedule out?
Well it really depends, in most modern operating systems implementations , if there is another process in the ready queue, the current process is scheduled out as soon as it is done with CPU , regardless of whether it still has time quantum left. So yeah if you are considering a modern OS design then the thread A is scheduled out right after 10ms.

How the kernel different subsystems share CPU time

Processes in userspace are scheduled by the kernel scheduler to get processor time but how the different kernel tasks get CPU time? I mean, when no process at userspace are requering CPU time (so CPU is iddle by executing NOP instructions) but some kernel subsystem need to carry out some task regularly, are timers and other hw and sw interrupts the common methods to get CPU time in kernel space?.
It's pretty much the same scheduler. The only difference I could think of is that kernel code has much more control over execution flow. For example, there is direct call to scheduler schedule().
Also in kernel you have 3 execution contexts - hardware interrupt, softirq/bh and process. In hard (and probably soft) interrupt context you can't sleep, so scheduling is not done during executing code in this context.

How to check if a thread is waiting?

For purposes of profiling and monitoring, I would like to know if a thread is currently active (using CPU time) or if it is waiting or sleeping.
Is there a way to find out if a thread is currently in one of the various Windows kernel waiting functions?
From WaitForSingleObject to various mutex, sleep, critical section, IOCP GetQueuedCompletionStatus, and other I/O functions etc. there are quite a few functions that can result in a thread waiting.
Is there a standard way to know if a thread is waiting?
The Wait Chain Traversal API does what you ask. And a whole lot more besides.

In windows, what does the CPU do while blocking

One has blocking calls whenever the CPU is waiting for some system to respond, e.g. waiting for an internet request. Is the CPU literally wasting time during these calls (I don't know whether there are machine instructions other than no-op that would correspond to the CPU literally wasting time). If not, what is it doing?
The thread is simply skipped when the operating system scheduler looks for work to hand off to a core. With the very common outcome that nothing needs to be done. The processor core then executes the HLT instruction.
In the HALT state it consumes (almost) no power. An interrupt is required to bring it back alive. Most typically that will be the clock interrupt, it ticks 64 times per second by default. It could be a device interrupt. The scheduler then again looks for work to do. Rinse and repeat.
Basically, the kernel maintains run queues or something similar to schedule threads. Each thread receives a time slice where it gets to execute until it expires or it volontarily yields its slice. When a thread yields or its slice expires, the scheduler decides which thread gets to execute next.
A blocking system call would result in a yield. It would also result in the thread being removed from the run queue and placed in a sleep/suspend queue where it is not eligible to receive time slices. It would remain in the sleep/suspend queue until some critiera is met (e.g. timer tick, data available on socket, etc.). Once the criteria is met, it'd be placed back into the run queue.
Sleep(1); // Yield, install a timer, and place the thread in a sleep queue.
As long as there are tasks in any of the run queues (there may be more than one, commonly one per processor core), the scheduler will keep handing out time slices. Depending on scheduler design and hardware constraints, these time slices may vary in length.
When there are no tasks in the run queue, the core can enter a powersaving state until an interrupt is received.
In essence, the processor never wastes time. Its either executing other threads, servicing interrupts or in a powersaving state (even for very short durations).
While a thread is blocked, especially if it is blocked on an efficient wait object that puts the blocked thread to sleep, the CPU is busy servicing other threads in the system. If there are no application threads running, there is always system threads running. The CPU is never truly idle.

Resources