mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-22 04:29:29 +02:00
* Moved to unix/ since there is nothing linux specific about it.
This commit is contained in:
parent
04346e325e
commit
13132aa761
192
rtl/unix/thread.inc
Normal file
192
rtl/unix/thread.inc
Normal file
@ -0,0 +1,192 @@
|
||||
{
|
||||
$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
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user