> As per the book Abraham Silberschatz, Greg Gagne, and Peter Baer Galvin,
"Operating System Concepts, Ninth Edition ", Chapter 4 :
4.3.2 One-To-One Model
The one-to-one model creates a separate kernel thread to handle each
user
thread.
One-to-one model overcomes the problems listed above involving blocking
system calls and the splitting of processes across multiple CPUs.
However the overhead of managing the one-to-one model is more
significant,
involving more overhead and slowing down the system.
Most implementations of this model place a limit on how many threads can
be created.
Linux and Windows from 95 to XP implement the one-to-one model for threads.
I would like to know
- Whether windows really creates a kernel thread for each user mode
thread? Or it has a limitation on how many threads can be created in
Kernel mode?
Back in the old MFC group, someone ranted on about how he could not even
remotely consider Windows because of its 64-thread restriction. Fifteen
minutes later, I had an app that created 10,000 threads. I posted the
code to demonstrate beyond any shadow of a double that the OP in this
thread was a complete idiot.
There may be a limit on the number of threads possible. In user space,
the CreateThread call takes a parameter which is the stack depth of the
thread’s stack. Since the default stack depth is a megabyte, this limits
the number of threads a process can create if it just uses the default.
If, however, you give a reasonable size to the stacks, and don’t do silly
things like declaring massive C arrays as local variables (std::vector and
MFC’s CArray don’t count, because the arrays themselves are created on the
heap), you can decrease the size to something much smaller-for example,
64K-which allows you to create many more threads. So the limit for a
given process is based upon two factors (a) the per-process handle limit
and (b) the amount of address space required to hold the stacks. On
Win64, the chance of running out of stack space begins to approach 0 for
any sized stack, which means it is limited by the handle limit. I have
not tried the experiment of creating a thread and immediately closing its
handle to see if I can create more threads than the handle limit.
In the kernel, stacks for threads are very small–I think around 8K or
so–so in general you can ignore this limit as part of thread creation
(but don’t write functions with massive local variable consumption or
highly-recursive functions unless you are willing to create your own
thread with a much larger stack). Address space will be likely to be the
limiting factor.
As already pointed out, there has never been, in the entire history of
Windows, even the MS-DOS versions such as Win95, a concept of 1:1 for
“user threads” and “kernel threads” and the author of that sentence
probably never once actually RTFM for Windows, but based it on some urban
myth.
- Only kernel mode threads are scheduled by the os scheduler or all
threads irrespective of whether they are user or kernel are scheduled by
the os scheduler?
Since there is only one kind of thread, used everywhere, the scheduler
schedules threads. They may be “user” threads, that is, threads created
by CreateProcess or subsequent CreateThread calls, or “kernel” threads,
created by PsCreateThread by kernel components such as drivers, but
ultimately there is exactly one kind of thread from the viewpoint of the
scheduler. It is an equal-opportunity scheduler; tt schedules them
without regard to race, ethnicity, religion, gender identification or
kernel/user beliefs. (To be fair, it does consider thread priority). To
the scheduler, all threads are the same.
- Does context switching among kernel threads takes longer than context
switching among user mode threads. If yes , why?
Since there is only one kind of thread, there is no distinquished issue of
cost. Note the answers you received about fibers, which are a
non-preemptive thread-like illusion implemented by a user-level library.
Inter-fiber “scheduling” is entirely a user-level concept and involves a
very tiny amount of context, specifically, the non-volatile registers (as
defined by the general languge interface standards implemented by the C
compiler).
Generally, you have to take the opinions of anyone who heard about
Windows, but never used it, with a grain of salt. In this case, however,
I would recommend buying your salt in 50-lb (22.6-kg) containers. The
author is so far off-base with this silly characterization that you can
probably safely ignore anything else the book says about Windows. It is
just as likely to be equivalently inaccurate.
There is absolutely zero reason for you to be concerned with the “1:1”
model since, in Windows, the concept does not exist. Note that fibers do
not exist as far as the scheduler is concerned.
As also pointed out, the use of fibers is rare. We had only one case: we
had to simulate the behavior of a non-preemptive embedded operating system
on a remote device in terms of how we communicated to the remote device
from our app. In over 20 years of Windows programming, that’s the only
time I’ve really needed them. Your Mileage May Vary. So it is
nonsensical to even think about a “1:1” model in terms of a user-library
fiction.
I have an example of programming fibers which I can send you; send me
private email. It is a conceptual demo which I gave out as part of my
Advanced Systems Programming course.
Note that when a user-level thread calls the kernel, the “user-level”
thread becomes, just by changing a few registers, a “kernel-level” thread,
with access to the kernel address space and the ability to execute certain
instructions (such as I/O and memory-map-management instructions, to name
a few). The scheduler still sees the same thread, and if you spend too
much time in it, or were called very close to the time-slice-end, then the
scheduler deschedules the thread without regard to its ethinicity, race,
etc. Generally, as driver writers, we are concerned about only two
states of a thread: is the thread executing in the context of the original
caller (hence having direct access to the user-level address space) or is
it executing in an unknown context (hence being unable to access
user-level address space)?
joe
NTDEV is sponsored by OSR
Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
OSR is HIRING!! See http://www.osr.com/careers
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer