mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-27 08:13:42 +02:00
193 lines
5.0 KiB
PHP
193 lines
5.0 KiB
PHP
{
|
|
$Id$
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 2001 by the Free Pascal development team.
|
|
|
|
Multithreading implementation for Linux
|
|
|
|
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.
|
|
|
|
**********************************************************************}
|
|
{$ifdef MT}
|
|
|
|
const
|
|
DefaultStackSize = 16384;
|
|
threadvarblocksize : dword = 0;
|
|
|
|
type
|
|
pthreadinfo = ^tthreadinfo;
|
|
tthreadinfo = record
|
|
f : tthreadfunc;
|
|
p : pointer;
|
|
end;
|
|
|
|
var
|
|
dataindex : pointer;
|
|
|
|
procedure init_threadvar(var offset : dword;size : dword);[public,alias: 'FPC_INIT_THREADVAR'];
|
|
begin
|
|
offset:=threadvarblocksize;
|
|
inc(threadvarblocksize,size);
|
|
end;
|
|
|
|
|
|
function relocate_threadvar(offset : dword) : pointer;[public,alias: 'FPC_RELOCATE_THREADVAR'];
|
|
begin
|
|
Relocate_ThreadVar := DataIndex + Offset;
|
|
end;
|
|
|
|
|
|
procedure AllocateThreadVars;
|
|
begin
|
|
{ we've to allocate the memory from system }
|
|
{ because the FPC heap management uses }
|
|
{ exceptions which use threadvars but }
|
|
{ these aren't allocated yet ... }
|
|
{ allocate room on the heap for the thread vars }
|
|
DataIndex:=Pointer(Sys_mmap(0,threadvarblocksize,3,MAP_PRIVATE+MAP_ANONYMOUS,-1,0));
|
|
FillChar(DataIndex^,threadvarblocksize,0);
|
|
end;
|
|
|
|
|
|
procedure ReleaseThreadVars;
|
|
begin
|
|
Sys_munmap(Longint(dataindex),threadvarblocksize);
|
|
end;
|
|
|
|
|
|
procedure InitThread;
|
|
begin
|
|
ResetFPU;
|
|
{ we don't need to set the data to 0 because we did this with }
|
|
{ the fillchar above, but it looks nicer }
|
|
|
|
{ ExceptAddrStack and ExceptObjectStack are threadvars }
|
|
{ so every thread has its on exception handling capabilities }
|
|
InitExceptions;
|
|
InOutRes:=0;
|
|
// ErrNo:=0;
|
|
end;
|
|
|
|
|
|
procedure DoneThread;
|
|
begin
|
|
{ release thread vars }
|
|
ReleaseThreadVars;
|
|
end;
|
|
|
|
|
|
function ThreadMain(param : pointer) : longint;cdecl;
|
|
var
|
|
ti : tthreadinfo;
|
|
begin
|
|
{$ifdef DEBUG_MT}
|
|
writeln('New thread started, initialising ...');
|
|
{$endif DEBUG_MT}
|
|
AllocateThreadVars;
|
|
InitThread;
|
|
ti:=pthreadinfo(param)^;
|
|
dispose(pthreadinfo(param));
|
|
{$ifdef DEBUG_MT}
|
|
writeln('Jumping to thread function');
|
|
{$endif DEBUG_MT}
|
|
ThreadMain:=ti.f(ti.p);
|
|
end;
|
|
|
|
|
|
function BeginThread(sa : Pointer;stacksize : dword;
|
|
ThreadFunction : tthreadfunc;p : pointer;
|
|
creationFlags : dword; var ThreadId : DWord) : DWord;
|
|
var
|
|
ti : pthreadinfo;
|
|
FStackPointer : pointer;
|
|
Flags : longint;
|
|
begin
|
|
{$ifdef DEBUG_MT}
|
|
writeln('Creating new thread');
|
|
{$endif DEBUG_MT}
|
|
IsMultithread:=true;
|
|
{ the only way to pass data to the newly created thread }
|
|
{ in a MT safe way, is to use the heap }
|
|
new(ti);
|
|
ti^.f:=ThreadFunction;
|
|
ti^.p:=p;
|
|
{$ifdef DEBUG_MT}
|
|
writeln('Starting new thread');
|
|
{$endif DEBUG_MT}
|
|
Flags := CLONE_VM + CLONE_FS + CLONE_FILES + CLONE_SIGHAND + SIGCHLD;
|
|
{ Setup stack }
|
|
Getmem(pointer(FStackPointer),StackSize);
|
|
inc(FStackPointer,StackSize);
|
|
{ Clone }
|
|
ThreadID:=Clone(@ThreadMain,pointer(FStackPointer),Flags,ti);
|
|
end;
|
|
|
|
|
|
function BeginThread(ThreadFunction : tthreadfunc) : DWord;
|
|
var
|
|
dummy : dword;
|
|
begin
|
|
BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,nil,0,dummy);
|
|
end;
|
|
|
|
|
|
function BeginThread(ThreadFunction : tthreadfunc;p : pointer) : DWord;
|
|
var
|
|
dummy : dword;
|
|
begin
|
|
BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,p,0,dummy);
|
|
end;
|
|
|
|
|
|
function BeginThread(ThreadFunction : tthreadfunc;p : pointer;var ThreadId : DWord) : DWord;
|
|
begin
|
|
BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,p,0,ThreadId);
|
|
end;
|
|
|
|
|
|
procedure EndThread(ExitCode : DWord);
|
|
begin
|
|
DoneThread;
|
|
Sys_Exit(ExitCode);
|
|
end;
|
|
|
|
|
|
procedure EndThread;
|
|
begin
|
|
EndThread(0);
|
|
end;
|
|
|
|
procedure InitCriticalSection(var cs : tcriticalsection);
|
|
begin
|
|
end;
|
|
|
|
procedure DoneCriticalSection(var cs : tcriticalsection);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure EnterCriticalSection(var cs : tcriticalsection);
|
|
begin
|
|
end;
|
|
|
|
procedure LeaveCriticalSection(var cs : tcriticalsection);
|
|
begin
|
|
end;
|
|
|
|
{$endif MT}
|
|
|
|
{
|
|
$Log$
|
|
Revision 1.1 2001-10-17 10:27:47 marco
|
|
* Moved to unix/ since there is nothing linux specific about it.
|
|
|
|
Revision 1.1 2001/10/14 13:33:20 peter
|
|
* start of thread support for linux
|
|
|
|
}
|