123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559 |
- {
- 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;
- {*****************************************************************************
- Threadvar initialization
- *****************************************************************************}
- procedure InitThread(stklen:SizeUInt);
- begin
- {$ifndef FPUNONE}
- SysResetFPU;
- SysInitFPU;
- {$endif}
- {$ifndef HAS_MEMORYMANAGER}
- { initialize this thread's heap }
- InitHeapThread;
- {$endif HAS_MEMORYMANAGER}
- if MemoryManager.InitThread <> nil then
- MemoryManager.InitThread();
- {$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}
- { Open all stdio fds again }
- SysInitStdio;
- InOutRes:=0;
- // ErrNo:=0;
- {$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}
- FinalizeHeap;
- {$endif HAS_MEMORYMANAGER}
- if MemoryManager.DoneThread <> nil then
- MemoryManager.DoneThread();
- CurrentTM.ReleaseThreadVars;
- 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}
- { Make sure that all output is written to the redirected file }
- Flush(Output);
- Flush(ErrOutput);
- Flush(StdOut);
- Flush(StdErr);
- {$endif FPC_HAS_FEATURE_CONSOLEIO}
- end;
- procedure EndThread(ExitCode : DWord);
- begin
- FlushThread;
- 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;
- 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 InitCriticalSection(var 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;
- procedure LeaveCriticalsection(var cs : TRTLCriticalSection);
- begin
- CurrentTM.LeaveCriticalSection(cs);
- end;
- Function GetThreadManager(Var TM : TThreadManager) : Boolean;
- begin
- TM:=CurrentTM;
- Result:=True;
- end;
- Function SetThreadManager(Const NewTM : TThreadManager; Var 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) : longint;
- begin
- result:=currenttm.basiceventWaitFor(Timeout,state);
- 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;
- procedure RTLeventsync(m:trtlmethod;p:tprocedure);
- begin
- currenttm.rtleventsync(m,p);
- 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
- {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
- If IsConsole then
- begin
- Writeln(StdErr,SNoThreads);
- Writeln(StdErr,SRecompileWithThreads);
- end;
- {$endif FPC_HAS_FEATURE_CONSOLEIO}
- RunError(232)
- end;
- function NoBeginThread(sa : Pointer;stacksize : PtrUInt;
- ThreadFunction : tthreadfunc;p : pointer;
- creationFlags : dword; var ThreadId : TThreadID) : TThreadID;
- begin
- NoThreadError;
- end;
- procedure NoEndThread(ExitCode : DWord);
- begin
- NoThreadError;
- end;
- function NoThreadHandler (threadHandle : TThreadID) : dword;
- begin
- NoThreadError;
- end;
- procedure NoThreadSwitch; {give time to other threads}
- begin
- NoThreadError;
- end;
- function NoWaitForThreadTerminate (threadHandle : TThreadID; TimeoutMs : longint) : dword; {0=no timeout}
- begin
- NoThreadError;
- end;
- function NoThreadSetPriority (threadHandle : TThreadID; Prio: longint): boolean; {-15..+15, 0=normal}
- begin
- NoThreadError;
- end;
- function NoThreadGetPriority (threadHandle : TThreadID): longint;
- begin
- NoThreadError;
- end;
- function NoGetCurrentThreadId : TThreadID;
- begin
- if IsMultiThread then
- NoThreadError
- else
- ThreadingAlreadyUsed:=true;
- result:=ThreadID;
- end;
- procedure NoCriticalSection(var CS);
- begin
- if IsMultiThread then
- NoThreadError
- else
- ThreadingAlreadyUsed:=true;
- end;
- procedure NoInitThreadvar(var offset : dword;size : dword);
- begin
- NoThreadError;
- end;
- function NoRelocateThreadvar(offset : dword) : pointer;
- begin
- NoThreadError;
- end;
- procedure NoAllocateThreadVars;
- begin
- NoThreadError;
- end;
- procedure NoReleaseThreadVars;
- begin
- NoThreadError;
- end;
- function noBasicEventCreate(EventAttributes : Pointer; AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;
- begin
- NoThreadError;
- end;
- procedure nobasiceventdestroy(state:peventstate);
- begin
- NoThreadError;
- end;
- procedure nobasiceventResetEvent(state:peventstate);
- begin
- NoThreadError;
- end;
- procedure nobasiceventSetEvent(state:peventstate);
- begin
- NoThreadError;
- end;
- function nobasiceventWaitFor(Timeout : Cardinal;state:peventstate) : longint;
- begin
- NoThreadError;
- end;
- function NORTLEventCreate :PRTLEvent;
- begin
- if IsMultiThread then
- NoThreadError
- else
- ThreadingAlreadyUsed:=true
- end;
- procedure NORTLeventdestroy(state:pRTLEvent);
- begin
- if IsMultiThread then
- NoThreadError
- else
- ThreadingAlreadyUsed:=true
- end;
- procedure NORTLeventSetEvent(state:pRTLEvent);
- begin
- NoThreadError;
- end;
- procedure NORTLeventWaitFor(state:pRTLEvent);
- begin
- NoThreadError;
- end;
- procedure NORTLeventWaitForTimeout(state:pRTLEvent;timeout : longint);
- begin
- NoThreadError;
- end;
- procedure NORTLeventsync(m:trtlmethod;p:tprocedure);
- begin
- NoThreadError;
- 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
- NoThreadManager : TThreadManager;
- Procedure SetNoThreadManager;
- begin
- With NoThreadManager do
- begin
- InitManager :=Nil;
- DoneManager :=Nil;
- BeginThread :=@NoBeginThread;
- EndThread :=@NoEndThread;
- SuspendThread :=@NoThreadHandler;
- ResumeThread :=@NoThreadHandler;
- KillThread :=@NoThreadHandler;
- ThreadSwitch :=@NoThreadSwitch;
- WaitForThreadTerminate :=@NoWaitForThreadTerminate;
- ThreadSetPriority :=@NoThreadSetPriority;
- ThreadGetPriority :=@NoThreadGetPriority;
- GetCurrentThreadId :=@NoGetCurrentThreadId;
- InitCriticalSection :=@NoCriticalSection;
- DoneCriticalSection :=@NoCriticalSection;
- EnterCriticalSection :=@NoCriticalSection;
- LeaveCriticalSection :=@NoCriticalSection;
- InitThreadVar :=@NoInitThreadVar;
- RelocateThreadVar :=@NoRelocateThreadVar;
- AllocateThreadVars :=@NoAllocateThreadVars;
- ReleaseThreadVars :=@NoReleaseThreadVars;
- BasicEventCreate :=@NoBasicEventCreate;
- basiceventdestroy :=@Nobasiceventdestroy;
- basiceventResetEvent :=@NobasiceventResetEvent;
- basiceventSetEvent :=@NobasiceventSetEvent;
- basiceventWaitFor :=@NobasiceventWaitFor;
- rtlEventCreate :=@NortlEventCreate;
- rtleventdestroy :=@Nortleventdestroy;
- rtleventSetEvent :=@NortleventSetEvent;
- rtleventWaitFor :=@NortleventWaitFor;
- rtleventsync :=@Nortleventsync;
- rtleventwaitfortimeout :=@NortleventWaitForTimeout;
- // semaphores stuff
- SemaphoreInit :=@NoSemaphoreInit;
- SemaphoreDestroy :=@NoSemaphoreDestroy;
- SemaphoreWait :=@NoSemaphoreWait;
- SemaphorePost :=@NoSemaphorePost;
- end;
- SetThreadManager(NoThreadManager);
- end;
- Procedure 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}
|