Sign in Join

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

Mailing lists / fpc-devel / 2003-11

promised tthread patch

26 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

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

KJK::Hyperion
to Johannes Berg
you wrote
Probably not complete, but an overview of what I have in mind -- read the notes in the file.

I don't agree with the notes about Suspend/Resume. Suspending a thread on POSIX is possible, as long as you define what "suspending" means. Assuming a "suspended" thread is a thread that doesn't execute application code, forcing the target thread to wait on a mutex would be enough, IMHO (on a side note, this is how some third party extensions for Windows implement SIGSTOP semantics). Don't be too quick about dismissing "suspending" as "non-portable": condition variables and thread canceling were thought as *impossible* to implement on Win32, before RedHat successfully implemented the POSIX threads interface on Win32

Reply by email

Johannes Berg
to KJK::Hyperion
Show quoted text 9 lines
I don't agree with the notes about Suspend/Resume. Suspending a thread on POSIX is possible, as long as you define what "suspending" means. Assuming a "suspended" thread is a thread that doesn't execute application code, forcing the target thread to wait on a mutex would be enough, IMHO (on a side note, this is how some third party extensions for Windows implement SIGSTOP semantics). Don't be too quick about dismissing "suspending" as "non-portable": condition variables and thread canceling were thought as *impossible* to implement on Win32, before RedHat successfully implemented the POSIX threads interface on Win32

Ok, let me rephrase.
Suspending at any arbitrary point as the semantics of .suspend() are, is afaik impossible (and besides -- not a good idea either).

I do plan on adding an implementation for the thread calling .suspend on itself though (could be implemented via the same pipe I already have in there again).

johannes

http://www.sipsolutions.de/ GnuPG key: http://www.sipsolutions.de/keys/JohannesBerg.asc Key-ID: 9AB78CA5 Johannes Berg Fingerprint = AD02 0176 4E29 C137 1DF6 08D2 FC44 CF86 9AB7 8CA5

Reply by email

KJK::Hyperion
to Johannes Berg: Ok, let me rephrase. Suspending at any arbitrary point as the semantics of .suspend()…
you wrote
Suspending at any arbitrary point as the semantics of .suspend() are, is afaik impossible

not arbitrary. The rules are roughly the same as those for signaling (SuspendThread, in Windows, is implemented with a kernel-mode signal, like most system calls targeting threads). The only problem I see is the interaction with waits - but, on the other hand, EINTR has been banned from POSIX threads as cumbersome and of limited usefulness, and all POSIX threading interfaces restart interrupted waits automatically

(and besides -- not a good idea either).

true. A crude and rude interface. But not supporting it at all?

Reply by email

Unknown author
to Johannes Berg: Ok, let me rephrase. Suspending at any arbitrary point as the semantics of .suspend()…
Johannes Berg wrote 18 lines
On Fri, 2003-11-14 at 21:34, KJK::Hyperion wrote: > I don't agree with the notes about Suspend/Resume. Suspending a thread on > POSIX is possible, as long as you define what "suspending" means. Assuming > a "suspended" thread is a thread that doesn't execute application code, > forcing the target thread to wait on a mutex would be enough, IMHO (on a > side note, this is how some third party extensions for Windows implement > SIGSTOP semantics). Don't be too quick about dismissing "suspending" as > "non-portable": condition variables and thread canceling were thought as > *impossible* to implement on Win32, before RedHat successfully implemented > the POSIX threads interface on Win32 Ok, let me rephrase. Suspending at any arbitrary point as the semantics of .suspend() are, is afaik impossible (and besides -- not a good idea either). I do plan on adding an implementation for the thread calling .suspend on itself though (could be implemented via the same pipe I already have in there again).

I don't understand what the problem is with implementing suspend? Linux and Unix in general have the STOP signal for this since ages.

All you need to do is send the STOP signal to the thread. pthreads provides functionality for this.

Michael.

Reply by email

KJK::Hyperion
to Unknown author
you wrote
All you need to do is send the STOP signal to the thread.

