Sign in Join

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

Mailing lists / fpc-devel / 2006-11

CSuspendThread/CResumeThread

17 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

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

Jonas Maebe

Hello,

Does anyone see a problem with the following CSuspendThread/ CResumeThread implementations?

   function  CSuspendThread (threadHandle : TThreadID) : dword;
     begin
       result := pthread_kill(threadHandle,SIGSTOP);
     end;
   function  CResumeThread  (threadHandle : TThreadID) : dword;
     begin
       result := pthread_kill(threadHandle,SIGCONT);
     end;

Those routines are currently empty, and called for *bsd/Darwin in case you try to tthread.suspend one thread from inside another one. FWIW, I guess Linux should be changed to also use the above (it currently uses the regular kill, which may have unintended side effects with NPTL).

Jonas

Reply by email

Ales Katona
to Jonas Maebe
Jonas Maebe wrote 16 lines
Hello, Does anyone see a problem with the following CSuspendThread/ CResumeThread implementations? function CSuspendThread (threadHandle : TThreadID) : dword; begin result := pthread_kill(threadHandle,SIGSTOP); end; function CResumeThread (threadHandle : TThreadID) : dword; begin result := pthread_kill(threadHandle,SIGCONT); end;

Not sure how the signal handling is done per-thread in pthreads, will need to study on this.

Show quoted text 7 lines
Those routines are currently empty, and called for *bsd/Darwin in case you try to tthread.suspend one thread from inside another one. FWIW, I guess Linux should be changed to also use the above (it currently uses the regular kill, which may have unintended side effects with NPTL).

Indeed, linux should follow this principle too as any unix with pthreads.

Ales

Reply by email

Michael Van Canneyt
to Jonas Maebe: Does anyone see a problem with the following CSuspendThread/ CResumeThread…
Jonas Maebe wrote 21 lines
Hello, Does anyone see a problem with the following CSuspendThread/CResumeThread implementations? function CSuspendThread (threadHandle : TThreadID) : dword; begin result := pthread_kill(threadHandle,SIGSTOP); end; function CResumeThread (threadHandle : TThreadID) : dword; begin result := pthread_kill(threadHandle,SIGCONT); end; Those routines are currently empty, and called for *bsd/Darwin in case you try to tthread.suspend one thread from inside another one. FWIW, I guess Linux should be changed to also use the above (it currently uses the regular kill, which may have unintended side effects with NPTL).

I think this is OK.

Michael.

Reply by email

Michael Schnell
to Jonas Maebe: Does anyone see a problem with the following CSuspendThread/ CResumeThread…
Jonas Maebe wrote
Does anyone see a problem with the following CSuspendThread/CResumeThread implementations?

1) This of course is the Linux version. Are the other implementation already in place so that the result is platform independent ?

2) In Linux we have the old ("Linux thread" -> each thread is a process) and the new Posix compatible "Kernel-Thread" implementation (as of Kernel 2.6, a Linux process can have multiple threads). I don't know if/how TThread can select which kind of threads are created. AFAIK, using the standard thread library, Kilix automatically uses the new threads with Kernel 2.6, while still using the old ones with Kernel 2.4.

As I feel that using the new Kernel-Thread way is highly recommended, it should be granted that TThread uses same (when running in 2.6) and that the "suspend" method is workable with both.

If I remember correctly, there is a signal handler per process and not per thread, so this _might_ be a problem.

-Michael

Reply by email

Michael Van Canneyt
to Michael Schnell
Michael Schnell wrote 8 lines
Jonas Maebe wrote: > > Does anyone see a problem with the following CSuspendThread/CResumeThread > implementations? > 1) This of course is the Linux version. Are the other implementation already in place so that the result is platform independent ?

The 'other' implementation is the win32 implementation, and it is in place.

Show quoted text 7 lines
2) In Linux we have the old ("Linux thread" -> each thread is a process) and the new Posix compatible "Kernel-Thread" implementation (as of Kernel 2.6, a Linux process can have multiple threads). I don't know if/how TThread can select which kind of threads are created. AFAIK, using the standard thread library, Kilix automatically uses the new threads with Kernel 2.6, while still using the old ones with Kernel 2.4.

