mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
9878b10455
commit
05a0501214
|
@ -29,6 +29,7 @@ function thread_alloc:p_kthread;
|
|||
procedure thread_free(td:p_kthread);
|
||||
|
||||
function sys_thr_new(_param:p_thr_param;_size:Integer):Integer;
|
||||
function sys_thr_create(ctx:p_ucontext_t;id:PDWORD;flags:Integer):Integer;
|
||||
function sys_thr_self(id:PDWORD):Integer;
|
||||
procedure sys_thr_exit(state:PQWORD);
|
||||
function sys_thr_kill(id,sig:Integer):Integer;
|
||||
|
@ -84,6 +85,7 @@ uses
|
|||
errno,
|
||||
systm,
|
||||
vm_machdep,
|
||||
machdep,
|
||||
md_proc,
|
||||
md_thread,
|
||||
kern_rwlock,
|
||||
|
@ -308,61 +310,10 @@ begin
|
|||
HAMT_get_value32(i,@Result);
|
||||
end;
|
||||
|
||||
function BaseQueryInfo(td:p_kthread):Integer;
|
||||
var
|
||||
TBI:THREAD_BASIC_INFORMATION;
|
||||
procedure before_start(td:p_kthread);
|
||||
begin
|
||||
TBI:=Default(THREAD_BASIC_INFORMATION);
|
||||
|
||||
Result:=NtQueryInformationThread(
|
||||
td^.td_handle,
|
||||
ThreadBasicInformation,
|
||||
@TBI,
|
||||
SizeOf(THREAD_BASIC_INFORMATION),
|
||||
nil);
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
td^.td_teb :=TBI.TebBaseAddress;
|
||||
td^.td_cpuset:=TBI.AffinityMask;
|
||||
|
||||
td^.td_teb^.thread:=td; //self
|
||||
end;
|
||||
|
||||
procedure BaseInitializeStack(InitialTeb :PINITIAL_TEB;
|
||||
StackAddress:Pointer;
|
||||
StackSize :Ptruint); inline;
|
||||
begin
|
||||
InitialTeb^.PreviousStackBase :=nil;
|
||||
InitialTeb^.PreviousStackLimit:=nil;
|
||||
InitialTeb^.StackBase :=StackAddress+StackSize; //start addr
|
||||
InitialTeb^.StackLimit :=StackAddress; //lo addr
|
||||
InitialTeb^.AllocatedStackBase:=StackAddress; //lo addr
|
||||
end;
|
||||
|
||||
procedure BaseInitializeContext(Context :PCONTEXT;
|
||||
Parameter :Pointer;
|
||||
StartAddress:Pointer;
|
||||
StackAddress:Pointer); inline;
|
||||
begin
|
||||
Context^:=Default(TCONTEXT);
|
||||
|
||||
Context^.Rsp:=ptruint(StackAddress);
|
||||
Context^.Rbp:=ptruint(StackAddress);
|
||||
Context^.Rdi:=ptruint(Parameter);
|
||||
Context^.Rip:=ptruint(StartAddress);
|
||||
|
||||
Context^.SegGs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegEs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegDs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegCs:=KGDT64_R3_CODE or RPL_MASK;
|
||||
Context^.SegSs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegFs:=KGDT64_R3_CMTEB or RPL_MASK;
|
||||
|
||||
Context^.EFlags:=$3000 or EFLAGS_INTERRUPT_MASK;
|
||||
|
||||
Context^.MxCsr:=INITIAL_MXCSR;
|
||||
|
||||
Context^.ContextFlags:=CONTEXT_THREAD;
|
||||
//init this
|
||||
ipi_sigreturn; //switch
|
||||
end;
|
||||
|
||||
function create_thread(td :p_kthread; //calling thread
|
||||
|
@ -377,20 +328,9 @@ function create_thread(td :p_kthread; //calling thread
|
|||
rtp :p_rtprio;
|
||||
name :PChar
|
||||
):Integer;
|
||||
label
|
||||
_term;
|
||||
var
|
||||
newtd:p_kthread;
|
||||
|
||||
_ClientId :array[0..SizeOf(TCLIENT_ID )+14] of Byte;
|
||||
_InitialTeb:array[0..SizeOf(TINITIAL_TEB)+14] of Byte;
|
||||
_Context :array[0..SizeOf(TCONTEXT )+14] of Byte;
|
||||
|
||||
ClientId :PCLIENT_ID;
|
||||
InitialTeb:PINITIAL_TEB;
|
||||
Context :PCONTEXT;
|
||||
|
||||
Stack:Pointer;
|
||||
stack:stack_t;
|
||||
|
||||
n:Integer;
|
||||
begin
|
||||
|
@ -422,39 +362,42 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
if (ctx<>nil) then Exit(EINVAL);
|
||||
if (stack_size<$1000) then
|
||||
begin
|
||||
if (ctx<>nil) then
|
||||
begin
|
||||
stack_size:=$1000;
|
||||
end else
|
||||
begin
|
||||
Exit(EINVAL);
|
||||
end;
|
||||
end;
|
||||
|
||||
if (ptruint(stack_base)<$1000) or (stack_size<$1000) then Exit(EINVAL);
|
||||
if (ptruint(stack_base)<$1000) then
|
||||
begin
|
||||
if (ctx<>nil) then
|
||||
begin
|
||||
stack_base:=Pointer(ctx^.mc_rsp-stack_size);
|
||||
|
||||
//re check
|
||||
if (ptruint(stack_base)<$1000) then
|
||||
begin
|
||||
Exit(EINVAL);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
Exit(EINVAL);
|
||||
end;
|
||||
end;
|
||||
|
||||
newtd:=thread_alloc;
|
||||
if (newtd=nil) then Exit(ENOMEM);
|
||||
|
||||
ClientId :=Align(@_ClientId ,16);
|
||||
InitialTeb:=Align(@_InitialTeb,16);
|
||||
Context :=Align(@_Context ,16);
|
||||
|
||||
ClientId^.UniqueProcess:=NtCurrentProcess;
|
||||
ClientId^.UniqueThread :=NtCurrentThread;
|
||||
|
||||
BaseInitializeStack(InitialTeb,stack_base,stack_size);
|
||||
|
||||
Stack:=InitialTeb^.StackBase;
|
||||
Stack:=Pointer((ptruint(Stack) and (not $F)){-Sizeof(Pointer)});
|
||||
|
||||
BaseInitializeContext(Context,
|
||||
arg,
|
||||
start_func,
|
||||
Stack);
|
||||
|
||||
n:=NtCreateThread(
|
||||
@newtd^.td_handle,
|
||||
THREAD_ALL_ACCESS,
|
||||
nil,
|
||||
NtCurrentProcess,
|
||||
ClientId,
|
||||
Context,
|
||||
InitialTeb,
|
||||
True);
|
||||
n:=cpu_thread_create(newtd,
|
||||
stack_base,
|
||||
stack_size,
|
||||
@before_start,
|
||||
Pointer(newtd));
|
||||
|
||||
if (n<>0) then
|
||||
begin
|
||||
|
@ -462,30 +405,47 @@ begin
|
|||
Exit(EINVAL);
|
||||
end;
|
||||
|
||||
newtd^.td_tid:=DWORD(ClientId^.UniqueThread);
|
||||
|
||||
if (BaseQueryInfo(newtd)<>0) then
|
||||
begin
|
||||
_term:
|
||||
NtTerminateThread(newtd^.td_handle,n);
|
||||
NtClose(newtd^.td_handle);
|
||||
|
||||
thread_free(newtd);
|
||||
Exit(EFAULT);
|
||||
end;
|
||||
|
||||
cpu_set_user_tls(newtd,tls_base);
|
||||
|
||||
if (child_tid<>nil) then
|
||||
begin
|
||||
n:=suword32(child_tid^,newtd^.td_tid);
|
||||
if (n<>0) then Goto _term;
|
||||
if (n<>0) then
|
||||
begin
|
||||
cpu_thread_terminate(newtd);
|
||||
thread_free(newtd);
|
||||
Exit(EFAULT);
|
||||
end;
|
||||
end;
|
||||
|
||||
if (parent_tid<>nil) then
|
||||
begin
|
||||
n:=suword32(parent_tid^,newtd^.td_tid);
|
||||
if (n<>0) then Goto _term;
|
||||
if (n<>0) then
|
||||
begin
|
||||
cpu_thread_terminate(newtd);
|
||||
thread_free(newtd);
|
||||
Exit(EFAULT);
|
||||
end;
|
||||
end;
|
||||
|
||||
if (ctx<>nil) then
|
||||
begin
|
||||
// old way to set user context
|
||||
n:=set_mcontext(newtd,ctx);
|
||||
if (n<>0) then
|
||||
begin
|
||||
cpu_thread_terminate(newtd);
|
||||
thread_free(newtd);
|
||||
Exit(n);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
// Set up our machine context.
|
||||
stack.ss_sp :=stack_base;
|
||||
stack.ss_size:=stack_size;
|
||||
// Set upcall address to user thread entry function.
|
||||
cpu_set_upcall_kse(newtd,start_func,arg,@stack);
|
||||
// Setup user TLS address and TLS pointer register.
|
||||
cpu_set_user_tls(newtd,tls_base);
|
||||
end;
|
||||
|
||||
if (td<>nil) then
|
||||
|
@ -519,8 +479,13 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
newtd^.td_state:=TDS_RUNNING;
|
||||
NtResumeThread(newtd^.td_handle,nil);
|
||||
n:=cpu_sched_add(newtd);
|
||||
if (n<>0) then
|
||||
begin
|
||||
cpu_thread_terminate(newtd);
|
||||
thread_free(newtd);
|
||||
Exit(EFAULT);
|
||||
end;
|
||||
end;
|
||||
|
||||
function kern_thr_new(td:p_kthread;param:p_thr_param):Integer;
|
||||
|
@ -574,6 +539,28 @@ begin
|
|||
Result:=kern_thr_new(curkthread,@param);
|
||||
end;
|
||||
|
||||
function sys_thr_create(ctx:p_ucontext_t;id:PDWORD;flags:Integer):Integer;
|
||||
var
|
||||
_ctx:ucontext_t;
|
||||
begin
|
||||
Result:=copyin(ctx,@_ctx,sizeof(ucontext_t));
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
//flags ignored
|
||||
Result:=create_thread(curkthread,
|
||||
@_ctx.uc_mcontext,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
0,
|
||||
nil,
|
||||
id,
|
||||
nil,
|
||||
nil,
|
||||
nil);
|
||||
|
||||
end;
|
||||
|
||||
procedure thread_exit;
|
||||
var
|
||||
td:p_kthread;
|
||||
|
|
|
@ -17,7 +17,17 @@ const
|
|||
_ufssel =(2 shl 3) or 3;
|
||||
_ugssel =(3 shl 3) or 3;
|
||||
|
||||
procedure bzero(ptr:Pointer;size:ptrint);
|
||||
Procedure bmove(src,dst:Pointer;size:ptrint);
|
||||
|
||||
function cpu_getstack(td:p_kthread):QWORD;
|
||||
procedure cpu_set_user_tls(td:p_kthread;base:Pointer);
|
||||
procedure cpu_set_syscall_retval(td:p_kthread;error:Integer);
|
||||
procedure cpu_set_upcall_kse(td:p_kthread;entry,arg:Pointer;stack:p_stack_t);
|
||||
|
||||
function get_mcontext(td:p_kthread;mcp:p_mcontext_t;flags:Integer):Integer;
|
||||
function set_mcontext(td:p_kthread;mcp:p_mcontext_t):Integer;
|
||||
|
||||
procedure sendsig(catcher:sig_t;ksi:p_ksiginfo;mask:p_sigset_t);
|
||||
function sys_sigreturn(sigcntxp:p_ucontext_t):Integer;
|
||||
|
||||
|
@ -30,6 +40,41 @@ uses
|
|||
kern_sig,
|
||||
trap;
|
||||
|
||||
//clearing memory without AVX optimizations
|
||||
procedure bzero(ptr:Pointer;size:ptrint);
|
||||
begin
|
||||
while (size>0) do
|
||||
begin
|
||||
PByte(ptr)^:=0;
|
||||
Inc(ptr);
|
||||
Dec(size);
|
||||
end;
|
||||
end;
|
||||
|
||||
//move memory without AVX optimizations
|
||||
Procedure bmove(src,dst:Pointer;size:ptrint);
|
||||
begin
|
||||
while (size>0) do
|
||||
begin
|
||||
PByte(dst)^:=PByte(src)^;
|
||||
Inc(src);
|
||||
Inc(dst);
|
||||
Dec(size);
|
||||
end;
|
||||
end;
|
||||
|
||||
function cpu_getstack(td:p_kthread):QWORD;
|
||||
begin
|
||||
Result:=td^.td_frame^.tf_rsp;
|
||||
end;
|
||||
|
||||
procedure cpu_set_user_tls(td:p_kthread;base:Pointer);
|
||||
begin
|
||||
td^.pcb_fsbase:=base;
|
||||
td^.td_teb^.tcb:=base;
|
||||
set_pcb_flags(td,PCB_FULL_IRET);
|
||||
end;
|
||||
|
||||
procedure cpu_set_syscall_retval(td:p_kthread;error:Integer);
|
||||
begin
|
||||
Case error of
|
||||
|
@ -57,6 +102,29 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure cpu_set_upcall_kse(td:p_kthread;entry,arg:Pointer;stack:p_stack_t);
|
||||
begin
|
||||
{
|
||||
* Set the trap frame to point at the beginning of the uts
|
||||
* function.
|
||||
}
|
||||
td^.td_frame^.tf_rbp:=0;
|
||||
td^.td_frame^.tf_rsp:=(ptruint(stack^.ss_sp) + stack^.ss_size) and (not $F);
|
||||
Dec(td^.td_frame^.tf_rsp,8);
|
||||
td^.td_frame^.tf_rip:=ptruint(entry);
|
||||
td^.td_frame^.tf_ds:=_udatasel;
|
||||
td^.td_frame^.tf_es:=_udatasel;
|
||||
td^.td_frame^.tf_fs:=_ufssel;
|
||||
td^.td_frame^.tf_gs:=_ugssel;
|
||||
td^.td_frame^.tf_flags:=TF_HASSEGS;
|
||||
|
||||
{
|
||||
* Pass the address of the mailbox for this kse to the uts
|
||||
* function as a parameter on the stack.
|
||||
}
|
||||
td^.td_frame^.tf_rdi:=ptruint(arg);
|
||||
end;
|
||||
|
||||
function get_fpcontext(td:p_kthread;mcp:p_mcontext_t;xstate:Pointer):Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
|
@ -65,7 +133,7 @@ begin
|
|||
mcp^.mc_fpformat:=_MC_FPFMT_XMM;
|
||||
mcp^.mc_ownedfp :=_MC_FPOWNED_FPU;
|
||||
|
||||
Move(td^.td_fpstate,xstate^,SizeOf(mcp^.mc_fpstate));
|
||||
bmove(@td^.td_fpstate,xstate,SizeOf(mcp^.mc_fpstate));
|
||||
end;
|
||||
|
||||
function set_fpcontext(td:p_kthread;mcp:p_mcontext_t;xstate:Pointer):Integer;
|
||||
|
@ -81,13 +149,146 @@ begin
|
|||
if (mcp^.mc_ownedfp=_MC_FPOWNED_FPU) or
|
||||
(mcp^.mc_ownedfp=_MC_FPOWNED_PCB) then
|
||||
begin
|
||||
Move(xstate^,td^.td_fpstate,SizeOf(mcp^.mc_fpstate));
|
||||
bmove(xstate,@td^.td_fpstate,SizeOf(mcp^.mc_fpstate));
|
||||
td^.td_frame^.tf_flags:=td^.td_frame^.tf_flags or TF_HASFPXSTATE;
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
Exit(EINVAL);
|
||||
end;
|
||||
|
||||
function get_mcontext(td:p_kthread;mcp:p_mcontext_t;flags:Integer):Integer;
|
||||
var
|
||||
tp:p_trapframe;
|
||||
begin
|
||||
tp:=td^.td_frame;
|
||||
|
||||
PROC_LOCK();
|
||||
mcp^.mc_onstack:=sigonstack(tp^.tf_rsp);
|
||||
PROC_UNLOCK();
|
||||
|
||||
mcp^.mc_r15 :=tp^.tf_r15;
|
||||
mcp^.mc_r14 :=tp^.tf_r14;
|
||||
mcp^.mc_r13 :=tp^.tf_r13;
|
||||
mcp^.mc_r12 :=tp^.tf_r12;
|
||||
mcp^.mc_r11 :=tp^.tf_r11;
|
||||
mcp^.mc_r10 :=tp^.tf_r10;
|
||||
mcp^.mc_r9 :=tp^.tf_r9;
|
||||
mcp^.mc_r8 :=tp^.tf_r8;
|
||||
mcp^.mc_rdi :=tp^.tf_rdi;
|
||||
mcp^.mc_rsi :=tp^.tf_rsi;
|
||||
mcp^.mc_rbp :=tp^.tf_rbp;
|
||||
mcp^.mc_rbx :=tp^.tf_rbx;
|
||||
mcp^.mc_rcx :=tp^.tf_rcx;
|
||||
mcp^.mc_rflags:=tp^.tf_rflags;
|
||||
|
||||
if ((flags and GET_MC_CLEAR_RET)<>0) then
|
||||
begin
|
||||
mcp^.mc_rax:=0;
|
||||
mcp^.mc_rdx:=0;
|
||||
mcp^.mc_rflags:=tp^.tf_rflags and (not PSL_C);
|
||||
end else
|
||||
begin
|
||||
mcp^.mc_rax:=tp^.tf_rax;
|
||||
mcp^.mc_rdx:=tp^.tf_rdx;
|
||||
end;
|
||||
|
||||
mcp^.mc_rip :=tp^.tf_rip;
|
||||
mcp^.mc_cs :=tp^.tf_cs;
|
||||
mcp^.mc_rsp :=tp^.tf_rsp;
|
||||
mcp^.mc_ss :=tp^.tf_ss;
|
||||
mcp^.mc_ds :=tp^.tf_ds;
|
||||
mcp^.mc_es :=tp^.tf_es;
|
||||
mcp^.mc_fs :=tp^.tf_fs;
|
||||
mcp^.mc_gs :=tp^.tf_gs;
|
||||
mcp^.mc_flags:=tp^.tf_flags;
|
||||
mcp^.mc_len :=sizeof(mcontext_t);
|
||||
|
||||
//xmm,ymm
|
||||
if ((tp^.tf_flags and TF_HASFPXSTATE)<>0) then
|
||||
begin
|
||||
get_fpcontext(td,mcp,@mcp^.mc_fpstate);
|
||||
end else
|
||||
begin
|
||||
//get md
|
||||
end;
|
||||
//xmm,ymm
|
||||
|
||||
mcp^.mc_fpformat:=_MC_FPFMT_XMM;
|
||||
|
||||
mcp^.mc_fsbase:=ptruint(td^.pcb_fsbase);
|
||||
mcp^.mc_gsbase:=ptruint(td^.pcb_gsbase);
|
||||
|
||||
bzero(@mcp^.mc_spare,sizeof(mcp^.mc_spare));
|
||||
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
function set_mcontext(td:p_kthread;mcp:p_mcontext_t):Integer;
|
||||
var
|
||||
tp:p_trapframe;
|
||||
rflags:QWORD;
|
||||
begin
|
||||
tp:=td^.td_frame;
|
||||
|
||||
if (mcp^.mc_len<>sizeof(mcontext_t)) or
|
||||
((mcp^.mc_flags and (not _MC_FLAG_MASK))<>0) then
|
||||
begin
|
||||
Exit(EINVAL);
|
||||
end;
|
||||
|
||||
tp:=td^.td_frame;
|
||||
|
||||
//xmm,ymm
|
||||
if ((mcp^.mc_rflags and _MC_HASFPXSTATE)<>0) then
|
||||
begin
|
||||
Result:=set_fpcontext(td,mcp,@mcp^.mc_fpstate);
|
||||
if (Result<>0) then Exit;
|
||||
end;
|
||||
//xmm,ymm
|
||||
|
||||
rflags:=(mcp^.mc_rflags and PSL_USERCHANGE) or
|
||||
(tp^.tf_rflags and (not PSL_USERCHANGE));
|
||||
|
||||
tp^.tf_r15 :=mcp^.mc_r15;
|
||||
tp^.tf_r14 :=mcp^.mc_r14;
|
||||
tp^.tf_r13 :=mcp^.mc_r13;
|
||||
tp^.tf_r12 :=mcp^.mc_r12;
|
||||
tp^.tf_r11 :=mcp^.mc_r11;
|
||||
tp^.tf_r10 :=mcp^.mc_r10;
|
||||
tp^.tf_r9 :=mcp^.mc_r9;
|
||||
tp^.tf_r8 :=mcp^.mc_r8;
|
||||
tp^.tf_rdi :=mcp^.mc_rdi;
|
||||
tp^.tf_rsi :=mcp^.mc_rsi;
|
||||
tp^.tf_rbp :=mcp^.mc_rbp;
|
||||
tp^.tf_rbx :=mcp^.mc_rbx;
|
||||
tp^.tf_rdx :=mcp^.mc_rdx;
|
||||
tp^.tf_rcx :=mcp^.mc_rcx;
|
||||
tp^.tf_rax :=mcp^.mc_rax;
|
||||
tp^.tf_rip :=mcp^.mc_rip;
|
||||
tp^.tf_rflags:=rflags;
|
||||
tp^.tf_rsp :=mcp^.mc_rsp;
|
||||
tp^.tf_ss :=mcp^.mc_ss;
|
||||
tp^.tf_flags :=mcp^.mc_flags;
|
||||
|
||||
if ((tp^.tf_flags and TF_HASSEGS)<>0) then
|
||||
begin
|
||||
tp^.tf_ds:=mcp^.mc_ds;
|
||||
tp^.tf_es:=mcp^.mc_es;
|
||||
tp^.tf_fs:=mcp^.mc_fs;
|
||||
tp^.tf_gs:=mcp^.mc_gs;
|
||||
end;
|
||||
|
||||
if ((mcp^.mc_flags and _MC_HASBASES)<>0) then
|
||||
begin
|
||||
td^.pcb_fsbase:=Pointer(mcp^.mc_fsbase);
|
||||
td^.pcb_gsbase:=Pointer(mcp^.mc_gsbase);
|
||||
end;
|
||||
|
||||
set_pcb_flags(td,PCB_FULL_IRET);
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
procedure sendsig(catcher:sig_t;ksi:p_ksiginfo;mask:p_sigset_t);
|
||||
var
|
||||
td:p_kthread;
|
||||
|
@ -136,7 +337,7 @@ begin
|
|||
regs^.tf_flags:=regs^.tf_flags or TF_HASSEGS;
|
||||
//set segs
|
||||
|
||||
Move(regs^,sf.sf_uc.uc_mcontext.mc_rdi,SizeOf(trapframe));
|
||||
bmove(regs,@sf.sf_uc.uc_mcontext.mc_rdi,SizeOf(trapframe));
|
||||
|
||||
sf.sf_uc.uc_mcontext.mc_len:=sizeof(mcontext_t);
|
||||
|
||||
|
@ -145,6 +346,7 @@ begin
|
|||
begin
|
||||
get_fpcontext(td,@sf.sf_uc.uc_mcontext,@sf.sf_uc.uc_mcontext.mc_fpstate);
|
||||
|
||||
//reset fpcontext usage
|
||||
regs^.tf_flags:=regs^.tf_flags and (not TF_HASFPXSTATE);
|
||||
end;
|
||||
//xmm,ymm
|
||||
|
@ -229,15 +431,16 @@ begin
|
|||
begin
|
||||
Result:=set_fpcontext(td,@ucp^.uc_mcontext,@ucp^.uc_mcontext.mc_fpstate);
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
regs^.tf_flags:=regs^.tf_flags or TF_HASFPXSTATE;
|
||||
end;
|
||||
//xmm,ymm
|
||||
|
||||
Move(ucp^.uc_mcontext.mc_rdi,regs^,sizeof(trapframe));
|
||||
bmove(@ucp^.uc_mcontext.mc_rdi,regs,sizeof(trapframe));
|
||||
|
||||
//pcb^.pcb_fsbase := ucp^.uc_mcontext.mc_fsbase;
|
||||
//pcb^.pcb_gsbase := ucp^.uc_mcontext.mc_gsbase;
|
||||
if ((ucp^.uc_mcontext.mc_flags and _MC_HASBASES)<>0) then
|
||||
begin
|
||||
td^.pcb_fsbase:=Pointer(ucp^.uc_mcontext.mc_fsbase);
|
||||
td^.pcb_gsbase:=Pointer(ucp^.uc_mcontext.mc_gsbase);
|
||||
end;
|
||||
|
||||
kern_sigprocmask(td,SIG_SETMASK,@ucp^.uc_sigmask,nil,0);
|
||||
|
||||
|
|
|
@ -16,11 +16,18 @@ Const
|
|||
|
||||
function cpu_thread_alloc():p_kthread;
|
||||
function cpu_thread_free(td:p_kthread):Integer;
|
||||
|
||||
function cpu_thread_create(td:p_kthread;
|
||||
stack_base:Pointer;
|
||||
stack_size:QWORD;
|
||||
start_func:Pointer;
|
||||
arg :Pointer):Integer;
|
||||
procedure cpu_thread_terminate(td:p_kthread);
|
||||
function cpu_sched_add(td:p_kthread):Integer;
|
||||
function cpu_thread_finished(td:p_kthread):Boolean;
|
||||
|
||||
function cpuset_setaffinity(td:p_kthread;new:Ptruint):Integer;
|
||||
procedure cpu_set_user_tls(td:p_kthread;base:Pointer);
|
||||
function cpu_set_priority(td:p_kthread;prio:Integer):Integer;
|
||||
function cpu_getstack(td:p_kthread):QWORD; inline;
|
||||
|
||||
implementation
|
||||
|
||||
|
@ -95,6 +102,8 @@ var
|
|||
data:Pointer;
|
||||
size:ULONG_PTR;
|
||||
begin
|
||||
if (td=nil) then Exit(0);
|
||||
|
||||
data:=td;
|
||||
size:=0;
|
||||
|
||||
|
@ -106,6 +115,146 @@ begin
|
|||
);
|
||||
end;
|
||||
|
||||
function BaseQueryInfo(td:p_kthread):Integer;
|
||||
var
|
||||
TBI:THREAD_BASIC_INFORMATION;
|
||||
begin
|
||||
TBI:=Default(THREAD_BASIC_INFORMATION);
|
||||
|
||||
Result:=NtQueryInformationThread(
|
||||
td^.td_handle,
|
||||
ThreadBasicInformation,
|
||||
@TBI,
|
||||
SizeOf(THREAD_BASIC_INFORMATION),
|
||||
nil);
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
td^.td_teb :=TBI.TebBaseAddress;
|
||||
td^.td_cpuset:=TBI.AffinityMask;
|
||||
|
||||
td^.td_teb^.thread:=td; //self
|
||||
end;
|
||||
|
||||
procedure BaseInitializeStack(InitialTeb :PINITIAL_TEB;
|
||||
StackAddress:Pointer;
|
||||
StackSize :Ptruint); inline;
|
||||
begin
|
||||
InitialTeb^.PreviousStackBase :=nil;
|
||||
InitialTeb^.PreviousStackLimit:=nil;
|
||||
InitialTeb^.StackBase :=StackAddress+StackSize; //start addr
|
||||
InitialTeb^.StackLimit :=StackAddress; //lo addr
|
||||
InitialTeb^.AllocatedStackBase:=StackAddress; //lo addr
|
||||
end;
|
||||
|
||||
procedure BaseInitializeContext(Context :PCONTEXT;
|
||||
Parameter :Pointer;
|
||||
StartAddress:Pointer;
|
||||
StackAddress:Pointer); inline;
|
||||
begin
|
||||
Context^:=Default(TCONTEXT);
|
||||
|
||||
Context^.Rsp:=ptruint(StackAddress);
|
||||
Context^.Rbp:=ptruint(StackAddress);
|
||||
Context^.Rdi:=ptruint(Parameter);
|
||||
Context^.Rip:=ptruint(StartAddress);
|
||||
|
||||
Context^.SegGs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegEs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegDs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegCs:=KGDT64_R3_CODE or RPL_MASK;
|
||||
Context^.SegSs:=KGDT64_R3_DATA or RPL_MASK;
|
||||
Context^.SegFs:=KGDT64_R3_CMTEB or RPL_MASK;
|
||||
|
||||
Context^.EFlags:=$3000 or EFLAGS_INTERRUPT_MASK;
|
||||
|
||||
Context^.MxCsr:=INITIAL_MXCSR;
|
||||
|
||||
Context^.ContextFlags:=CONTEXT_THREAD;
|
||||
end;
|
||||
|
||||
function cpu_thread_create(td:p_kthread;
|
||||
stack_base:Pointer;
|
||||
stack_size:QWORD;
|
||||
start_func:Pointer;
|
||||
arg :Pointer):Integer;
|
||||
var
|
||||
_ClientId :array[0..SizeOf(TCLIENT_ID )+14] of Byte;
|
||||
_InitialTeb:array[0..SizeOf(TINITIAL_TEB)+14] of Byte;
|
||||
_Context :array[0..SizeOf(TCONTEXT )+14] of Byte;
|
||||
|
||||
ClientId :PCLIENT_ID;
|
||||
InitialTeb:PINITIAL_TEB;
|
||||
Context :PCONTEXT;
|
||||
|
||||
Stack:Pointer;
|
||||
begin
|
||||
if (td=nil) then Exit(-1);
|
||||
|
||||
ClientId :=Align(@_ClientId ,16);
|
||||
InitialTeb:=Align(@_InitialTeb,16);
|
||||
Context :=Align(@_Context ,16);
|
||||
|
||||
ClientId^.UniqueProcess:=NtCurrentProcess;
|
||||
ClientId^.UniqueThread :=NtCurrentThread;
|
||||
|
||||
BaseInitializeStack(InitialTeb,stack_base,stack_size);
|
||||
|
||||
//use kernel stack to init
|
||||
Stack:=td^.td_kstack;
|
||||
Stack:=Pointer((ptruint(Stack) and (not $F)));
|
||||
|
||||
BaseInitializeContext(Context,
|
||||
arg,
|
||||
start_func,
|
||||
Stack);
|
||||
|
||||
Result:=NtCreateThread(
|
||||
@td^.td_handle,
|
||||
THREAD_ALL_ACCESS,
|
||||
nil,
|
||||
NtCurrentProcess,
|
||||
ClientId,
|
||||
Context,
|
||||
InitialTeb,
|
||||
True);
|
||||
|
||||
if (Result=0) then
|
||||
begin
|
||||
td^.td_tid:=DWORD(ClientId^.UniqueThread);
|
||||
|
||||
Result:=BaseQueryInfo(td);
|
||||
|
||||
if (Result<>0) then
|
||||
begin
|
||||
cpu_thread_terminate(td);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure cpu_thread_terminate(td:p_kthread);
|
||||
begin
|
||||
if (td=nil) then Exit;
|
||||
if (td^.td_handle=0) or (td^.td_handle=THandle(-1)) then Exit;
|
||||
NtTerminateThread(td^.td_handle,0);
|
||||
NtClose(td^.td_handle);
|
||||
td^.td_handle:=0;
|
||||
td^.td_tid:=0;
|
||||
end;
|
||||
|
||||
function cpu_sched_add(td:p_kthread):Integer;
|
||||
begin
|
||||
if (td=nil) then Exit(-1);
|
||||
if (td^.td_handle=0) or (td^.td_handle=THandle(-1)) then Exit(-1);
|
||||
|
||||
td^.td_state:=TDS_RUNNING;
|
||||
Result:=NtResumeThread(td^.td_handle,nil);
|
||||
|
||||
if (Result<>0) then
|
||||
begin
|
||||
td^.td_state:=TDS_INACTIVE;
|
||||
end;
|
||||
end;
|
||||
|
||||
function cpu_thread_finished(td:p_kthread):Boolean;
|
||||
var
|
||||
R:DWORD;
|
||||
|
@ -124,23 +273,24 @@ begin
|
|||
begin
|
||||
NtClose(td^.td_handle);
|
||||
td^.td_handle:=0;
|
||||
td^.td_tid:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function cpuset_setaffinity(td:p_kthread;new:Ptruint):Integer;
|
||||
begin
|
||||
if (td=nil) then Exit;
|
||||
if (td^.td_handle=0) or (td^.td_handle=THandle(-1)) then Exit(-1);
|
||||
|
||||
td^.td_cpuset:=new;
|
||||
Result:=NtSetInformationThread(td^.td_handle,ThreadAffinityMask,@new,SizeOf(Ptruint));
|
||||
end;
|
||||
|
||||
procedure cpu_set_user_tls(td:p_kthread;base:Pointer); inline;
|
||||
begin
|
||||
td^.pcb_fsbase:=base;
|
||||
td^.td_teb^.tcb:=base;
|
||||
end;
|
||||
|
||||
function cpu_set_priority(td:p_kthread;prio:Integer):Integer;
|
||||
begin
|
||||
if (td=nil) then Exit;
|
||||
if (td^.td_handle=0) or (td^.td_handle=THandle(-1)) then Exit(-1);
|
||||
|
||||
td^.td_priority:=prio;
|
||||
|
||||
Case prio of
|
||||
|
@ -157,11 +307,6 @@ begin
|
|||
Result:=NtSetInformationThread(td^.td_handle,ThreadBasePriority,@prio,SizeOf(Integer));
|
||||
end;
|
||||
|
||||
function cpu_getstack(td:p_kthread):QWORD; inline;
|
||||
begin
|
||||
Result:=td^.td_frame^.tf_rsp;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
|
|
@ -242,6 +242,7 @@ begin
|
|||
td^.td_retval[1]:=td_frame^.tf_rdx;
|
||||
|
||||
error:=0;
|
||||
scall:=nil;
|
||||
|
||||
if (td_frame^.tf_rax<=High(sysent_table)) then
|
||||
begin
|
||||
|
|
|
@ -158,7 +158,6 @@ var
|
|||
td:p_kthread;
|
||||
Context:PCONTEXT;
|
||||
regs:p_trapframe;
|
||||
save:Pointer;
|
||||
begin
|
||||
td:=curkthread;
|
||||
regs:=td^.td_frame;
|
||||
|
|
|
@ -1095,6 +1095,7 @@ var
|
|||
_tv:timeval;
|
||||
|
||||
_thr_param:thr_param;
|
||||
_uctx:ucontext_t;
|
||||
|
||||
ru:t_rusage;
|
||||
|
||||
|
@ -1152,7 +1153,7 @@ begin
|
|||
_thr_param.rtp :=@prio;
|
||||
_thr_param.name :='test';
|
||||
|
||||
thr_new(@_thr_param,SizeOf(_thr_param));
|
||||
//thr_new(@_thr_param,SizeOf(_thr_param));
|
||||
|
||||
_thr_param.start_func:=@test_thread;
|
||||
_thr_param.arg :=nil;
|
||||
|
@ -1164,7 +1165,15 @@ begin
|
|||
_thr_param.rtp :=@prio;
|
||||
_thr_param.name :='test2';
|
||||
|
||||
thr_new(@_thr_param,SizeOf(_thr_param));
|
||||
//thr_new(@_thr_param,SizeOf(_thr_param));
|
||||
|
||||
_uctx:=Default(ucontext_t);
|
||||
_uctx.uc_mcontext.mc_len:=sizeof(mcontext_t);
|
||||
|
||||
_uctx.uc_mcontext.mc_rsp:=qword(_thr_param.stack_base)+_thr_param.stack_size-8;
|
||||
_uctx.uc_mcontext.mc_rip:=qword(@test_thread);
|
||||
|
||||
thr_create(@_uctx,nil,0);
|
||||
|
||||
//readln;
|
||||
|
||||
|
|
16
sys/thr.pas
16
sys/thr.pas
|
@ -7,6 +7,7 @@ interface
|
|||
|
||||
uses
|
||||
time,
|
||||
ucontext,
|
||||
kern_thr,
|
||||
kern_thread;
|
||||
|
||||
|
@ -17,6 +18,7 @@ type
|
|||
function getpid:Integer;
|
||||
|
||||
function thr_new(param:p_thr_param;param_size:Integer):Integer;
|
||||
function thr_create(ctx:p_ucontext_t;id:PDWORD;flags:Integer):Integer;
|
||||
function thr_self(id:PQWORD):Integer;
|
||||
procedure thr_exit(state:PQWORD);
|
||||
function thr_kill(id:QWORD;sig:Integer):Integer;
|
||||
|
@ -24,7 +26,6 @@ function thr_suspend(timeout:ptimespec):Integer;
|
|||
function thr_wake(id:QWORD):Integer;
|
||||
function thr_set_name(id:QWORD;name:PChar):Integer;
|
||||
|
||||
//int thr_create(ucontext_t *ctx, long *id, int flags);
|
||||
//int thr_kill2(pid_t pid, long id, int sig);
|
||||
|
||||
function amd64_set_fsbase(base:Pointer):Integer;
|
||||
|
@ -54,6 +55,19 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function thr_create(ctx:p_ucontext_t;id:PDWORD;flags:Integer):Integer;
|
||||
begin
|
||||
if (curkthread=nil) then
|
||||
begin
|
||||
Result:=sys_thr_create(ctx,id,flags);
|
||||
end else
|
||||
asm
|
||||
movq sys_thr_new,%rax
|
||||
call fast_syscall
|
||||
jmp cerror
|
||||
end;
|
||||
end;
|
||||
|
||||
function thr_self(id:PQWORD):Integer; assembler; nostackframe;
|
||||
asm
|
||||
movq sys_thr_self,%rax
|
||||
|
|
|
@ -191,6 +191,8 @@ const
|
|||
|
||||
UCF_SWAPPED=$00000001; // Used by swapcontext(3)
|
||||
|
||||
GET_MC_CLEAR_RET=1;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
|
|
Loading…
Reference in New Issue