This is a common misunderstanding. I quote from IEEE 1003.1:

"[...]

Note that pthread_kill() only causes the signal to be handled in the context of the given thread; the signal action (termination or stopping) affects the process as a whole.

[...]"

Reply by email

Unknown author
to KJK::Hyperion
Show quoted text 12 lines
At 12.27 15/11/2003, you wrote: >All you need to do is send the STOP signal to the thread. This is a common misunderstanding. I quote from IEEE 1003.1: "[...] Note that pthread_kill() only causes the signal to be handled in the context of the given thread; the signal action (termination or stopping) affects the process as a whole. [...]"

Strange. How do you explain that Kylix uses it ? I've used threads in Kylix, and they definitely work with suspend... Probably because for linux, each thread is a different process anyway ? (at least till the 2.4 kernels)

Michael.

Reply by email

Pedro Lopez-Cabanillas
to Unknown author
Show quoted text 17 lines
On Sat, 15 Nov 2003, KJK::Hyperion wrote: > At 12.27 15/11/2003, you wrote: > >All you need to do is send the STOP signal to the thread. > > This is a common misunderstanding. I quote from IEEE 1003.1: > > "[...] > > Note that pthread_kill() only causes the signal to be handled in the > context of the given thread; the signal action (termination or stopping) > affects the process as a whole. > > [...]" Strange. How do you explain that Kylix uses it ? I've used threads in Kylix, and they definitely work with suspend... Probably because for linux, each thread is a different process anyway ? (at least till the 2.4 kernels)

Red Hat has already backported the new NPT to 2.4, and it is included in RH9 IIRC. You can expect that Kylix multithreaded programs won't work very well under RH9 and newer Linux distributions, if they use TThread.Suspend and TThread.Resume (implemented using the signals SIGSTOP and SIGCONT). Borland shows little interest on Kylix updates, giving to the competitors a good chance to increase market share ;-)

It is on-topic a little citation of the announcement of Native POSIX Thread Library. The complete article can be found here:
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&safe=off&selm=3D8A6EC1.1010809%40redhat.com&rnum=1

Earlier message 31 lines
From: Ulrich Drepper () Subject: [ANNOUNCE] Native POSIX Thread Library 0.1 Date: 2002-09-19 17:50:06 PST [...] The thread library is designed to be binary compatible with the old LinuxThreads implementation. This compatibility obviously has some limitations. In places where the LinuxThreads implementation diverged from the POSIX standard incompatibilities exist. Users of the old library have been warned from day one that this day will come and code which added work-arounds for the POSIX non-compliance better be prepared to remove that code. The visible changes of the library include: - - The signal handling changes from per-thread signal handling to the POSIX process signal handling. This change will require changes in programs which exploit the non-conformance of the old implementation. One consequence of this is that SIGSTOP works on the process. Job control in the shell and stopping the whole process in a debugger work now. - - getpid() now returns the same value in all threads [...] Regards, Pedro -- ALSA Library Bindings for Pascal http://alsapas.alturl.com

Reply by email

Unknown author
to Pedro Lopez-Cabanillas
Pedro Lopez-Cabanillas wrote 21 lines
wrote: > On Sat, 15 Nov 2003, KJK::Hyperion wrote: > > At 12.27 15/11/2003, you wrote: > > >All you need to do is send the STOP signal to the thread. > > > > This is a common misunderstanding. I quote from IEEE 1003.1: > > > > "[...] > > > > Note that pthread_kill() only causes the signal to be handled in the > > context of the given thread; the signal action (termination or stopping) > > affects the process as a whole. > > > > [...]" > > Strange. How do you explain that Kylix uses it ? I've used threads in > Kylix, and they definitely work with suspend... Probably because for linux, > each thread is a different process anyway ? (at least till the 2.4 kernels) Red Hat has already backported the new NPT to 2.4, and it is included in RH9 IIRC.

I work with SuSE :-)

