Browse Source

* adds semaphore support to ThreadManager, removes pipe hack from non linux
+ adds SemaphoreInit, SemaphorePost, SemaphoreWait and SemaphoreDestroy to TM

git-svn-id: trunk@4900 -

Almindor 19 years ago
parent
commit
2ee7e64a4a
8 changed files with 162 additions and 330 deletions
  1. 7 61
      rtl/darwin/tthread.inc
  2. 17 62
      rtl/freebsd/tthread.inc
  3. 24 0
      rtl/inc/thread.inc
  4. 10 0
      rtl/inc/threadh.inc
  5. 21 58
      rtl/netbsd/tthread.inc
  6. 23 69
      rtl/openbsd/tthread.inc
  7. 24 77
      rtl/solaris/tthread.inc
  8. 36 3
      rtl/unix/cthreads.pp

+ 7 - 61
rtl/darwin/tthread.inc

@@ -63,64 +63,9 @@
 {$define WRITE_DEBUG := //}      // just comment out those lines
 {$define WRITE_DEBUG := //}      // just comment out those lines
 {$ENDIF}
 {$ENDIF}
 
 
-// ========== semaphore stuff ==========
-{
-  I don't like this. It eats up 2 filedescriptors for each thread,
-  and those are a limited resource. If you have a server programm
-  handling client connections (one per thread) it will not be able
-  to handle many if we use 2 fds already for internal structures.
-  However, right now I don't see a better option unless some sem_*
-  functions are added to systhrds.
-  I encapsulated all used functions here to make it easier to
-  change them completely.
-}
-
-function SemaphoreInit: Pointer;
-begin
-  SemaphoreInit := GetMem(SizeOf(TFilDes));
-  fppipe(PFilDes(SemaphoreInit)^);
-  WRITE_DEBUG('Opened file descriptor ',PFilDes(SemaphoreInit)^[0]);
-end;
-
-procedure SemaphoreWait(const FSem: Pointer);
-var
-  b: byte;
-begin
-  WRITE_DEBUG('Waiting for file descriptor ',PFilDes(FSem)^[0]);
-  repeat
-    if fpread(PFilDes(FSem)^[0], b, 1) = -1 then
-      WRITE_DEBUG('Error reading from semaphore ',PFilDes(FSem)^[0],' error = ',fpgeterrno);
-  until fpgeterrno <> ESysEIntr;
-end;
-
-procedure SemaphorePost(const FSem: Pointer);
-{$ifdef VER2_0}
-var
-  b : byte;
-{$endif}
-begin
-  WRITE_DEBUG('Activating file descriptor ',PFilDes(FSem)^[0]);
-{$ifdef VER2_0}
-  b:=0;
-  fpwrite(PFilDes(FSem)^[1], b, 1);
-{$else}
-  if fpwrite(PFilDes(FSem)^[1], #0, 1) = -1 then
-    WRITE_DEBUG('Error writing file descriptor ',PFilDes(FSem)^[0],' error = ',fpgeterrno);
-{$endif}
-end;
-
-procedure SemaphoreDestroy(const FSem: Pointer);
-begin
-  WRITE_DEBUG('Closing file descriptor ',PFilDes(FSem)^[0]);
-  fpclose(PFilDes(FSem)^[0]);
-  fpclose(PFilDes(FSem)^[1]);
-  FreeMemory(FSem);
-end;
-
-// =========== semaphore end ===========
-
 var
 var
   ThreadsInited: boolean = false;
   ThreadsInited: boolean = false;
+  CurrentTM: TThreadManager;
 const
 const
   // stupid, considering its not even implemented...
   // stupid, considering its not even implemented...
   Priorities: array [TThreadPriority] of Integer =
   Priorities: array [TThreadPriority] of Integer =
@@ -128,6 +73,7 @@ const
 
 
 procedure InitThreads;
 procedure InitThreads;
 begin
 begin
+  GetThreadManager(CurrentTM);
   if not ThreadsInited then begin
   if not ThreadsInited then begin
     ThreadsInited := true;
     ThreadsInited := true;
   end;
   end;
@@ -148,7 +94,7 @@ begin
   try
   try
     if LThread.FInitialSuspended then
     if LThread.FInitialSuspended then
       begin
       begin
-        SemaphoreWait(LThread.FSem);
+        CurrentTM.SemaphoreWait(LThread.FSem);
         if not(LThread.FTerminated) then
         if not(LThread.FTerminated) then
           begin
           begin
             if not LThread.FSuspended then
             if not LThread.FSuspended then
@@ -196,7 +142,7 @@ begin
   // via BeginThread and creates the first TThread Object in there!
   // via BeginThread and creates the first TThread Object in there!
   InitThreads;
   InitThreads;
   inherited Create;
   inherited Create;
-  FSem := SemaphoreInit;
+  FSem := CurrentTM.SemaphoreInit;
   FSuspended := CreateSuspended;
   FSuspended := CreateSuspended;
   FSuspendedExternal := false;
   FSuspendedExternal := false;
   FInitialSuspended := CreateSuspended;
   FInitialSuspended := CreateSuspended;
@@ -225,7 +171,7 @@ begin
     end;
     end;
   FFatalException.Free;
   FFatalException.Free;
   FFatalException := nil;
   FFatalException := nil;
-  SemaphoreDestroy(FSem);
+  CurrentTM.SemaphoreDestroy(FSem);
   { threadvars have been released by cthreads.ThreadMain -> DoneThread }
   { threadvars have been released by cthreads.ThreadMain -> DoneThread }
   inherited Destroy;
   inherited Destroy;
 end;
 end;
@@ -244,7 +190,7 @@ begin
   if not FSuspended then begin
   if not FSuspended then begin
     if FThreadID = GetCurrentThreadID then begin
     if FThreadID = GetCurrentThreadID then begin
       FSuspended := true;
       FSuspended := true;
-      SemaphoreWait(FSem);
+      CurrentTM.SemaphoreWait(FSem);
     end else begin
     end else begin
       FSuspendedExternal := true;
       FSuspendedExternal := true;
       SuspendThread(FHandle);
       SuspendThread(FHandle);
@@ -258,7 +204,7 @@ begin
   if (not FSuspendedExternal) then begin
   if (not FSuspendedExternal) then begin
     if FSuspended then begin
     if FSuspended then begin
       FSuspended := False;
       FSuspended := False;
-      SemaphorePost(FSem);
+      CurrentTM.SemaphorePost(FSem);
     end;
     end;
   end else begin
   end else begin
     FSuspendedExternal := false;
     FSuspendedExternal := false;

+ 17 - 62
rtl/freebsd/tthread.inc

@@ -54,56 +54,19 @@
   Johannes Berg <[email protected]>, Sunday, November 16 2003
   Johannes Berg <[email protected]>, Sunday, November 16 2003
 }
 }
 
 
-// ========== semaphore stuff ==========
-{
-  I don't like this. It eats up 2 filedescriptors for each thread,
-  and those are a limited resource. If you have a server programm
-  handling client connections (one per thread) it will not be able
-  to handle many if we use 2 fds already for internal structures.
-  However, right now I don't see a better option unless some sem_*
-  functions are added to systhrds.
-  I encapsulated all used functions here to make it easier to
-  change them completely.
-}
-
-function SemaphoreInit: Pointer;
-begin
-  SemaphoreInit := GetMem(SizeOf(TFilDes));
-  fppipe(PFilDes(SemaphoreInit)^);
-end;
-
-procedure SemaphoreWait(const FSem: Pointer);
-var
-  b: byte;
-begin
-  fpread(PFilDes(FSem)^[0], b, 1);
-end;
-
-procedure SemaphorePost(const FSem: Pointer);
-{$ifdef VER2_0}
-var
-  b : byte;
-{$endif}
-begin
-{$ifdef VER2_0}
-  b:=0;
-  fpwrite(PFilDes(FSem)^[1], b, 1);
-{$else}
-  fpwrite(PFilDes(FSem)^[1], #0, 1);
-{$endif}
-end;
-
-procedure SemaphoreDestroy(const FSem: Pointer);
-begin
-  fpclose(PFilDes(FSem)^[0]);
-  fpclose(PFilDes(FSem)^[1]);
-  FreeMemory(FSem);
-end;
-
-// =========== semaphore end ===========
+{ ok, so this is a hack, but it works nicely. Just never use
+  a multiline argument with WRITE_DEBUG! }
+{$MACRO ON}
+{$IFDEF DEBUG_MT}
+{$define WRITE_DEBUG := writeln} // actually write something
+{$ELSE}
+{$define WRITE_DEBUG := //}      // just comment out those lines
+{$ENDIF}
 
 
 var
 var
   ThreadsInited: boolean = false;
   ThreadsInited: boolean = false;
+  CurrentTM: TThreadManager;
+  
 const
 const
   // stupid, considering its not even implemented...
   // stupid, considering its not even implemented...
   Priorities: array [TThreadPriority] of Integer =
   Priorities: array [TThreadPriority] of Integer =
@@ -111,6 +74,7 @@ const
 
 
 procedure InitThreads;
 procedure InitThreads;
 begin
 begin
+  GetThreadManager(CurrentTM);
   if not ThreadsInited then
   if not ThreadsInited then
     ThreadsInited := true;
     ThreadsInited := true;
 end;
 end;
@@ -120,15 +84,6 @@ begin
   ThreadsInited := false;
   ThreadsInited := false;
 end;
 end;
 
 
-{ ok, so this is a hack, but it works nicely. Just never use
-  a multiline argument with WRITE_DEBUG! }
-{$MACRO ON}
-{$IFDEF DEBUG_MT}
-{$define WRITE_DEBUG := writeln} // actually write something
-{$ELSE}
-{$define WRITE_DEBUG := //}      // just comment out those lines
-{$ENDIF}
-
 function ThreadFunc(parameter: Pointer): LongInt;
 function ThreadFunc(parameter: Pointer): LongInt;
 var
 var
   LThread: TThread;
   LThread: TThread;
@@ -139,7 +94,7 @@ begin
   WRITE_DEBUG('thread initing, parameter = ', LongInt(LThread));
   WRITE_DEBUG('thread initing, parameter = ', LongInt(LThread));
   try
   try
     if LThread.FInitialSuspended then begin
     if LThread.FInitialSuspended then begin
-      SemaphoreWait(LThread.FSem);
+      CurrentTM.SemaphoreWait(LThread.FSem);
       if not LThread.FSuspended then begin
       if not LThread.FSuspended then begin
         LThread.FInitialSuspended := false;
         LThread.FInitialSuspended := false;
         WRITE_DEBUG('going into LThread.Execute');
         WRITE_DEBUG('going into LThread.Execute');
@@ -180,7 +135,7 @@ begin
   // via BeginThread and creates the first TThread Object in there!
   // via BeginThread and creates the first TThread Object in there!
   InitThreads;
   InitThreads;
   inherited Create;
   inherited Create;
-  FSem := SemaphoreInit;
+  FSem := CurrentTM.SemaphoreInit;
   FSuspended := CreateSuspended;
   FSuspended := CreateSuspended;
   FSuspendedExternal := false;
   FSuspendedExternal := false;
   FInitialSuspended := CreateSuspended;
   FInitialSuspended := CreateSuspended;
@@ -205,12 +160,12 @@ begin
   end;
   end;
   if (FInitialSuspended) then begin
   if (FInitialSuspended) then begin
     // thread was created suspended but never woken up.
     // thread was created suspended but never woken up.
-    SemaphorePost(FSem);
+    CurrentTM.SemaphorePost(FSem);
     WaitFor;
     WaitFor;
   end;
   end;
   FFatalException.Free;
   FFatalException.Free;
   FFatalException := nil;
   FFatalException := nil;
-  SemaphoreDestroy(FSem);
+  CurrentTM.SemaphoreDestroy(FSem);
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
@@ -228,7 +183,7 @@ begin
   if not FSuspended then begin
   if not FSuspended then begin
     if FThreadID = GetCurrentThreadID then begin
     if FThreadID = GetCurrentThreadID then begin
       FSuspended := true;
       FSuspended := true;
-      SemaphoreWait(FSem);
+      CurrentTM.SemaphoreWait(FSem);
     end else begin
     end else begin
       FSuspendedExternal := true;
       FSuspendedExternal := true;
       SuspendThread(FHandle);
       SuspendThread(FHandle);
@@ -242,7 +197,7 @@ begin
   if (not FSuspendedExternal) then begin
   if (not FSuspendedExternal) then begin
     if FSuspended then begin
     if FSuspended then begin
       FSuspended := False;
       FSuspended := False;
-      SemaphorePost(FSem);
+      CurrentTM.SemaphorePost(FSem);
     end;
     end;
   end else begin
   end else begin
     FSuspendedExternal := false;
     FSuspendedExternal := false;

+ 24 - 0
rtl/inc/thread.inc

@@ -449,6 +449,25 @@ procedure NORTLeventsync(m:trtlmethod;p:tprocedure);
     NoThreadError;
     NoThreadError;
   end;
   end;
 
 
+function NoSemaphoreInit: Pointer;
+begin
+  NoThreadError;
+end;
+
+procedure NoSemaphoreWait(const FSem: Pointer);
+begin
+  NoThreadError;
+end;
+
+procedure NoSemaphorePost(const FSem: Pointer);
+begin
+  NoThreadError;
+end;
+
+procedure NoSemaphoreDestroy(const FSem: Pointer);
+begin
+  NoThreadError;
+end;
 
 
 Var
 Var
   NoThreadManager : TThreadManager;
   NoThreadManager : TThreadManager;
@@ -490,6 +509,11 @@ begin
     rtleventWaitFor        :=@NortleventWaitFor;
     rtleventWaitFor        :=@NortleventWaitFor;
     rtleventsync           :=@Nortleventsync;
     rtleventsync           :=@Nortleventsync;
     rtleventwaitfortimeout :=@NortleventWaitForTimeout;
     rtleventwaitfortimeout :=@NortleventWaitForTimeout;
+    // semaphores stuff
+    SemaphoreInit          :=@NoSemaphoreInit;
+    SemaphoreDestroy       :=@NoSemaphoreDestroy;
+    SemaphoreWait          :=@NoSemaphoreWait;
+    SemaphorePost          :=@NoSemaphorePost;
     end;
     end;
   SetThreadManager(NoThreadManager);
   SetThreadManager(NoThreadManager);
 end;
 end;

+ 10 - 0
rtl/inc/threadh.inc

@@ -46,6 +46,11 @@ type
   TRTLEventHandlerTimeout   = procedure(AEvent:PRTLEvent;timeout : longint);
   TRTLEventHandlerTimeout   = procedure(AEvent:PRTLEvent;timeout : longint);
   TRTLCreateEventHandler    = function:PRTLEvent;
   TRTLCreateEventHandler    = function:PRTLEvent;
   TRTLEventSyncHandler      = procedure (m:trtlmethod;p:tprocedure);
   TRTLEventSyncHandler      = procedure (m:trtlmethod;p:tprocedure);
+  // semaphores stuff
+  TSempahoreInitHandler     = function: Pointer;
+  TSemaphoreDestroyHandler  = procedure (const sem: Pointer);
+  TSemaphorePostHandler     = procedure (const sem: Pointer);
+  TSemaphoreWaitHandler     = procedure (const sem: Pointer);
 
 
   // TThreadManager interface.
   // TThreadManager interface.
   TThreadManager = Record
   TThreadManager = Record
@@ -82,6 +87,11 @@ type
     RTLEventWaitFor        : TRTLEventHandler;
     RTLEventWaitFor        : TRTLEventHandler;
     RTLEventSync           : TRTLEventSyncHandler;
     RTLEventSync           : TRTLEventSyncHandler;
     RTLEventWaitForTimeout : TRTLEventHandlerTimeout;
     RTLEventWaitForTimeout : TRTLEventHandlerTimeout;
+    // semaphores stuff
+    SemaphoreInit          : TSempahoreInitHandler;
+    SemaphoreDestroy       : TSemaphoreDestroyHandler;
+    SemaphorePost          : TSemaphorePostHandler;
+    SemaphoreWait          : TSemaphoreWaitHandler;
   end;
   end;
 
 
 {*****************************************************************************
 {*****************************************************************************

+ 21 - 58
rtl/netbsd/tthread.inc

@@ -54,47 +54,19 @@
   Johannes Berg <[email protected]>, Sunday, November 16 2003
   Johannes Berg <[email protected]>, Sunday, November 16 2003
 }
 }
 
 
-// ========== semaphore stuff ==========
-{
-  I don't like this. It eats up 2 filedescriptors for each thread,
-  and those are a limited resource. If you have a server programm
-  handling client connections (one per thread) it will not be able
-  to handle many if we use 2 fds already for internal structures.
-  However, right now I don't see a better option unless some sem_*
-  functions are added to systhrds.
-  I encapsulated all used functions here to make it easier to
-  change them completely.
-}
-
-function SemaphoreInit: Pointer;
-begin
-  SemaphoreInit := GetMem(SizeOf(TFilDes));
-  fppipe(PFilDes(SemaphoreInit)^);
-end;
-
-procedure SemaphoreWait(const FSem: Pointer);
-var
-  b: byte;
-begin
-  fpread(PFilDes(FSem)^[0], b, 1);
-end;
-
-procedure SemaphorePost(const FSem: Pointer);
-begin
-  fpwrite(PFilDes(FSem)^[1], #0, 1);
-end;
-
-procedure SemaphoreDestroy(const FSem: Pointer);
-begin
-  fpclose(PFilDes(FSem)^[0]);
-  fpclose(PFilDes(FSem)^[1]);
-  FreeMemory(FSem);
-end;
-
-// =========== semaphore end ===========
+{ ok, so this is a hack, but it works nicely. Just never use
+  a multiline argument with WRITE_DEBUG! }
+{$MACRO ON}
+{$IFDEF DEBUG_MT}
+{$define WRITE_DEBUG := writeln} // actually write something
+{$ELSE}
+{$define WRITE_DEBUG := //}      // just comment out those lines
+{$ENDIF}
 
 
 var
 var
   ThreadsInited: boolean = false;
   ThreadsInited: boolean = false;
+  CurrentTM: TThreadManager;
+  
 const
 const
   // stupid, considering its not even implemented...
   // stupid, considering its not even implemented...
   Priorities: array [TThreadPriority] of Integer =
   Priorities: array [TThreadPriority] of Integer =
@@ -102,9 +74,9 @@ const
 
 
 procedure InitThreads;
 procedure InitThreads;
 begin
 begin
-  if not ThreadsInited then begin
+  GetThreadManager(CurrentTM);
+  if not ThreadsInited then
     ThreadsInited := true;
     ThreadsInited := true;
-  end;
 end;
 end;
 
 
 procedure DoneThreads;
 procedure DoneThreads;
@@ -112,16 +84,7 @@ begin
   ThreadsInited := false;
   ThreadsInited := false;
 end;
 end;
 
 
-{ ok, so this is a hack, but it works nicely. Just never use
-  a multiline argument with WRITE_DEBUG! }
-{$MACRO ON}
-{$IFDEF DEBUG_MT}
-{$define WRITE_DEBUG := writeln} // actually write something
-{$ELSE}
-{$define WRITE_DEBUG := //}      // just comment out those lines
-{$ENDIF}
-
-function ThreadFunc(parameter: Pointer): LongInt; cdecl;
+function ThreadFunc(parameter: Pointer): LongInt;
 var
 var
   LThread: TThread;
   LThread: TThread;
   c: char;
   c: char;
@@ -131,7 +94,7 @@ begin
   WRITE_DEBUG('thread initing, parameter = ', LongInt(LThread));
   WRITE_DEBUG('thread initing, parameter = ', LongInt(LThread));
   try
   try
     if LThread.FInitialSuspended then begin
     if LThread.FInitialSuspended then begin
-      SemaphoreWait(LThread.FSem);
+      CurrentTM.SemaphoreWait(LThread.FSem);
       if not LThread.FSuspended then begin
       if not LThread.FSuspended then begin
         LThread.FInitialSuspended := false;
         LThread.FInitialSuspended := false;
         WRITE_DEBUG('going into LThread.Execute');
         WRITE_DEBUG('going into LThread.Execute');
@@ -172,13 +135,13 @@ begin
   // via BeginThread and creates the first TThread Object in there!
   // via BeginThread and creates the first TThread Object in there!
   InitThreads;
   InitThreads;
   inherited Create;
   inherited Create;
-  FSem := SemaphoreInit;
+  FSem := CurrentTM.SemaphoreInit;
   FSuspended := CreateSuspended;
   FSuspended := CreateSuspended;
   FSuspendedExternal := false;
   FSuspendedExternal := false;
   FInitialSuspended := CreateSuspended;
   FInitialSuspended := CreateSuspended;
   FFatalException := nil;
   FFatalException := nil;
-  WRITE_DEBUG('creating thread, self = ',longint(self));
-  FHandle:= BeginThread(@ThreadFunc, Pointer(Self), FThreadID, StackSize);
+  WRITE_DEBUG('creating thread, self = ',PtrInt(self));
+  FHandle:= BeginThread(@ThreadFunc, Pointer(Self), FThreadID,StackSize);
   WRITE_DEBUG('TThread.Create done');
   WRITE_DEBUG('TThread.Create done');
 end;
 end;
 
 
@@ -197,12 +160,12 @@ begin
   end;
   end;
   if (FInitialSuspended) then begin
   if (FInitialSuspended) then begin
     // thread was created suspended but never woken up.
     // thread was created suspended but never woken up.
-    SemaphorePost(FSem);
+    CurrentTM.SemaphorePost(FSem);
     WaitFor;
     WaitFor;
   end;
   end;
   FFatalException.Free;
   FFatalException.Free;
   FFatalException := nil;
   FFatalException := nil;
-  SemaphoreDestroy(FSem);
+  CurrentTM.SemaphoreDestroy(FSem);
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
@@ -220,7 +183,7 @@ begin
   if not FSuspended then begin
   if not FSuspended then begin
     if FThreadID = GetCurrentThreadID then begin
     if FThreadID = GetCurrentThreadID then begin
       FSuspended := true;
       FSuspended := true;
-      SemaphoreWait(FSem);
+      CurrentTM.SemaphoreWait(FSem);
     end else begin
     end else begin
       FSuspendedExternal := true;
       FSuspendedExternal := true;
       SuspendThread(FHandle);
       SuspendThread(FHandle);
@@ -234,7 +197,7 @@ begin
   if (not FSuspendedExternal) then begin
   if (not FSuspendedExternal) then begin
     if FSuspended then begin
     if FSuspended then begin
       FSuspended := False;
       FSuspended := False;
-      SemaphorePost(FSem);
+      CurrentTM.SemaphorePost(FSem);
     end;
     end;
   end else begin
   end else begin
     FSuspendedExternal := false;
     FSuspendedExternal := false;

+ 23 - 69
rtl/openbsd/tthread.inc

@@ -14,7 +14,6 @@
 }
 }
 
 
 
 
-
 {
 {
   What follows, is a short description on my implementation of TThread.
   What follows, is a short description on my implementation of TThread.
   Most information can also be found by reading the source and accompanying
   Most information can also be found by reading the source and accompanying
@@ -55,56 +54,19 @@
   Johannes Berg <[email protected]>, Sunday, November 16 2003
   Johannes Berg <[email protected]>, Sunday, November 16 2003
 }
 }
 
 
-// ========== semaphore stuff ==========
-{
-  I don't like this. It eats up 2 filedescriptors for each thread,
-  and those are a limited resource. If you have a server programm
-  handling client connections (one per thread) it will not be able
-  to handle many if we use 2 fds already for internal structures.
-  However, right now I don't see a better option unless some sem_*
-  functions are added to systhrds.
-  I encapsulated all used functions here to make it easier to
-  change them completely.
-}
-
-function SemaphoreInit: Pointer;
-begin
-  SemaphoreInit := GetMem(SizeOf(TFilDes));
-  fppipe(PFilDes(SemaphoreInit)^);
-end;
-
-procedure SemaphoreWait(const FSem: Pointer);
-var
-  b: byte;
-begin
-  fpread(PFilDes(FSem)^[0], b, 1);
-end;
-
-procedure SemaphorePost(const FSem: Pointer);
-{$ifdef VER2_0}
-var
-  b : byte;
-{$endif}
-begin
-{$ifdef VER2_0}
-  b:=0;
-  fpwrite(PFilDes(FSem)^[1], b, 1);
-{$else}
-  fpwrite(PFilDes(FSem)^[1], #0, 1);
-{$endif}
-end;
-
-procedure SemaphoreDestroy(const FSem: Pointer);
-begin
-  fpclose(PFilDes(FSem)^[0]);
-  fpclose(PFilDes(FSem)^[1]);
-  FreeMemory(FSem);
-end;
-
-// =========== semaphore end ===========
+{ ok, so this is a hack, but it works nicely. Just never use
+  a multiline argument with WRITE_DEBUG! }
+{$MACRO ON}
+{$IFDEF DEBUG_MT}
+{$define WRITE_DEBUG := writeln} // actually write something
+{$ELSE}
+{$define WRITE_DEBUG := //}      // just comment out those lines
+{$ENDIF}
 
 
 var
 var
   ThreadsInited: boolean = false;
   ThreadsInited: boolean = false;
+  CurrentTM: TThreadManager;
+  
 const
 const
   // stupid, considering its not even implemented...
   // stupid, considering its not even implemented...
   Priorities: array [TThreadPriority] of Integer =
   Priorities: array [TThreadPriority] of Integer =
@@ -112,9 +74,9 @@ const
 
 
 procedure InitThreads;
 procedure InitThreads;
 begin
 begin
-  if not ThreadsInited then begin
+  GetThreadManager(CurrentTM);
+  if not ThreadsInited then
     ThreadsInited := true;
     ThreadsInited := true;
-  end;
 end;
 end;
 
 
 procedure DoneThreads;
 procedure DoneThreads;
@@ -122,16 +84,7 @@ begin
   ThreadsInited := false;
   ThreadsInited := false;
 end;
 end;
 
 
-{ ok, so this is a hack, but it works nicely. Just never use
-  a multiline argument with WRITE_DEBUG! }
-{$MACRO ON}
-{$IFDEF DEBUG_MT}
-{$define WRITE_DEBUG := writeln} // actually write something
-{$ELSE}
-{$define WRITE_DEBUG := //}      // just comment out those lines
-{$ENDIF}
-
-function ThreadFunc(parameter: Pointer): LongInt; cdecl;
+function ThreadFunc(parameter: Pointer): LongInt;
 var
 var
   LThread: TThread;
   LThread: TThread;
   c: char;
   c: char;
@@ -141,7 +94,7 @@ begin
   WRITE_DEBUG('thread initing, parameter = ', LongInt(LThread));
   WRITE_DEBUG('thread initing, parameter = ', LongInt(LThread));
   try
   try
     if LThread.FInitialSuspended then begin
     if LThread.FInitialSuspended then begin
-      SemaphoreWait(LThread.FSem);
+      CurrentTM.SemaphoreWait(LThread.FSem);
       if not LThread.FSuspended then begin
       if not LThread.FSuspended then begin
         LThread.FInitialSuspended := false;
         LThread.FInitialSuspended := false;
         WRITE_DEBUG('going into LThread.Execute');
         WRITE_DEBUG('going into LThread.Execute');
@@ -175,19 +128,20 @@ begin
 end;
 end;
 
 
 { TThread }
 { TThread }
-constructor TThread.Create(CreateSuspended: Boolean; const StackSize: SizeUInt = DefaultStackSize);
+constructor TThread.Create(CreateSuspended: Boolean;
+                           const StackSize: SizeUInt = DefaultStackSize);
 begin
 begin
   // lets just hope that the user doesn't create a thread
   // lets just hope that the user doesn't create a thread
   // via BeginThread and creates the first TThread Object in there!
   // via BeginThread and creates the first TThread Object in there!
   InitThreads;
   InitThreads;
   inherited Create;
   inherited Create;
-  FSem := SemaphoreInit;
+  FSem := CurrentTM.SemaphoreInit;
   FSuspended := CreateSuspended;
   FSuspended := CreateSuspended;
   FSuspendedExternal := false;
   FSuspendedExternal := false;
   FInitialSuspended := CreateSuspended;
   FInitialSuspended := CreateSuspended;
   FFatalException := nil;
   FFatalException := nil;
-  WRITE_DEBUG('creating thread, self = ',longint(self));
-  FHandle:= BeginThread(@ThreadFunc, Pointer(Self), FThreadID, StackSize);
+  WRITE_DEBUG('creating thread, self = ',PtrInt(self));
+  FHandle:= BeginThread(@ThreadFunc, Pointer(Self), FThreadID,StackSize);
   WRITE_DEBUG('TThread.Create done');
   WRITE_DEBUG('TThread.Create done');
 end;
 end;
 
 
@@ -206,12 +160,12 @@ begin
   end;
   end;
   if (FInitialSuspended) then begin
   if (FInitialSuspended) then begin
     // thread was created suspended but never woken up.
     // thread was created suspended but never woken up.
-    SemaphorePost(FSem);
+    CurrentTM.SemaphorePost(FSem);
     WaitFor;
     WaitFor;
   end;
   end;
   FFatalException.Free;
   FFatalException.Free;
   FFatalException := nil;
   FFatalException := nil;
-  SemaphoreDestroy(FSem);
+  CurrentTM.SemaphoreDestroy(FSem);
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
@@ -229,7 +183,7 @@ begin
   if not FSuspended then begin
   if not FSuspended then begin
     if FThreadID = GetCurrentThreadID then begin
     if FThreadID = GetCurrentThreadID then begin
       FSuspended := true;
       FSuspended := true;
-      SemaphoreWait(FSem);
+      CurrentTM.SemaphoreWait(FSem);
     end else begin
     end else begin
       FSuspendedExternal := true;
       FSuspendedExternal := true;
       SuspendThread(FHandle);
       SuspendThread(FHandle);
@@ -243,7 +197,7 @@ begin
   if (not FSuspendedExternal) then begin
   if (not FSuspendedExternal) then begin
     if FSuspended then begin
     if FSuspended then begin
       FSuspended := False;
       FSuspended := False;
-      SemaphorePost(FSem);
+      CurrentTM.SemaphorePost(FSem);
     end;
     end;
   end else begin
   end else begin
     FSuspendedExternal := false;
     FSuspendedExternal := false;

+ 24 - 77
rtl/solaris/tthread.inc

@@ -1,17 +1,17 @@
 {
 {
-    This file is part of the Free Component Library (FCL)
-    Copyright (c) 1999-2000 by Peter Vreman
+   This file is part of the Free Pascal run time library.
+   (c) 2000-2003 by Marco van de Voort
+   member of the Free Pascal development team.
 
 
-    Darwin TThread implementation
+   See the file COPYING.FPC, included in this distribution,
+   for details about the copyright.
 
 
-    See the file COPYING.FPC, included in this distribution,
-    for details about the copyright.
+   TThread implementation old (1.0) and new (pthreads) style
 
 
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
- **********************************************************************}
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY;without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+}
 
 
 
 
 {
 {
@@ -63,64 +63,10 @@
 {$define WRITE_DEBUG := //}      // just comment out those lines
 {$define WRITE_DEBUG := //}      // just comment out those lines
 {$ENDIF}
 {$ENDIF}
 
 
-// ========== semaphore stuff ==========
-{
-  I don't like this. It eats up 2 filedescriptors for each thread,
-  and those are a limited resource. If you have a server programm
-  handling client connections (one per thread) it will not be able
-  to handle many if we use 2 fds already for internal structures.
-  However, right now I don't see a better option unless some sem_*
-  functions are added to systhrds.
-  I encapsulated all used functions here to make it easier to
-  change them completely.
-}
-
-function SemaphoreInit: Pointer;
-begin
-  SemaphoreInit := GetMem(SizeOf(TFilDes));
-  fppipe(PFilDes(SemaphoreInit)^);
-  WRITE_DEBUG('Opened file descriptor ',PFilDes(SemaphoreInit)^[0]);
-end;
-
-procedure SemaphoreWait(const FSem: Pointer);
-var
-  b: byte;
-begin
-  WRITE_DEBUG('Waiting for file descriptor ',PFilDes(FSem)^[0]);
-  repeat
-    if fpread(PFilDes(FSem)^[0], b, 1) = -1 then
-      WRITE_DEBUG('Error reading from semaphore ',PFilDes(FSem)^[0],' error = ',fpgeterrno);
-  until fpgeterrno <> ESysEIntr;
-end;
-
-procedure SemaphorePost(const FSem: Pointer);
-{$ifdef VER2_0}
-var
-  b : byte;
-{$endif}
-begin
-  WRITE_DEBUG('Activating file descriptor ',PFilDes(FSem)^[0]);
-{$ifdef VER2_0}
-  b:=0;
-  fpwrite(PFilDes(FSem)^[1], b, 1);
-{$else}
-  if fpwrite(PFilDes(FSem)^[1], #0, 1) = -1 then
-    WRITE_DEBUG('Error writing file descriptor ',PFilDes(FSem)^[0],' error = ',fpgeterrno);
-{$endif}
-end;
-
-procedure SemaphoreDestroy(const FSem: Pointer);
-begin
-  WRITE_DEBUG('Closing file descriptor ',PFilDes(FSem)^[0]);
-  fpclose(PFilDes(FSem)^[0]);
-  fpclose(PFilDes(FSem)^[1]);
-  FreeMemory(FSem);
-end;
-
-// =========== semaphore end ===========
-
 var
 var
   ThreadsInited: boolean = false;
   ThreadsInited: boolean = false;
+  CurrentTM: TThreadManager;
+  
 const
 const
   // stupid, considering its not even implemented...
   // stupid, considering its not even implemented...
   Priorities: array [TThreadPriority] of Integer =
   Priorities: array [TThreadPriority] of Integer =
@@ -128,9 +74,9 @@ const
 
 
 procedure InitThreads;
 procedure InitThreads;
 begin
 begin
-  if not ThreadsInited then begin
+  GetThreadManager(CurrentTM);
+  if not ThreadsInited then
     ThreadsInited := true;
     ThreadsInited := true;
-  end;
 end;
 end;
 
 
 procedure DoneThreads;
 procedure DoneThreads;
@@ -141,13 +87,14 @@ end;
 function ThreadFunc(parameter: Pointer): LongInt;
 function ThreadFunc(parameter: Pointer): LongInt;
 var
 var
   LThread: TThread;
   LThread: TThread;
+  c: char;
 begin
 begin
   WRITE_DEBUG('ThreadFunc is here...');
   WRITE_DEBUG('ThreadFunc is here...');
   LThread := TThread(parameter);
   LThread := TThread(parameter);
   WRITE_DEBUG('thread initing, parameter = ', LongInt(LThread));
   WRITE_DEBUG('thread initing, parameter = ', LongInt(LThread));
   try
   try
     if LThread.FInitialSuspended then begin
     if LThread.FInitialSuspended then begin
-      SemaphoreWait(LThread.FSem);
+      CurrentTM.SemaphoreWait(LThread.FSem);
       if not LThread.FSuspended then begin
       if not LThread.FSuspended then begin
         LThread.FInitialSuspended := false;
         LThread.FInitialSuspended := false;
         WRITE_DEBUG('going into LThread.Execute');
         WRITE_DEBUG('going into LThread.Execute');
@@ -188,13 +135,13 @@ begin
   // via BeginThread and creates the first TThread Object in there!
   // via BeginThread and creates the first TThread Object in there!
   InitThreads;
   InitThreads;
   inherited Create;
   inherited Create;
-  FSem := SemaphoreInit;
+  FSem := CurrentTM.SemaphoreInit;
   FSuspended := CreateSuspended;
   FSuspended := CreateSuspended;
   FSuspendedExternal := false;
   FSuspendedExternal := false;
   FInitialSuspended := CreateSuspended;
   FInitialSuspended := CreateSuspended;
   FFatalException := nil;
   FFatalException := nil;
-  WRITE_DEBUG('creating thread, self = ',longint(self));
-  FHandle:= BeginThread(@ThreadFunc, Pointer(Self), FThreadID, StackSize);
+  WRITE_DEBUG('creating thread, self = ',PtrInt(self));
+  FHandle:= BeginThread(@ThreadFunc, Pointer(Self), FThreadID,StackSize);
   WRITE_DEBUG('TThread.Create done');
   WRITE_DEBUG('TThread.Create done');
 end;
 end;
 
 
@@ -213,12 +160,12 @@ begin
   end;
   end;
   if (FInitialSuspended) then begin
   if (FInitialSuspended) then begin
     // thread was created suspended but never woken up.
     // thread was created suspended but never woken up.
-    SemaphorePost(FSem);
+    CurrentTM.SemaphorePost(FSem);
     WaitFor;
     WaitFor;
   end;
   end;
   FFatalException.Free;
   FFatalException.Free;
   FFatalException := nil;
   FFatalException := nil;
-  SemaphoreDestroy(FSem);
+  CurrentTM.SemaphoreDestroy(FSem);
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
@@ -236,7 +183,7 @@ begin
   if not FSuspended then begin
   if not FSuspended then begin
     if FThreadID = GetCurrentThreadID then begin
     if FThreadID = GetCurrentThreadID then begin
       FSuspended := true;
       FSuspended := true;
-      SemaphoreWait(FSem);
+      CurrentTM.SemaphoreWait(FSem);
     end else begin
     end else begin
       FSuspendedExternal := true;
       FSuspendedExternal := true;
       SuspendThread(FHandle);
       SuspendThread(FHandle);
@@ -250,7 +197,7 @@ begin
   if (not FSuspendedExternal) then begin
   if (not FSuspendedExternal) then begin
     if FSuspended then begin
     if FSuspended then begin
       FSuspended := False;
       FSuspended := False;
-      SemaphorePost(FSem);
+      CurrentTM.SemaphorePost(FSem);
     end;
     end;
   end else begin
   end else begin
     FSuspendedExternal := false;
     FSuspendedExternal := false;
@@ -266,7 +213,7 @@ end;
 
 
 function TThread.WaitFor: Integer;
 function TThread.WaitFor: Integer;
 begin
 begin
-  WRITE_DEBUG('waiting for thread ',ptrint(FHandle));
+  WRITE_DEBUG('waiting for thread ',FHandle);
   WaitFor := WaitForThreadTerminate(FHandle, 0);
   WaitFor := WaitForThreadTerminate(FHandle, 0);
   WRITE_DEBUG('thread terminated');
   WRITE_DEBUG('thread terminated');
 end;
 end;

+ 36 - 3
rtl/unix/cthreads.pp

@@ -570,7 +570,36 @@ procedure intRTLEventWaitForTimeout(AEvent: PRTLEvent;timeout : longint);
     if (errres=0) or (errres=ESysETIMEDOUT) then
     if (errres=0) or (errres=ESysETIMEDOUT) then
       pthread_mutex_unlock(@p^.mutex);
       pthread_mutex_unlock(@p^.mutex);
   end;
   end;
+  
+function cSemaphoreInit: Pointer;
+var
+  s: PSemaphore;
+begin
+  GetMem(s, SizeOf(TSemaphore));
+  if sem_init(s, 0, 0) = 0 then
+    cSemaphoreInit:=s
+  else
+    cSemaphoreInit:=nil;
+end;
+
+procedure cSemaphoreWait(const FSem: Pointer);
+begin
+  sem_wait(PSemaphore(FSem));
+end;
+
+procedure cSemaphorePost(const FSem: Pointer);
+begin
+  sem_post(PSemaphore(FSem));
+end;
 
 
+procedure cSemaphoreDestroy(const FSem: Pointer);
+var
+  s: PSemaphore;
+begin
+  s:=FSem;
+  sem_destroy(PSemaphore(FSem));
+  FreeMem(s);
+end;
 
 
 type
 type
   threadmethod = procedure of object;
   threadmethod = procedure of object;
@@ -610,8 +639,7 @@ Var
 Procedure SetCThreadManager;
 Procedure SetCThreadManager;
 
 
 begin
 begin
-  With CThreadManager do
-    begin
+  With CThreadManager do begin
     InitManager            :=@CInitThreads;
     InitManager            :=@CInitThreads;
     DoneManager            :=@CDoneThreads;
     DoneManager            :=@CDoneThreads;
     BeginThread            :=@CBeginThread;
     BeginThread            :=@CBeginThread;
@@ -644,7 +672,12 @@ begin
     rtlEventStartWait      :=@intrtlEventStartWait;
     rtlEventStartWait      :=@intrtlEventStartWait;
     rtleventWaitForTimeout :=@intrtleventWaitForTimeout;
     rtleventWaitForTimeout :=@intrtleventWaitForTimeout;
     rtleventWaitFor        :=@intrtleventWaitFor;
     rtleventWaitFor        :=@intrtleventWaitFor;
-    end;
+    // semaphores
+    SemaphoreInit          :=@cSemaphoreInit;
+    SemaphoreDestroy       :=@cSemaphoreDestroy;
+    SemaphoreWait          :=@cSemaphoreWait;
+    SemaphorePost          :=@cSemaphorePost;
+  end;
   SetThreadManager(CThreadManager);
   SetThreadManager(CThreadManager);
   InitHeapMutexes;
   InitHeapMutexes;
 end;
 end;