mirror of https://github.com/red-prig/fpPS4.git
Initial hazard pointers
This commit is contained in:
parent
d7bbf46985
commit
67203f2394
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue