Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2006-07

Threading in FPC DOS

19 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Andreas Berger

I need to implement some simple threading in a DOS application I am writing with FPC. What I need to know is the following:

1) Does FPC protect it's stack or can I allocate memory from the heap and point SS and ESP to it for the threads stack.

2) If the stack is protected, how do I allocate stack memory for new threads?

Regards,
Andreas

Tomas Hajny
to Andreas Berger
Andreas Berger wrote 5 lines
I need to implement some simple threading in a DOS application I am writing with FPC. What I need to know is the following: 1) Does FPC protect it's stack or can I allocate memory from the heap and point SS and ESP to it for the threads stack.

I believe the latter is correct (except that no
SS change should be needed), at least this is how
it works for other targets as far as I know.
Amount of memory to be allocated for stack is
passed as a parameter during thread creation.

BTW, in case you manage to create thread manager
(systhrd.inc implementation) for GO32v2 target
and are willing to share it with others, we'd be
certainly interested to add it to FPC.

Tomas

Andreas Berger
to Tomas Hajny
Show quoted text 13 lines
> I need to implement some simple threading in a DOS application I am > writing with FPC. What I need to know is the following: > > 1) Does FPC protect it's stack or can I allocate memory from the heap > and point SS and ESP to it for the threads stack. > I believe the latter is correct (except that no SS change should be needed), at least this is how it works for other targets as far as I know. Amount of memory to be allocated for stack is passed as a parameter during thread creation.

Oh, so all the segments are the same in FPC? I mean CS = DS = SS? That would really be swell.

Show quoted text 6 lines
BTW, in case you manage to create thread manager (systhrd.inc implementation) for GO32v2 target and are willing to share it with others, we'd be certainly interested to add it to FPC.

Hmm, I had thought to implement the TThread class. What is systhrd.inc? It seems to be implemented with different methods for each target.

Andreas

Marco van de Voort
to Andreas Berger
Show quoted text 23 lines
>> I need to implement some simple threading in a DOS application I am >> writing with FPC. What I need to know is the following: >> >> 1) Does FPC protect it's stack or can I allocate memory from the heap >> and point SS and ESP to it for the threads stack. >> > > I believe the latter is correct (except that no > SS change should be needed), at least this is how > it works for other targets as far as I know. > Amount of memory to be allocated for stack is > passed as a parameter during thread creation. > Oh, so all the segments are the same in FPC? I mean CS = DS = SS? That would really be swell. > BTW, in case you manage to create thread manager > (systhrd.inc implementation) for GO32v2 target > and are willing to share it with others, we'd be > certainly interested to add it to FPC. > > Hmm, I had thought to implement the TThread class. What is systhrd.inc? It seems to be implemented with different methods for each target.

The includefile with the system dependant base for the tthread class.

See how Unix does it (unix/systhrd.inc and unix/cthreads.pp). Unix default has threading disabled, but it is enabled if unit cthreads is included.

Since Dos can have multiple ways of multitasking (it could e.g. also plug in to DV or Win3.x or TopView via int 2FH etc) this model seems advisable to me.

I assume you are implementing a basic fixed timeslicer? What are you going to use it for btw? This because DV/X (which is free nowadays) afaik gives you preemptive scheduling on Dos.

Tomas Hajny
to Marco van de Voort
Marco van de Voort wrote 15 lines
> >> I need to implement some simple threading in a DOS application I am > >> writing with FPC. What I need to know is the following: > >> > >> 1) Does FPC protect it's stack or can I allocate memory from the heap > >> and point SS and ESP to it for the threads stack. > >> > > > > I believe the latter is correct (except that no > > SS change should be needed), at least this is how > > it works for other targets as far as I know. > > Amount of memory to be allocated for stack is > > passed as a parameter during thread creation. > > > Oh, so all the segments are the same in FPC? I mean CS = DS = SS? That > would really be swell.

You certainly cannot rely on CS being the same as the other two. It points to the same address space, but possibly using different selector to allow different access rights (no write access to CS).

