Non-preemptive kernel and computational processes - linux-kernel

I've read in a text book that a non-preemptive kernel has an advantage when dealing with computational processes. I couldn't understand what is the reason for this. I know that non-preemptive kernel allows to run 1 process each time but why is that an advantage for computational process?

Related

FCFS scheduling algorithm is non-preemptive, but what if any system/kernel process arrives?

The first come, first served scheduling algorithm is a non-preemptive algorithm, it means that if there's a process in running state, it cannot be preempted, till it completes. But if some kernel process arrives in between, will the CPU be allocated to that kernel process?
If yes, will this be the case with any higher priority process, irrespective of whether it is a system process or not?
As mrBen told in his answer, there is no notion of priority. It will still be treated as any such process waiting on the ready queue. Hence, this algorithm cannot just be used in Practical.
However, that being said, there are certain situations which makes FCFS a practical use. Consider the use case where the Process Scheduling algorithm uses Priority Scheduling and consider there are 2 processes having the same priority. In this situation to resolve the conflict, FCFS may be used.
In such cases, Kernel Process will always be having higher priority than the user processes. Within Kernel processes, the hardware interrupt has higher priority than the software interrupt since you cannot have a device waiting and starve it while executing signals.
Hope I answered your question!

The Goroutines and the scheduled

i didn't understand this sentence plz explain me in detail and use an easy english to do that
Go routines are cooperatively scheduled, rather than relying on the kernel to manage their time sharing.
Disclaimer: this is a rough and inaccurate description of the scheduling in the kernel and in the go runtime aimed at explaining the concepts, not at being an exact or detailed explanation of the real system.
As you may (or not know), a CPU can't actually run two programs at the same time: a CPU only have one execution thread, which can execute one instruction at a time. The direct consequence on early systems was that you couldn't run two programs at the same time, each program needing (system-wise) a dedicated thread.
The solution currently adopted is called pseudo-parallelism: given a number of logical threads (e.g multiple programs), the system will execute one of the logical threads during a certain amount of time then switch to the next one. Using really small amounts of time (in the order of milliseconds), you give the human user the illusion of parallelism. This operation is called scheduling.
The Go language doesn't use this system directly: it itself implement a scheduler that run on top of the system scheduler, and schedule the execution of the goroutines itself, bypassing the performance cost of using a real thread for each routine. This type of system is called light/green thread.

Parallelism (Threads and Processes)

I have a question. I know the differece between a thread and a process in theory. But I still don't understand when we should use the first and when the latter. For example, we have a difficult task which needs to be parelleled. But in which way? Which is faster and MORE EFFECTIVE and in what cases? Should we split our task into a few processes or into a few threads? Could you give a few examples? I know that my question may seem silly, but I'm new to the topic of parallel computing. I hope that you understand my question. Thank you in advance.
In general, there is only one main difference between processes and threads: All threads of a given process share the same virtual address space. Whereas each process has its own virtual address space.
When dealing with problems that require concurrent access to the same set of data, it is easier to use threads, because they can all directly access the same memory.
Threads share memory. Processes do not.
This means that processes are somewhat more expensive to start up. It also means that threads can conveniently communicate through shared memory, and processes cannot.
However, from a coding perspective, it also means that threads are significantly more difficult to program correctly. It's very easy for threads to stomp on each others' memory in unintended ways. Processes are somewhat safer.
Welcome to the world of concurrency!
There is no theoretical difference between threads and processes that is practical to generalize from. There are many, many different ways to implement threads, including ways that nearly mirror those of processes (e.g. Linux threads). Then there's lightweight threading, which involves the process managing the threading by itself; but there's more variation there, because you can then have either co-operative or semi-preemptive threading model.
For example, we describe Haskell's threading model and Python's.
Haskell offers lightweight threads that introduce little runtime overhead; there are well-defined points at which threads may yield control, but this is largely hidden from the user, giving the appearance of pre-emptive multitasking. Shared state is held in specially typed variables that are treated specially by the language. Because of this, multi-threaded, even concurrent programs can be written in a largely single-threaded way, then forked from the main process. So there, threads are and abstraction mechanism, and may even be beneficial in a single-(OS)-threaded process to model the program; however, it scales well to N-threads, where N may be chosen dynamically. (And N Haskell threads are mapped dynamically to OS threads.)
Python allows threading, but with a huge bottleneck: the Global Interpreter lock. Therefore, to gain serious performance benefits, one must use processes in practice. There is no feasible, performant threading model to speak of.

When should I use parallel-programming?

