scePthreadKeyCreate and etc

This commit is contained in:
Pavel 2022-12-09 17:08:27 +03:00
parent 703d9426fd
commit 56f0d24fcc
4 changed files with 246 additions and 157 deletions

View File

@ -11,6 +11,7 @@ uses
ps4_map_mm,
ps4_mspace,
ps4_pthread,
ps4_pthread_key,
ps4_signal,
ps4_mutex,
ps4_cond,
@ -1058,12 +1059,21 @@ begin
lib^.set_proc($D71BED515C75FD28,@ps4___pthread_cleanup_push_imp);
lib^.set_proc($896B0595831FDCAC,@ps4___pthread_cleanup_pop_imp);
//thread
//pthread_key
lib^.set_proc($9AA50B35D8A64E7D,@ps4_pthread_key_create);
lib^.set_proc($E81A4466E0D3ED82,@ps4_pthread_key_delete);
lib^.set_proc($D3F297692EF4C72E,@ps4_pthread_getspecific);
lib^.set_proc($5AB38BBC7534C903,@ps4_pthread_setspecific);
//thread
lib^.set_proc($81E0DAAA01FD9538,@ps4_scePthreadKeyCreate);
lib^.set_proc($3EB747BAE0DE9216,@ps4_scePthreadKeyDelete);
lib^.set_proc($7A886DEE640E0A6A,@ps4_scePthreadGetspecific);
lib^.set_proc($F81CD7624A9878B1,@ps4_scePthreadSetspecific);
//pthread_key
lib^.set_proc($5AC95C2B51507062,@ps4_sceKernelIsNeoMode);
lib^.set_proc($9A9C4076A5BB74A6,@ps4_sceKernelIsProspero);

View File

