mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-05 10:18:22 +02:00

Notes: - Netware had a ThreadSwitch in there, but that is not really required - some platform were missing the setting of FTerminated to True, thus they'll now do that as well git-svn-id: trunk@46543 -
226 lines
5.9 KiB
PHP
226 lines
5.9 KiB
PHP
{
|
|
This file is part of the Free Component Library (FCL)
|
|
Copyright (c) 1999-2002 by the Free Pascal development team
|
|
|
|
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.
|
|
|
|
**********************************************************************}
|
|
{****************************************************************************}
|
|
{* TThread *}
|
|
{****************************************************************************}
|
|
|
|
(* OS/2 specific declarations - see unit DosCalls for descriptions *)
|
|
|
|
type
|
|
{ TByteArray = array [0..$fff0] of byte;
|
|
PByteArray = ^TByteArray;
|
|
}
|
|
{ TThreadEntry = function (Param: pointer): longint; cdecl;
|
|
}
|
|
TSysThreadIB = record
|
|
TID, Priority, Version: longint;
|
|
MCCount, MCForceFlag: word;
|
|
end;
|
|
PSysThreadIB = ^TSysThreadIB;
|
|
|
|
TThreadInfoBlock = record
|
|
Exh_Chain, Stack, StackLimit: pointer;
|
|
TIB2: PSysThreadIB;
|
|
Version, Ordinal: longint;
|
|
end;
|
|
PThreadInfoBlock = ^TThreadInfoBlock;
|
|
PPThreadInfoBlock = ^PThreadInfoBlock;
|
|
|
|
TProcessInfoBlock = record
|
|
PID, ParentPID, HMTE: longint;
|
|
Cmd, Env: PByteArray;
|
|
flStatus, tType: longint;
|
|
end;
|
|
PProcessInfoBlock = ^TProcessInfoBlock;
|
|
PPProcessInfoBlock = ^PProcessInfoBlock;
|
|
|
|
|
|
const
|
|
{ deThread = 0;
|
|
deProcess = 1;
|
|
}
|
|
dtSuspended = 1;
|
|
dtStack_Commited = 2;
|
|
|
|
dtWait = 0;
|
|
dtNoWait = 1;
|
|
|
|
|
|
procedure DosGetInfoBlocks (PATIB: PPThreadInfoBlock;
|
|
PAPIB: PPProcessInfoBlock); cdecl; external 'DOSCALLS' index 312;
|
|
|
|
function DosSetPriority (Scope, TrClass: cardinal; Delta: longint;
|
|
PortID: cardinal): cardinal; cdecl; external 'DOSCALLS' index 236;
|
|
{
|
|
procedure DosExit (Action, Result: cardinal); cdecl;
|
|
external 'DOSCALLS' index 233;
|
|
|
|
function DosCreateThread (var TID: cardinal; Address: TThreadEntry;
|
|
aParam: pointer; Flags: cardinal; StackSize: cardinal): cardinal; cdecl;
|
|
external 'DOSCALLS' index 311;
|
|
|
|
function DosKillThread (TID: cardinal): cardinal; cdecl;
|
|
external 'DOSCALLS' index 111;
|
|
|
|
function DosResumeThread (TID: cardinal): cardinal; cdecl;
|
|
external 'DOSCALLS' index 237;
|
|
|
|
function DosSuspendThread (TID: cardinal): cardinal; cdecl;
|
|
external 'DOSCALLS' index 238;
|
|
}
|
|
function DosWaitThread (var TID: cardinal; Option: cardinal): cardinal; cdecl;
|
|
external 'DOSCALLS' index 349;
|
|
|
|
|
|
const
|
|
Priorities: array [TThreadPriority] of word = ($100, $200, $207, $20F, $217,
|
|
$21F, $300);
|
|
ThreadCount: longint = 0;
|
|
|
|
(* Implementation of exported functions *)
|
|
|
|
procedure AddThread;
|
|
begin
|
|
InterlockedIncrement (ThreadCount);
|
|
end;
|
|
|
|
|
|
procedure RemoveThread;
|
|
begin
|
|
InterlockedDecrement (ThreadCount);
|
|
end;
|
|
|
|
|
|
procedure TThread.SysCreate(CreateSuspended: Boolean;
|
|
const StackSize: SizeUInt);
|
|
var
|
|
Flags: cardinal;
|
|
begin
|
|
AddThread;
|
|
{ Always start in suspended state, will be resumed in AfterConstruction if necessary
|
|
See Mantis #16884 }
|
|
Flags := dtStack_Commited or dtSuspended;
|
|
FSuspended := CreateSuspended;
|
|
FInitialSuspended := CreateSuspended;
|
|
if FSuspended then Flags := Flags or dtSuspended;
|
|
FHandle := BeginThread (nil, StackSize, @ThreadProc, pointer (Self),
|
|
Flags, FThreadID);
|
|
FFatalException := nil;
|
|
end;
|
|
|
|
|
|
procedure TThread.SysDestroy;
|
|
begin
|
|
if not FFinished and not Suspended then
|
|
begin
|
|
Terminate;
|
|
WaitFor;
|
|
end;
|
|
{ if FHandle <> 0 then DosKillThread (cardinal (FHandle));}
|
|
FFatalException.Free;
|
|
FFatalException := nil;
|
|
RemoveThread;
|
|
end;
|
|
|
|
|
|
procedure TThread.CallOnTerminate;
|
|
begin
|
|
FOnTerminate (Self);
|
|
end;
|
|
|
|
|
|
procedure TThread.DoTerminate;
|
|
begin
|
|
if Assigned (FOnTerminate) then
|
|
Synchronize (@CallOnTerminate);
|
|
end;
|
|
|
|
|
|
function TThread.GetPriority: TThreadPriority;
|
|
var
|
|
PTIB: PThreadInfoBlock;
|
|
PPIB: PProcessInfoBlock;
|
|
I: TThreadPriority;
|
|
begin
|
|
DosGetInfoBlocks (@PTIB, @PPIB);
|
|
with PTIB^.TIB2^ do
|
|
if Priority >= $300 then GetPriority := tpTimeCritical else
|
|
if Priority < $200 then GetPriority := tpIdle else
|
|
begin
|
|
I := Succ (Low (TThreadPriority));
|
|
while (I < High (TThreadPriority)) and
|
|
(Priority - Priorities [I] <= Priorities [Succ (I)] - Priority) do Inc (I);
|
|
GetPriority := I;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TThread.SetPriority(Value: TThreadPriority);
|
|
var
|
|
PTIB: PThreadInfoBlock;
|
|
PPIB: PProcessInfoBlock;
|
|
RC: cardinal;
|
|
begin
|
|
DosGetInfoBlocks (@PTIB, @PPIB);
|
|
(*
|
|
PTIB^.TIB2^.Priority := Priorities [Value];
|
|
*)
|
|
RC := DosSetPriority (2, High (Priorities [Value]),
|
|
Low (Priorities [Value]) - PTIB^.TIB2^.Priority, FHandle);
|
|
if RC <> 0 then
|
|
OSErrorWatch (RC);
|
|
end;
|
|
|
|
|
|
procedure TThread.SetSuspended(Value: Boolean);
|
|
begin
|
|
if Value <> FSuspended then
|
|
begin
|
|
if Value then
|
|
Suspend
|
|
else
|
|
Resume;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TThread.Suspend;
|
|
begin
|
|
FSuspended := true;
|
|
SuspendThread (FHandle);
|
|
{DosSuspendThread (cardinal (FHandle)) = 0;}
|
|
end;
|
|
|
|
|
|
procedure TThread.Resume;
|
|
begin
|
|
if ResumeThread (FHandle) = 1 then
|
|
FSuspended := false;
|
|
{ FSuspended := not (DosResumeThread (cardinal (FHandle)) = 0);}
|
|
end;
|
|
|
|
|
|
function TThread.WaitFor: Integer;
|
|
var
|
|
FH: cardinal;
|
|
RC: cardinal;
|
|
begin
|
|
if GetCurrentThreadID = MainThreadID then
|
|
while not (FFinished) do
|
|
CheckSynchronize (1000);
|
|
RC := DosWaitThread (FH, dtWait);
|
|
if RC <> 0 then
|
|
OSErrorWatch (RC);
|
|
WaitFor := RC;
|
|
end;
|