What could be a typical or real problem for using parallel programming? It can be quite challenging to implement. On the internet they explain how to use it but not why.
Performance is the most common reason to use parallel programming. But: Not all programs will become faster by using parallel programming. In most cases your algorithm consists of parts that are parallelizable and parts, that are inherently sequential. You always have to reason about the potential performance gain of using parallel programming. In some cases the overhead for using it will actually make your program slower. Have a look at Amdahl's law to learn more about the potential performance improvements you can reach.
If you only want some examples of usage of parallel computations: There are some classes of algorithms that are inherently parallel, see this article the dwarfs of berkeley
Another reason for using a multithreaded application architecture is it's responsiveness. There are certain functions which block program execution for a certain amount of time, i.e. reads from files, network, waiting for user inputs, etc. While waiting like this does not consume CPU power, it often blocks or slows program flow.
Using threads in such case is simply a good practice to make the code clearer. Instead of using (often complex or unintuitive) checks for inputs, integrating those checks into program flow, manual switching between handling input and other tasks, a programmer may choose to use threads and let one thread wait for input, and the other i.e. to perform calculations.
In other words, multiple threads sometimes allow for better use of different resources at your computer's disposal: network, disk, input devices or simply monitor.
Generalization: using multiple threads (including parallel data processing) is advisable when the speed and responsiveness gains outweigh the synchronization costs and work required to parallelize the application.
The reason why there is increased interest in parallel programming is partly because the hardware we use today is more parallel. (multicore processors, many-core GPU). To fully benefit from this hardware you need to program in parallel.
Interestingly, parallel processing also improves battery life:
Having 4 cores at 1Ghz draws less power than one single core at 4Ghz.
A phone with a multicore CPU will try to run as much tasks as possible simultaneously, so it can turn off the CPU when all work is done. This is sometimes called "the rush to idle".
Now, some programs are more easy parallelize than others. You should not randomly try to parallelize your entire code base. But it can be a useful excersise to do so even if there is no business reason: then you will be more ready the day when you really need it.
There are very few problems which can't be solved more quickly by a parallel program than by a serial program. There are very few computers which do not have multiple processing units.
I conclude, therefore, that you should use parallel programming all the time.

Linux CFS Volunteer Context Switches SCHED_OTHER SCHED_FIFO

I'm doing some Linux CFS analysis for my OS class and have an observation that I cannot explain.
For two otherwise identical processes, when they are executed with a SCHED_OTHER policy, I am seeing about 50% more voluntary context switches than when I exeucute them with a SCHED_FIFO or a SCHED_RR policy.
This wouldn't surprise me a bit for involuntary switches, since SCHED_OTHER has a much lower priority, so it has to give up the CPU. But why would this be the case for voluntary switches. Why would SCHED_OTHER volunteer to give up the CPU more often than the real-time processes? It's an identical process, so it only volunteers to give up the CPU when it switches over to I/O, right? And I don't think that the choice of policy would affect the frequency of I/O attempts.
Any Linux people have an idea? Thanks!
First understand that the scheduling policies are nothing but the scheduling algorithms that are implemented in the kernel. So SCHED_FIFO, SCHED_RR, SCHED_OTHER are different algorithms in the kernel. SCHED_FIFO and SCHED_RR belong to the real time scheduling algorithms "class". SCHED_OTHER is nothing but the scheduling algorithm for normal processes in the system, more popularly known as the CFS(Completely Fair Scheduler) algorithm.
SCHED_OTHER has a much lower priority
To be precise it doesn't have "much" lower priority but has "a" lower priority than the Real time scheduling class. There are three scheduling classes in the Linux Scheduler - Real-Time scheduling class, Normal Process scheduling class and Idle Tasks scheduling class. The priority levels are as follows:
Real Time Scheduling Class.
Normal Task Scheduling Class.
Idle Tasks Scheduling Class.
Tasks on the system belong to one of these classes. (Note that at any point in time a task can belong to only one scheduling class, although its class can be changed). The scheduler in Linux first checks whether there is a task in the real time class. If any, then it invokes the SCHED_FIFO or SCHED_RR algorithm, depending on what is configured on the system. If there are no real time tasks, then the scheduler checks for the normal tasks and invokes the CFS algorithm depending on whether there is any normal task ready to run. Also
Coming to the main question, why do see more context switches when you run the same process in two different scheduling classes. There are two cases:
Generally on a simple system, there are hardly any real time tasks and most task belong to normal task class. Thus, when you run that process in real time class, you will have all the processor to this process exclusively(since the real time scheduling class has a higher priority than normal task scheduling class, and there are no(/very few real) time task(s) to share the CPU with). When you run the same process in the normal task class, the process has to share the processor with various other processes, thus leading to more context switches.
Even if there are many real time tasks in the system, the nature of the real time scheduling algorithms in question, FIFO and RR, lead to lower context switches. In FIFO, a processor is not switched to other task until the current one completes and in RR there is a fixed interval(time-quanta) that is given to the processes. When you look at CFS, the timeslice that a process gets is proportional to the number of tasks in runqueue of the processor. It is a function of its weight and the total weight of the processor runqueue. I assume you are well versed with FIFO and RR since you are taking OS classes. For more information on CFS I will advice you to google it or if you are brave enough then go through its source code.
Hope the answer is complete :)

Resources