Show quoted text 9 lines
You can expect that Kylix multithreaded programs won't work very well under RH9 and newer Linux distributions, if they use TThread.Suspend and TThread.Resume (implemented using the signals SIGSTOP and SIGCONT). Borland shows little interest on Kylix updates, giving to the competitors a good chance to increase market share ;-) It is on-topic a little citation of the announcement of Native POSIX Thread Library. The complete article can be found here: http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&safe=off&selm=3D8A6EC1.1010809%40redhat.com&rnum=1

OK, thanks, this cleared up some stuff. Seems that another way will be needed. If it will be don't see how if you can't have per-thread signal handling...

I don't think this is a change for the better, but who am I to say so...

Michael.

Reply by email

Johannes Berg
to KJK::Hyperion: not arbitrary. The rules are roughly the same as those for signaling (SuspendThread, in…
Show quoted text 6 lines
not arbitrary. The rules are roughly the same as those for signaling (SuspendThread, in Windows, is implemented with a kernel-mode signal, like most system calls targeting threads). The only problem I see is the interaction with waits - but, on the other hand, EINTR has been banned from POSIX threads as cumbersome and of limited usefulness, and all POSIX threading interfaces restart interrupted waits automatically

Thats nice. However, I need to patch fpSleep(), it uses some _WEIRD_ code to block signals and stuff -- it never ever sleeps for me! Haven't taken a look at it yet, used fpnanosleep for the time being.

true. A crude and rude interface. But not supporting it at all?

Well, I'm all for supporting it from within threads, in a nice way. Btw, forget my second part of writing in the patch (about the warning), its not really possible, I was thinking .suspend should never be called but its ok from within a thread!

Anyway, I'm trying to think of a way to suspend a thread (maybe force a signal to be handled by that thread and then suspend somehow from the sighandler, I don't know how though, probably not possible). If anyone things of something I'm ok with adding it, but I want a _clean_ solution for suspending from within the thread itself.

johannes

http://www.sipsolutions.de/ GnuPG key: http://www.sipsolutions.de/keys/JohannesBerg.asc Key-ID: 9AB78CA5 Johannes Berg Fingerprint = AD02 0176 4E29 C137 1DF6 08D2 FC44 CF86 9AB7 8CA5

Reply by email

Johannes Berg
to Pedro Lopez-Cabanillas: Can you include also a patch for rtl/objpas/classes/classesh.inc ? Pedro ALSA Library…
Pedro Lopez-Cabanillas wrote
Can you include also a patch for rtl/objpas/classes/classesh.inc ?

Sorry! Here it is (inline, so short):

--- ./objpas/classes/classesh.inc 3 Nov 2003 09:42:28 -0000 1.6
+++ ./objpas/classes/classesh.inc 16 Nov 2003 18:38:44 -0000 @@ -1123,11 +1123,22 @@

     property Terminated: Boolean read FTerminated;
   public

{$ifdef Unix}
+{$IFDEF VER1_0} // keeping this around for ver 1 now { Needed for linux }

     FStackPointer : Pointer;
     FStackSize    : integer;
     FCallExitProcess : boolean;

+{$ELSE}
+private
+ // see tthread.inc, ThreadFunc and TThread.Resume
+ // these are FDs used from CreateSuspended
+ FCreateSuspDescriptorIn, FCreateSuspDescriptorOut: LongInt; +{$IFDEF LINUX}
+ FPid: LongInt;
+{$ENDIF}
+{$ENDIF}
{$endif}
+public

     constructor Create(CreateSuspended: Boolean);
     destructor Destroy; override;
     procedure Resume;

johannes

http://www.sipsolutions.de/ GnuPG key: http://www.sipsolutions.de/keys/JohannesBerg.asc Key-ID: 9AB78CA5 Johannes Berg Fingerprint = AD02 0176 4E29 C137 1DF6 08D2 FC44 CF86 9AB7 8CA5

Reply by email

KJK::Hyperion
to Unknown author: I work with SuSE :-) OK, thanks, this cleared up some stuff. Seems that another way will…
you wrote
OK, thanks, this cleared up some stuff. Seems that another way will be needed. If it will be don't see how if you can't have per-thread signal handling...

