diff --git a/fpPS4.lpi b/fpPS4.lpi
index 7abfa4a1..c4f51bd0 100644
--- a/fpPS4.lpi
+++ b/fpPS4.lpi
@@ -1590,6 +1590,10 @@
+
+
+
+
diff --git a/sys/kern/kern_hazard_pointer.pas b/sys/kern/kern_hazard_pointer.pas
new file mode 100644
index 00000000..154a709b
--- /dev/null
+++ b/sys/kern/kern_hazard_pointer.pas
@@ -0,0 +1,307 @@
+unit kern_hazard_pointer;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+type
+ TGuard=object
+ private
+ type
+ PGuardHandle=^TGuardHandle;
+ TGuardHandle=packed record
+ Item:Pointer;
+ end;
+ Var
+ Handle:PGuardHandle;
+ public
+ type
+ TFuncFree=Function(P:Pointer):SizeUInt;
+ TFuncGet =function(P:Pointer):Pointer;
+ function New:TGuard; static;
+ procedure Free;
+ procedure Clear;
+ function Assign(P:Pointer):Pointer;
+ function Get:Pointer;
+ function Protect(Var P:Pointer;Func:TFuncGet=nil):Pointer;
+ Procedure Retire (P:Pointer;FuncFree:TFuncFree); static;
+ Procedure Flush; static;
+ end;
+
+Procedure tlHpInit;
+Procedure tlHpFree;
+
+implementation
+
+uses
+ atomic,
+ mqueue,
+ g_node_splay,
+ kern_thr;
+
+function AllocGuard:Pointer;
+var
+ td:p_kthread;
+ i:Byte;
+begin
+ Result:=nil;
+ td:=curkthread;
+ Assert(td<>nil,'AllocGuard#1');
+
+ For i:=0 to High(kthread.td_guards) do
+ if (td^.td_guards[i]=nil) then
+ begin
+ td^.td_guards[i]:=Pointer(1);
+ Exit(@td^.td_guards[i]);
+ end;
+
+ Assert(false,'AllocGuard#2');
+end;
+
+Procedure FreeGuard(P:Pointer); inline;
+begin
+ PPointer(P)^:=nil;
+end;
+
+////////
+
+type
+ p_r_node=^t_r_node;
+ t_r_node=record
+ entry:LIST_ENTRY;
+ //
+ P:Pointer;
+ F:TGuard.TFuncFree;
+ end;
+
+ p_pointer_node=^t_pointer_node;
+ t_pointer_node=object
+ //key should be first
+ P:Pointer;
+ //
+ pLeft :p_pointer_node;
+ pRight:p_pointer_node;
+ //
+ function c(n1,n2:p_pointer_node):Integer; static;
+ end;
+ TPointerSet=specialize TNodeSplay;
+
+function t_pointer_node.c(n1,n2:p_pointer_node):Integer;
+begin
+ Result:=Integer(n1^.P>n2^.P)-Integer(n1^.Pnil) do
+ begin
+
+ For i:=0 to High(kthread.td_guards) do
+ if (ttd^.td_guards[i]<>nil) and
+ (ttd^.td_guards[i]<>Pointer(1)) then
+ begin
+ p_node:=AllocMem(SizeOf(t_pointer_node));
+ p_node^.P:=ttd^.td_guards[i];
+ p_set.Insert(p_node);
+ end;
+
+ ttd:=TAILQ_NEXT(ttd,@ttd^.td_plist)
+ end;
+
+ threads_unlock;
+
+ while (r_node<>nil) do
+ begin
+ r_next:=LIST_NEXT(r_node,@r_node^.entry);
+ //
+ p_node:=p_set.Find(@r_node^.P);
+ //
+ if (p_node=nil) then
+ begin
+ //delete node
+ LIST_REMOVE(r_node,@r_node^.entry);
+ //free element
+ if (r_node^.F<>nil) then
+ begin
+ r_node^.F(r_node^.P);
+ end;
+ //
+ if (mode=smLazyOne) then
+ begin
+ //set result and exit
+ Dec(rcount);
+ Result:=r_node;
+ Break;
+ end else
+ begin
+ //free node
+ Dec(rcount);
+ FreeMem(r_node);
+ end;
+ end;
+ //
+ r_node:=r_next;
+ end;
+
+ //free set
+ p_node:=p_set.Min;
+ while (p_node<>nil) do
+ begin
+ p_set.Delete(p_node);
+ //
+ FreeMem(p_node);
+ //
+ p_node:=p_set.Min;
+ end;
+end;
+
+Procedure Retire(P:Pointer;FuncFree:TGuard.TFuncFree);
+var
+ node:p_r_node;
+begin
+ node:=Scan(smLazyOne);
+ //
+ if (node<>nil) then
+ begin
+ node:=AllocMem(SizeOf(t_r_node));
+ end;
+ node^.P:=P;
+ node^.F:=FuncFree;
+ //
+ LIST_INSERT_HEAD(@rlist,node,@node^.entry);
+ //
+ Inc(rcount);
+ //
+ if rcount>(4*256) then
+ begin
+ Scan(smLazy);
+ end;
+end;
+
+Procedure tlHpInit; public;
+begin
+ rlist :=Default(LIST_HEAD);
+ rcount:=0;
+end;
+
+Procedure tlHpFree; public;
+begin
+ Scan(smForce);
+end;
+
+////////
+
+function TGuard.New:TGuard;
+begin
+ Result.Handle:=AllocGuard;
+ Result.Clear;
+end;
+
+procedure TGuard.Free;
+begin
+ if Assigned(Handle) then
+ begin
+ Clear;
+ FreeGuard(Handle);
+ Handle:=nil;
+ end;
+end;
+
+procedure TGuard.Clear;
+begin
+ if Assigned(Handle) then
+ begin
+ PGuardHandle(Handle)^.Item:=Pointer(1);
+ end;
+end;
+
+function TGuard.Assign(P:Pointer):Pointer;
+begin
+ Result:=nil;
+ if Assigned(Handle) then
+ begin
+ store_seq_cst(PGuardHandle(Handle)^.Item,P);
+ Result:=P;
+ end;
+end;
+
+function TGuard.Get:Pointer;
+begin
+ Result:=nil;
+ if Assigned(Handle) then
+ begin
+ Result:=PGuardHandle(Handle)^.Item;
+ end;
+end;
+
+function TGuard.Protect(Var P:Pointer;Func:TFuncGet=nil):Pointer;
+Var
+ pCur,pRet:Pointer;
+begin
+ Assert(Handle<>nil);
+ Result:=nil;
+ if Assigned(Handle) then
+ begin
+ pCur:=load_acq_rel(P);
+ repeat
+ if (Func=nil) then
+ begin
+ store_seq_cst(PGuardHandle(Handle)^.Item,pCur);
+ end else
+ begin
+ store_seq_cst(PGuardHandle(Handle)^.Item,Func(pCur));
+ end;
+ pRet:=load_acquire(pCur);
+ pCur:=load_acq_rel(P);
+ until (pRet=pCur);
+ Result:=pCur;
+ end;
+end;
+
+Procedure TGuard.Retire(P:Pointer;FuncFree:TFuncFree);
+begin
+ if Assigned(P) and Assigned(FuncFree) then
+ begin
+ Retire(P,FuncFree);
+ end;
+end;
+
+Procedure TGuard.Flush;
+begin
+ Scan(smForce);
+end;
+
+/////////
+
+end.
+
diff --git a/sys/kern/kern_rtprio.pas b/sys/kern/kern_rtprio.pas
index 8d84e71a..b8a2a91f 100644
--- a/sys/kern/kern_rtprio.pas
+++ b/sys/kern/kern_rtprio.pas
@@ -22,7 +22,6 @@ uses
systm,
errno,
kern_proc,
- kern_thread,
sched_ule,
md_proc;
@@ -174,7 +173,7 @@ begin
threads_lock;
- tdp:=TAILQ_FIRST(@p_threads);
+ tdp:=TAILQ_FIRST(get_p_threads);
while (tdp<>nil) do
begin
@@ -210,7 +209,7 @@ begin
begin
threads_lock;
- tdp:=TAILQ_FIRST(@p_threads);
+ tdp:=TAILQ_FIRST(get_p_threads);
while (tdp<>nil) do
begin
diff --git a/sys/kern/kern_sig.pas b/sys/kern/kern_sig.pas
index 5755cd73..3fb0814b 100644
--- a/sys/kern/kern_sig.pas
+++ b/sys/kern/kern_sig.pas
@@ -122,7 +122,6 @@ uses
systm,
kern_mtx,
md_time,
- kern_thread,
kern_exit,
kern_prot,
kern_synch,
@@ -422,7 +421,7 @@ begin
threads_lock;
- td0:=TAILQ_FIRST(@p_threads);
+ td0:=TAILQ_FIRST(get_p_threads);
while (td0<>nil) do
begin
@@ -1374,7 +1373,7 @@ begin
threads_lock;
- td:=TAILQ_FIRST(@p_threads);
+ td:=TAILQ_FIRST(get_p_threads);
while (td<>nil) do
begin
diff --git a/sys/kern/kern_thr.pas b/sys/kern/kern_thr.pas
index d259455d..bbf33b83 100644
--- a/sys/kern/kern_thr.pas
+++ b/sys/kern/kern_thr.pas
@@ -265,6 +265,7 @@ type
pcb_fsbase :Pointer;
pcb_gsbase :Pointer;
pcb_onfault :Pointer;
+ td_guards :array[0..1] of Pointer;
td_temp :t_td_buffer;
td_padding :t_td_buffer;
end;
@@ -348,10 +349,18 @@ procedure THREAD_NO_SLEEPING();
procedure THREAD_SLEEPING_OK();
function THREAD_IS_NOSLEEPING:Boolean;
+function SIGPENDING(td:p_kthread):Boolean; external;
+
function curthread_pflags_set(flags:Integer):Integer;
procedure curthread_pflags_restore(save:Integer);
procedure curthread_set_pcb_onfault(v:Pointer);
+procedure threads_lock; external;
+function threads_trylock:Boolean; external;
+procedure threads_unlock; external;
+
+function get_p_threads:Pointer; external;
+
procedure thread_inc_ref(td:p_kthread); external;
procedure thread_dec_ref(td:p_kthread); external;
diff --git a/sys/kern/kern_thread.pas b/sys/kern/kern_thread.pas
index 973a4644..657f8722 100644
--- a/sys/kern/kern_thread.pas
+++ b/sys/kern/kern_thread.pas
@@ -46,6 +46,7 @@ procedure thread_unlock (td:p_kthread);
function tdfind(tid:DWORD):p_kthread;
procedure threads_lock;
+function threads_trylock:Boolean;
procedure threads_unlock;
procedure KernSetThreadDebugName(newtd:p_kthread;prefix:PChar);
@@ -63,9 +64,6 @@ procedure thread_resume_all (exclude:p_kthread);
var
init_tty_cb:Tprocedure;
- p_threads:TAILQ_HEAD=(tqh_first:nil;tqh_last:@p_threads.tqh_first);
- p_numthreads:Integer=0;
-
implementation
uses
@@ -80,14 +78,15 @@ uses
kern_proc,
kern_rangelock,
sched_ule,
- sys_sleepqueue;
+ sys_sleepqueue,
+ kern_hazard_pointer;
//
procedure umtx_thread_init(td:p_kthread); external;
procedure umtx_thread_exit(td:p_kthread); external;
procedure umtx_thread_fini(td:p_kthread); external;
-function kern_umtx_wake(td:p_kthread;umtx:Pointer;n_wake,priv:Integer):Integer; external;
+function kern_umtx_wake (td:p_kthread;umtx:Pointer;n_wake,priv:Integer):Integer; external;
function umtx_copyin_timeout(addr:Pointer;tsp:p_timespec):Integer; external;
procedure jit_ctx_free(td:p_kthread); external;
@@ -95,21 +94,29 @@ procedure jit_ctx_free(td:p_kthread); external;
//
var
- tidhashtbl:TSTUB_HAMT32;
+ p_threads :TAILQ_HEAD=(tqh_first:nil;tqh_last:@p_threads.tqh_first);
+ p_numthreads:Integer=0;
+
+ tidhashtbl :TSTUB_HAMT32;
tidhash_lock:Pointer=nil;
zombie_threads:TAILQ_HEAD=(tqh_first:nil;tqh_last:@zombie_threads.tqh_first);
- zombie_lock:Pointer=nil;
+ zombie_lock :Pointer=nil;
const
max_threads_per_proc=1500;
-function SIGPENDING(td:p_kthread):Boolean;
+function SIGPENDING(td:p_kthread):Boolean; public;
begin
Result:=SIGNOTEMPTY(@td^.td_sigqueue.sq_signals) and
sigsetmasked(@td^.td_sigqueue.sq_signals,@td^.td_sigmask);
end;
+function get_p_threads:Pointer; public;
+begin
+ Result:=@p_threads;
+end;
+
//
function _thread_null(parameter:pointer):ptrint; register;
@@ -196,6 +203,7 @@ begin
rlqentry_free(td^.td_rlqe);
umtx_thread_fini(td);
cpu_thread_free(td);
+ tlHpFree;
end;
procedure thread_inc_ref(td:p_kthread); public;
@@ -315,12 +323,17 @@ begin
end;
end;
-procedure threads_lock;
+procedure threads_lock; public;
begin
rw_wlock(tidhash_lock);
end;
-procedure threads_unlock;
+function threads_trylock:Boolean; public;
+begin
+ Result:=rw_try_wlock(tidhash_lock);
+end;
+
+procedure threads_unlock; public;
begin
rw_wunlock(tidhash_lock);
end;
@@ -365,6 +378,8 @@ begin
InitThread(td^.td_ustack.stack-td^.td_ustack.sttop);
+ tlHpInit;
+
Set8087CW(__INITIAL_FPUCW__);
SetMXCSR (__INITIAL_MXCSR__);
@@ -387,6 +402,8 @@ begin
InitThread(td^.td_ustack.stack-td^.td_ustack.sttop);
+ tlHpInit;
+
Set8087CW(__INITIAL_FPUCW__);
SetMXCSR (__INITIAL_MXCSR__);
diff --git a/sys/sys_event.pas b/sys/sys_event.pas
index 8c213748..c5f15612 100644
--- a/sys/sys_event.pas
+++ b/sys/sys_event.pas
@@ -180,7 +180,7 @@ type
{$IF sizeof(t_knlist)<>48}{$STOP sizeof(t_knlist)<>48}{$ENDIF}
p_filterops=^t_filterops;
- t_filterops=packed record
+ t_filterops=packed object
f_isfd :Integer; // true if ident == filedescriptor
_align :Integer;
f_attach:function (kn:p_knote):Integer;