I'm not quite sure how to interpret this. Our implementation is a hosted
implementation. Are we required to support *concurrent* threads (even on,
say, DOS)? It seems so. On the other hand if we declare our DOS target as a
freestanding implementation are we allowed to then not support threads at
all? It seems so.
The confusion I'm experiencing is due to the fact that there is something
between truly concurrent threads and no threads... namely cooperative threads
that only context switch at certain well defined places. Sometimes they are
called "user mode" threads.
I guess I need to understand better what the standard means by "concurrent,"
exactly. I have a feeling that one needs to slog through the detailed
discussion of the C++ memory model to understand just what must be supported.
That's pretty heavy reading, but I guess it needs to be read. :)
Peter
>As you may know the upcoming C++ standard has support for threading. It might
>be fun to start thinking about how we are going to implement that support.
>The draft standard says that in a hosted implementation a program "can have
>more than one thread running concurrently." Note the use of the word "can"
>and "concurrent." On the other hand, for a freestanding implementation it
>is "implementation defined whether a program can have more than one thread of
>execution."
>
>I'm not quite sure how to interpret this. Our implementation is a hosted
>implementation. Are we required to support *concurrent* threads (even on,
>say, DOS)? It seems so. On the other hand if we declare our DOS target as a
>freestanding implementation are we allowed to then not support threads at
>all? It seems so.
Unless the definition of "freestanding" has changed, that won't work
(n2135.pdf):
"A freestanding implementation is one in which execution may take
place without the benefit of an operating system, and has an
implementation-defined set of libraries that includes certain
language-support libraries (17.4.1.3)."
Hopefully, one of these statements is true:
1) The Standard no longer applies to DOS.
2) The Standard makes an exception for DOS.
3) The Standard qualifies its assertion with something like "depending
on what the underlying operating system provides".
If worst comes to worst, we can always note that our DOS (and, if
appropriate, Win16/Win386) support does not comply with the standard
in that it does not provide "concurrent threads" and not worry about
it.
>The confusion I'm experiencing is due to the fact that there is something
>between truly concurrent threads and no threads... namely cooperative threads
>that only context switch at certain well defined places. Sometimes they are
>called "user mode" threads.
Way back when, this difference was between "preemptive" and
"cooperative" multitasking.
Of course, way back then, a "thread" was a "light-weight process" and
multitasking was discussed in terms of processes, not threads.
So the terminology may well have changed a bit in the intervening
decades.
>I guess I need to understand better what the standard means by "concurrent,"
>exactly. I have a feeling that one needs to slog through the detailed
>discussion of the C++ memory model to understand just what must be supported.
>That's pretty heavy reading, but I guess it needs to be read. :)
If it's in a PDF file, searching on "concurrent" might turn up a
definition. Or not. You never know until you try.
Hopefully, "concurrent" will turn out to include both the "preemptive"
and "cooperative" variants.
Win16 is "cooperative". Well, OK, enhanced mode may be preemptive in
fact, but the programming model is cooperative: that's why programmers
are encouraged to do things that, in cooperative multitasking, amount
to requesting a task switch. And a lot of "the cooperative task
switches" are hidden inside other functions that would be called
anyway, such as requesting the next message or asynchronous I/O (this
thread is waiting for I/O? Run a different one for a while!). For user
code, it's mostly about not doing busy-wait loops (not looping around
waiting for a key to be pressed, for example).
And there is at least one commerical library (Multi-C) that does
cooperative task switching under DOS. So, if cooperative multitasking
counts, it can be done. OTOH, if preemptive task switching is
required, it is highly unlikely that that will work with DOS (just
imagine a task switch occurring in the middle of an interrupt-service
function!).
And, of course, there's always the possibility that they actually mean
/concurrent/: that is, that each thread must run on its own processor
(core), and so the number of threads that must be supported is limited
to the number of available processors (cores). Most "multitasking" is
not really "concurrent"; it only looks that way.
--
Nature must be explained in
her own terms through
the experience of our senses.
Yes. It is impossible to implement preemptive task switching in
DOS, simply because DOS was designed in such a stupid way
it was. The worst thing was the stack-switch that every int 21
function did upon entry. This in itself make multitasking in ordinary
DOS impossible.
That was the original reason why I started the RDOS project. To provide
a reentrant DOS.
Leif Ekblad
| OTOH, if preemptive task switching is
| required, it is highly unlikely that that will work with DOS (just
| imagine a task switch occurring in the middle of an interrupt-service
| function!).
Actually, MS-DOS is not the only OS incapable of doing that. No system with
a single processing unit could do it, no matter what OS is in use, be it
MS-DOS or Windows 7, Linux or BSD, or even OpenVMS. As long as peripheral
devices with finite buffering capability and data transfer not under
processor control exist, e.g., communication channels, they will require
high priority servicing that would need to be completed to prevent data
loss, before the processor could perform the application process/thread/task
switching. However, time spent completing such OS functions would not be
available for application processing anyway, and is not normally considered
eligible for task switching. The customary definition of preemptive task
switching would refer to which task gets control when the OS service is
completed.
| And, of course, there's always the possibility that they actually
| mean /concurrent/: that is, that each thread must run on its own
| processor (core), and so the number of threads that must be
| supported is limited to the number of available processors (cores).
| Most "multitasking" is not really "concurrent"; it only looks that
| way.
I seriously doubt a language standard would require the availability of
multiple processing units. It would make most of the computers in the world
incapable of executing standard-compliant programs.
I'd conclude that for any target OS which does not contain its own
multithreading capability OW would need to provide its own software to be
fully standard compliant. Since our C++ is still far from compliance, I'd
consider this issue could go on the back burner. Something to do when OW
complies with other significant aspects of the standard.
--
Steve
Of course it would be a nice to have compiling and running mthreads under
DOS. But I think the library should deny cimpiling under DOS. Maybe simply
by mapping the class thread to a define under DOS which leads to an error
pragma saying that mutliple threads are excluded by operation system.
The same applies to freestanding implementations: Since there is no OS which
supports multithreading it depends on the implementation itself if it can
support it.
I see DOS as half of a freestanding implementation since multi tasking or
even multithreading or multiprocessing is not supported (last one does not
apply to NWDOS where some sort of it is possible).
"Peter C. Chapin" <pe...@openwatcom.org> schrieb im Newsbeitrag
news:hmgopc$aik$1...@www.openwatcom.org...
I am not sure if they by concurrent mean pre-emptable. If the standard does
not specify pre-emptable threads I guess there is no problem to support a
version on DOS. As an example: http://upthread.sourceforge.net/
(BSD license) I have seen several sources like the one above over the years.
> The confusion I'm experiencing is due to the fact that there is something
> between truly concurrent threads and no threads... namely cooperative threads
> that only context switch at certain well defined places. Sometimes they are
> called "user mode" threads.
My understanding may be off, but the difference in this case should be
talked about as "non pre-emptable" or "pre-emptable" thread systems.
Maybe the standard accepts both?
> I guess I need to understand better what the standard means by "concurrent,"
> exactly. I have a feeling that one needs to slog through the detailed
> discussion of the C++ memory model to understand just what must be supported.
> That's pretty heavy reading, but I guess it needs to be read. :)
Here is a draft compliant thread lib for C++. It is commercial, but
maybe someone can learn enough from the documentation to know the answers...
Roald
David Golub
"Peter C. Chapin" <pe...@openwatcom.org> wrote in message
news:hmgopc$aik$1...@www.openwatcom.org...
Note the use of the word "can" [...]
... and the absence of the word "shall", which is the usual way of specifying a normative requirement.
I will put this to some people on the mailing list, as an example of how the draft isn't clear to implementors. But, informally and speaking just for myself, my own interim advice is this: Don't go down the road of thinking that you need to implement multithreading for a PC/MS/DR-DOS target. The intent is almost certainly not to require such heroic efforts from implementations.
Note, by the way, that this is a draft standard. It's not in its final form, yet. (I was at a standards meeting last week where we turned up several things that are less than ideal about the current draft.) Threading is still subject to change, not least in the area of thread local variables.
On that parenthetical point: The review process for proceeding to FDIS is now. If, with the fresh eyes of an implementor trying to implement what the standard requires, you spot any problems, inconsistencies, or outright errors, feel free to let me, or others involved in the process (such as the national body members in your own countries), know. We're composing issues lists right now. I stress, for clarity, that at this stage problems, inconsistencies, and errors are sought, preferably with concrete ways of correcting the text of the standard accompanying them. We are not seeking blue sky proposals, wild new language or library features, half-baked ideas, or vague "Fixing the issue is somebody else's problem." handwaving.
For an example of a proposed wording change, see this
(This hyperlink may rot quickly.) and the rationale that accompanies
it. Wording changes usually involve showing exactly what (if anything)
to remove and what (if anything) to replace it with. A more complex,
and relevant, example will be in Anthony Williams' forthcoming papers
on thread-local variables and on the return types of wait_until
and wait_for in futures. (-:
> As far as I know, it's impossible to write multithreaded programs on DOS or
> Win16. I'd say to just either not provide the functions in question on
> those operating systems or write stub functions that always fail.
I think it would be possible to implement a form of user mode threads
(cooperative threads) for DOS. Years ago I used an Ada compiler for DOS that
supported Ada's required concurrency features. It worked fairly well.
However, Ada specifically allows a non-preemptive implementation and that's
what was done in that case.
The draft C++ standard isn't direct about it, but my guess is that a careful
reading of the thread execution model will reveal that a non-preemptive
implementation can be conforming. I say that only because I have faith in the
authors of the standard to account for that possibility. I have not yet
digested the material well enough to say for sure.
I'm not particularly in favor of defining our DOS target as a freestanding
implementation. That certainly hasn't been the intent in the past...
obviously.
Peter
Not true. Early versions of Linux couldn't handle task-switching in kernel,
but
I think current versions can. Windows had task-switching in the kernel for
some
time. RDOS uses a lot threads in kernel-space, only has a small part of code
associated
with the scheduler that cannot be task-switched, and can even do (remote)
kernel-level
debugging on single threads without affecting system stability. This novel
approach
to debugging is also why RDOS will need special functions in traps / wd to
support
the functionality fully.
> As long as peripheral devices with finite buffering capability and data
> transfer not under processor control exist, e.g., communication channels,
> they will require high priority servicing that would need to be completed
> to prevent data loss, before the processor could perform the application
> process/thread/task switching. However, time spent completing such OS
> functions would not be available for application processing anyway, and is
> not normally considered eligible for task switching. The customary
> definition of preemptive task switching would refer to which task gets
> control when the OS service is completed.
Yes, but only small parts of the scheduler itself needs to be protected from
task switching in a "good design". What hinders multitasking in MS-DOS is
that syscalls set up a single stack upon entry. When another thread enters a
syscall, it will reuse the same stack, and crash. This could easily be
solved by
having one syscall stack per thread, but since MS-DOS don't know about
threads, it does not have this. The obvious solution to just put a semaphore
on syscalls also do not work since some syscalls never returns (for instance
load program and terminate program).
Leif Ekblad
I would think that user-level threads (non-preemptive) could be useful for
any
environment. They can also be implemented rather independently from
preemptive
multitasking threads part of OSes. Especially on systems where
multithreading
is costly (Windows), user-threads could be an alternative. User-level
threads
also do not require the use of synchronization primitives, and are probably
easier to work with for people that don't know so much about multithreaded
development.
Leif Ekblad
The intent is that the implementation is NOT REQUIRED to provide
multithreading, though the classes and functions from the thread library
must be supported in a minimal fashion.
Note that the std::thread constructor is allowed to throw a
std::system_error with an error condition of
resource_not_available_try_again if "the system lacked the necessary
resources to create another thread, or the system-imposed limit on the
number of threads in a process would be exceeded."
On DOS I would expect that the limit on threads per process is 1 --- the
initial thread --- and that all uses of this would throw.
Any multithreading supported as part of the C++ library must in practice
be pre-emptive. For example, if you have a thread running a loop that
tests an atomic variable and another thread that sets that variable then
the second thread must be given a chance to run so the first thread can
complete. You could in theory put a context switch on every possible
synchronization point including atomic variables, but I think that would
be hideously slow.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++0x thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
> On DOS I would expect that the limit on threads per process is 1 --- the
> initial thread --- and that all uses of this would throw.
>
> Any multithreading supported as part of the C++ library must in practice
> be pre-emptive. For example, if you have a thread running a loop that
> tests an atomic variable and another thread that sets that variable then
> the second thread must be given a chance to run so the first thread can
> complete.
It would probably be useful to provide a thread library for DOS that allows
the programmer to create multiple non-preemptive threads with the
understanding that attempts to spin on an atomic variable will just loop
infinitely. Are you saying that the draft standard specifically requires the
use case you described above (regarding atomic variables) to work on all
platforms?
My guess is that there are many useful programs that don't actually care if
the threads are preemptive or not. It would be nice if those programs
compiled and ran correctly on DOS.
On the other hand, for a first time around it may make sense to just stub out
the thread support on DOS with errors. Or maybe, as Leif said, it makes sense
to just offer non-preemptive threads only on all platforms initially.
Peter
> User-level threads
> also do not require the use of synchronization primitives...
I don't think this is entirely true. Even with explicit context switching at
certain places in the program it is still possible that a programmer will
want to leave a complex data structure in an inconsistent state before doing
such a switch.
The Linux kernel used synchronization primitives internally even when it was
not preemptive. In some places theads would sleep while the data structures
they were manipulating were inconsistent. The need for synchronization is
reduced by using non-preemptive threads, but not eliminated.
Peter
Yes. See 29.4p11 of the current working draft
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3035.pdf
"Implementations should make atomic stores visible to atomic loads
within a reasonable amount of time."
If you have non-preemptive threads then this will not be satisfied
unless the threads involved do something that causes a context switch.
> On the other hand, for a first time around it may make sense to just stub out
> the thread support on DOS with errors. Or maybe, as Leif said, it makes sense
> to just offer non-preemptive threads only on all platforms initially.
Support for non-preemptive threads is outside the scope of the C++0x
standard. You could provide them as an extension, but if that is the
only threading provided I would suggest using another mechanism than
std::thread to start the threads.
| Not true. Early versions of Linux couldn't handle task-switching in
| kernel, but I think current versions can. Windows had task-switching
| in the kernel for some time. RDOS uses a lot threads in kernel-space,
| only has a small part of code associated with the scheduler that
| cannot be task-switched, and can even do (remote) kernel-level
| debugging on single threads without affecting system stability. This
| novel approach to debugging is also why RDOS will need special
| functions in traps / wd to support the functionality fully.
I was not referring to the question of what part of the software does
the task switching. I was referring to the fact that there are
operations the OS must perform during which task switching cannot
take place without loss of data, and potentially even loss of system
integrity. For example, in any modern OS a preemptive thread switch
in the middle of updating the paging table wolud wreak havoc.
|| As long as peripheral devices with finite buffering capability and
|| data transfer not under processor control exist, e.g.,
|| communication channels, they will require high priority servicing
|| that would need to be completed to prevent data loss, before the
|| processor could perform the application process/thread/task
|| switching. However, time spent completing such OS functions would
|| not be available for application processing anyway, and is not
|| normally considered eligible for task switching. The customary
|| definition of preemptive task switching would refer to which task
|| gets control when the OS service is completed.
| Yes, but only small parts of the scheduler itself needs to be
| protected from task switching in a "good design". What hinders
| multitasking in MS-DOS is that syscalls set up a single stack upon
| entry...
You are agreeing with me that there are times when preemptive task
switching must be delayed! As to MS-DOS, I did not go into why it is
unsuitable for OS-level multithreading, indeed, I was showing that no
matter what hardware and what OS you use, there are uninterruptible
tasks, so that totally preemptive task switching is possible only if
there is always available a processor never used for uninterruptible
operations.
--
Steve
Several OW targets already have preemptive threads (Win32, Linux, RDOS),
and providing this functionality would probably not be too hard for these.
Somebody
just need to put up the framwork (or implement it for one of the targets).
With
an existing framework in place, I think I could provide the RDOS
implementation
without much effort. There is also the Posix thread functions, which some
targets
support, and libc has been designed with multithreading in mind.
Leif Ekblad
Naturally, but this is always so, regardless if you have a single processor
or multiple processors. Multi-processor systems also need to protect
shared data, and it is actually harder to do in such a system than in
a single processor system were "cli" / "sti" is all you need.
Leif Ekblad
<snippo>
>| And, of course, there's always the possibility that they actually
>| mean /concurrent/: that is, that each thread must run on its own
>| processor (core), and so the number of threads that must be
>| supported is limited to the number of available processors (cores).
>| Most "multitasking" is not really "concurrent"; it only looks that
>| way.
>
>I seriously doubt a language standard would require the availability of
>multiple processing units. It would make most of the computers in the world
>incapable of executing standard-compliant programs.
I was unclear. The suggestion was that the Standard would require
multiple threads /only/ when multiple processors were present: one
processor, only one thread required.
I actually doubt that they are using "concurrent" to actually mean
"concurrent"; rather, as has been the case for most computers for the
last several decades, they include in it the simulated concurrency we
are accustomed to. Only time will tell.
Presumably, this being a C++ standard, the net effect will be to
require the implementation of a new set of classes and/or functions,
no doubt fully and exhaustively featured and templatized.
>As far as I know, it's impossible to write multithreaded programs on DOS or
>Win16.
<snipped a bit>
That would be news for Mix Software, which has been selling Multi-C
(http://www.mixsoftware.com/product/multic.htm) for nearly two decades
(the manual is copyright 1992).
Of course, this is /cooperative/ multithreading. If you are thinking
of /preemptive/ multithreading, then I would agree with you.
I think better words would be "overlapping" or "interleaved", which would
clarify that a single processing unit can only execute a single process at
any particular instant.
Jonathan, is it possible for you to make such a recommendation to the
stadards committee?
--
Steve
The C++ draft talks about threads not processes. What prevents the
implementation from hooking int 21 and switching threads only when the
program happens to be executing user code? I have done this 15 years ago and
it worked well. This worked even in the environments controlled by a DOS
extender. The situation was only a little bit tricky, because the DPMI ISR
routines were usually called on a separate stack provided by the DPMI
server. Hence the stack could not be switched directly. But again, one could
completely bypass the extender by directly installing the switch ISR to
the IDT table. Not a big deal.
-Marek
FYI, 1.10p1 of the C++0x draft says (amongst other things) "Note:
Usually the execution can be viewed as an interleaving of all its threads".
And then there is DR-DOS (OpenDOS/Novell DOS) that has preemptive
multitasking and multithreading (info here:
http://www.drdos.com/dosdoc/multtask/index.htm). That option is probably
not useful as it's limited to DR-DOS. It does however show that it's
possible.
Matjaz
What a pre-emptive task switcher does do is guarantee that an impolite
application cannot hog more than its share of CPU time. It also frees the
programmer from the extra code necessary to be polite, and generally makes
the OS appear more responsive (as Windows sometimes is not).
What a pre-emptive task switcher also does is take more CPU time and memory
to operate. In the best case scenario it salvages enough wasted time by
task switching blocked tasks to more than make up for the extra overhead.
In the worst case scenario, it may free the programmer from sharing concerns
and make the system appear more responsive, while actually accomplishing
less per unit of time because of the considerable extra overhead required to
safely switch pre-emptively. Where a given system falls along that line
will depend on a number of things such as the "tick" time and how well
applications obeys the rules. I write some fairly efficient systems without
a task switcher of any kind (pre-emptive or otherwise) but only because I
control everything on the CPU.
Wilton
Wilton
Unfortunately Gary Kildall was not available when IBM was looking for an OS
for the original IBM PC, else we would have DR-DOS based OS-s in common use
today. Regardless, the OS supported by OW is MS-DOS, not DR-DOS. I agree
with others that providing preemptive multitasking for C++ programs executed
on MS-DOS platforms would require too much effort for too little return.
--
Steve
Wilton, since you did not indicate whose post you are replying to, and
relying on the message threading capability of Outlook Express is fraught
with danger, I'll assume you are responding to mine. Some of the posts
triggering my post seemingly implied (and not having access to the draft
standard I must rely on them) - contrary to your interpretation above - that
"preemptive switching" is intended to be instantaneous, like a high priority
interrupt that cannot be disabled. Messages posted later, including my
message in this subthread, agree that that is not possible. However, as both
you and others wrote, there is a consensus that "preemptive switching" is
not required to interrupt OS processes. I also appreciated Anthony Williams'
note that the new C++ draft standard contains the following remark about
multithreading: "Note: Usually the execution can be viewed as an
interleaving of all its threads".
| What a pre-emptive task switcher also does is take more CPU time and
| memory to operate. In the best case scenario it salvages enough
| wasted time by task switching blocked tasks to more than make up for
| the extra overhead. In the worst case scenario, it may free the
| programmer from sharing concerns and make the system appear more
| responsive, while actually accomplishing less per unit of time
| because of the considerable extra overhead required to safely switch
| pre-emptively. Where a given system falls along that line will
| depend on a number of things such as the "tick" time and how well
| applications obeys the rules. I write some fairly efficient systems
| without a task switcher of any kind (pre-emptive or otherwise) but
| only because I control everything on the CPU.
I, too, have written many real time programs which did not require task
switching. Of course, in many of these cases there was no real OS available
to begin with, so task switching would have required me to write the switch
software. As to the efficiency issue, a similar situation exists when
comparing a specifically designed overlay structure to fit a large program
into limited internal storage and with the use of virtual memory, which
tries to be "all things to all people".
--
Steve
>> use case you described above (regarding atomic variables) to work on all
>> platforms?
>
> Yes. See 29.4p11 of the current working draft
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3035.pdf
Section 29.4 appears to have only 3 paragraphs. That's the section on
the "Lock Free Property." Perhaps you meant a different section?
> "Implementations should make atomic stores visible to atomic loads
> within a reasonable amount of time."
Taken out of context, I'm not sure what this means. For example if I have a
thread spinning on an atomic read and another thread that will eventually
update that variable but is currently computing Pi to 10,000,000 decimal
places is the "atomic store" being made visible to the "atomic read" in a
reasonable amount of time?
I'm wondering if they are talking about the delay between when the store
occurs and the read sees the newly stored value (for example they want to be
sure the store is not stalled in a memory cache indefinitely). If so, that
would have nothing really to do with the issue of preemption or otherwise.
Peter
I forgot another instance where int 21 will stay for a long time. That is
input
from stdin. So if you use stdin or something that is redirected to stdin in
MSDOS,
the system will basically hang on the semaphore. The BIOS is also not
reentrant
and needs to be protected, and contains code that executes for a long time.
There are also chaining problems for int 21. Some TSRs chain int 21 and do
lengthy operations.
> I have done this 15 years ago and
> it worked well. This worked even in the environments controlled by a DOS
> extender. The situation was only a little bit tricky, because the DPMI ISR
> routines were usually called on a separate stack provided by the DPMI
> server. Hence the stack could not be switched directly. But again, one
> could
> completely bypass the extender by directly installing the switch ISR to
> the IDT table. Not a big deal.
Depends on what you want to do. If your tasks don't use DOS/BIOS, there
will be no problems.
DOS-extenders also are not garanteed to be reentrant. They do many things
on fixed stacks or fixed memory locations that will be broken if code is not
written
in a "good" way.
I've used BCCs 16-bit run-time environment for many years as well with
multithreading,
and most of the functions do work. But there is no garantee that it does as
it is written
for DOS and non-preemptive multitasking. Borlands 32-bit debugger even
disables
threads "hard" when they believe the application is a DOS-extender
application. Even
if it reports thread-creation events. That is one of the major reasons why I
wanted to
leave this environment.
Leif Ekblad
Oops, I meant 29.3p11.
>> "Implementations should make atomic stores visible to atomic loads
>> within a reasonable amount of time."
>
> Taken out of context, I'm not sure what this means. For example if I have a
> thread spinning on an atomic read and another thread that will eventually
> update that variable but is currently computing Pi to 10,000,000 decimal
> places is the "atomic store" being made visible to the "atomic read" in a
> reasonable amount of time?
Well, the thread doing the store has to actually get there for this to
be relevant.
> I'm wondering if they are talking about the delay between when the store
> occurs and the read sees the newly stored value (for example they want to be
> sure the store is not stalled in a memory cache indefinitely). If so, that
> would have nothing really to do with the issue of preemption or otherwise.
That is indeed the primary concern.
I checked the discussion archives for the memory model, and there is
disagreement among committee members about support for non-preemptive
schedulers. This discussion actually stemmed from the paragraph I quoted
above.
Some people (like me) think that the wording assumes everything is
preemptive. Others think that we do not want to rule out non-preemptive
schedulers.
The standard makes no requirements about fairness or liveness
guarantees, so in theory you could probably be strictly conforming with
a non-preemptive scheduler (e.g. task switch only on entry to certain
functions). Note that the "should" in the above paragraph means that the
implementation ought to if it can, but doesn't have to to be conforming.
I realise that a preemptive scheduler is very hard to do for DOS and
other similar systems, but if you have the expertise to do it I would
STRONGLY recommend it as the preferred option for C++0x threads.
However, if you think it's too hard or the cost isn't worth the benefit
then go with non-preemptive threads. Just be aware that this will break
programs that assume preemption and use atomics to communicate between
threads (e.g. with a lockfree queue). Personally, I've assumed that all
schedulers are preemptive since I stopped developing for 16-bit Windows,
and I expect most people writing C++0x code will make that assumption.
Then again, if DOS is one of your targets you might be more careful.
Matjaz
> I checked the discussion archives for the memory model, and there is
> disagreement among committee members about support for non-preemptive
> schedulers. This discussion actually stemmed from the paragraph I quoted
> above.
>
> Some people (like me) think that the wording assumes everything is
> preemptive. Others think that we do not want to rule out non-preemptive
> schedulers.
Thanks for your comments; I found them quite interesting. I can imagine that
there would be debate about this. I think I would be on the side that
supports implementability by non-preemptive schedulers... but then I worry
about targetting DOS and similar kinds of systems. It seems like there are
still enough users of such systems to warrant their consideration in the
standard, but I can see how others might want to move on.
My guess is that programmers targetting DOS will be content to get
non-preemptive threads and will understand that certain kinds of programming
techniques won't work for them. Thus some otherwise standard programs may
misbehave on their platform.
Years ago I did write a preemptive thread library for DOS. It appeared to
work. However one had to be very careful using it. I provided a master lock
that each thread needed to grab before it could enter the operating system.
It was very easy to forget to do that. Of course in our case we supposedly
have control over all entries into the OS since we are providing the C
library so I guess in theory we could tend to the lock management ourselves
internally. Users trying to call DOS directly would have to take
responsibility for locking the OS on their own (using our lock, of course).
It does sound like a lot of trouble. :)
Peter
That's an interesting option.
It also seems like it would be nice to have a cross platform implementation of
something like pthreads in the Open Watcom tool kit (do we already??). One
could imagine implementing standard C++ threads on top of pthreads... here I
assume that's possible... and then just let the cross platform pthreads take
care of porting std::thread to all our target platforms. Users might want to
call into the cross platform pthreads directly as well.
I understand writing such a thing from scratch might be ambitious. I do know
there is an open source pthreads implementation for Windows. Perhaps that
could be used/adapted.
My understanding is also that pthreads does allow for non-preemptive
implementations (let me know if I'm wrong). So that might be a way to bury
this issue in a layer below std::threads... at least to a degree.
Peter
David Golub
"Peter C. Chapin" <pe...@openwatcom.org> wrote in message
news:hmli6b$dn9$2...@www.openwatcom.org...
In some cases yes, but not all. See:
http://sourceware.org/pthreads-win32/
On Mar 3, 5:42 am, "Peter C. Chapin" <pe...@openwatcom.org> wrote:
> Anthony Williams wrote:
> > I checked the discussion archives for the memory model, and there is
> > disagreement among committee members about support for non-preemptive
> > schedulers. This discussion actually stemmed from the paragraph I quoted
> > above.
>
> > Some people (like me) think that the wording assumes everything is
> > preemptive. Others think that we do not want to rule out non-preemptive
> > schedulers.
>
> Thanks for your comments; I found them quite interesting. I can imagine that
> there would be debate about this. I think I would be on the side that
> supports implementability by non-preemptive schedulers... but then I worry
> about targetting DOS and similar kinds of systems. It seems like there are
> still enough users of such systems to warrant their consideration in the
> standard, but I can see how others might want to move on.
I'm honestly surprised anybody here cares about DOS at all ! In my
experience (in general, not specifically related to OW), barely
anybody does, and they get hostile if you mention it. It's not the
hard stuff that's annoying, only when an easy fix is available and
someone refuses to use it. That's frustrating! :-(
But yes, (Free)DOS is very important to some of us. ;-) Heck,
I still occasionally use DR-DOS 7.03 on an old box, which is
multitasking (although I generally avoid that part). Check here if
really curious:
http://www.drdos.com/dosdoc/
http://www.drdos.com/dosdoc/multtask/index.htm
http://www.drdos.com/dosdoc/sysprog/httoc.htm
> My guess is that programmers targetting DOS will be content to get
> non-preemptive threads and will understand that certain kinds of programming
> techniques won't work for them. Thus some otherwise standard programs may
> misbehave on their platform.
Beggars can't be choosers. (However ....)
> Years ago I did write a preemptive thread library for DOS. It appeared to
> work. However one had to be very careful using it. I provided a master lock
> that each thread needed to grab before it could enter the operating system.
> It was very easy to forget to do that. Of course in our case we supposedly
> have control over all entries into the OS since we are providing the C
> library so I guess in theory we could tend to the lock management ourselves
> internally. Users trying to call DOS directly would have to take
> responsibility for locking the OS on their own (using our lock, of course).
>
> It does sound like a lot of trouble. :)
For the record, here's what I found the other day (by Lawrence Rust):
http://www.softsystem.co.uk/products/swsmtc.htm
SwsMtc : A multithreading library for C and C++ programs that is open
source, cross platform, small footprint and high performance.
Features
* Pre-emptively scheduled threads.
* Priority inversion protection.
* Mutexes.
* Semaphores.
* Very low overhead, millisecond timers.
* Message passing.
* Multiple readers, single writer locks.
* Barriers.
* Thread local heaps.
* Small footprint (typically < 10K code).
* Fast context switching - under 2 microseconds on a 200 MHz
Pentium.
* 100% ANSI C90 source with a single, small, platform/compiler
adaptation module.
* Lightweight ANSI C++ 99 class wrappers.
* Ideal for embedded systems.
The package consists of the library sources, C/C++ header files,
example C and C++ applications and projects or makefiles.
The following targets and compilers are currently supported:
* POSIX, Linux 2.6.x -i686 and -powerpc with gcc 3.4 or 4.0
* POSIX, Win32 Cygwin 1.5.19 and gcc 3.4
* Win32, Microsoft Visual C++
* Win32, OpenWatcom C++ 1.04
* Win32, BorlandC++ 5.5
* 32-bit DOS, DJGPP and gcc 4.0
* 32-bit DOS, OpenWatcom C++ 1.04
* 16-bit DOS, Microsoft Visual C++ 1.52c
* 16-bit DOS, OpenWatcom C++ 1.04
* Mac OS 9 PowerPC, CodeWarrior 8
* ARM 7, ARM SDT 2.51
* NDS devkitPro
Limitations
SwsMtc is freeware and open source. It may be freely used by any
individual for personal or private use or for their business without
any restriction or charge. Companies, organisations or governments may
not use it without a license. In no case may SwsMtc be used to deprive
anyone of life, liberty or livelihood.
P.S. I assume A.W. is the same U.K. dude who wrote ALink, but I of all
people understand that such a common name does exist in more than one
place! ;-))
I suggest, furthermore, that any proposed heroic efforts in OpenWatcom
be structured along the same lines as the default windowing mechanism
(-bw) for Win16 is: By default one gets a system where there is exactly
one thread, and that maps directly to whatever the underlying
PC/MS/DR-DOS API does; but for those programmers that want it a magic
multithreading switch can be thrown, with the caveat that it doesn't
provide "real" multithreading (just as default windowing doesn't produce
"real" console support for Win16) but only something that looks like
multithreading as long as one doesn't prod it too hard.
> Years ago I did write a preemptive thread library for DOS. It appeared
> to work. However one had to be very careful using it. I provided a
> master lock that each thread needed to grab before it could enter the
> operating system. It was very easy to forget to do that. Of course in
> our case we supposedly have control over all entries into the OS since
> we are providing the C library so I guess in theory we could tend to
> the lock management ourselves internally. Users trying to call DOS
> directly would have to take responsibility for locking the OS on their
> own (using our lock, of course).
>
As I said: something that looks like multithreading as long as one
Yes, that's me. I've known lots of people share my name, but I'm not
aware of any other programmers who do.
Actually most of the work will have to be done on the code generator itself
to implement the concurrency memory model. Once that is done, plans could be
made about the library level support for low level atomics and high level
threads.
-Marek
Didn't DPMI 1.0 define multithreading? Did anyone ever implemented it?
I've only ever seen 0.9 implementations.
REH
> Didn't DPMI 1.0 define multithreading?
Don't really know.
> Did anyone ever implemented it?
I seem to remember 386^MAX did.
> I've only ever seen 0.9 implementations.
And you've just named one major reason why: unreasonably complex
requirements to the server-side implementation.
The other major reason probably was that the very institution that
defined DPMI (Microsoft) never bothered to actually implement it in any
of their products. They torpedoed it for good and left it dead in the
water.
In a more paranoid mood one might suspect that MS may only ever have
prepared the DPMI 1.0 document as a ploy intended to burn other people's
money and bind their work force in trying to implement this concoction.
None of the producers of 386 extenders of the time could afford to
just ignore the existence of DPMI 1.0 --- well, not until it became
clear that MS had no intention whatsoever to do anything else with that
document besides publishing it.
QEMM + DESQView ?
Bartosz
That may well be so, but, does not the existence of _beginthread() and
_endthread() in the Open Watcom 1.8 C Library suggest that at least
some of that work has been done already?
And that implementing threads on the platforms supported by
_beginthread() and _endthread() may be more a matter of rebranding
than of anything else?
Or, at least, might they not act as an indication of what has been
done and what needs to be done in the future?
--
Nature must be explained in
her own terms through
the experience of our senses.
See http://lambda-the-ultimate.org/node/950 or google for "threads can not
be implemented as a library". If the compiler has no notion of threads, the
code below can easily fail. Assuming the compiler sees the definitions of
enter_critical_section() and leave_critical_section() and is able to verify
that
those functions do not access x, the write "x = 1" can be moved outside the
critical section according to the current standard. That is because, in a
single
threaded environment, there is no way to tell whether "x = 1" happened
within the criticial section or not. That is however not true in a
multi-threaded environment, when other threads can see the difference. The
point of the
proposed memory model is to say what optimizations are valid and introduce
low-level atomics with various consistency guarantees about what writes in
one thread are visible to what reads in other threads and under what
cirmcumstances.
enter_critical_section();
x = 1;
leave_critical_section();
In essence, the current C++ multithreaded programs work only
by chance, by relying on the fact the compiler is unable to perform certain
optimizations that it could do according to the current standard. Most
often, the optimizations are defeated by hiding the "critical" parts in
different libraries or making them accessible only via expensive syscalls.
This is clearly suboptimal and there are
many concurrency techniques (like lock free programming) that currently can
not be done in C++ unless the multithreaded model is standardized.
-Marek
> That may well be so, but, does not the existence of _beginthread() and
> _endthread() in the Open Watcom 1.8 C Library suggest that at least
> some of that work has been done already?
There are issues beyond just library support... namely the memory model. The
current standard says nothing about the order in which threads can access
memory relative to each other. We need to be sure the compiler obeys the
rules and restrictions of the new C++ memory model.
I suppose we might be lucky and it might do so already. I'm not sure how
likely that is.
Peter
>> That may well be so, but, does not the existence of _beginthread() and
>> _endthread() in the Open Watcom 1.8 C Library suggest that at least
>> some of that work has been done already?
<snip response>
You did examine the existing implementation to ensure that your
comments were relevant, I hope.
Isn't it possible that the implementors of these functions knew what
they were doing and that your theoretical comments are irrelevant?
And, by the way, these are C functions, not C++.
I am only suggesting that it is worth checking it out, once a firm
understanding of what the actual requirements will be.
Except for the DOS support, the function description of _beginthread()
reads as if it were a wrapper for an OS function, presumably setting
up some internal structures as well.
Or perhaps a completely new setup will be needed. But the chance of
using the existing code to do at least some of the heavy lifting
should not be ignored. Nor should compatibility between our C and C++
threads be sacrificed unless that is unavoidable.
Also, it is not clear from these function descriptions whether the
other impedimenta of multithreading (terms like "lock", "critical
section", "semaphore" come to mind) are also implemented in OW
already, or whether those required by the standard will need to be
done from scratch. This may or may not be related to the memory model
issue you describe above, but, yes, some work may be needed to
implement the standard.
The apparent DOS support is very interesting. I wonder what sort of
threading it provides. Perhaps one of the other help files discusses
this.
> I am only suggesting that it is worth checking it out, once a firm
> understanding of what the actual requirements will be.
Yes, I agree with what you are saying. We should definitely try to capitalize
on the thread support that already exists, just for the reasons you say.
Peter
And extend or replace it in a way that keeps compatibility between
C and C++ if possible.
Roald
No. I don't think so. Few operating systems ever supported 1.0. Windows,
for one, never supported anything else than 0.9 AFAIK. RDOS does support
1.0, though.
Leif Ekblad
> And extend or replace it in a way that keeps compatibility between
> C and C++ if possible.
For fun, I started tinkering around with creating a cross platfrom pthreads
for Open Watcom. I haven't done much (just a couple of hours last night!). My
first impression is that it would probably be feasible. Of course I'm sure
there would be many issues to solve before it could become a reality.
Peter
Further spelunking in the Help Files found, in the User's Guide, this
interesting item:
__declspec( thread )
which is used to define Thread Local Storage (TLS). The section even
/defines/ TLS and provides quite a few examples of how to use it.
Also possibly related is option -sg, which can apparently make stack
crashes less likely when threading, at least with Win32 and OS/2 32.
The Programmer's Guide appears to have info on threads in Win32 and
OS/2 32, including examples. These are most helpful: they show
OS-specific functions being used to create a critical section. This
file also clearly states that _beginthread() must be used if any C
Library functions are to be used. Presumably, the end result is that a
multithreading-specific form of the library is linked in.
The Master Help Index have a lot of entries which are from the
Debugger Guide: apparently, wdw has support for debugging threads.
At least, for 32-bit OS/2 and Windows. I couldn't find anything on
DOS. In fact, re-examining the _beginthread() page suggests that I
mistook "16-bit" for "DOS". The evidence would suggest that "16-bit"
refers to other 16-bit applications, although whether Windows or OS/2
or both isn't immediately clear.
IIRC, someone posted something to the effect that we would only have
to support as many threads as the underlying OS, and raise an
exception if that limit would be exceeded. It appears from the above
that we might be able to get away with wrapping _beginthread() and
_endthread() -- but for anything else (critical sections, etc) we
might need to wrap the OS-provided equivalents.
That should simplify things a lot: the host OS would worry about
switching threads, critical sections, etc. Provided the standard is
written so conveniently, of course, as to make this possible. Is the
draft standard containing the new requirements available online?
As for DOS: we support several extenders, perhaps we could wrap one or
more of the shareware multithreading packages which appear to have
been identified. Unless someone wants to write one of our own, of
course.
> The Programmer's Guide appears to have info on threads in Win32 and
> OS/2 32, including examples. These are most helpful: they show
> OS-specific functions being used to create a critical section. This
> file also clearly states that _beginthread() must be used if any C
> Library functions are to be used. Presumably, the end result is that a
> multithreading-specific form of the library is linked in.
I've always been under the impression that the library needed to create some
thread local storage for each thread, hence the need to use _beginthread().
> At least, for 32-bit OS/2 and Windows. I couldn't find anything on
> DOS. In fact, re-examining the _beginthread() page suggests that I
> mistook "16-bit" for "DOS". The evidence would suggest that "16-bit"
> refers to other 16-bit applications, although whether Windows or OS/2
> or both isn't immediately clear.
Yes I think "16-bit" refers to 16-bit OS/2.
> It appears from the above
> that we might be able to get away with wrapping _beginthread() and
> _endthread() -- but for anything else (critical sections, etc) we
> might need to wrap the OS-provided equivalents.
That is my assumption.
> That should simplify things a lot: the host OS would worry about
> switching threads, critical sections, etc. Provided the standard is
> written so conveniently, of course, as to make this possible. Is the
> draft standard containing the new requirements available online?
You can download the current draft from here
http://www.open-std.org/jtc1/sc22/wg21/
Peter
Thanks. I don't know why I am so interested in this but, since I
clearly am, I will no doubt search through it and see what I can
conclude over the next few days or weeks or however long it takes.
Great, but ... did you miss my link to the already-existing thread lib
for DOS(16-/32-bit) that supports OW??
> Great, but ... did you miss my link to the already-existing thread lib
> for DOS(16-/32-bit) that supports OW??
>
> http://www.softsystem.co.uk/products/swsmtc.htm
Yes, I probably missed it. Sorry about that!
I just took a look and it seems like an interesting library. I have a few
questions/concerns about it from the point of view if using it with Open
Watcom.
First it seems like we would need to obtain a license to use it since we are
an organization. I'm not sure what that would entail. Also the author
says, "In no case may the library or any part thereof be re-badged, re-sold
or used in a system to deprive anyone of life, liberty or livelihood." I
suspect that clause is incompatible with the Open Watcom License since I
don't believe we make that restriction.
My other concern is technical. Based on a quick look at the source code, it
appears that the library works by handling preemption and task switching on
its own. It relies on the operating system to send the library timer events
but otherwise it ignores (it seems) the OS's native support for threading.
I suspect that means the library can't take advantage of any physical
parallelism that might be available. In the eyes of the operating system,
programs using this library have only one thread. This seems pretty
unacceptable to me in today's multicore world. People will want to use
threads to increase performance of compute intensive tasks. My current
thinking is that it would not be possible to do that using this library.
I could be wrong... I didn't spend a huge amount of time digging into the
code. I did look over the documentation briefly as well, but it appears to be
silent on this point either way (which troubles me a little too... it's a
critical piece of information).
Finally in the long term it would be nice to have a cross platform
implementation of the POSIX thread API if, for no other reason, pthreads are
a well established standard. The pthreads API is widely used in the Unix
world and there are many tutorials and other reference materials that support
it. This library provides its own API and while I have no objection to it
particularly, it is not standard.
Peter
On Mar 7, 5:41 am, "Peter C. Chapin" <pe...@openwatcom.org> wrote:
> Rugxulo wrote:
> > Great, but ... did you miss my link to the already-existing thread lib
> > for DOS(16-/32-bit) that supports OW??
>
> >http://www.softsystem.co.uk/products/swsmtc.htm
>
> Yes, I probably missed it. Sorry about that!
>
> I just took a look and it seems like an interesting library. I have a few
> questions/concerns about it from the point of view if using it with Open
> Watcom.
I was afraid of that, hence why I quoted the license in my first post.
But it shouldn't be anything too difficult to sort out (I hope).
> First it seems like we would need to obtain a license to use it since we are
> an organization. I'm not sure what that would entail.
Not sure, it doesn't mention specifics. Probably somebody should
contact the author. I blindly guess that he just doesn't want anyone
selling it outright as their own. You're probably okay.
> Also the author
> says, "In no case may the library or any part thereof be re-badged, re-sold
> or used in a system to deprive anyone of life, liberty or livelihood." I
> suspect that clause is incompatible with the Open Watcom License since I
> don't believe we make that restriction.
Heh. Surely you don't mean OpenWatcom allows such. Those are illegal
anyways, so it's not like anybody would do that. Besides, if somebody
did want to do that with software (how?), they wouldn't obey any wimpy
license text anyways. Perhaps he really means "for non-military" use
here.
> My other concern is technical. Based on a quick look at the source code, it
> appears that the library works by handling preemption and task switching on
> its own. It relies on the operating system to send the library timer events
> but otherwise it ignores (it seems) the OS's native support for threading.
I was mainly pointing out that it supports DOS (16- or 32-bit) and
OpenWatcom pre-emptively. MS-DOS has no thread support, so there's no
toes to step on there.
> I suspect that means the library can't take advantage of any physical
> parallelism that might be available. In the eyes of the operating system,
> programs using this library have only one thread. This seems pretty
> unacceptable to me in today's multicore world. People will want to use
> threads to increase performance of compute intensive tasks. My current
> thinking is that it would not be possible to do that using this library.
So don't use it for other OSes, only DOS! :-)
> Finally in the long term it would be nice to have a cross platform
> implementation of the POSIX thread API if, for no other reason, pthreads are
> a well established standard. The pthreads API is widely used in the Unix
> world and there are many tutorials and other reference materials that support
> it. This library provides its own API and while I have no objection to it
> particularly, it is not standard.
GNU Pth was ported to DJGPP, and it (also) supports the POSIX pthread
API. But it's cooperative only, slightly buggy, and very *nix-
oriented. In other words, probably not easy to port to OpenWatcom. In
fact, most *nix stuff is very difficult to port to OpenWatcom. While
your goal is admirable, it's highly unlikely that any app will be much
easier to port due to using POSIX. AFAICT, OpenWatcom was never about
POSIX, at least not on Win32 or OS/2 or DOS. (Even DJGPP has a hard
time with most GNU software.)
> Not sure, it doesn't mention specifics. Probably somebody should
> contact the author. I blindly guess that he just doesn't want anyone
> selling it outright as their own. You're probably okay.
Yes, if we wanted to use the library we could contact the author and see what
his intentions and feelings really are.
> Heh. Surely you don't mean OpenWatcom allows such. Those are illegal
> anyways, so it's not like anybody would do that. Besides, if somebody
> did want to do that with software (how?), they wouldn't obey any wimpy
> license text anyways. Perhaps he really means "for non-military" use
> here.
I assume he's talking about military applications. At least that's my
interpretation.
> So don't use it for other OSes, only DOS! :-)
I understand what you mean. Yes, that could be a reasonable approach.
> GNU Pth was ported to DJGPP, and it (also) supports the POSIX pthread
> API. But it's cooperative only, slightly buggy, and very *nix-
> oriented. In other words, probably not easy to port to OpenWatcom. In
> fact, most *nix stuff is very difficult to port to OpenWatcom. While
> your goal is admirable, it's highly unlikely that any app will be much
> easier to port due to using POSIX. AFAICT, OpenWatcom was never about
> POSIX, at least not on Win32 or OS/2 or DOS. (Even DJGPP has a hard
> time with most GNU software.)
Open Watcom has some cross platform POSIX-like functions in its C library
already (open(), read(), etc). We even have a collection of POSIX-like tools
that we've talked about distributing. I entertain fantasies of one day
bundling Open Watcom with a (approximately) complete collection of cross
platform POSIX functions. However, I should probably finish OWSTL before
worrying about that. :)
Peter
To me this means that it may not be used by prosecuting attorneys, judges,
prison systems, etc. in the performance of their official duties. It cannot
be used by police to arrest a murderer, but it can be used for issuing
parking or speeding tickets.
--
Steve
"In no case may the library or any part thereof be re-badged, re-sold or used in a system to deprive anyone of life, liberty or livelihood."
To me this means that it may not be used by prosecuting attorneys, judges, prison systems, etc. in the performance of their official duties. It cannot be used by police to arrest a murderer, but it can be used for issuing parking or speeding tickets.
It's a Frequently Given Answer by the Free Software Foundation that non-military/non-commercial
use restrictions result in software that is not free. Software
that restricts the licencee, saying "You may not freely use
this software for purpose XYZ." and "You may not sell this
software.", is not free software. Software Systems' claim that it is
producing freeware is belied by its (several) quite wide-ranging
restrictions upon freedom (stated pretty much in the same breath). If
Open Watcom is to be free software, it cannot contain any Software
Systems' bits until that company gets some clue about what it really
means to be free software.