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;