mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-26 16:10:25 +00:00
scePthreadKeyCreate and etc
This commit is contained in:
parent
703d9426fd
commit
56f0d24fcc
@ -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);
|
||||
|
@ -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
230
kernel/ps4_pthread_key.pas
Normal 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.
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user