*handling* (such as, like I proposed, waiting on a mutex stored in TThread
- which also puts the thread in a non-cancellable state) is per-thread. It's just the default actions "terminate" and "stop/continue" that affect the whole process

Reply by email

Johannes Berg
to Johannes Berg: Probably not complete, but an overview of what I have in mind -- read the notes in the…

Hi,

Attached is a new version, this time with the diff of classesh.inc

This one contains the following new features:
* calling suspend from within threads is possible
and properly supported
* exceptions now work (I accidentally forgot AcquireExceptionObject)
* a thread trying to free itself yields an exception (if it propagates up completely the FreeOnTerminate flag is set and the thread destroyed none-the-less)
* factored out code for synchronization because I want to use semaphores as they don't fill up the file descriptor table, not used yet because they are not available in classes.pp (yet?), so still uses a pipe
* moved FThreadID to protected visibility in case someone needs to use the base pthread_* functions on the thread
- the pipe thing is most likely not signal safe (recv can be interrupted). I'm pretty sure actually, but need to test that and add loops as appropriate.
- still no synchronization support. I don't think this is too hard, but need information on how the foreground thread should be notified. A pipe would work well, the foreground thread could select() it and see if any thread wants it to do work for it (I expect that the GUI app main loop already selects anyway)

Have fun! :)

I consider this pretty good to use, but the signal issue blocks it.

johannes

http://www.sipsolutions.de/ GnuPG key: http://www.sipsolutions.de/keys/JohannesBerg.asc Key-ID: 9AB78CA5 Johannes Berg Fingerprint = AD02 0176 4E29 C137 1DF6 08D2 FC44 CF86 9AB7 8CA5

Reply by email

Michael Van Canneyt
to Johannes Berg
Johannes Berg wrote 25 lines
Hi, Attached is a new version, this time with the diff of classesh.inc This one contains the following new features: * calling suspend from within threads is possible and properly supported * exceptions now work (I accidentally forgot AcquireExceptionObject) * a thread trying to free itself yields an exception (if it propagates up completely the FreeOnTerminate flag is set and the thread destroyed none-the-less) * factored out code for synchronization because I want to use semaphores as they don't fill up the file descriptor table, not used yet because they are not available in classes.pp (yet?), so still uses a pipe * moved FThreadID to protected visibility in case someone needs to use the base pthread_* functions on the thread - the pipe thing is most likely not signal safe (recv can be interrupted). I'm pretty sure actually, but need to test that and add loops as appropriate. - still no synchronization support. I don't think this is too hard, but need information on how the foreground thread should be notified. A pipe would work well, the foreground thread could select() it and see if any thread wants it to do work for it (I expect that the GUI app main loop already selects anyway)

Delphi needs you to explicitly insert calls to CheckSynchronize. This is handled in the main loop of Delphi applications, and if you don't use that (e.g. no forms), then no synchronization is performed. I discovered that the hard way.

I'll look into implementing it.

Michael.

Reply by email

Johannes Berg
Btw, the syncobj demo you send me yesterday gives an access violation.

Maybe I messed up some FreeOnTerminate stuff, will have to look at it again.

johannes

Reply by email

Johannes Berg
Delphi needs you to explicitly insert calls to CheckSynchronize. This is handled in the main loop of Delphi applications, and if you don't use that (e.g. no forms), then no synchronization is performed. I discovered that the hard way.

Yes, but if we had a way that could be hooked right into the select/poll mechanism of the GUI, it would be more efficient. That means using a filedescriptor for synchronize stuff, but that would be OK imho, its only one global pipe.
But I don't know enough about the GTK main loop to do that. But if we implement CheckSynchronize via a pipe mechanism then we could always later add that.

johannes

Reply by email

Johannes Berg
.... under FreeBSD it fails. Probably due to the pipe trick I'm still investigating.

Weird, the pipe trick should be very portable, unless there are signals involved.
Try changing the
fpread(...) to

// pseudo code:
repeat
if fpread(...) = -1 then
not_signalled := errno = EINTR;
else
not_signalled := true;
until not_signalled;