Show quoted text 23 lines
> > BTW, in case you manage to create thread manager > > (systhrd.inc implementation) for GO32v2 target > > and are willing to share it with others, we'd be > > certainly interested to add it to FPC. > > > > > Hmm, I had thought to implement the TThread class. What is systhrd.inc? > It seems to be implemented with different methods for each target. The includefile with the system dependant base for the tthread class. See how Unix does it (unix/systhrd.inc and unix/cthreads.pp). Unix default has threading disabled, but it is enabled if unit cthreads is included. Since Dos can have multiple ways of multitasking (it could e.g. also plug in to DV or Win3.x or TopView via int 2FH etc) this model seems advisable to me. I assume you are implementing a basic fixed timeslicer? What are you going to use it for btw? This because DV/X (which is free nowadays) afaik gives you preemptive scheduling on Dos.

Well, multitasking multithreading. I'm not sure if DV or Win 3.x provide special multithreading support for DOS applications... In contrary to Marco's suggestion, I can imagine the multithreading support could be general and included by default for GO32v2 (similarly to Win32). However, it certainly depends on whether a general solution (not requiring special support like DV, etc.) is really feasible and practical.

Tomas

Marco van de Voort
to Tomas Hajny
Show quoted text 9 lines
Marco van de Voort wrote: > me. > I assume you are implementing a basic fixed timeslicer? What are you > going > to use it for btw? This because DV/X (which is free nowadays) afaik gives > you preemptive scheduling on Dos. Well, multitasking multithreading. I'm not sure if DV or Win 3.x provide special multithreading support for DOS applications...

Totally right. Sorry. They might, but that is a different thing from what I was thinking about.

In contrary to Marco's suggestion, I can imagine the multithreading support could be general and included by default for GO32v2 (similarly to Win32).

However, even then, the scheduler would be probably so crude that every non trivial use would need its own tweaks, one reason the more to make it pluggable. It's not like win32 where the preemptive scheduler can deal with a wide range of behaviour.

However, it certainly depends on whether a general solution (not requiring special support like DV, etc.) is really feasible and practical.

I doubt it. Note that it also probably needs enhancing of the threadinterface with a giveuptimeslice functionality, something for which now sleep(0) is abused.

Jonas Maebe
to Marco van de Voort
Marco van de Voort wrote
I doubt it. Note that it also probably needs enhancing of the threadinterface with a giveuptimeslice functionality, something for which now sleep(0) is abused.

sleep(0) is quite bad, because it may not necessarily give up any timeslice. At least very short nanosleeps seem to be implemented as spinning loops on Mac OS X, so maybe sleep(0) is the same.

Jonas

Tomas Hajny
to Marco van de Voort: Totally right. Sorry. They might, but that is a different thing from what I was thinking…
Marco van de Voort wrote
> Marco van de Voort wrote:

.
.

Show quoted text 7 lines
> However, it certainly depends on whether a general solution (not > requiring special support like DV, etc.) is really feasible and > practical. I doubt it. Note that it also probably needs enhancing of the threadinterface with a giveuptimeslice functionality, something for which now sleep(0) is abused.

Let's add it then? I believe such a call belongs to system unit anyway, even without multithreading... SysUtils.Sleep can then call such function explicitely for platforms not ensuring giving up timeslice as part of the usual sleep functionality, Drivers.GiveUpTimeslice (from FV) should use the same call.

Tomas

Vinzent Hoefler
to Tomas Hajny: You certainly cannot rely on CS being the same as the other two. It points to the same…
Tomas Hajny wrote
Well, multitasking multithreading. I'm not sure if DV or Win 3.x provide special multithreading support for DOS applications...

Nope, not really (at least for Win3.x). There are some services to aid multi-tasking-aware applications at the multiplexer interrupt Marco mentioned, but multi-threading is simply not supported by the underlying DOS-Kernel because of its non-reentrancy.

Show quoted text 6 lines
In contrary to Marco's suggestion, I can imagine the multithreading support could be general and included by default for GO32v2 (similarly to Win32). However, it certainly depends on whether a general solution (not requiring special support like DV, etc.) is really feasible and practical.

Well, once you manage to encapsulate each and every system call you've done the most work. ;) Basically I only see the solution that the thread manager intercepts int21h and probably some more others (int10h comes to mind), and blocks any multiple system calls from occuring at the same time. But it's too hot to think right now.