FPC does not decide anything. The pthread library decides this.

As I feel that using the new Kernel-Thread way is highly recommended, it should be granted that TThread uses same (when running in 2.6) and that the "suspend" method is workable with both.

We totally depend on the pthread implementation.

We'd like to have a native 100% FPC implementation, but none of the core developers currently has time to look into it.

If you are knowledgeable in this area, we would HUGELY appreaciate it if you could create a 100% FPC implementation. It would resolve many problems :-)

Michael.

Reply by email

Jonas Maebe
to Michael Schnell: 1) This of course is the Linux version. Are the other implementation already in place so…
Michael Schnell wrote
> Does anyone see a problem with the following CSuspendThread/ > CResumeThread implementations? 1) This of course is the Linux version.

No, it's the generic *nix version (i.e., also used for Free/Net/ OpenBSD, Darwin and Solaris).

Are the other implementation already in place so that the result is platform independent ?

I don't know.

Show quoted text 7 lines
2) In Linux we have the old ("Linux thread" -> each thread is a process) and the new Posix compatible "Kernel-Thread" implementation (as of Kernel 2.6, a Linux process can have multiple threads). I don't know if/how TThread can select which kind of threads are created. AFAIK, using the standard thread library, Kilix automatically uses the new threads with Kernel 2.6, while still using the old ones with Kernel 2.4.

We also use the standard thread library.

As I feel that using the new Kernel-Thread way is highly recommended, it should be granted that TThread uses same (when running in 2.6) and that the "suspend" method is workable with both.

pthread_kill is defined as sending a signal to a particular thread.

If I remember correctly, there is a signal handler per process and not per thread, so this _might_ be a problem.

That's why I use pthread_kill and not kill, as it's defined as sending a signal to a particular thread. If the Linux pthreads library does not handle this correctly, it's a bug in the Linux pthreads library. If you know another way to suspend a thread from inside another thread, feel free to say how that can be done.

The previous Linux code used plain kill which is wrong anyway (and the others mentioned above didn't do anything whatsoever), so this is at least an improvement.

Jonas

Reply by email

Ales Katona
to Jonas Maebe

Jonas currently fpc2.1.1 doesn't compile on 2.1.1 with:

rtl/units/i386-freebsd -di386 -dRELEASE ../unix/cthreads.pp cthreads.pp(252,42) Error: Incompatible type for arg no. 1: Got "LongInt", expected "Pointer"

Note:
unixtypes thread_t = pointer
pthreads.inc thread_t (BSD and linux) = cInt {linux is Longint but that's just bug)
pthreads.inc thread_t (Darwin) = pointer

Result of pthread_most = cInt
Result of ThreadManager.Killfunctions = DWord

This is some serious mess. First the threadmanager functions need to return a signed result, second the pointer vs cInt stuff has to be properly cleaned, remove thread_t from unittypes etc.

I'd do it myself but am asking for reasons against.

Ales

Reply by email

Michael Van Canneyt
to Ales Katona
Ales Katona wrote 20 lines
Jonas currently fpc2.1.1 doesn't compile on 2.1.1 with: rtl/units/i386-freebsd -di386 -dRELEASE ../unix/cthreads.pp cthreads.pp(252,42) Error: Incompatible type for arg no. 1: Got "LongInt", expected "Pointer" Note: unixtypes thread_t = pointer pthreads.inc thread_t (BSD and linux) = cInt {linux is Longint but that's just bug) pthreads.inc thread_t (Darwin) = pointer Result of pthread_most = cInt Result of ThreadManager.Killfunctions = DWord This is some serious mess. First the threadmanager functions need to return a signed result, second the pointer vs cInt stuff has to be properly cleaned, remove thread_t from unittypes etc. I'd do it myself but am asking for reasons against.

No reasons agains.

If you clean it up, please do it toroughly :-)

Michael.

Reply by email

Marco van de Voort
to Ales Katona: Jonas currently fpc2.1.1 doesn't compile on 2.1.1 with: rtl/units/i386-freebsd -di386…
Note: unixtypes thread_t = pointer

Wrong, same as in ptypes.inc