@ -5,7 +5,6 @@ unit ps4_pthread;
interface
uses
LFQueue,
windows,
sys_crt,
sys_pthread,
@ -92,11 +91,6 @@ procedure ps4___pthread_cleanup_push_imp(routine:t_cb_proc;
info:p_pthread_cleanup); SysV_ABI_CDecl;
procedure ps4___pthread_cleanup_pop_imp(execute:Integer); SysV_ABI_CDecl;
function ps4_pthread_key_create(pKey:Ppthread_key_t;dest:t_cb_proc):Integer; SysV_ABI_CDecl;
function ps4_pthread_key_delete(Key:pthread_key_t):Integer; SysV_ABI_CDecl;
function ps4_pthread_getspecific(Key:pthread_key_t):Pointer; SysV_ABI_CDecl;
function ps4_pthread_setspecific(Key:pthread_key_t;value:Pointer):Integer; SysV_ABI_CDecl;
function _pthread_run_entry(pthread:p_pthread;name:Pchar;stack:PDWORD):Integer;
implementation
@ -105,26 +99,12 @@ uses
atomic,
spinlock,
sys_kernel,
ps4_pthread_key,
ps4_mutex,
ps4_map_mm,
ps4_program,
ps4_elf;
type
p_pthread_key_node=^_pthread_key_node;
_pthread_key_node=packed record
next_:p_pthread_key_node;
version_:ptruint;
dest_:t_cb_proc;
end;
var
_pthread_key_nodes:array[0..SCE_PTHREAD_KEYS_MAX-1] of _pthread_key_node;
_pthread_key_queue:TIntrusiveMPSCQueue;
_pthread_key_queue_lock:Pointer;
procedure _pthread_keys_cleanup_dest; forward;
//struct dl_phdr_info
procedure ps4_pthread_cxa_finalize(P:Pointer); SysV_ABI_CDecl;
begin
@ -391,7 +371,7 @@ begin
end;
_sig_lock;
_pthread_keys_cleanup_dest;
_thread_cleanupspecific;
ps4_app.FreeThread;
UnRegistredStack;
_sig_unlock;
@ -1023,139 +1003,6 @@ begin
end;
end;
procedure _pthread_keys_init;
var
i:Integer;
begin
_pthread_key_queue.Create;
For i:=Low(_pthread_key_nodes) to High(_pthread_key_nodes) do
begin
_pthread_key_nodes[i]:=Default(_pthread_key_node);
_pthread_key_queue.Push(@_pthread_key_nodes[i]);
end;
end;
procedure _pthread_keys_cleanup_dest;
var
i:Integer;
local:p_pthread_key_data;
node:p_pthread_key_node;
version:ptruint;
dest:t_cb_proc;
begin
local:=@tcb_thread^.keys[0];
For i:=Low(_pthread_key_nodes) to High(_pthread_key_nodes) do
begin
node:=@_pthread_key_nodes[i];
version:=load_consume(node^.version_);
dest:=t_cb_proc(load_consume(Pointer(node^.dest_)));
if (ptruint(dest)>1) and
(local[i].version_=version) and
(local[i].data_<>nil) then
begin
dest(local[i].data_);
end;
end;
end;
function ps4_pthread_key_create(pKey:Ppthread_key_t;dest:t_cb_proc):Integer; SysV_ABI_CDecl;
var
node:p_pthread_key_node;
Key:pthread_key_t;
begin
if (pKey=nil) then Exit(EINVAL);
Writeln('pthread_key_create',' ',ps4_pthread_self^.sig._lock);
if (dest=nil) then dest:=t_cb_proc(1);
node:=nil;
spin_lock(_pthread_key_queue_lock);
_pthread_key_queue.Pop(node);
spin_unlock(_pthread_key_queue_lock);
if (node=nil) then Exit(EAGAIN);
System.InterlockedIncrement(Pointer(node^.version_));
XCHG(Pointer(node^.dest_),Pointer(dest));
Key:=(node-p_pthread_key_node(@_pthread_key_nodes));
Key:=Key+1;
pKey^:=Key;
Result:=0;
end;
function ps4_pthread_key_delete(Key:pthread_key_t):Integer; SysV_ABI_CDecl;
var
node:p_pthread_key_node;
begin
Key:=Key-1;
if (DWORD(Key)>SCE_PTHREAD_KEYS_MAX) then Exit(EINVAL);
Writeln('pthread_key_delete');
node:=@_pthread_key_nodes[Key];
if (XCHG(Pointer(node^.dest_),nil)=nil) then Exit(EINVAL);
System.InterlockedIncrement(Pointer(node^.version_));
_pthread_key_queue.Push(node);
end;
function ps4_pthread_getspecific(Key:pthread_key_t):Pointer; SysV_ABI_CDecl;
var
node:p_pthread_key_node;
version:ptruint;
local:p_pthread_key_data;
begin
Key:=Key-1;
if (DWORD(Key)>=SCE_PTHREAD_KEYS_MAX) then Exit(nil);
node:=@_pthread_key_nodes[Key];
version:=load_consume(node^.version_);
if (load_consume(Pointer(node^.dest_))=nil) then Exit(nil);
local:=@tcb_thread^.keys[Key];
if (local^.version_<>version) then Exit(nil);
Result:=local^.data_;
end;
function ps4_pthread_setspecific(Key:pthread_key_t;value:Pointer):Integer; SysV_ABI_CDecl;
var
node:p_pthread_key_node;
version:ptruint;
local:p_pthread_key_data;
begin
Key:=Key-1;
if (DWORD(Key)>=SCE_PTHREAD_KEYS_MAX) then Exit(EINVAL);
node:=@_pthread_key_nodes[Key];
version:=load_consume(node^.version_);
if (load_consume(Pointer(node^.dest_))=nil) then Exit(EINVAL);
local:=@tcb_thread^.keys[Key];
local^.version_:=version;
local^.data_ :=value;
Result:=0;
end;
initialization
_pthread_keys_init;
end.

230
kernel/ps4_pthread_key.pas Normal file
View File

