mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 10:11:27 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			681 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			681 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| {
 | |
|     This file is part of the Free Pascal Run time library.
 | |
|     Copyright (c) 2000 by the Free Pascal development team
 | |
| 
 | |
|     OS independent thread functions/overloads
 | |
| 
 | |
|     See the File COPYING.FPC, included in this distribution,
 | |
|     for details about the copyright.
 | |
| 
 | |
|     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.
 | |
| 
 | |
|  **********************************************************************}
 | |
| 
 | |
| 
 | |
| Var
 | |
|   CurrentTM : TThreadManager;
 | |
| {$ifndef THREADVAR_RELOCATED_ALREADY_DEFINED}
 | |
|   fpc_threadvar_relocate_proc : TRelocateThreadVarHandler; public name 'FPC_THREADVAR_RELOCATE';
 | |
| {$endif THREADVAR_RELOCATED_ALREADY_DEFINED}
 | |
| 
 | |
| {$ifndef HAS_GETCPUCOUNT}
 | |
|     function GetCPUCount: LongWord;
 | |
|       begin
 | |
|         Result := 1;
 | |
|       end;
 | |
| {$endif}
 | |
| 
 | |
| 
 | |
| {*****************************************************************************
 | |
|                            Threadvar initialization
 | |
| *****************************************************************************}
 | |
| 
 | |
|     procedure InitThread(stklen:SizeUInt);
 | |
|       begin
 | |
| {$ifndef FPUNONE}
 | |
|         SysResetFPU;
 | |
| {$endif}
 | |
| {$ifndef HAS_MEMORYMANAGER}
 | |
| {$ifndef FPC_NO_DEFAULT_HEAP}
 | |