pthreads.inc thread_t (BSD and linux) = cInt {linux is Longint but that's just bug)

freebsd/pthreads.inc doesn't define thread_t, neither does the linux version?

There is a small issue with tthreadid which is already used to avoid this problem (typing of threadids) in cthreads. This is now defined in sysos, and could be made to match thread_t (which probably only got to ptypes.inc later)

This is some serious mess.

I don't see the exact problem. Sure ctypes needs some workaround for this, but just extending the current one. (see typecasting to tthreadid already in ctypes).

First the threadmanager functions need to return a signed result,

If so, then it should it should

second

the pointer vs cInt stuff has to be properly cleaned, remove thread_t from unittypes etc.

This is not possible. There should be none there:

unit unixtype;
Interface
{$i ptypes.inc}
Implementation
End.

And this situation is by design.

Reply by email

Jonas Maebe
to Ales Katona: Jonas currently fpc2.1.1 doesn't compile on 2.1.1 with: rtl/units/i386-freebsd -di386…
Ales Katona wrote 5 lines
Jonas currently fpc2.1.1 doesn't compile on 2.1.1 with: rtl/units/i386-freebsd -di386 -dRELEASE ../unix/cthreads.pp cthreads.pp(252,42) Error: Incompatible type for arg no. 1: Got "LongInt", expected "Pointer"

So either TThreadID or pthread_t is declared wrongly for FreeBSD (since that routine passes a TThreadID to a routine expecting a pthread_t)

Note: unixtypes thread_t = pointer

No. unixtype includes ptypes.inc. ptypes.inc is OS-dependent. For *BSD and Darwin, pthread_t (not thread_t) is defined as a pointer. For Linux it's defined as a cuLong. It's not defined in that file at all for Solaris, which is a bug I think (it's defined in solaris/ pthread.inc instead).

pthreads.inc thread_t (BSD and linux) = cInt {linux is Longint but that's just bug)

I don't see this. Afaics, pthread_t (and ppthread_t) is used appropriately everywhere in pthread.inc for both Linux and FreeBSD. I didn't check all declarations in detail, but at first sight the cInts (and longints in Linux) are used where the C versions also return an int, and not instead of pthread_t.

Show quoted text 7 lines
pthreads.inc thread_t (Darwin) = pointer Result of pthread_most = cInt Result of ThreadManager.Killfunctions = DWord This is some serious mess. First the threadmanager functions need to return a signed result,

Or possibly a result depending on the OS (just like TThreadID is an OS-dependent type). I don't know what the Windows versions return.

second the pointer vs cInt stuff has to be properly cleaned, remove thread_t from unittypes etc.

Sorry, I'm not following the last point. What do you mean with "unittypes"? The UnixType unit or "types used in various units"? Most stuff should in fact be based on pthread_t I think, since that's how the C declaration of those routines looks.

We could define pthread_t as TThreadID to avoid duplication of information though.

Jonas

Reply by email

Ales Katona
to Marco van de Voort: Wrong, same as in ptypes.inc freebsd/pthreads.inc doesn't define thread_t, neither does…

A cleaner naming of problematic parts:

1. TThreadID is defined stand-alone not as a pthread_t, should be fixed.
2. TThreadHandler (the callback for resume, suspend) has result as DWord while posix stuff (pthread_kill etc.) usualy return cInt
3. in linux I saw pthreads functions return longint, I think this is also investigation worthy.

Question about #1. How should this be handled? Not sure if I can "use" unixtypes in sysosh.inc...

Question about #2. Well.. this is a tough nut? I suspect it's because of various threading backends, but we need to handle those -1 properly if nothing else but this implies going over by all used pthread functions and seeing all possible values (which might be OS specific)

#3 is to be investigated.

Will look at it later.

Ales

Reply by email

Jonas Maebe
to Ales Katona
Ales Katona wrote 12 lines
A cleaner naming of problematic parts: 1. TThreadID is defined stand-alone not as a pthread_t, should be fixed. 2. TThreadHandler (the callback for resume, suspend) has result as DWord while posix stuff (pthread_kill etc.) usualy return cInt 3. in linux I saw pthreads functions return longint, I think this is also investigation worthy. Question about #1. How should this be handled? Not sure if I can "use" unixtypes in sysosh.inc...

No, you probably can't since that would add all those types to the interface of the system unit. But in my mail I proposed a simple solution: just do it the other way round (type pthread_t = TThreadID)

Show quoted text 5 lines
Question about #2. Well.. this is a tough nut? I suspect it's because of various threading backends, but we need to handle those -1 properly if nothing else but this implies going over by all used pthread functions and seeing all possible values (which might be OS specific)

A similar solution as TThreadID probably (unless all OSes use signed results).

#3 is to be investigated.

Simply replace the longints with cInt. Those declarations are from before the time we had aliases for ctypes in the RTL.

Jonas

Reply by email

Michael Van Canneyt
to Ales Katona: A cleaner naming of problematic parts: 1. TThreadID is defined stand-alone not as a…
Ales Katona wrote 5 lines
A cleaner naming of problematic parts: 1. TThreadID is defined stand-alone not as a pthread_t, should be fixed. 2. TThreadHandler (the callback for resume, suspend) has result as DWord while posix stuff (pthread_kill etc.) usualy return cInt

Just define an opaque type TThreadResult:

TThreadResult = DWord // Windows

TThreadResult = cInt // Unices

3. in linux I saw pthreads functions return longint, I think this is also investigation worthy.

Yes.

Question about #1. How should this be handled? Not sure if I can "use" unixtypes in sysosh.inc...

You can't. But jonas has a solution.

Michael.

Reply by email

Jonas Maebe
to Jonas Maebe: No, you probably can't since that would add all those types to the interface of the…
Jonas Maebe wrote 10 lines
> Question about #2. Well.. this is a tough nut? I suspect it's > because of > various threading backends, but we need to handle those -1 > properly if > nothing else but this implies going over by all used pthread > functions > and seeing all possible values (which might be OS specific) A similar solution as TThreadID probably (unless all OSes use signed results).

Actually, maybe this should not be the case. After all, how do you do error checking in your program then? You'll have to add ifdef's everywhere, while this is supposed to be platform-neutral code.

If e.g. on windows the result $ffffffff is not possible, we can define that one as an error result (or, similarly, define -1 as an error result and change the result type to cInt).

Jonas

Reply by email

Ales Katona
to Michael Van Canneyt: Just define an opaque type TThreadResult: TThreadResult = DWord // Windows TThreadResult…
Show quoted text 6 lines
Just define an opaque type TThreadResult: TThreadResult = DWord // Windows TThreadResult = cInt // Unices

I don't like this solution for several reasons:

1. What if one OS has more backends for threading available, which differ in this?

2. How are we going to handle error states on cross-platform TThreadManager using code?

Ofcourse, in a perfect world I'd come up with something nice by now myself.. well surprise surprise I haven't.

I don't think there's a 100% clean solution but IMHO we should pick one internal scheme and go with it. For example say we choose to use a signed integer, -1 for error and specific values for specific situations needed.

Back-ends which follow it would just be used like now (result:=...)
while those which differ would be "translated" (eg: if ...  xxx then
Result:=-1)

As I said it's far from perfect, but it gives a consistent interface atleast.

Ales

P.S: I do realize that there might be functions which result value returns eg: something which needs to be taken and passed along, or which value is variable (not constant). In case we abstract the return value, we limit this, so I say we abstract it to something BIG

Reply by email

Michael Van Canneyt
to Ales Katona
Ales Katona wrote 11 lines
> Just define an opaque type TThreadResult: > > TThreadResult = DWord // Windows > > TThreadResult = cInt // Unices > I don't like this solution for several reasons: 1. What if one OS has more backends for threading available, which differ in this?

Good question :-)

But we can easily decide that this is not allowed; On Unix cInt is the regular type for error codes, so I don't see why anyone in his right mind would want to do something else.

2. How are we going to handle error states on cross-platform TThreadManager using code?

You can't do this reliable anyway IMHO. You would need a huge table with error conditions and do some kind of mapping on 'known values'.

Apart from the difficulty in coding this, do you know all error conditions and codes for all platforms ? Are they all documented ? I don't think so...

I don't see an easy way out, short of using exceptions, which are hard to do in a threading context.

Michael.

Reply by email