I have read the Many to Many Model in Operating System book by "Abraham Silberschatz". In chapter 4 it says that
"The Solaris operating system supported the many to many model in versions older than Solaris 9. However,
beginning with Solaris 9, this system uses the one-to-one model."
My Question are given in the following.
May be answer mention in book and I can't understand it, and I search on internet also but can't find a useful information why shift happen?
what are the issues with many to many model?
Why shift occur from many to many model to one to one model?
I've only worked on systems that implement what some call the one-to-one model. This classification of one-to-one/many-to-many/and many-to-one IMHO is misleading.
The suggestion here is that, in the "one-to-one model," each thread really creates two threads: A kernel mode thread and a user mode thread. In reality, all that is needed a single thread that can operate in both user and kernel modes (i.e., a kernel mode stack).
The advantage a thread that can operate in both kernel and user mode (an possibly other modes as well, aka one-to-one model) is that the threads can operate completely independently and is likely simpler to implement. Each thread can enter kernel mode (e.g. perform I/O) without blocking any other thread. The alleged downside is that this requires each thread to have its own kernel mode stack.
Again, I have not worked on a many-to-one or many-to-many system but I would suspect that these are not implemented with separate kernel mode threads but rather with kernel mode data structures that are shared by multiple threads.
what are the issues with many to many model?
The clear downside to many-to-many and many-to-one is that kernel mode becomes a resource whose unavailability can cause one group of threads to block another group of threads.
Let's say you have 3 kernel mode "threads" and 10 user mode threads. If 4 user mode threads try to do I/O at the same time, the 4th thread will block until one of the first three threads complete.
It is also more complicated to implement because you would have to manage the kernel mode "threads" as resources.
Why shift occur from many to many model to one to one model?
I cannot think of any practicable advantage of one-to-many or many-to-many and can think of many disadvantages (above). That is probably why there was a shift.
That said, IMHO, this is a confusing way to explain threading.
Related
I'm aware that User Level threads are created on the User Mode( no privileges) and Kernel threads are created in the Kernel Mode( privileged).
I am also aware that Processor threads are hardware threads that operate on Kernel Threads( I hope I am correct by putting it in this way)
Here is my confusion:-
User Level threads are not recognized by the OS as they are created, maintained and destroyed on the User Level. The OS doesn't see a multithreaded process from the User Mode as being multithreaded. It treats it as a single threaded process. Therefore, this program cannot take advantage of Multiprocessing, I guess it cannot take advantage of hyperthreading as well since it appears as single threaded in the OS.
So what's the use of Multithreading in this case? I mean the computation time will still be the same🤷♂️.
The last question is, do POSIX thread API and OPenMP create user level threads or Kernel threads?
I know what both libraries are, please don't explain about that.
If none creates Kernel threads then how do we create a multithreaded program that takes advantage of multiprocessing?
...what's the use of Multithreading in this case?
Multithreading is older than multiprocessing. Multithreading is one model of concurrent computing. That is to say, it's a way to write a computer program in which different activities are allowed to happen independently from each other. A classic example is a multi-user network server that creates a new thread for each connected client. Each thread can talk to its own client in a simple, synchronous way even though there may be no synchrony between what the different clients want to do. You don't need to have multiple CPUs for that.
When multi-CPU computers were invented, using multiple threads to exploit them for parallel processing was a natural and obvious choice.
I mean the computation time [for a green-threaded program that cannot exploit multiple CPUs] will still be the same.
That is true, but depending on what the different activities are that the program performs concurrently, the multi-threaded version of it may be easier to read and understand* than a program that's built around a different model of concurrency.
The reason is, we all were taught to write single-threaded, synchronous code when we were beginners. We understood that we were writing instructions that "the computer" would follow. We now say "a thread" instead of saying "the computer," but otherwise, the code executed by each thread can be mostly similar to the style of code that we wrote as beginners.
Part of what makes it so simple is, that the state of each of the concurrent activities can be mostly implicit in the contexts and the local variables (i.e., the stacks) of the different threads. If you choose a different model of concurrency (e.g., an event driven model) then you may have to explicitly represent more of that state with (maybe complex) data structures.
* Easier to read but not necessarily easier to write without making subtle mistakes. But, when I started working with large teams of software developers, they taught me that I'd be reading about ten lines of code for every one line that I wrote, so "easier to read but harder to write" turns out to be a win in the long run.
Pure user level threads are (as you pointed out) not a lot of use because they don't allow you to exploit the processing capability of multiple cores within a process.
The flip-side is that pure kernel level threads will typically incur substantial overheads when switch between threads. (There are things that you can do to deal with that, but ... that's another topic.) But the upshot is that the overheads make it inefficient to preform small tasks (units of work) using kernel level threads.
Another alternative to both is a hybrid of user level and kernel level threads. For example, suppose:
each process has one kernel level thread for each physical core,
each kernel level thread can switch between a bunch of user level threads and,
switching between a user level threads is handled by a scheduler in user space.
The Java Loom project is developing a new threading model (roughly) along those lines. Classic Java threads are still kernel level threads. New virtual threads are user level threads. A Java program gets to choose whether it uses classic or virtual threads ... or both.
There is a lot of material on Loom on the web; e.g.
https://blogs.oracle.com/javamagazine/post/java-loom-virtual-threads-platform-threads
https://www.infoq.com/news/2022/05/virtual-threads-for-jdk19/
https://wiki.openjdk.org/display/loom/Main
Loom is likely to be part of the next Java release: Java 19.
I'm pretty sure that (C / C++) POSIX threads are kernel level. I don't know about OpenMPI threads, but I'd expect they are kernel level too. (They wouldn't be fit for purpose as pure user level threads.)
I have heard of hybrid threading models for C / C++, though I don't know about actual implementations. Look for articles, etcetera that talk about Threads vs Fibres.
I understand that the user level threads or green threads are managed by some user-level threading library and have to be "linked" to some operating system thread to perform its task. I understand that threads are just an abstraction for a sequence of independent code. Threads are represented with some data structures stored in the memory. In the case of user level or green threads are present in the user space and are managed by the user-level threading library. In case of OS level or kernel level threads, they are stored and managed by the kernel or OS. What I don't understand is what actually is meant by the linking a green thread to OS thread?? I know about the 1:1, n:1, n:m schemes and that is not what my question is about. My question is what data structures are copied or shared (or something else) between the green thread and the kernel thread it is bound to?? And what does the user level threading library do to these structures when green threads have to context switched??
There are THREADS and there are SIMULATED THREAD. What you are calling a "green thread" is a SIMULATED THREAD.
The kernel has no knowledge whatsoever of the existence of a simulated thread.
My question is what data structures are copied or shared (or something else) between the green thread and the kernel thread it is bound to?
The answer then is NONE; at least at the operating system level. The process must keep track of the threads in the user space.
I know about the 1:1, n:1, n:m schemes and that is not what my question is about.
The 1:1, n:1 and n:M schemes are complete and total academic BullS*&T designed to confuse students. There is no such thing as an n:M in threading. It is impracticable theoretical nonsense. 1:1 just means real THREADS. n:1 means SIMULATED THREADS.
Only two models exist in real life:
In the classic model, a process consisted of an execution stream and an address space.
In the current model, a process consists of multiple execution streams and an address space.
In the classic model there are no threads. If you want threads, you have to simulate them using libraries with timers; a topic that is not fit for an operating systems course, except for historical background.
In the current model, the multiple execution streams are called threads. There is no reason whatsoever to use simulated/green/user threads in the current model. The textbooks that say simulated/green/user threads have any advantage are only fit to be used for cat box liner.
I'm looking for some background explanations about context switch in modern personal computers with mainstream architecture (say x64).
While context switch is mainly done by the hardware, I wonder what in the computer decides of task scheduling and context switch when running multiple threads and/or multiple processes. Is it the CPU itself, the operating system, the compiler/virtual machine... ?
I'd like to have an idea of what strategies are used to decide when to switch. For example, if I start a hundred threads doing independent dummy additions in endless loops, when will the context switches happen?
This is a complex subject that I can't do justice in a simple response here. But let me hit some high-points. I further am going to assume modern OS's like Windows or the various Unix derivatives and ignore embedded real-time systems.
The context switch is not performed in hardware. It is critical to understand this. It is performed in software via a OS subsystem known as the scheduler. The scheduler is a glorified interrupt controller that will fire many times a microsecond and decide what thread will execute next. The algorithms for doing so are numerous and the subject of many a PHD thesis. A good overview I found quickly is here: http://www.studytonight.com/operating-system/cpu-scheduling
Good Operating Systems books will go over this in detail. There are too many to note so pick your poison.
One last point, to grasp at a complete level how scheduling is performed it really helps to understand how virtual addressing schemes work as that is truly what differentiates processes from threads. Threads are what is critical in terms of the Scheduler put processes encapsulate threads and the virtual memory space.
I'm not sure this helps but I was at least able to correct one misconception and point you at a simple article on OS thread scheduling.
I have been following a course on Operating Systems over the past few months. However, I'd like some clarification on one point that I read. From my understanding, there are three types of multithreading models to map user level threads to kernel level threads -
Many to one model
Many to many model
One to one model
I can see why the many to one model is not very efficient when it comes to parallel processing - because a blocking system call would mean halting of any processing.
However, in the book I'm referring, Operating System Concepts (By Abraham Silberschatz, Greg Gagne and Peter Galvin), it says that both Linux and the Windows family use the one to one model, even though there is the extra overhead of creating a kernel thread for every user thread that's created.
Wouldn't a many to many model be better? Because you have a number of kernel threads, sufficient to have a high degree of parallelism, and you can always opt for a two level model to bind a user level thread to a kernel level thread.
TLDR: Why is the one to one multithreading model preferred over many to many model despite the overhead in Windows and Linux systems?
Wouldn't a many to many model be better?
I'd suggest getting another book. AFAIK the Many-to-Many model is entirely theoretical (If someone knows of a system that uses it, please indicate in a comment). These models are a very poor way of explaining threads.
In ye olde days operating system had no concept of threads. They scheduled processes for execution. In fact, this is still the case for many operating systems.
The need for threads was largely driven by the Ada programming language that required "task" support. In order to have a compliant Ada implementation there had to be a library that simulated threads within a single process. In such a system a process schedules its own thread execution ("user threads). This has the drawback that the threads always run interleaved (never in parallel on different processors).
This is being called "many to one" but that is a poor description of what is happening. Your model calls that "many user threads" are being mapped to a single "kernel thread." In reality, there are no kernel threads. Instead threads are being implemented in the context of a process.
It has become common for operating systems to view processes as an address space with multiple schedulable threads of execution. in such a system the thread is the basic unit of scheduling; not the process. Is is the one-to-one model in your scheme.
it says that both Linux and the Windows family use the one to one model, even though there is the extra overhead of creating a kernel thread for every user thread that's created.
This is kind of BS.There is overhead for a thread no matter how they are implemented. You will often find people claiming that "Many-to-One" is more efficient than "One-to-One." This claim appears to be just urban legend.
Why is the one to one multithreading model preferred over many to many model despite the overhead in Windows and Linux systems?
The "one-to-one" (aka kernel threads) model is preferable because it takes advantage of multiple processors and allows actual execution in parallel. It also avoids blocking problems that can occur in some systems (e.g. Eunuchs).
AFAIK, the "many to many" model implies doing the scheduling in user space, so it means that each program must have its own scheduler running in each kernel thread, using it to share that thread between the user threads assigned to it. In other words: you need something like GNU Portable Threads running in each kernel thread to dispatch the user threads assigned to that kernel thread (https://www.gnu.org/software/pth/).
What is the difference between kernel threads and user threads? Is it that kernel thread are scheduled and executed in kernel mode? What are techniques used for creating kernel threads?
Is it that user thread is scheduled, executed in user mode? Is it that Kernel does not participate in executing/scheduling user threads? When interrupts occur in executing user thread then who handles it?
Whenever, thread is created a TCB is created for each. now in case of user level threads
Is it that this TCB is created in user's address space ?
In case of switching between two user level threads who handles the context switching ?
There is a concept of multithreading models :
Many to one
One to one
Many to Many.
What are these models? How are these models practically used?
Have read few articles on this topic but still confused
Wants to clear the concept ..
Thanks in advance,
Tazim
Wikipedia has answers to most if not all of these questions.
http://en.wikipedia.org/wiki/Thread_(computer_science)
http://en.wikipedia.org/wiki/Thread_(computer_science)#Processes.2C_kernel_threads.2C_user_threads.2C_and_fibers
What is the difference between kernel threads and user threads?
Kernel threads are privileged and can access things off-limits to user mode threads. Take a look at "Ring (Computer Security)" on Wikipedia. On Windows, user mode corresponds to Ring 3, while kernel mode corresponds to Ring 0.
What are techniques used for creating kernel threads?
This is extremely dependent upon the operating system.
now in case of user level threads Is it that this TCB is created in user's address space ?
The TCB records information about a thread that the kernel uses in running that thread, right? So if it were allocated in user space, the user mode thread could modify or corrupt it, which doesn't seem like a very good idea. So, don't you suppose it's created in kernel space?
What are these models? How are these models practically used?
Wikipedia seems really clear about that.
Kernel thread means a thread that the kernel is responsible for scheduling. This means, among other things, that the kernel is able to schedule each thread on different cpus/cores at the same time.
How to use them varies a lot with programming languages and threading APIs, but as a simple illustration,
void task_a();
void task_b();
int main() {
new_thread(task_a);
new_thread(task_b);
// possibly do something else in the main thread
// wait for the threads to complete their work
}
In every implementation I am familiar with, the kernel may pause them at any time. ("pre-emptive")
User threads, or "User scheduled threads", make the program itself responsible for switching between them. There are many ways of doing this and correspondingly there is a variety of names for them.
On one end you have "Green threads"; basically trying to do the same thing as kernel threads do. Thus you keep all the complications of programming with real threads.
On the opposite end, you have "Fibers", which are required to yield before any other fiber gets run. This means
The fibers are run sequentially. There is no parallell performance gains to be had.
The interactions between fibers is very well defined. Other code run only at the exact points you yield. Other code won't be changing variables while you're working on them.
Most of the low-level complexities programmers struggle with in multithreading, such as cache coherency (looking at MT questions on this site, most people don't get that), are not a factor.
As the simplest example of fibers I can think of:
while(tasks_not_done) {
do_part_of_a();
do_part_of_b();
}
where each does some work, then returns when that part is done. Note that these are done sequentially in the same "hardware thread" meaning you do not get a performance increase from parallellism. On the other hand, interactions between them are very well defined, so you don't have race conditions. The actual working of each function can vary. They could also be "user thread objects" from some vector/array.
Essentially user threads run in the context of a user with the appropriate privilege levels e.g. user threads most certainly won't have access to kernel-level memory/data structures/routines etc. Whereas Kernel threads run in the context of the OS kernel thus giving them privileges to execute code which has access to low level kernel routines/memory/data structures.