summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarco <marco@3ad0048d-3df7-0310-abae-a5850022a9f2>2020-05-22 10:35:15 +0000
committermarco <marco@3ad0048d-3df7-0310-abae-a5850022a9f2>2020-05-22 10:35:15 +0000
commitbb2689e3fcb42a7808d29c6ba65bc35d3211f0da (patch)
tree973c7443400315a709c5bb101d23e7137f1a4c5c
parent682c7b8fbc5c115777301dc73928553bea489dcd (diff)
downloadfpc-bb2689e3fcb42a7808d29c6ba65bc35d3211f0da.tar.gz
--- Merging r43589 into '.':
U rtl/linux/pthread.inc U rtl/unix/cthreads.pp --- Recording mergeinfo for merge of r43589 into '.': U . # revisions: 43589 r43589 | florian | 2019-11-25 21:58:18 +0100 (Mon, 25 Nov 2019) | 1 line Changed paths: M /trunk/rtl/linux/pthread.inc M /trunk/rtl/unix/cthreads.pp * patch by Benjamin Rosseaux: TEvent.WaitFor on *nix uses Monotonic Clock now git-svn-id: https://svn.freepascal.org/svn/fpc/branches/fixes_3_2@45460 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--rtl/linux/pthread.inc3
-rw-r--r--rtl/unix/cthreads.pp91
2 files changed, 87 insertions, 7 deletions
diff --git a/rtl/linux/pthread.inc b/rtl/linux/pthread.inc
index a584fb09b7..50522c9994 100644
--- a/rtl/linux/pthread.inc
+++ b/rtl/linux/pthread.inc
@@ -153,6 +153,7 @@ Type
function pthread_cond_timedwait(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t; __abstime:ptimespec):longint;cdecl;external;
function pthread_condattr_init(__attr:ppthread_condattr_t):longint;cdecl;external;
function pthread_condattr_destroy(__attr:ppthread_condattr_t):longint;cdecl;external;
+ function pthread_condattr_setclock(__attr:ppthread_condattr_t; __clock_id: longint):longint;cdecl;external;
function pthread_key_create(__key:ppthread_key_t; __destr_function:__destr_function_t):longint;cdecl;external;
function pthread_key_delete(__key:pthread_key_t):longint;cdecl;external;
function pthread_setspecific(__key:pthread_key_t; __pointer:pointer):longint;cdecl;external;
@@ -228,6 +229,7 @@ Var
{$ifndef ANDROID}
pthread_condattr_init : Function(__attr:ppthread_condattr_t):longint;cdecl;
pthread_condattr_destroy : Function(__attr:ppthread_condattr_t):longint;cdecl;
+ pthread_condattr_setclock: Function(__attr:ppthread_condattr_t; __clock_id: longint):longint;cdecl;
{$endif}
pthread_key_create : Function(__key:ppthread_key_t; __destr_function:__destr_function_t):longint;cdecl;
pthread_key_delete : Function(__key:pthread_key_t):longint;cdecl;
@@ -321,6 +323,7 @@ begin
{$ifndef ANDROID}
Pointer(pthread_condattr_init) := dlsym(PthreadDLL,'pthread_condattr_init');
Pointer(pthread_condattr_destroy) := dlsym(PthreadDLL,'pthread_condattr_destroy');
+ Pointer(pthread_condattr_setclock) := dlsym(PthreadDLL,'pthread_condattr_setclock');
{$endif}
Pointer(pthread_key_create) := dlsym(PthreadDLL,'pthread_key_create');
Pointer(pthread_key_delete) := dlsym(PthreadDLL,'pthread_key_delete');
diff --git a/rtl/unix/cthreads.pp b/rtl/unix/cthreads.pp
index 2aeb9414e3..0ea07e3530 100644
--- a/rtl/unix/cthreads.pp
+++ b/rtl/unix/cthreads.pp
@@ -67,6 +67,9 @@ Procedure SetCThreadManager;
implementation
Uses
+{$if defined(Linux) and not defined(Android)}
+ Linux,
+{$endif}
BaseUnix,
unix,
unixtype,
@@ -547,6 +550,10 @@ type
TPthreadMutex = pthread_mutex_t;
Tbasiceventstate=record
FCondVar: TPthreadCondition;
+{$if defined(Linux) and not defined(Android)}
+ FAttr: pthread_condattr_t;
+ FClockID: longint;
+{$ifend}
FEventSection: TPthreadMutex;
FWaiters: longint;
FIsSet,
@@ -565,19 +572,67 @@ Const
function IntBasicEventCreate(EventAttributes : Pointer; AManualReset,InitialState : Boolean;const Name : ansistring):pEventState;
var
MAttr : pthread_mutexattr_t;
- res : cint;
+ res : cint;
+{$if defined(Linux) and not defined(Android)}
+ timespec: ttimespec;
+{$ifend}
begin
new(plocaleventstate(result));
plocaleventstate(result)^.FManualReset:=AManualReset;
plocaleventstate(result)^.FWaiters:=0;
plocaleventstate(result)^.FDestroying:=False;
plocaleventstate(result)^.FIsSet:=InitialState;
- res := pthread_cond_init(@plocaleventstate(result)^.FCondVar, nil);
+{$if defined(Linux) and not defined(Android)}
+ res := pthread_condattr_init(@plocaleventstate(result)^.FAttr);
+ if (res <> 0) then
+ begin
+ FreeMem(result);
+ fpc_threaderror;
+ end;
+
+ if clock_gettime(CLOCK_MONOTONIC_RAW, @timespec) = 0 then
+ begin
+ res := pthread_condattr_setclock(@plocaleventstate(result)^.FAttr, CLOCK_MONOTONIC_RAW);
+ end
+ else
+ begin
+ res := -1; // No support for CLOCK_MONOTONIC_RAW
+ end;
+
+ if (res = 0) then
+ begin
+ plocaleventstate(result)^.FClockID := CLOCK_MONOTONIC_RAW;
+ end
+ else
+ begin
+ res := pthread_condattr_setclock(@plocaleventstate(result)^.FAttr, CLOCK_MONOTONIC);
+ if (res = 0) then
+ begin
+ plocaleventstate(result)^.FClockID := CLOCK_MONOTONIC;
+ end
+ else
+ begin
+ pthread_condattr_destroy(@plocaleventstate(result)^.FAttr);
+ FreeMem(result);
+ fpc_threaderror;
+ end;
+ end;
+
+ res := pthread_cond_init(@plocaleventstate(result)^.FCondVar, @plocaleventstate(result)^.FAttr);
if (res <> 0) then
begin
+ pthread_condattr_destroy(@plocaleventstate(result)^.FAttr);
FreeMem(result);
fpc_threaderror;
end;
+{$else}
+ res := pthread_cond_init(@plocaleventstate(result)^.FCondVar, nil);
+ if (res <> 0) then
+ begin
+ FreeMem(result);
+ fpc_threaderror;
+ end;
+{$ifend}
res:=pthread_mutexattr_init(@MAttr);
if res=0 then
@@ -595,6 +650,9 @@ begin
if res <> 0 then
begin
pthread_cond_destroy(@plocaleventstate(result)^.FCondVar);
+{$if defined(Linux) and not defined(Android)}
+ pthread_condattr_destroy(@plocaleventstate(result)^.FAttr);
+{$ifend}
FreeMem(result);
fpc_threaderror;
end;
@@ -616,6 +674,9 @@ begin
{ and clean up }
pthread_cond_destroy(@plocaleventstate(state)^.Fcondvar);
+{$if defined(Linux) and not defined(Android)}
+ pthread_condattr_destroy(@plocaleventstate(state)^.FAttr);
+{$ifend}
pthread_mutex_destroy(@plocaleventstate(state)^.FEventSection);
dispose(plocaleventstate(state));
end;
@@ -646,6 +707,7 @@ var
isset: boolean;
tnow : timeval;
begin
+
{ safely check whether we are being destroyed, if so immediately return. }
{ otherwise (under the same mutex) increase the number of waiters }
pthread_mutex_lock(@plocaleventstate(state)^.feventsection);
@@ -668,17 +730,32 @@ begin
else
begin
//Wait with timeout using pthread_cond_timedwait
- fpgettimeofday(@tnow,nil);
+{$if defined(Linux) and not defined(Android)}
+ if clock_gettime(plocaleventstate(state)^.FClockID, @timespec) <> 0 then
+ begin
+ Result := Ord(wrError);
+ Exit;
+ end;
+ timespec.tv_sec := timespec.tv_sec + (clong(timeout) div 1000);
+ timespec.tv_nsec := ((clong(timeout) mod 1000) * 1000000) + (timespec.tv_nsec);
+{$else}
+ // TODO: FIX-ME: Also use monotonic clock for other *nix targets
+ fpgettimeofday(@tnow, nil);
timespec.tv_sec := tnow.tv_sec + (clong(timeout) div 1000);
- timespec.tv_nsec := (clong(timeout) mod 1000)*1000000 + tnow.tv_usec*1000;
+ timespec.tv_nsec := ((clong(timeout) mod 1000) * 1000000) + (tnow.tv_usec * 1000);
+{$ifend}
if timespec.tv_nsec >= 1000000000 then
begin
inc(timespec.tv_sec);
dec(timespec.tv_nsec, 1000000000);
end;
- errres:=0;
- while (not plocaleventstate(state)^.FDestroying) and (not plocaleventstate(state)^.FIsSet) and (errres<>ESysETIMEDOUT) do
- errres:=pthread_cond_timedwait(@plocaleventstate(state)^.Fcondvar, @plocaleventstate(state)^.feventsection, @timespec);
+ errres := 0;
+ while (not plocaleventstate(state)^.FDestroying) and
+ (not plocaleventstate(state)^.FIsSet) and
+ (errres<>ESysETIMEDOUT) do
+ errres := pthread_cond_timedwait(@plocaleventstate(state)^.Fcondvar,
+ @plocaleventstate(state)^.feventsection,
+ @timespec);
end;
isset := plocaleventstate(state)^.FIsSet;