All in all, I'd say, it's not *that* hard to do it, especially if you have a multi-threading aware RTL already, but it's certainly not done in a couple of hours.

The thing is, I'd really love to do that, but as anyone here might have noticed, I already did a pi*s-poor job just maintaining the GO32V2 target...

Vinzent.

Marco van de Voort
to Jonas Maebe: sleep(0) is quite bad, because it may not necessarily give up any timeslice. At least…
Show quoted text 10 lines
On 12 jul 2006, at 11:25, Marco van de Voort wrote: > I doubt it. Note that it also probably needs enhancing of the > threadinterface with a giveuptimeslice functionality, something for > which > now sleep(0) is abused. sleep(0) is quite bad, because it may not necessarily give up any timeslice. At least very short nanosleeps seem to be implemented as spinning loops on Mac OS X, so maybe sleep(0) is the same.

Do you know a correct way of doing this on *nix?

(it is a hack nevertheless, but a much used one in Delphi code because Windows guarantees it, the better uses are to emulate blocking I/O, the worse parts for uh, everything, including updating time on a form)

Tomas Hajny
to Marco van de Voort
Marco van de Voort wrote 16 lines
> On 12 jul 2006, at 11:25, Marco van de Voort wrote: > > > I doubt it. Note that it also probably needs enhancing of the > > threadinterface with a giveuptimeslice functionality, something for > > which > > now sleep(0) is abused. > > sleep(0) is quite bad, because it may not necessarily give up any > timeslice. At least very short nanosleeps seem to be implemented as > spinning loops on Mac OS X, so maybe sleep(0) is the same. Do you know a correct way of doing this on *nix? (it is a hack nevertheless, but a much used one in Delphi code because Windows guarantees it, the better uses are to emulate blocking I/O, the worse parts for uh, everything, including updating time on a form)

I certainly don't know a general solution for *nix. However, even old "single-task" DOS provides such a function and it's a great help that can be provided by programmer to scheduler in the underlying OS, so *nix systems should provide such function too, right? If they don't, you probably don't have anything better than sleep(0) anyway.

Tomas

Vinzent Hoefler
to Marco van de Voort: Do you know a correct way of doing this on *nix? (it is a hack nevertheless, but a much…
Marco van de Voort wrote 7 lines
> On 12 jul 2006, at 11:25, Marco van de Voort wrote: > > sleep(0) is quite bad, because it may not necessarily give up any > timeslice. At least very short nanosleeps seem to be implemented as > spinning loops on Mac OS X, so maybe sleep(0) is the same. Do you know a correct way of doing this on *nix?

"sched_yield()"? Seems to be POSIX, so I suppose it's available on most Unices.

Vinzent.

Vinzent Hoefler
to Tomas Hajny: I certainly don't know a general solution for *nix. However, even old "single-task" DOS…
Tomas Hajny wrote 5 lines
I certainly don't know a general solution for *nix. However, even old "single-task" DOS provides such a function and it's a great help that can be provided by programmer to scheduler in the underlying OS, so *nix systems should provide such function too, right? If they don't, you probably don't have anything better than sleep(0) anyway.

Bad thing with Sleep(0) on those systems is that it does about the same as coding "{null};", with the disadvantage of needing infinitely more code and being infinitely slower. ;-)

Vinzent.

Vinzent Hoefler
to Marco van de Voort
Marco van de Voort wrote 9 lines
> > > spinning loops on Mac OS X, so maybe sleep(0) is the same. > > > > Do you know a correct way of doing this on *nix? > > "sched_yield()"? Seems to be POSIX, so I suppose it's available on > most Unices. Yes, and not so recent ('93) that it is risky. At least FreeBSD seems to have it.

Footer of the man-page here says:

|Linux 1.3.81 1996-04-10 SCHED_YIELD(2)

Vinzent.

Andreas Berger
to Marco van de Voort: The includefile with the system dependant base for the tthread class. See how Unix does…
Show quoted text 7 lines
Since Dos can have multiple ways of multitasking (it could e.g. also plug in to DV or Win3.x or TopView via int 2FH etc) this model seems advisable to me. I assume you are implementing a basic fixed timeslicer? What are you going to use it for btw? This because DV/X (which is free nowadays) afaik gives you preemptive scheduling on Dos.