and hope the loop doesn't get tight. but fpread should block in any case

johannes

Reply by email

Marco van de Voort
to Johannes Berg

[ Charset ISO-8859-1 unsupported, converting... ]

Show quoted text 18 lines
> .... under FreeBSD it fails. Probably due to the pipe trick > > I'm still investigating. Weird, the pipe trick should be very portable, unless there are signals involved. Try changing the fpread(...) to // pseudo code: repeat if fpread(...) = -1 then not_signalled := errno = EINTR; else not_signalled := true; until not_signalled; and hope the loop doesn't get tight. but fpread should block in any case

It's the assumptio that fpread returns EINTR. That is a a linuxism I guess.

It returns ESysEAGAIN.

I'm currently patching all these occurances when pipe related.

Reply by email

Marco van de Voort
to Marco van de Voort
Show quoted text 15 lines
> // pseudo code: > repeat > if fpread(...) = -1 then > not_signalled := errno = EINTR; > else > not_signalled := true; > until not_signalled; > > and hope the loop doesn't get tight. but fpread should block in any case It's the assumptio that fpread returns EINTR. That is a a linuxism I guess. It returns ESysEAGAIN. I'm currently patching all these occurances when pipe related.

Done, only two occurances that fix read(ln) and write(ln).

pthreads demo works now, the syncobjs demo still acts strange:

-bash-2.05b$ ./tevs
TEST OK
-bash-2.05b

(note that there is a significant pause between running and the "TEST OK" msg)

This looks ok, but shouldn't it give more output?

Reply by email

Peter Vreman
to Marco van de Voort: [ Charset ISO-8859-1 unsupported, converting... ] It's the assumptio that fpread returns…
Show quoted text 26 lines
[ Charset ISO-8859-1 unsupported, converting... ] > > .... under FreeBSD it fails. Probably due to the pipe trick > > > > I'm still investigating. > > Weird, the pipe trick should be very portable, unless there are signals > involved. > Try changing the > fpread(...) to > > // pseudo code: > repeat > if fpread(...) = -1 then > not_signalled := errno = EINTR; > else > not_signalled := true; > until not_signalled; > > and hope the loop doesn't get tight. but fpread should block in any case It's the assumptio that fpread returns EINTR. That is a a linuxism I guess. It returns ESysEAGAIN. I'm currently patching all these occurances when pipe related.

EAGAIN is only used for Non-blocking IO. The provided EINTR loop is correct for Linux,Solaris,Tru64 and UnixWare.

Reply by email

Marco van de Voort
to Peter Vreman
Show quoted text 25 lines
>> >> Weird, the pipe trick should be very portable, unless there are signals >> involved. >> Try changing the >> fpread(...) to >> >> // pseudo code: >> repeat >> if fpread(...) = -1 then >> not_signalled := errno = EINTR; >> else >> not_signalled := true; >> until not_signalled; >> >> and hope the loop doesn't get tight. but fpread should block in any case > > It's the assumptio that fpread returns EINTR. That is a a linuxism I > guess. > > It returns ESysEAGAIN. > > I'm currently patching all these occurances when pipe related. EAGAIN is only used for Non-blocking IO. The provided EINTR loop is correct for Linux,Solaris,Tru64 and UnixWare.

The FreeBSD read(2) manpage also says that it is for nonblocking.

I'll see what Stevens says about this tonight.

Reply by email

Johannes Berg
Show quoted text 5 lines
-bash-2.05b$ ./tevs TEST OK -bash-2.05b (note that there is a significant pause between running and the "TEST
OK"
msg) This looks ok, but shouldn't it give more output?

Thats ok, no more output required (I think). And the pause is there for a reason -- the main thread has to wait for the check.

johannes

Reply by email

Johannes Berg
The FreeBSD read(2) manpage also says that it is for nonblocking.

But its supposed to be using blocking IO, and EINTR is returned when the call was interrupted by a signal. But I don't know if that is cause of the problem -- was the only thing I could think of right now :-)

johannes

Reply by email