mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-12-13 00:58:25 +00:00
1128 lines
30 KiB
ObjectPascal
1128 lines
30 KiB
ObjectPascal
unit ps4_pthread;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
LFQueue,
|
|
windows,
|
|
sys_crt,
|
|
sys_pthread,
|
|
sys_signal;
|
|
|
|
procedure ps4_pthread_cxa_finalize(P:Pointer); SysV_ABI_CDecl;
|
|
|
|
function ps4_scePthreadAttrInit(pAttr:p_pthread_attr_t):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrDestroy(pAttr:p_pthread_attr_t):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_attr_init(pAttr:p_pthread_attr_t):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_attr_destroy(pAttr:p_pthread_attr_t):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrSetstacksize(pAttr:p_pthread_attr_t;size:size_t):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_attr_setstacksize(pAttr:p_pthread_attr_t;size:size_t):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrSetdetachstate(pAttr:p_pthread_attr_t;detachstate:Integer):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_attr_setdetachstate(pAttr:p_pthread_attr_t;detachstate:Integer):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrSetschedpolicy(pAttr:p_pthread_attr_t;policy:Integer):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrSetschedparam(pAttr:p_pthread_attr_t;param:PInteger):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrGetschedparam(pAttr:p_pthread_attr_t;param:PInteger):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_attr_setschedparam(pAttr:p_pthread_attr_t;param:PInteger):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_attr_getschedparam(pAttr:p_pthread_attr_t;param:PInteger):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrSetaffinity(pAttr:p_pthread_attr_t;mask:QWORD):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrGetaffinity(pAttr:p_pthread_attr_t;mask:PQWORD):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrSetinheritsched(pAttr:p_pthread_attr_t;inheritSched:Integer):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrGetguardsize(pAttr:p_pthread_attr_t;guardSize:PQWORD):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrGetstackaddr(pAttr:p_pthread_attr_t;stackAddr:PPointer):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrGetstacksize(pAttr:p_pthread_attr_t;stackSize:PQWORD):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrGetstack(pAttr:p_pthread_attr_t;stackAddr:PPointer;stackSize:PQWORD):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadAttrGetdetachstate(pAttr:p_pthread_attr_t;detachstate:Pinteger):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_attr_getdetachstate(pAttr:p_pthread_attr_t;detachstate:Pinteger):Integer; SysV_ABI_CDecl;
|
|
|
|
function ps4_scePthreadAttrGet(pid:pthread;pAttr:p_pthread_attr_t):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadCreate(pthread:p_pthread;pAttr:p_pthread_attr_t;entry:Pointer;arg:Pointer;name:Pchar):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_create(pthread:p_pthread;pAttr:p_pthread_attr_t;entry:Pointer;arg:Pointer):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadDetach(_pthread:pthread):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_detach(_pthread:pthread):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadJoin(_pthread:pthread;value:PPointer):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_join(_pthread:pthread;value:PPointer):Integer; SysV_ABI_CDecl;
|
|
|
|
function ps4_pthread_once(once_control:p_pthread_once_t;init_routine:t_init_routine_proc):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadOnce(once_control:p_pthread_once_t;init_routine:t_init_routine_proc):Integer; SysV_ABI_CDecl;
|
|
|
|
function ps4_scePthreadEqual(t1,t2:pthread):Integer; SysV_ABI_CDecl;
|
|
function ps4_pthread_equal(t1,t2:pthread):Integer; SysV_ABI_CDecl;
|
|
|
|
procedure ps4_scePthreadExit(value_ptr:Pointer); SysV_ABI_CDecl;
|
|
procedure ps4_pthread_exit(value_ptr:Pointer); SysV_ABI_CDecl;
|
|
|
|
function ps4_pthread_setcancelstate(state:Integer;oldstate:PInteger):Integer; SysV_ABI_CDecl;
|
|
|
|
function ps4_pthread_self():pthread; SysV_ABI_CDecl;
|
|
function ps4_scePthreadSelf():pthread; SysV_ABI_CDecl;
|
|
|
|
function ps4_getpid():Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadGetthreadid():Integer; SysV_ABI_CDecl;
|
|
|
|
function ps4_scePthreadGetname(_pthread:pthread;name:Pchar):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadRename(_pthread:pthread;name:Pchar):Integer; SysV_ABI_CDecl;
|
|
|
|
function ps4_scePthreadSetaffinity(_pthread:pthread;mask:QWORD):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadGetaffinity(_pthread:pthread;mask:PQWORD):Integer; SysV_ABI_CDecl;
|
|
|
|
function ps4_scePthreadGetprio(_pthread:pthread;prio:PInteger):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadSetprio(_pthread:pthread;prio:Integer):Integer; SysV_ABI_CDecl;
|
|
|
|
function ps4_scePthreadGetschedparam(_pthread:pthread;policy:PInteger;param:PSceKernelSchedParam):Integer; SysV_ABI_CDecl;
|
|
function ps4_scePthreadSetschedparam(_pthread:pthread;policy:Integer;param:PSceKernelSchedParam):Integer; SysV_ABI_CDecl;
|
|
|
|
function ps4_sched_get_priority_max(policy:Integer):Integer; SysV_ABI_CDecl;
|
|
function ps4_sched_get_priority_min(policy:Integer):Integer; SysV_ABI_CDecl;
|
|
|
|
procedure ps4_scePthreadYield; SysV_ABI_CDecl;
|
|
function ps4_pthread_yield:Integer; SysV_ABI_CDecl;
|
|
function ps4_sched_yield:Integer; SysV_ABI_CDecl;
|
|
|
|
procedure ps4_pthread_cleanup_push(routine:t_cb_proc;arg:Pointer); SysV_ABI_CDecl;
|
|
procedure ps4_pthread_cleanup_pop(execute:Integer); SysV_ABI_CDecl;
|
|
procedure ps4___pthread_cleanup_push_imp(routine:t_cb_proc;
|
|
arg:Pointer;
|
|
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
|
|
|
|
uses
|
|
atomic,
|
|
spinlock,
|
|
sys_kernel,
|
|
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
|
|
Writeln('__pthread_cxa_finalize');
|
|
end;
|
|
|
|
//struct pthread_attr _pthread_attr_default = {
|
|
// .sched_policy = SCHED_OTHER,
|
|
// .sched_inherit = PTHREAD_INHERIT_SCHED,
|
|
// .prio = 0,
|
|
// .suspend = THR_CREATE_RUNNING,
|
|
// .flags = PTHREAD_SCOPE_SYSTEM,
|
|
// .stackaddr_attr = NULL,
|
|
// .stacksize_attr = THR_STACK_DEFAULT,
|
|
// .guardsize_attr = 0,
|
|
// .cpusetsize = 0,
|
|
// .cpuset = NULL
|
|
//};
|
|
|
|
function ps4_scePthreadAttrInit(pAttr:p_pthread_attr_t):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Writeln('scePthreadAttrInit');
|
|
if (pAttr=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
pAttr^:=SwAllocMem(SizeOf(tthread_attr_t));
|
|
if (pAttr^=nil) then Exit(SCE_KERNEL_ERROR_ENOMEM);
|
|
pAttr^^.stacksize_attr:=PTHREAD_STACK_MIN;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrDestroy(pAttr:p_pthread_attr_t):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Writeln('scePthreadAttrDestroy');
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
if (pAttr=nil) then Exit;
|
|
SwFreeMem(XCHG(pAttr^,nil));
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_pthread_attr_init(pAttr:p_pthread_attr_t):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Writeln('pthread_attr_init');
|
|
if (pAttr=nil) then Exit(EINVAL);
|
|
pAttr^:=SwAllocMem(SizeOf(tthread_attr_t));
|
|
if (pAttr^=nil) then Exit(ENOMEM);
|
|
pAttr^^.stacksize_attr:=PTHREAD_STACK_MIN;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_pthread_attr_destroy(pAttr:p_pthread_attr_t):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Writeln('pthread_attr_destroy');
|
|
Result:=EINVAL;
|
|
if (pAttr=nil) then Exit;
|
|
SwFreeMem(XCHG(pAttr^,nil));
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrSetstacksize(pAttr:p_pthread_attr_t;size:size_t):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (pAttr=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
if (pAttr^=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
if (size<PTHREAD_STACK_MIN) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
pAttr^^.stacksize_attr:=size;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_pthread_attr_setstacksize(pAttr:p_pthread_attr_t;size:size_t):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (pAttr=nil) then Exit(EINVAL);
|
|
if (pAttr^=nil) then Exit(EINVAL);
|
|
if (size<PTHREAD_STACK_MIN) then Exit(EINVAL);
|
|
pAttr^^.stacksize_attr:=size;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrSetdetachstate(pAttr:p_pthread_attr_t;detachstate:Integer):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
if (pAttr=nil) then Exit;
|
|
if (pAttr^=nil) then Exit;
|
|
|
|
Case detachstate of
|
|
PTHREAD_CREATE_JOINABLE:;
|
|
PTHREAD_CREATE_DETACHED:;
|
|
else
|
|
Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
end;
|
|
|
|
pAttr^^.flags:=detachstate;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_pthread_attr_setdetachstate(pAttr:p_pthread_attr_t;detachstate:Integer):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=EINVAL;
|
|
if (pAttr=nil) then Exit;
|
|
if (pAttr^=nil) then Exit;
|
|
|
|
Case detachstate of
|
|
PTHREAD_CREATE_JOINABLE:;
|
|
PTHREAD_CREATE_DETACHED:;
|
|
else
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
pAttr^^.flags:=detachstate;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrSetschedpolicy(pAttr:p_pthread_attr_t;policy:Integer):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
if (pAttr=nil) then Exit;
|
|
if (pAttr^=nil) then Exit;
|
|
pAttr^^.sched_policy:=policy;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrSetschedparam(pAttr:p_pthread_attr_t;param:PInteger):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
if (pAttr=nil) or (param=nil) then Exit;
|
|
if (pAttr^=nil) then Exit;
|
|
pAttr^^.prio:=param^;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrGetschedparam(pAttr:p_pthread_attr_t;param:PInteger):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
if (pAttr=nil) or (param=nil) then Exit;
|
|
if (pAttr^=nil) then Exit;
|
|
param^:=pAttr^^.prio;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_pthread_attr_setschedparam(pAttr:p_pthread_attr_t;param:PInteger):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=EINVAL;
|
|
if (pAttr=nil) or (param=nil) then Exit;
|
|
if (pAttr^=nil) then Exit;
|
|
pAttr^^.prio:=param^;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_pthread_attr_getschedparam(pAttr:p_pthread_attr_t;param:PInteger):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=EINVAL;
|
|
if (pAttr=nil) or (param=nil) then Exit;
|
|
if (pAttr^=nil) then Exit;
|
|
param^:=pAttr^^.prio;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrSetaffinity(pAttr:p_pthread_attr_t;mask:QWORD):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
if (pAttr=nil) then Exit;
|
|
if (pAttr^=nil) then Exit;
|
|
pAttr^^.cpuset:=mask;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrGetaffinity(pAttr:p_pthread_attr_t;mask:PQWORD):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
if (pAttr=nil) or (mask=nil) then Exit;
|
|
if (pAttr^=nil) then Exit;
|
|
mask^:=pAttr^^.cpuset;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrSetinheritsched(pAttr:p_pthread_attr_t;inheritSched:Integer):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
if (pAttr=nil) then Exit;
|
|
if (pAttr^=nil) then Exit;
|
|
pAttr^^.sched_inherit:=inheritSched;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrGetguardsize(pAttr:p_pthread_attr_t;guardSize:PQWORD):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (pAttr=nil) or (guardSize=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
if (pAttr^=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
guardSize^:=pAttr^^.guardsize_attr;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrGetstackaddr(pAttr:p_pthread_attr_t;stackAddr:PPointer):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (pAttr=nil) or (stackAddr=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
if (pAttr^=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
stackAddr^:=pAttr^^.stackaddr_attr;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrGetstacksize(pAttr:p_pthread_attr_t;stackSize:PQWORD):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (pAttr=nil) or (stackSize=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
if (pAttr^=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
stackSize^:=pAttr^^.stacksize_attr;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrGetstack(pAttr:p_pthread_attr_t;stackAddr:PPointer;stackSize:PQWORD):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (pAttr=nil) or (stackAddr=nil) or (stackSize=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
if (pAttr^=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
stackAddr^:=pAttr^^.stackaddr_attr;
|
|
stackSize^:=pAttr^^.stacksize_attr;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrGetdetachstate(pAttr:p_pthread_attr_t;detachstate:Pinteger):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (pAttr=nil) or (detachstate=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
if (pAttr^=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
detachstate^:=pAttr^^.flags;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_pthread_attr_getdetachstate(pAttr:p_pthread_attr_t;detachstate:Pinteger):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (pAttr=nil) or (detachstate=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
if (pAttr^=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
detachstate^:=pAttr^^.flags;
|
|
Result:=0;
|
|
end;
|
|
|
|
procedure _free_pthread(data:pthread);
|
|
begin
|
|
_sig_lock;
|
|
System.CloseThread(data^.handle);
|
|
FreeMem(data);
|
|
_sig_unlock;
|
|
end;
|
|
|
|
procedure _thread_init;
|
|
begin
|
|
_sig_lock;
|
|
RegistredStack;
|
|
ps4_app.InitThread(0);
|
|
_sig_unlock;
|
|
end;
|
|
|
|
procedure _pthread_cleanup_pop; inline;
|
|
var
|
|
curthread:pthread;
|
|
begin
|
|
curthread:=_get_curthread;
|
|
if (curthread=nil) then Exit;
|
|
|
|
While (curthread^.cleanup<>nil) do ps4___pthread_cleanup_pop_imp(1);
|
|
end;
|
|
|
|
procedure _thread_cleanup;
|
|
begin
|
|
_pthread_cleanup_pop;
|
|
|
|
if (sceKernelThreadDtors<>nil) then
|
|
begin
|
|
sceKernelThreadDtors();
|
|
end;
|
|
|
|
_sig_lock;
|
|
_pthread_keys_cleanup_dest;
|
|
ps4_app.FreeThread;
|
|
UnRegistredStack;
|
|
_sig_unlock;
|
|
end;
|
|
|
|
function on_ps4_run_entry(arg:Pointer):Pointer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=nil;
|
|
ps4_app.InitThread(1);
|
|
ps4_app.InitCode;
|
|
Telf_file(ps4_app.prog).mapCodeEntry;
|
|
writeln('--[END]--');
|
|
end;
|
|
|
|
const
|
|
default_name:Pchar='main';
|
|
default_stack:Integer=DefaultStackSize;
|
|
|
|
function _pthread_run_entry(pthread:p_pthread;name:Pchar;stack:PDWORD):Integer;
|
|
var
|
|
attr:pthread_attr_t;
|
|
begin
|
|
if (name=nil) then
|
|
begin
|
|
name:=default_name;
|
|
end;
|
|
if (stack=nil) then
|
|
begin
|
|
stack:=@default_stack;
|
|
end else
|
|
if (stack^<PTHREAD_STACK_MIN) then
|
|
begin
|
|
stack:=@default_stack;
|
|
end;
|
|
|
|
ps4_pthread_attr_init(@attr);
|
|
ps4_pthread_attr_setstacksize(@attr,stack^);
|
|
Result:=ps4_scePthreadCreate(pthread,@attr,@on_ps4_run_entry,nil,name);
|
|
ps4_pthread_attr_destroy(@attr);
|
|
end;
|
|
|
|
const
|
|
_PREPARE_FREE=2;
|
|
_PREPARE_JOIN=3;
|
|
|
|
function on_ps4_run_thread(data:pthread):Longint; stdcall;
|
|
type
|
|
Tps4entry=function(arg:Pointer):Pointer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=0;
|
|
|
|
sys_crt_init;
|
|
|
|
//StackTop - Max
|
|
//StackBottom - Min
|
|
|
|
StackLength:=data^.Attr.stacksize_attr;
|
|
Assert(StackLength<>0);
|
|
|
|
StackBottom:=StackTop-StackLength;
|
|
|
|
//Writeln('StackTop :',HexStr(StackTop));
|
|
//Writeln('Sptr :',HexStr(Sptr));
|
|
//
|
|
//Writeln('StackBottom:',HexStr(StackBottom));
|
|
//Writeln('StackLength:',HexStr(StackLength,16));
|
|
|
|
ReadBarrier;
|
|
if (data<>nil) and (data^.entry<>nil) then
|
|
begin
|
|
//if (data^.Attr.stackaddr_attr=nil) then
|
|
//begin
|
|
data^.Attr.stackaddr_attr:=StackBottom;
|
|
data^.Attr.stacksize_attr:=StackLength;
|
|
//end;
|
|
|
|
writeln('BeginThread:',data^.name,':',HexStr(data^.entry));
|
|
tcb_thread:=data;
|
|
_thread_init;
|
|
|
|
wait_until_equal(data^.handle,0);
|
|
|
|
//data^.arg:=Tps4entry(data^.entry)(data^.arg);
|
|
data^.arg:=sysv_wrapper(data^.arg,data^.entry);
|
|
ReadWriteBarrier;
|
|
|
|
_thread_cleanup;
|
|
writeln('EndThread:',data^.name);
|
|
|
|
if CAS(data^.detachstate,PTHREAD_CREATE_DETACHED,_PREPARE_FREE) then
|
|
begin
|
|
_free_pthread(data);
|
|
end else
|
|
begin
|
|
CAS(data^.detachstate,PTHREAD_CREATE_JOINABLE,_PREPARE_JOIN);
|
|
end;
|
|
|
|
end;
|
|
|
|
DoneThread;
|
|
end;
|
|
|
|
function ps4_scePthreadAttrGet(pid:pthread;pAttr:p_pthread_attr_t):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (pid=nil) or (pAttr=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
if (pAttr^=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
pAttr^^:=pid^.Attr;
|
|
end;
|
|
|
|
//typedef pthread_t ScePthread;
|
|
|
|
function ps4_scePthreadCreate(pthread:p_pthread;pAttr:p_pthread_attr_t;entry:Pointer;arg:Pointer;name:Pchar):Integer; SysV_ABI_CDecl;
|
|
Var
|
|
data:pthread;
|
|
Handle,ThreadId:TThreadID;
|
|
sa:Pointer;
|
|
ss:SizeUInt;
|
|
creationFlags:dword;
|
|
begin
|
|
Writeln('scePthreadCreate:',HexStr(entry),' ',name);
|
|
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
if (pthread=nil) then Exit;
|
|
|
|
//if {false} name='AudioOutThread' then
|
|
//if (name='streamThread') or (name='AudioOutThread') then
|
|
//if false then
|
|
begin
|
|
data:=SwAllocMem(SizeOf(pthread_t));
|
|
if (data=nil) then Exit(SCE_KERNEL_ERROR_ENOMEM);
|
|
|
|
sigqueue_init(@data^.sig);
|
|
|
|
data^.entry:=entry;
|
|
data^.arg:=arg;
|
|
if (name<>nil) then MoveChar0(name^,data^.name,32);
|
|
|
|
ReadWriteBarrier;
|
|
|
|
if (pAttr<>nil) and (pAttr^<>nil) then
|
|
begin
|
|
data^.Attr:=pAttr^^;
|
|
data^.detachstate:=pAttr^^.flags;
|
|
ReadWriteBarrier;
|
|
|
|
creationFlags:=0;
|
|
sa:=pAttr^^.stackaddr_attr;
|
|
ss:=pAttr^^.stacksize_attr;
|
|
|
|
if (ss<PTHREAD_STACK_MIN) then
|
|
begin
|
|
ss:=PTHREAD_STACK_MIN;
|
|
data^.Attr.stacksize_attr:=ss;
|
|
end;
|
|
|
|
ThreadId:=0;
|
|
_sig_lock;
|
|
|
|
Handle:=SysBeginThread(sa,ss,@on_ps4_run_thread,data,creationFlags,ThreadId);
|
|
|
|
_sig_unlock;
|
|
if (Handle=0) then
|
|
begin
|
|
SwFreeMem(data);
|
|
Exit(SCE_KERNEL_ERROR_EAGAIN);
|
|
end;
|
|
|
|
if (pAttr^^.cpuset<>0) then
|
|
begin
|
|
_sig_lock;
|
|
SetThreadAffinityMask(Handle,pAttr^^.cpuset);
|
|
_sig_unlock;
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
ThreadId:=0;
|
|
_sig_lock;
|
|
|
|
ss:=PTHREAD_STACK_MIN;
|
|
data^.Attr.stacksize_attr:=ss;
|
|
|
|
Handle:=SysBeginThread(nil,ss,@on_ps4_run_thread,data,0,ThreadId);
|
|
|
|
_sig_unlock;
|
|
if (Handle=0) then
|
|
begin
|
|
SwFreeMem(data);
|
|
Exit(SCE_KERNEL_ERROR_EAGAIN);
|
|
end;
|
|
end;
|
|
|
|
XCHG(data^.ThreadId,ThreadId);
|
|
XCHG(data^.handle,Handle);
|
|
|
|
pthread^:=data;
|
|
end;
|
|
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_pthread_create(pthread:p_pthread;pAttr:p_pthread_attr_t;entry:Pointer;arg:Pointer):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=sce2px(ps4_scePthreadCreate(pthread,pAttr,entry,arg,nil));
|
|
end;
|
|
|
|
function ps4_scePthreadDetach(_pthread:pthread):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (_pthread=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
Writeln('scePthreadDetach:',_pthread^.name);
|
|
if CAS(_pthread^.detachstate,PTHREAD_CREATE_JOINABLE,PTHREAD_CREATE_DETACHED) then
|
|
begin
|
|
_pthread^.Attr.flags:=PTHREAD_CREATE_DETACHED;
|
|
Result:=0
|
|
end else
|
|
if CAS(_pthread^.detachstate,_PREPARE_JOIN,_PREPARE_FREE) then
|
|
begin
|
|
_free_pthread(_pthread);
|
|
Result:=0
|
|
end else
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
end;
|
|
end;
|
|
|
|
function ps4_pthread_detach(_pthread:pthread):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=sce2px(ps4_scePthreadDetach(_pthread));
|
|
end;
|
|
|
|
function ps4_scePthreadJoin(_pthread:pthread;value:PPointer):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (_pthread=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
Writeln('scePthreadJoin:',_pthread^.name);
|
|
|
|
if CAS(_pthread^.detachstate,PTHREAD_CREATE_JOINABLE,_PREPARE_FREE) then
|
|
begin
|
|
SwWaitFor(_pthread^.handle,nil);
|
|
if (value<>nil) then value^:=_pthread^.arg;
|
|
_free_pthread(_pthread);
|
|
Result:=0;
|
|
end else
|
|
if CAS(_pthread^.detachstate,_PREPARE_JOIN,_PREPARE_FREE) then
|
|
begin
|
|
if (value<>nil) then value^:=_pthread^.arg;
|
|
_free_pthread(_pthread);
|
|
Result:=0;
|
|
end else
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_EINVAL;
|
|
end;
|
|
end;
|
|
|
|
function ps4_pthread_join(_pthread:pthread;value:PPointer):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=sce2px(ps4_scePthreadJoin(_pthread,value));
|
|
end;
|
|
|
|
function ps4_pthread_once(once_control:p_pthread_once_t;init_routine:t_init_routine_proc):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=0;
|
|
if (once_control=nil) or (init_routine=nil) then Exit(EINVAL);
|
|
|
|
if (once_control^.state<>PTHREAD_NEEDS_INIT) then Exit(0);
|
|
|
|
Result:=ps4_pthread_mutex_lock(@once_control^.mutex);
|
|
if (Result<>0) then Exit;
|
|
|
|
if (once_control^.state=PTHREAD_NEEDS_INIT) then
|
|
begin
|
|
//pthread_cleanup_push(_pthread_once_cleanup, co);
|
|
|
|
init_routine();
|
|
|
|
//pthread_cleanup_pop(0);
|
|
|
|
once_control^.state:=PTHREAD_DONE_INIT;
|
|
end;
|
|
|
|
ps4_pthread_mutex_unlock(@once_control^.mutex);
|
|
end;
|
|
|
|
function ps4_scePthreadOnce(once_control:p_pthread_once_t;init_routine:t_init_routine_proc):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=px2sce(ps4_pthread_once(once_control,init_routine));
|
|
end;
|
|
|
|
function ps4_scePthreadEqual(t1,t2:pthread):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (t1=t2) then
|
|
Result:=1
|
|
else
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_pthread_equal(t1,t2:pthread):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (t1=t2) then
|
|
Result:=1
|
|
else
|
|
Result:=0;
|
|
end;
|
|
|
|
procedure ps4_scePthreadExit(value_ptr:Pointer); SysV_ABI_CDecl;
|
|
var
|
|
data:pthread;
|
|
begin
|
|
data:=tcb_thread;
|
|
if (data=nil) then Exit;
|
|
Writeln('ExitThread:',data^.name);
|
|
data^.arg:=value_ptr;
|
|
|
|
ReadWriteBarrier;
|
|
|
|
_thread_cleanup;
|
|
|
|
if CAS(data^.detachstate,PTHREAD_CREATE_DETACHED,_PREPARE_FREE) then
|
|
begin
|
|
_free_pthread(data);
|
|
end else
|
|
begin
|
|
CAS(data^.detachstate,PTHREAD_CREATE_JOINABLE,_PREPARE_JOIN);
|
|
end;
|
|
|
|
_sig_lock;
|
|
System.EndThread(0);
|
|
end;
|
|
|
|
procedure ps4_pthread_exit(value_ptr:Pointer); SysV_ABI_CDecl;
|
|
begin
|
|
ps4_scePthreadExit(value_ptr);
|
|
end;
|
|
|
|
function ps4_pthread_setcancelstate(state:Integer;oldstate:PInteger):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=0;
|
|
|
|
Case state of
|
|
PTHREAD_CANCEL_DISABLE:Writeln('PTHREAD_CANCEL_DISABLE');
|
|
PTHREAD_CANCEL_ENABLE :Writeln('PTHREAD_CANCEL_ENABLE');
|
|
else
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
end;
|
|
|
|
function ps4_pthread_self():pthread; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=tcb_thread;
|
|
end;
|
|
|
|
function ps4_scePthreadSelf():pthread; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=tcb_thread;
|
|
end;
|
|
|
|
function ps4_getpid():Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=tcb_thread^.ThreadId;
|
|
end;
|
|
|
|
function ps4_scePthreadGetthreadid():Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=tcb_thread^.ThreadId;
|
|
end;
|
|
|
|
function ps4_scePthreadGetname(_pthread:pthread;name:Pchar):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (_pthread=nil) or (name=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
MoveChar0(_pthread^.name,name^,32);
|
|
end;
|
|
|
|
function ps4_scePthreadRename(_pthread:pthread;name:Pchar):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (_pthread=nil) or (name=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
MoveChar0(name^,_pthread^.name,32);
|
|
end;
|
|
|
|
function ps4_scePthreadSetaffinity(_pthread:pthread;mask:QWORD):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
if (_pthread=nil) then Exit(SCE_KERNEL_ERROR_ESRCH);
|
|
Result:=0;
|
|
_pthread^.Attr.cpuset:=mask;
|
|
_sig_lock;
|
|
SetThreadAffinityMask(_pthread^.handle,mask);
|
|
_sig_unlock;
|
|
end;
|
|
|
|
function ps4_scePthreadGetaffinity(_pthread:pthread;mask:PQWORD):Integer; SysV_ABI_CDecl;
|
|
var
|
|
tmp:QWORD;
|
|
begin
|
|
if (_pthread=nil) then Exit(SCE_KERNEL_ERROR_ESRCH);
|
|
if (mask=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
Result:=0;
|
|
if (_pthread^.Attr.cpuset=0) then
|
|
begin
|
|
_sig_lock;
|
|
GetProcessAffinityMask(GetCurrentProcess,@_pthread^.Attr.cpuset,@tmp);
|
|
_sig_unlock;
|
|
end;
|
|
mask^:=_pthread^.Attr.cpuset;
|
|
end;
|
|
|
|
const
|
|
PRIORITY_TABLE:array[0..30] of SmallInt=(
|
|
{ 0} THREAD_PRIORITY_IDLE , //-15
|
|
{ 1} THREAD_PRIORITY_IDLE , //-15
|
|
{ 2} THREAD_PRIORITY_IDLE , //-15
|
|
{ 3} THREAD_PRIORITY_LOWEST , // -2
|
|
{ 4} THREAD_PRIORITY_LOWEST , // -2
|
|
{ 5} THREAD_PRIORITY_LOWEST , // -2
|
|
{ 6} THREAD_PRIORITY_LOWEST , // -2
|
|
{ 7} THREAD_PRIORITY_LOWEST , // -2
|
|
{ 8} THREAD_PRIORITY_BELOW_NORMAL , // -1
|
|
{ 9} THREAD_PRIORITY_BELOW_NORMAL , // -1
|
|
{10} THREAD_PRIORITY_BELOW_NORMAL , // -1
|
|
{11} THREAD_PRIORITY_BELOW_NORMAL , // -1
|
|
{12} THREAD_PRIORITY_BELOW_NORMAL , // -1
|
|
{13} THREAD_PRIORITY_NORMAL , // 0
|
|
{14} THREAD_PRIORITY_NORMAL , // 0
|
|
{15} THREAD_PRIORITY_NORMAL , // 0
|
|
{16} THREAD_PRIORITY_NORMAL , // 0
|
|
{17} THREAD_PRIORITY_NORMAL , // 0
|
|
{18} THREAD_PRIORITY_ABOVE_NORMAL , // 1
|
|
{19} THREAD_PRIORITY_ABOVE_NORMAL , // 1
|
|
{20} THREAD_PRIORITY_ABOVE_NORMAL , // 1
|
|
{21} THREAD_PRIORITY_ABOVE_NORMAL , // 1
|
|
{22} THREAD_PRIORITY_ABOVE_NORMAL , // 1
|
|
{23} THREAD_PRIORITY_HIGHEST , // 2
|
|
{24} THREAD_PRIORITY_HIGHEST , // 2
|
|
{25} THREAD_PRIORITY_HIGHEST , // 2
|
|
{26} THREAD_PRIORITY_HIGHEST , // 2
|
|
{27} THREAD_PRIORITY_HIGHEST , // 2
|
|
{28} THREAD_PRIORITY_TIME_CRITICAL, // 15
|
|
{29} THREAD_PRIORITY_TIME_CRITICAL, // 15
|
|
{30} THREAD_PRIORITY_TIME_CRITICAL // 15
|
|
);
|
|
|
|
//ThreadGetPriority = -15 and 15. :0..30
|
|
//scePthreadGetprio = 767 and 256 :0..511
|
|
function ps4_scePthreadGetprio(_pthread:pthread;prio:PInteger):Integer; SysV_ABI_CDecl;
|
|
Var
|
|
r:Integer;
|
|
begin
|
|
if (_pthread=nil) or (prio=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
_sig_lock;
|
|
r:=System.ThreadGetPriority(_pthread^.handle);
|
|
_sig_unlock;
|
|
prio^:=767-(((r+15)*511) div 30);
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadSetprio(_pthread:pthread;prio:Integer):Integer; SysV_ABI_CDecl;
|
|
Var
|
|
r:Integer;
|
|
begin
|
|
if (_pthread=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
|
|
if (prio>767) then prio:=767;
|
|
if (prio<256) then prio:=256;
|
|
|
|
//Writeln('scePthreadSetprio:',prio);
|
|
r:=(((767-prio)*30) div 511);
|
|
r:=PRIORITY_TABLE[r];
|
|
|
|
Result:=0;
|
|
_sig_lock;
|
|
if not System.ThreadSetPriority(_pthread^.handle,r) then
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_ESRCH;
|
|
end;
|
|
_sig_unlock;
|
|
end;
|
|
|
|
//ThreadGetPriority = -15 and 15. :0..30
|
|
function ps4_scePthreadGetschedparam(_pthread:pthread;policy:PInteger;param:PSceKernelSchedParam):Integer; SysV_ABI_CDecl;
|
|
Var
|
|
r:Integer;
|
|
begin
|
|
if (_pthread=nil) or (policy=nil) or (param=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
|
|
policy^:=SCE_KERNEL_SCHED_RR;
|
|
|
|
_sig_lock;
|
|
r:=System.ThreadGetPriority(_pthread^.handle);
|
|
_sig_unlock;
|
|
param^.sched_priority:=(r+15);
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_scePthreadSetschedparam(_pthread:pthread;policy:Integer;param:PSceKernelSchedParam):Integer; SysV_ABI_CDecl;
|
|
Var
|
|
r:Integer;
|
|
begin
|
|
if (_pthread=nil) or (param=nil) then Exit(SCE_KERNEL_ERROR_EINVAL);
|
|
|
|
r:=param^.sched_priority;
|
|
|
|
if (r>30) then r:=30;
|
|
if (r<0) then r:=0;
|
|
|
|
r:=PRIORITY_TABLE[r];
|
|
|
|
Result:=0;
|
|
_sig_lock;
|
|
if not System.ThreadSetPriority(_pthread^.handle,r) then
|
|
begin
|
|
Result:=SCE_KERNEL_ERROR_ESRCH;
|
|
end;
|
|
_sig_unlock;
|
|
end;
|
|
|
|
|
|
function ps4_sched_get_priority_max(policy:Integer):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=30;
|
|
end;
|
|
|
|
function ps4_sched_get_priority_min(policy:Integer):Integer; SysV_ABI_CDecl;
|
|
begin
|
|
Result:=0;
|
|
end;
|
|
|
|
procedure ps4_scePthreadYield; SysV_ABI_CDecl;
|
|
begin
|
|
SwYieldExecution;
|
|
end;
|
|
|
|
function ps4_pthread_yield:Integer; SysV_ABI_CDecl;
|
|
begin
|
|
SwYieldExecution;
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_sched_yield:Integer; SysV_ABI_CDecl;
|
|
begin
|
|
SwYieldExecution;
|
|
Result:=0;
|
|
end;
|
|
|
|
procedure ps4_pthread_cleanup_push(routine:t_cb_proc;arg:Pointer); SysV_ABI_CDecl;
|
|
var
|
|
curthread:pthread;
|
|
newbuf:p_pthread_cleanup;
|
|
begin
|
|
Writeln('pthread_cleanup_push');
|
|
|
|
curthread:=_get_curthread;
|
|
if (curthread=nil) then Exit;
|
|
|
|
newbuf:=AllocMem(SizeOf(pthread_cleanup));
|
|
if (newbuf=nil) then Exit;
|
|
|
|
newbuf^.routine :=routine;
|
|
newbuf^.routine_arg:=arg;
|
|
newbuf^.onheap :=1;
|
|
newbuf^.prev :=curthread^.cleanup;
|
|
|
|
curthread^.cleanup:=newbuf;
|
|
end;
|
|
|
|
procedure ps4_pthread_cleanup_pop(execute:Integer); SysV_ABI_CDecl;
|
|
begin
|
|
ps4___pthread_cleanup_pop_imp(execute);
|
|
end;
|
|
|
|
procedure ps4___pthread_cleanup_push_imp(routine:t_cb_proc;
|
|
arg:Pointer;
|
|
info:p_pthread_cleanup); SysV_ABI_CDecl;
|
|
var
|
|
curthread:pthread;
|
|
begin
|
|
//Writeln('__pthread_cleanup_push_imp');
|
|
|
|
curthread:=_get_curthread;
|
|
if (curthread=nil) then Exit;
|
|
|
|
info^.routine :=routine;
|
|
info^.routine_arg:=arg;
|
|
info^.onheap :=0;
|
|
info^.prev :=curthread^.cleanup;
|
|
|
|
curthread^.cleanup:=info;
|
|
end;
|
|
|
|
procedure ps4___pthread_cleanup_pop_imp(execute:Integer); SysV_ABI_CDecl;
|
|
var
|
|
curthread:pthread;
|
|
old:p_pthread_cleanup;
|
|
begin
|
|
//Writeln('__pthread_cleanup_pop_imp');
|
|
|
|
curthread:=_get_curthread;
|
|
if (curthread=nil) then Exit;
|
|
|
|
old:=curthread^.cleanup;
|
|
if (old<>nil) then
|
|
begin
|
|
curthread^.cleanup:=old^.prev;
|
|
if (execute<>0) then
|
|
begin
|
|
old^.routine(old^.routine_arg);
|
|
end;
|
|
if (old^.onheap<>0) then
|
|
begin
|
|
FreeMem(old);
|
|
end;
|
|
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;
|
|
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));
|
|
|
|
pKey^:=(node-p_pthread_key_node(@_pthread_key_nodes));
|
|
Result:=0;
|
|
end;
|
|
|
|
function ps4_pthread_key_delete(Key:pthread_key_t):Integer; SysV_ABI_CDecl;
|
|
var
|
|
node:p_pthread_key_node;
|
|
begin
|
|
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
|
|
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
|
|
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.
|
|
|
|
|