DV is not suitable since it is a multi-tasker but does not have a multithreading library (at least I don't think so). I want to implement TThread so that I can have threads running in the background. Basically the threading system will have:

- Implement full TThread functionality.
- Protection of int21. When a thread is using int21, other threads that try to use it are blocked until the first thread releases int21. I will probably make keyboard reads non-blocking (of int21) as well.
- When the first thread is created, the main application becomes a thread as well. (ei. multi-treading is enabled). The main thread can not be deleted.

I already have a good threading library for Watcom C, but it is only for systems that don't use floating point since I don't know how to save and restore the floating point unit. I will need to do this for FPC, so if someone knows how to save and restore the FPU, I would apreciate the help. Ideally I could also discover (via an exception on first FPU usage?) if a thread needs to save/restore the FPU. This would greatly speed up swapping of FPU-free threads.

Regards,
Andreas

Vinzent Hoefler
to Andreas Berger: DV is not suitable since it is a multi-tasker but does not have a multithreading library…
Andreas Berger wrote
save and restore the floating point unit. I will need to do this for FPC, so if someone knows how to save and restore the FPU, I would apreciate the help.

F(X)SAVE/F(X)RSTOR

The X-Versions are more efficient, but only available on newer CPUs.

Ideally I could also discover (via an exception on first FPU usage?) if a thread needs to save/restore the FPU.

Well, I'd say, this is quite hard to do in an efficient way, because you need to detect the usage of MMX instructions, too. As you may recall, Intel decided to implement another brain damaged design and mapped the MMX registers onto the FPU registers.

I have to dig deep in my memory now, so take the following paragraphs with caution, I may be wrong (it's just too long ago):

In theory it is possible to do, but only if you have write access to the EFLAGS register (where you could temporarily set a flag to raise an exception on MMX usage). But the usual DOS-target means DPMI, which means privilege level 3 which means: You're just not allowed to fiddle around with those. IIRC, there's a ring0-mode DPMI-Host available (should be CWSDPR0.EXE), but this only works in real plain DOS, so the option to run the program inside a Windows-DOS-Box would be out completely, I guess.

Depending on your needs this might be ok, but as a general solution for FPC/GO32V2 this wouldn't be acceptable, I think.

Vinzent.

Andreas Berger
to Vinzent Hoefler

@Vincent
thanks for your detailed reply :)

@All

Vinzent Hoefler wrote 13 lines
On Wednesday 12 July 2006 11:34, Andreas Berger wrote: > save and restore the floating point unit. I will need to do this for > FPC, so if someone knows how to save and restore the FPU, I would > apreciate the help. > F(X)SAVE/F(X)RSTOR The X-Versions are more efficient, but only available on newer CPUs.

Now that you mention it, I have used these in the past :). BTW, The X version is available at what CPU's? Would it be acceptable to use this for FPC or should I use the normal FSAVE/FRSTOR functions? Does FPC have a function that tells me what processor I'm running on? In this case I could optimize.

Show quoted text 24 lines
> Ideally I could also discover (via an exception > on first FPU usage?) if a thread needs to save/restore the FPU. > Well, I'd say, this is quite hard to do in an efficient way, because you need to detect the usage of MMX instructions, too. As you may recall, Intel decided to implement another brain damaged design and mapped the MMX registers onto the FPU registers. I have to dig deep in my memory now, so take the following paragraphs with caution, I may be wrong (it's just too long ago): In theory it is possible to do, but only if you have write access to the EFLAGS register (where you could temporarily set a flag to raise an exception on MMX usage). But the usual DOS-target means DPMI, which means privilege level 3 which means: You're just not allowed to fiddle around with those. IIRC, there's a ring0-mode DPMI-Host available (should be CWSDPR0.EXE), but this only works in real plain DOS, so the option to run the program inside a Windows-DOS-Box would be out completely, I guess. Depending on your needs this might be ok, but as a general solution for FPC/GO32V2 this wouldn't be acceptable, I think.

You're right, better not to do this for a general library.

Ok, will be start to write the threads.

Andreas