|         { initialize this thread's heap }
 | |
|         InitHeapThread;
 | |
| {$endif ndef FPC_NO_DEFAULT_HEAP}
 | |
| {$else HAS_MEMORYMANAGER}
 | |
|         if MemoryManager.InitThread <> nil then
 | |
|           MemoryManager.InitThread();
 | |
| {$endif HAS_MEMORYMANAGER}
 | |
| {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
 | |
|         if assigned(widestringmanager.ThreadInitProc) then
 | |
|           widestringmanager.ThreadInitProc;
 | |
| {$endif FPC_HAS_FEATURE_WIDESTRINGS}
 | |
| {$ifdef FPC_HAS_FEATURE_EXCEPTIONS}
 | |
|         { ExceptAddrStack and ExceptObjectStack are threadvars       }
 | |
|         { so every thread has its on exception handling capabilities }
 | |
|         SysInitExceptions;
 | |
| {$endif FPC_HAS_FEATURE_EXCEPTIONS}
 | |
| {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
 | |
| {$ifndef EMBEDDED}
 | |
|         { Open all stdio fds again }
 | |
|         SysInitStdio;
 | |
|         InOutRes:=0;
 | |
|         // ErrNo:=0;
 | |
| {$endif EMBEDDED}
 | |
| {$endif FPC_HAS_FEATURE_CONSOLEIO}
 | |
| {$ifdef FPC_HAS_FEATURE_STACKCHECK}
 | |
|         { Stack checking }
 | |
|         StackLength:= CheckInitialStkLen(stkLen);
 | |
|         StackBottom:=Sptr - StackLength;
 | |
| {$endif FPC_HAS_FEATURE_STACKCHECK}
 | |
|         ThreadID := CurrentTM.GetCurrentThreadID();
 | |
|       end;
 | |
| 
 | |
|     procedure DoneThread;
 | |
|       begin
 | |
| {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
 | |
|         if assigned(widestringmanager.ThreadFiniProc) then
 | |
|           widestringmanager.ThreadFiniProc;
 | |
| {$endif FPC_HAS_FEATURE_WIDESTRINGS}
 | |
| {$ifndef HAS_MEMORYMANAGER}
 | |
| {$ifndef FPC_NO_DEFAULT_HEAP}
 | |
|         FinalizeHeap;
 | |
| {$endif ndef FPC_NO_DEFAULT_HEAP}
 | |
| {$endif HAS_MEMORYMANAGER}
 | |
|         if MemoryManager.DoneThread <> nil then
 | |
|           MemoryManager.DoneThread();
 | |
| {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
 | |
|         { Open all stdio fds again }
 | |
|         SysFlushStdio;
 | |
| {$endif FPC_HAS_FEATURE_CONSOLEIO}
 | |
|         { Support platforms where threadvar memory is managed outside of the RTL:
 | |
|           reset ThreadID and allow ReleaseThreadVars to be unassigned }
 | |
|         ThreadID := TThreadID(0);
 | |
|         if assigned(CurrentTM.ReleaseThreadVars) then
 | |
|           CurrentTM.ReleaseThreadVars;
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     procedure InitThread;
 | |
|       begin
 | |
|         { we should find a reasonable value here }
 | |
|         InitThread($1000000);
 | |
|       end;
 | |
| 
 | |
| {*****************************************************************************
 | |
|                             Overloaded functions
 | |
| *****************************************************************************}
 | |
| 
 | |
|     function BeginThread(ThreadFunction : tthreadfunc) : TThreadID;
 | |
|       var
 | |
|         dummy : TThreadID;
 | |
|       begin
 | |
|         BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,nil,0,dummy);
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     function BeginThread(ThreadFunction : tthreadfunc;p : pointer) : TThreadID;
 | |
|       var
 | |
|         dummy : TThreadID;
 | |
|       begin
 | |
|         BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,p,0,dummy);
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     function BeginThread(ThreadFunction : tthreadfunc;p : pointer;var ThreadId : TThreadID) : TThreadID;
 | |
|       begin
 | |
|         BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,p,0,ThreadId);
 | |
|       end;
 | |
| 
 | |
|     function BeginThread(ThreadFunction : tthreadfunc;p : pointer;
 | |
|                      var ThreadId : TThreadID; const stacksize: SizeUInt) : TThreadID;
 | |
|       begin
 | |
|         BeginThread:=BeginThread(nil,stacksize,ThreadFunction,p,0,ThreadId);
 | |
|       end;
 | |
| 
 | |
|     procedure EndThread;
 | |
|       begin
 | |
|         EndThread(0);
 | |
|       end;
 | |
| 
 | |
| function BeginThread(sa : Pointer;stacksize : SizeUInt; ThreadFunction : tthreadfunc;p : pointer;creationFlags : dword;  var ThreadId : TThreadID) : TThreadID;
 | |
| 
 | |
| begin
 | |
|   Result:=CurrentTM.BeginThread(sa,stacksize,threadfunction,P,creationflags,ThreadID);
 | |
| end;
 | |
| 
 | |
| procedure FlushThread;
 | |
| 
 | |
| begin
 | |
| {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
 | |
|   SysFlushStdio;
 | |
| {$endif FPC_HAS_FEATURE_CONSOLEIO}
 | |
| end;
 | |
| 
 | |
| procedure EndThread(ExitCode : DWord);
 | |
| 
 | |
| begin
 | |
|   CurrentTM.EndThread(ExitCode);
 | |
| end;
 | |
| 
 | |
| function  SuspendThread (threadHandle : TThreadID) : dword;
 | |
| 
 | |
| begin
 | |
|   Result:=CurrentTM.SuspendThread(ThreadHandle);
 | |
| end;
 | |
| 
 | |
| function ResumeThread  (threadHandle : TThreadID) : dword;
 | |
| 
 | |
| begin
 | |
|   Result:=CurrentTM.ResumeThread(ThreadHandle);
 | |
| end;
 | |
| 
 | |
| function CloseThread  (threadHandle : TThreadID):dword;
 | |
| 
 | |
| begin
 | |
|   result:=CurrentTM.CloseThread(ThreadHandle);
 | |
| end;
 | |
| 
 | |
| procedure ThreadSwitch;
 | |
| 
 | |
| begin
 | |
|   CurrentTM.ThreadSwitch;
 | |
| end;
 | |
| 
 | |
| function  KillThread (threadHandle : TThreadID) : dword;
 | |
| 
 | |
| begin
 | |
|   Result:=CurrentTM.KillThread(ThreadHandle);
 | |
| end;
 | |
| 
 | |
| function  WaitForThreadTerminate (threadHandle : TThreadID; TimeoutMs : longint) : dword;
 | |
| 
 | |
| begin
 | |
|   Result:=CurrentTM.WaitForThreadTerminate(ThreadHandle,TimeOutMS);
 | |
| end;
 | |
| 
 | |
| function  ThreadSetPriority (threadHandle : TThreadID; Prio: longint): boolean;
 | |
| begin
 | |
|   Result:=CurrentTM.ThreadSetPriority(ThreadHandle,Prio);
 | |
| end;
 | |
| 
 | |
| function  ThreadGetPriority (threadHandle : TThreadID): longint;
 | |
| 
 | |
| begin
 | |
|   Result:=CurrentTM.ThreadGetPriority(ThreadHandle);
 | |
| end;
 | |
| 
 | |
| function  GetCurrentThreadId : TThreadID;
 | |
| 
 | |
| begin
 | |
|   Result:=CurrentTM.GetCurrentThreadID();
 | |
| end;
 | |
| 
 | |
| procedure SetThreadDebugName(threadHandle: TThreadID; const ThreadName: AnsiString);
 | |
| begin
 | |
|   CurrentTM.SetThreadDebugNameA(threadHandle, ThreadName);
 | |
| end;
 | |
| 
 | |
| {$ifdef FPC_HAS_FEATURE_UNICODESTRINGS}
 | |
| procedure SetThreadDebugName(threadHandle: TThreadID; const ThreadName: UnicodeString);
 | |
| begin
 | |
|   CurrentTM.SetThreadDebugNameU(threadHandle, ThreadName);
 | |
| end;
 | |
| {$endif FPC_HAS_FEATURE_UNICODESTRINGS}
 | |
| 
 | |
| procedure InitCriticalSection(out cs : TRTLCriticalSection);
 | |
| 
 | |
| begin
 | |
|   CurrentTM.InitCriticalSection(cs);
 | |
| end;
 | |
| 
 | |
| procedure DoneCriticalSection(var cs : TRTLCriticalSection);
 | |
| 
 | |
| begin
 | |
|   CurrentTM.DoneCriticalSection(cs);
 | |
| end;
 | |
| 
 | |
| procedure EnterCriticalSection(var cs : TRTLCriticalSection);
 | |
| 
 | |
| begin
 | |
|   CurrentTM.EnterCriticalSection(cs);
 | |
| end;
 | |
| 
 | |
| function TryEnterCriticalSection(var cs : TRTLCriticalSection):longint;
 | |
| 
 | |
| begin
 | |
|   result:=CurrentTM.TryEnterCriticalSection(cs);
 | |
| end;
 | |
| 
 | |
| procedure LeaveCriticalSection(var cs : TRTLCriticalSection);
 | |
| 
 | |
| begin
 | |
|   CurrentTM.LeaveCriticalSection(cs);
 | |
| end;
 | |
| 
 | |
| Function GetThreadManager(Out TM : TThreadManager) : Boolean;
 | |
| 
 | |
| begin
 | |
|   TM:=CurrentTM;
 | |
|   Result:=True;
 | |
| end;
 | |
| 
 | |
| Function SetThreadManager(Const NewTM : TThreadManager; Out OldTM : TThreadManager) : Boolean;
 | |
| 
 | |
| begin
 | |
|   GetThreadManager(OldTM);
 | |
|   Result:=SetThreadManager(NewTM);
 | |
| end;
 | |
| 
 | |
| Function SetThreadManager(Const NewTM : TThreadManager) : Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=True;
 | |
|   If Assigned(CurrentTM.DoneManager) then
 | |
|     Result:=CurrentTM.DoneManager();
 | |
|   If Result then
 | |
|     begin
 | |
|     CurrentTM:=NewTM;
 | |
|     If Assigned(CurrentTM.InitManager) then
 | |
|       Result:=CurrentTM.InitManager();
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| function  BasicEventCreate(EventAttributes : Pointer; AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;
 | |
| 
 | |
| begin
 | |
|   result:=currenttm.BasicEventCreate(EventAttributes,AManualReset,InitialState, Name);
 | |
| end;
 | |
| 
 | |
| procedure BasicEventDestroy(state:peventstate);
 | |
| 
 | |
| begin
 | |
|   currenttm.BasicEventDestroy(state);
 | |
| end;
 | |
| 
 | |
| procedure BasicEventResetEvent(state:peventstate);
 | |
| 
 | |
| begin
 | |
|   currenttm.BasicEventResetEvent(state);
 | |
| end;
 | |
| 
 | |
| procedure BasicEventSetEvent(state:peventstate);
 | |
| 
 | |
| begin
 | |
|   currenttm.BasicEventSetEvent(state);
 | |
| end;
 | |
| 
 | |
| function  BasicEventWaitFor(Timeout : Cardinal;state:peventstate;FUseComWait : Boolean=False) : longint;
 | |
| 
 | |
| begin
 | |
|  result:=currenttm.BasicEventWaitFor(Timeout,state,FUseComWait);
 | |
| end;
 | |
| 
 | |
| function  RTLEventCreate :PRTLEvent;
 | |
| 
 | |
| begin
 | |
|   result:=currenttm.RTLEventCreate();
 | |
| end;
 | |
| 
 | |
| 
 | |
| procedure RTLeventDestroy(state:pRTLEvent);
 | |
| 
 | |
| begin
 | |
|   currenttm.RTLEventDestroy(state);
 | |
| end;
 | |
| 
 | |
| procedure RTLeventSetEvent(state:pRTLEvent);
 | |
| 
 | |
| begin
 | |
|   currenttm.RTLEventSetEvent(state);
 | |
| end;
 | |
| 
 | |
| procedure RTLeventResetEvent(state:pRTLEvent);
 | |
| 
 | |
| begin
 | |
|   currenttm.RTLEventResetEvent(state);
 | |
| end;
 | |
| 
 | |
| procedure RTLeventWaitFor(state:pRTLEvent);
 | |
| 
 | |
| begin
 | |
|   currenttm.RTLEventWaitFor(state);
 | |
| end;
 | |
| 
 | |
| procedure RTLeventWaitFor(state:pRTLEvent;timeout : longint);
 | |
| 
 | |
| begin
 | |
|   currenttm.RTLEventWaitForTimeout(state,timeout);
 | |
| end;
 | |
| 
 | |
| { ---------------------------------------------------------------------
 | |
|     lazy thread initialization support
 | |
|   ---------------------------------------------------------------------}
 | |
| 
 | |
| type
 | |
|   PLazyInitThreadingProcInfo = ^TLazyInitThreadingProcInfo;
 | |
|   TLazyInitThreadingProcInfo = Record
 | |
|     Next     : PLazyInitThreadingProcInfo;
 | |
|     Proc     : TProcedure;
 | |
|   End;
 | |
| const
 | |
|   LazyInitThreadingProcList: PLazyInitThreadingProcInfo = nil;
 | |
| 
 | |
| procedure FinalizeLazyInitThreading;
 | |
| var
 | |
|   p: PLazyInitThreadingProcInfo;
 | |
| begin
 | |
|   while assigned(LazyInitThreadingProcList) do
 | |
|     begin
 | |
|     p:=LazyInitThreadingProcList^.Next;
 | |
|     Dispose(LazyInitThreadingProcList);
 | |
|     LazyInitThreadingProcList:=p;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| procedure RegisterLazyInitThreadingProc(const proc: TProcedure);
 | |
| var
 | |
|   p: PLazyInitThreadingProcInfo;
 | |
| begin
 | |
|   if IsMultiThread then
 | |
|     begin
 | |
|     { multithreading is already enabled - execute directly }
 | |
|     proc();
 | |
|     end
 | |
|   else
 | |
|     begin
 | |
|     if not assigned(LazyInitThreadingProcList) then
 | |
|       AddExitProc(@FinalizeLazyInitThreading);
 | |
|     new(p);
 | |
|     p^.Next:=LazyInitThreadingProcList;
 | |
|     p^.Proc:=proc;
 | |
|     LazyInitThreadingProcList:=p;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| procedure LazyInitThreading;
 | |
| var
 | |
|   p: PLazyInitThreadingProcInfo;
 | |
| begin
 | |
|   p:=LazyInitThreadingProcList;
 | |
|   while assigned(p) do
 | |
|     begin
 | |
|     p^.Proc();
 | |
|     p:=p^.Next;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| { ---------------------------------------------------------------------
 | |
|     ThreadManager which gives run-time error. Use if no thread support.
 | |
|   ---------------------------------------------------------------------}
 | |
| 
 | |
| {$ifndef DISABLE_NO_THREAD_MANAGER}
 | |
| 
 | |
| { resourcestrings are not supported by the system unit,
 | |
|   they are in the objpas unit and not available for fpc/tp modes }
 | |
| const
 | |
|   SNoThreads = 'This binary has no thread support compiled in.';
 | |
|   SRecompileWithThreads = 'Recompile the application with a thread-driver in the program uses clause before other units using thread.';
 | |
| 
 | |
| Procedure NoThreadError;
 | |
| 
 | |
| begin
 | |
| {$ifndef EMBEDDED}
 | |
| {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
 | |
| {$ifndef FPC_SYSTEM_NO_VERBOSE_THREADERROR}
 | |
|   If IsConsole then
 | |
|     begin
 | |
|     Writeln(StdErr,SNoThreads);
 | |
|     Writeln(StdErr,SRecompileWithThreads);
 | |
|     end;
 | |
| {$endif FPC_SYSTEM_NO_VERBOSE_THREADERROR}
 | |
| {$endif FPC_HAS_FEATURE_CONSOLEIO}
 | |
| {$endif EMBEDDED}
 | |
|   RunError(232)
 | |
| end;
 | |
| 
 | |
| function NoBeginThread(sa : Pointer;stacksize : PtrUInt;
 | |
|                      ThreadFunction : tthreadfunc;p : pointer;
 | |
|                      creationFlags : dword; var ThreadId : TThreadID) : TThreadID;
 | |
| begin
 | |
|   NoThreadError;
 | |
|   result:=tthreadid(-1);
 | |
| end;
 | |
| 
 | |
| procedure NoEndThread(ExitCode : DWord);
 | |
| begin
 | |
|   NoThreadError;
 | |
| end;
 | |
| 
 | |
| function  NoThreadHandler (threadHandle : TThreadID) : dword;
 | |
| begin
 | |
|   NoThreadError;
 | |
|   result:=dword(-1);
 | |
| end;
 | |
| 
 | |
| function  NoWaitForThreadTerminate (threadHandle : TThreadID; TimeoutMs : longint) : dword;  {0=no timeout}
 | |
| begin
 | |
|   NoThreadError;
 | |
|   result:=dword(-1);
 | |
| end;
 | |
| 
 | |
| function  NoThreadSetPriority (threadHandle : TThreadID; Prio: longint): boolean; {-15..+15, 0=normal}
 | |
| begin
 | |
|   NoThreadError;
 | |
|   result:=false;
 | |
| end;
 | |
| 
 | |
| function  NoThreadGetPriority (threadHandle : TThreadID): longint;
 | |
| begin
 | |
|   NoThreadError;
 | |
|   result:=-1;
 | |
| end;
 | |
| 
 | |
| function  NoGetCurrentThreadId : TThreadID;
 | |
| begin
 | |
|   if IsMultiThread then
 | |
|     NoThreadError
 | |
|   else
 | |
|     ThreadingAlreadyUsed:=true;
 | |
|   result:=TThreadID(1);
 | |
| end;
 | |
| 
 | |
| procedure NoSetThreadDebugNameA(threadHandle: TThreadID; const ThreadName: AnsiString);
 | |
| begin
 | |
|   NoThreadError;
 | |
| end;
 | |
| 
 | |
| {$ifdef FPC_HAS_FEATURE_UNICODESTRINGS}
 | |
| procedure NoSetThreadDebugNameU(threadHandle: TThreadID; const ThreadName: UnicodeString);
 | |
| begin
 | |
|   NoThreadError;
 | |
| end;
 | |
| {$endif FPC_HAS_FEATURE_UNICODESTRINGS}
 | |
| 
 | |
| procedure NoCriticalSection(var CS);
 | |
| 
 | |
| begin
 | |
|   if IsMultiThread then
 | |
|     NoThreadError
 | |
|   else
 | |
|     ThreadingAlreadyUsed:=true;
 | |
| end;
 | |
| 
 | |
| function NoTryEnterCriticalSection(var CS):longint;
 | |
| 
 | |
| begin
 | |
|   if IsMultiThread then
 | |
|     NoThreadError
 | |
|   else
 | |
|     ThreadingAlreadyUsed:=true;
 | |
|   Result:=-1;
 | |
| end;
 | |
| 
 | |
| procedure NoInitThreadvar(var offset : {$ifdef cpu16}word{$else}dword{$endif};size : dword);
 | |
| 
 | |
| begin
 | |
|   NoThreadError;
 | |
| end;
 | |
| 
 | |
| function NoRelocateThreadvar(offset : {$ifdef cpu16}word{$else}dword{$endif}) : pointer;
 | |
| 
 | |
| begin
 | |
|   NoThreadError;
 | |
|   result:=nil;
 | |
| end;
 | |
| 
 | |
| 
 | |
| function  NoBasicEventCreate(EventAttributes : Pointer; AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;
 | |
| 
 | |
| begin
 | |
|   if IsMultiThread then
 | |
|     NoThreadError
 | |
|   else
 | |
|     ThreadingAlreadyUsed:=true;
 | |
|   result:=nil;
 | |
| end;
 | |
| 
 | |
| procedure NoBasicEvent(state:peventstate);
 | |
| 
 | |
| begin
 | |
|   if IsMultiThread then
 | |
|     NoThreadError
 | |
|   else
 | |
|     ThreadingAlreadyUsed:=true;
 | |
| end;
 | |
| 
 | |
| function  NoBasicEventWaitFor(Timeout : Cardinal;state:peventstate;FUseComWait : Boolean=False) : longint;
 | |
| 
 | |
| begin
 | |
|   if IsMultiThread then
 | |
|     NoThreadError
 | |
|   else
 | |
|     ThreadingAlreadyUsed:=true;
 | |
|   result:=-1;
 | |
| end;
 | |
| 
 | |
| function  NoRTLEventCreate :PRTLEvent;
 | |
| 
 | |
| begin
 | |
|   if IsMultiThread then
 | |
|     NoThreadError
 | |
|   else
 | |
|     ThreadingAlreadyUsed:=true;
 | |
|   result:=nil;
 | |
| end;
 | |
| 
 | |
| procedure NoRTLEvent(state:pRTLEvent);
 | |
| 
 | |
| begin
 | |
|   if IsMultiThread then
 | |
|     NoThreadError
 | |
|   else
 | |
|     ThreadingAlreadyUsed:=true
 | |
| end;
 | |
| 
 | |
| procedure NoRTLEventWaitForTimeout(state:pRTLEvent;timeout : longint);
 | |
| begin
 | |
|   if IsMultiThread then
 | |
|     NoThreadError
 | |
|   else
 | |
|     ThreadingAlreadyUsed:=true;
 | |
| end;
 | |
| 
 | |
| 
 | |
| const
 | |
|   NoThreadManager : TThreadManager = (
 | |
|          InitManager            : Nil;
 | |
|          DoneManager            : Nil;
 | |
| {$ifdef EMBEDDED}
 | |
|          { while this is pretty hacky, it reduces the size of typical embedded programs
 | |
|            and works fine on arm and avr }
 | |
|          BeginThread            : @NoBeginThread;
 | |
|          EndThread              : TEndThreadHandler(@NoThreadError);
 | |
|          SuspendThread          : TThreadHandler(@NoThreadError);
 | |
|          ResumeThread           : TThreadHandler(@NoThreadError);
 | |
|          KillThread             : TThreadHandler(@NoThreadError);
 | |
|          CloseThread            : TThreadHandler(@NoThreadError);
 | |
|          ThreadSwitch           : TThreadSwitchHandler(@NoThreadError);
 | |
|          WaitForThreadTerminate : TWaitForThreadTerminateHandler(@NoThreadError);
 | |
|          ThreadSetPriority      : TThreadSetPriorityHandler(@NoThreadError);
 | |
|          ThreadGetPriority      : TThreadGetPriorityHandler(@NoThreadError);
 | |
|          GetCurrentThreadId     : @NoGetCurrentThreadId;
 | |
|          SetThreadDebugNameA    : TThreadSetThreadDebugNameHandlerA(@NoThreadError);
 | |
|          {$ifdef FPC_HAS_FEATURE_UNICODESTRINGS}
 | |
|          SetThreadDebugNameU    : TThreadSetThreadDebugNameHandlerU(@NoThreadError);
 | |
|          {$endif FPC_HAS_FEATURE_UNICODESTRINGS}
 | |
|          InitCriticalSection    : TCriticalSectionHandler(@NoThreadError);
 | |
|          DoneCriticalSection    : TCriticalSectionHandler(@NoThreadError);
 | |
|          EnterCriticalSection   : TCriticalSectionHandler(@NoThreadError);
 | |
|          TryEnterCriticalSection: TCriticalSectionHandlerTryEnter(@NoThreadError);
 | |
|          LeaveCriticalSection   : TCriticalSectionHandler(@NoThreadError);
 | |
|          InitThreadVar          : TInitThreadVarHandler(@NoThreadError);
 | |
|          RelocateThreadVar      : TRelocateThreadVarHandler(@NoThreadError);
 | |
|          AllocateThreadVars     : @NoThreadError;
 | |
|          ReleaseThreadVars      : @NoThreadError;
 | |
|          BasicEventCreate       : TBasicEventCreateHandler(@NoThreadError);
 | |
|          BasicEventdestroy      : TBasicEventHandler(@NoThreadError);
 | |
|          BasicEventResetEvent   : TBasicEventHandler(@NoThreadError);
 | |
|          BasicEventSetEvent     : TBasicEventHandler(@NoThreadError);
 | |
|          BasicEventWaitFor      : TBasicEventWaitForHandler(@NoThreadError);
 | |
|          RTLEventCreate         : TRTLCreateEventHandler(@NoThreadError);
 | |
|          RTLEventdestroy        : TRTLEventHandler(@NoThreadError);
 | |
|          RTLEventSetEvent       : TRTLEventHandler(@NoThreadError);
 | |
|          RTLEventResetEvent     : TRTLEventHandler(@NoThreadError);
 | |
|          RTLEventWaitFor        : TRTLEventHandler(@NoThreadError);
 | |
|          RTLEventwaitfortimeout : TRTLEventHandlerTimeout(@NoThreadError);
 | |
| {$else EMBEDDED}
 | |
|          BeginThread            : @NoBeginThread;
 | |
|          EndThread              : @NoEndThread;
 | |
|          SuspendThread          : @NoThreadHandler;
 | |
|          ResumeThread           : @NoThreadHandler;
 | |
|          KillThread             : @NoThreadHandler;
 | |
|          CloseThread            : @NoThreadHandler;
 | |
|          ThreadSwitch           : @NoThreadError;
 | |
|          WaitForThreadTerminate : @NoWaitForThreadTerminate;
 | |
|          ThreadSetPriority      : @NoThreadSetPriority;
 | |
|          ThreadGetPriority      : @NoThreadGetPriority;
 | |
|          GetCurrentThreadId     : @NoGetCurrentThreadId;
 | |
|          SetThreadDebugNameA    : @NoSetThreadDebugNameA;
 | |
|          {$ifdef FPC_HAS_FEATURE_UNICODESTRINGS}
 | |
|          SetThreadDebugNameU    : @NoSetThreadDebugNameU;
 | |
|          {$endif FPC_HAS_FEATURE_UNICODESTRINGS}
 | |
|          InitCriticalSection    : @NoCriticalSection;
 | |
|          DoneCriticalSection    : @NoCriticalSection;
 | |
|          EnterCriticalSection   : @NoCriticalSection;
 | |
|          TryEnterCriticalSection: @NoTryEnterCriticalSection;
 | |
|          LeaveCriticalSection   : @NoCriticalSection;
 | |
|          InitThreadVar          : @NoInitThreadVar;
 | |
|          RelocateThreadVar      : @NoRelocateThreadVar;
 | |
|          AllocateThreadVars     : @NoThreadError;
 | |
|          ReleaseThreadVars      : @NoThreadError;
 | |
|          BasicEventCreate       : @NoBasicEventCreate;
 | |
|          BasicEventDestroy      : @NoBasicEvent;
 | |
|          BasicEventResetEvent   : @NoBasicEvent;
 | |
|          BasicEventSetEvent     : @NoBasicEvent;
 | |
|          BasicEventWaitFor      : @NoBasiceventWaitFor;
 | |
|          RTLEventCreate         : @NoRTLEventCreate;
 | |
|          RTLEventDestroy        : @NoRTLevent;
 | |
|          RTLEventSetEvent       : @NoRTLevent;
 | |
|          RTLEventResetEvent     : @NoRTLEvent;
 | |
|          RTLEventWaitFor        : @NoRTLEvent;
 | |
|          RTLEventWaitforTimeout : @NoRTLEventWaitForTimeout;
 | |
| {$endif EMBEDDED}
 | |
|       );
 | |
| 
 | |
| Procedure SetNoThreadManager;
 | |
| 
 | |
| begin
 | |
|   SetThreadManager(NoThreadManager);
 | |
| end;
 | |
| 
 | |
| Procedure InitSystemThreads; public name '_FPC_InitSystemThreads';
 | |
| begin
 | |
|   { This should be changed to a real value during
 | |
|     thread driver initialization if appropriate. }
 | |
|   ThreadID := TThreadID(1);
 | |
|   SetNoThreadManager;
 | |
| end;
 | |
| 
 | |
| {$endif DISABLE_NO_THREAD_MANAGER}
 | 
