From: neves@duvel.cs.colorado.edu (NEVES RICHARD K)
Subject: win32s threads (was Re: NT Products)
Organization: University of Colorado, Boulder
Date: Tue, 1 Sep 1992 03:29:42 GMT

In article <1992Aug31.220520.36021@ans.net> db3l@ans.net (David Bolen) writes:
>In article <1992Aug31.150612.10353@hellgate.utah.edu> brian%jaguar.cs.utah.edu@cs.utah.edu (Brian Sturgill) writes:
>
>>Threads will be "faked" in software under 3.1, there will be thread, but
>
>Hmm - would this really work though?  I mean - one of my complaints with
>thread implementations under Unix variants that work at application level is
>that you can't block in a kernel call without blocking the entire application.
>It seems to me that a popular use of threads in an application (at least in
>my applications) is to allow a background thread to perform lengthy I/O (say
>to a printer, COM port, or disk file) without interfering with the processing
>of the main thread.  With application threads - if I block on an I/O call to
>the COM port, my entire application is blocked, no?
>

Yeah, on the current time slice, but not the next one.

In the current literature, I believe "fake" threads (as referenced above) are 
called "user" threads and threads recognized by the OS are called "kernel" 
threads.

As you point out, the main problem with user threads is that *all* the threads
in an application are treated as a *single* schedulable entity instead of
many entities.  When a thread blocks on IO, the OS says "the process is now
blocked" and doesn't give CPU time to the other threads in the process (ON
THE CURRENT TIME SLICE).  The problems with this strategy are not catastrophic,
just less than optimal.  Your app doesn't block on the next time slice.

[ignore the rest if I made myself clear enough]

The obvious way that win32s would work is: each process has it's own
*thread* scheduler.  When an IO bound thread blocks, the blocked thread is put
at the back of the list of threads to run on the next time slice.  So, the
next time the OS (*process* scheduler) schedules the process with the blocked
thread, the process gives the CPU to a non-blocked thread (while the blocked
thread is probably still be blocked - e.g. your com port - so you aren't
waiting unnecessarily).

Yes, *per timeslice*, user threads are treated unfairly if one of them
blocks since their well-earned time slice is not being fully cashed in.
But since windows doesn't have time slices (all the way around) this 
doesn't matter (ok, not 100% matter).

Since kernel threads are recognized  by the OS, this isn't a problem.  The
OS gives control to the other threads for the remainder of the timeslice.

[slight digression]

User threads are *much* faster at context switching than kernel threads.  
So, in many situations, "fake" threads, are much more efficient than OS
(kernel) threads.

For example, you still have Mach users (Mach has kernel threads) writing 
their own user level thread package to achieve fast context switching.

The best solution is to have a kernel thread for every gang of related user 
threads (i.e. gang scheduling).

There are 1 billion and 1 papers on all this with an equal number of hacks
and tricks that make things quick.  

[in summary]

The user level threads in win32s will probably be limited by windows 
pre-emptive scheduling problems.  Currently, to print in the background,
one "yields".  This relies on Windows passing the processor around fairly
(which it can't).

In short, it doesn't matter that the win32s threads are user threads.
The whole goal of win32s is to allow Windows developers to be source compatible
with NT.  User threads in win32s will do just fine in fullfilling this goal.

Rich Neves
Newsgroups: comp.os.os2.advocacy