Initial hazard pointers

This commit is contained in:
Pavel 2025-02-20 15:15:51 +03:00
parent d7bbf46985
commit 67203f2394
7 changed files with 352 additions and 17 deletions

View File

@ -1590,6 +1590,10 @@
<IsPartOfProject Value="True"/>
<UnitName Value="ps4_libSceNpSignaling"/>
</Unit>
<Unit>
<Filename Value="sys\kern\kern_hazard_pointer.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>

View File

@ -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<t_pointer_node>;
function t_pointer_node.c(n1,n2:p_pointer_node):Integer;
begin
Result:=Integer(n1^.P>n2^.P)-Integer(n1^.P<n2^.P);
end;
threadvar
rlist :LIST_HEAD;
rcount:Integer;
type
t_scan_mode=(smLazy,smLazyOne,smForce);
function Scan(mode:t_scan_mode):Pointer;
var
p_set :TPointerSet;
p_node:p_pointer_node;
r_node:p_r_node;
r_next:p_r_node;
ttd :p_kthread;
i :Byte;
begin
Result:=nil;
r_node:=LIST_FIRST(@rlist);
if (r_node=nil) then Exit;
p_set:=Default(TPointerSet);
if (mode=smForce) then
begin
threads_lock;
end else
begin
if not threads_trylock then Exit;
end;
ttd:=TAILQ_FIRST(get_p_threads);
while (ttd<>nil) 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.

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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__);

View File

@ -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;