From 05a0501214f6c8c157a2897871eee9bd3c98643b Mon Sep 17 00:00:00 2001 From: Pavel <68122101+red-prig@users.noreply.github.com> Date: Wed, 7 Jun 2023 16:12:20 +0300 Subject: [PATCH] + --- sys/kern/kern_thread.pas | 211 ++++++++++++++++++------------------- sys/kern/machdep.pas | 219 +++++++++++++++++++++++++++++++++++++-- sys/kern/md_thread.pas | 171 +++++++++++++++++++++++++++--- sys/kern/trap.pas | 1 + sys/kern/vm_machdep.pas | 1 - sys/test/project1.lpr | 13 ++- sys/thr.pas | 16 ++- sys/ucontext.pas | 2 + 8 files changed, 497 insertions(+), 137 deletions(-) diff --git a/sys/kern/kern_thread.pas b/sys/kern/kern_thread.pas index 9fc0ce07..862ed8c1 100644 --- a/sys/kern/kern_thread.pas +++ b/sys/kern/kern_thread.pas @@ -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; diff --git a/sys/kern/machdep.pas b/sys/kern/machdep.pas index ba4ee962..23e22605 100644 --- a/sys/kern/machdep.pas +++ b/sys/kern/machdep.pas @@ -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); diff --git a/sys/kern/md_thread.pas b/sys/kern/md_thread.pas index 72d99d03..c94252f4 100644 --- a/sys/kern/md_thread.pas +++ b/sys/kern/md_thread.pas @@ -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. diff --git a/sys/kern/trap.pas b/sys/kern/trap.pas index cc868e82..486d5834 100644 --- a/sys/kern/trap.pas +++ b/sys/kern/trap.pas @@ -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 diff --git a/sys/kern/vm_machdep.pas b/sys/kern/vm_machdep.pas index e4ee90ba..2c09de1e 100644 --- a/sys/kern/vm_machdep.pas +++ b/sys/kern/vm_machdep.pas @@ -158,7 +158,6 @@ var td:p_kthread; Context:PCONTEXT; regs:p_trapframe; - save:Pointer; begin td:=curkthread; regs:=td^.td_frame; diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr index 9d1d8778..e0fcf78e 100644 --- a/sys/test/project1.lpr +++ b/sys/test/project1.lpr @@ -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; diff --git a/sys/thr.pas b/sys/thr.pas index ea1c02c5..5a32234d 100644 --- a/sys/thr.pas +++ b/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 diff --git a/sys/ucontext.pas b/sys/ucontext.pas index 51770d59..0f9bf0f8 100644 --- a/sys/ucontext.pas +++ b/sys/ucontext.pas @@ -191,6 +191,8 @@ const UCF_SWAPPED=$00000001; // Used by swapcontext(3) + GET_MC_CLEAR_RET=1; + implementation end.