@ -0,0 +1,230 @@
unit ps4_pthread_key;
{$mode ObjFPC}{$H+}
interface
uses
LFQueue,
spinlock,
sys_kernel,
sys_pthread,
sys_signal;
procedure _thread_cleanupspecific;
function ps4_pthread_key_create(pKey:Ppthread_key_t;dest:t_cb_proc):Integer; SysV_ABI_CDecl;
function ps4_pthread_key_delete(Key:pthread_key_t):Integer; SysV_ABI_CDecl;
function ps4_pthread_getspecific(Key:pthread_key_t):Pointer; SysV_ABI_CDecl;
function ps4_pthread_setspecific(Key:pthread_key_t;value:Pointer):Integer; SysV_ABI_CDecl;
//undefined8 pthread_get_specificarray_np(long param_1,undefined4 *param_2)
function ps4_scePthreadKeyCreate(pKey:Ppthread_key_t;dest:t_cb_proc):Integer; SysV_ABI_CDecl;
function ps4_scePthreadKeyDelete(Key:pthread_key_t):Integer; SysV_ABI_CDecl;
function ps4_scePthreadGetspecific(Key:pthread_key_t):Pointer; SysV_ABI_CDecl;
function ps4_scePthreadSetspecific(Key:pthread_key_t;value:Pointer):Integer; SysV_ABI_CDecl;
implementation
type
p_pthread_key_node=^_pthread_key_node;
_pthread_key_node=packed record
next_:p_pthread_key_node;
version_:ptruint;
dest_:t_cb_proc;
end;
var
_pthread_key_nodes:array[0..SCE_PTHREAD_KEYS_MAX-1] of _pthread_key_node;
_pthread_key_queue:TIntrusiveMPSCQueue;
_pthread_key_queue_lock:Pointer;
procedure _pthread_keys_init;
var
i:Integer;
begin
_pthread_key_queue.Create;
For i:=Low(_pthread_key_nodes) to High(_pthread_key_nodes) do
begin
_pthread_key_nodes[i]:=Default(_pthread_key_node);
_pthread_key_queue.Push(@_pthread_key_nodes[i]);
end;
end;
const
PTHREAD_DESTRUCTOR_ITERATIONS=4;
procedure _thread_cleanupspecific;
var
i,k:Integer;
keys:p_pthread_key_data;
local:p_pthread_key_data;
node:p_pthread_key_node;
version:ptruint;
dest:t_cb_proc;
nofree:Boolean;
begin
keys:=tcb_thread^.specific;
if (keys=nil) then Exit;
local:=@keys[0];
For i:=0 to PTHREAD_DESTRUCTOR_ITERATIONS-1 do
begin
nofree:=True;
For k:=Low(_pthread_key_nodes) to High(_pthread_key_nodes) do
begin
node:=@_pthread_key_nodes[k];
version:=load_consume(node^.version_);
dest:=t_cb_proc(load_consume(Pointer(node^.dest_)));
if (ptruint(dest)>1) and
(local[k].version_=version) and
(local[k].data_<>nil) then
begin
dest(local[k].data_);
local[k].data_:=nil;
nofree:=False;
end;
end;
if nofree then Break;
end;
tcb_thread^.specific:=nil;
SwFreeMem(keys);
end;
function ps4_pthread_key_create(pKey:Ppthread_key_t;dest:t_cb_proc):Integer; SysV_ABI_CDecl;
var
node:p_pthread_key_node;
Key:pthread_key_t;
begin
if (pKey=nil) then Exit(EINVAL);
Writeln('pthread_key_create');
if (dest=nil) then dest:=t_cb_proc(1);
node:=nil;
spin_lock(_pthread_key_queue_lock);
_pthread_key_queue.Pop(node);
spin_unlock(_pthread_key_queue_lock);
if (node=nil) then Exit(EAGAIN);
System.InterlockedIncrement(Pointer(node^.version_));
XCHG(Pointer(node^.dest_),Pointer(dest));
Key:=(node-p_pthread_key_node(@_pthread_key_nodes));
Key:=Key+1;
pKey^:=Key;
Result:=0;
end;
function ps4_pthread_key_delete(Key:pthread_key_t):Integer; SysV_ABI_CDecl;
var
node:p_pthread_key_node;
begin
Key:=Key-1;
if (DWORD(Key)>SCE_PTHREAD_KEYS_MAX) then Exit(EINVAL);
Writeln('pthread_key_delete');
node:=@_pthread_key_nodes[Key];
if (XCHG(Pointer(node^.dest_),nil)=nil) then Exit(EINVAL);
System.InterlockedIncrement(Pointer(node^.version_));
_pthread_key_queue.Push(node);
end;
function ps4_pthread_getspecific(Key:pthread_key_t):Pointer; SysV_ABI_CDecl;
var
node:p_pthread_key_node;
version:ptruint;
keys:p_pthread_key_data;
local:p_pthread_key_data;
begin
Key:=Key-1;
if (DWORD(Key)>=SCE_PTHREAD_KEYS_MAX) then Exit(nil);
node:=@_pthread_key_nodes[Key];
version:=load_consume(node^.version_);
if (load_consume(Pointer(node^.dest_))=nil) then Exit(nil);
keys:=tcb_thread^.specific;
if (keys=nil) then Exit(nil);
local:=@keys[Key];
if (local^.version_<>version) then Exit(nil);
Result:=local^.data_;
end;
function ps4_pthread_setspecific(Key:pthread_key_t;value:Pointer):Integer; SysV_ABI_CDecl;
var
node:p_pthread_key_node;
version:ptruint;
keys:p_pthread_key_data;
local:p_pthread_key_data;
begin
Key:=Key-1;
if (DWORD(Key)>=SCE_PTHREAD_KEYS_MAX) then Exit(EINVAL);
node:=@_pthread_key_nodes[Key];
version:=load_consume(node^.version_);
if (load_consume(Pointer(node^.dest_))=nil) then Exit(EINVAL);
keys:=tcb_thread^.specific;
if (keys=nil) then
begin
keys:=SwAllocMem(SizeOf(_pthread_keys));
if (keys=nil) then Exit(ENOMEM);
tcb_thread^.specific:=keys;
end;
local:=@keys[Key];
local^.version_:=version;
local^.data_ :=value;
Result:=0;
end;
//interface
function ps4_scePthreadKeyCreate(pKey:Ppthread_key_t;dest:t_cb_proc):Integer; SysV_ABI_CDecl;
begin
Result:=px2sce(ps4_pthread_key_create(pKey,dest));
end;
function ps4_scePthreadKeyDelete(Key:pthread_key_t):Integer; SysV_ABI_CDecl;
begin
Result:=px2sce(ps4_pthread_key_delete(Key));
end;
function ps4_scePthreadGetspecific(Key:pthread_key_t):Pointer; SysV_ABI_CDecl;
begin
Result:=ps4_pthread_getspecific(Key);
end;
function ps4_scePthreadSetspecific(Key:pthread_key_t;value:Pointer):Integer; SysV_ABI_CDecl;
begin
Result:=px2sce(ps4_pthread_setspecific(Key,value));
end;
initialization
_pthread_keys_init;
end.

View File

@ -122,6 +122,8 @@ type
data_:Pointer;
end;
_pthread_keys=array[0..SCE_PTHREAD_KEYS_MAX-1] of _pthread_key_data;
t_init_routine_proc=procedure; SysV_ABI_CDecl;
t_cb_proc=procedure(data:Pointer); SysV_ABI_CDecl;
@ -151,7 +153,7 @@ type
//
cleanup:p_pthread_cleanup;
//
keys:array[0..SCE_PTHREAD_KEYS_MAX-1] of _pthread_key_data;
specific:p_pthread_key_data;
//
sig:sigqueue_t;
end;