diff --git a/sys/kern/kern_context.pas b/sys/kern/kern_context.pas index 650b4404..008e7b02 100644 --- a/sys/kern/kern_context.pas +++ b/sys/kern/kern_context.pas @@ -12,14 +12,21 @@ function sys_getcontext(ucp:p_ucontext_t):Integer; function sys_setcontext(ucp:p_ucontext_t):Integer; function sys_swapcontext(oucp,ucp:p_ucontext_t):Integer; +function sys_thr_get_ucontext(tid:Integer;ucp:p_ucontext_t):Integer; +function sys_thr_suspend_ucontext(tid:Integer):Integer; +function sys_thr_resume_ucontext(tid:Integer):Integer; + implementation uses errno, systm, kern_thr, + kern_thread, signal, kern_sig, + kern_synch, + sched_ule, machdep; { @@ -108,6 +115,202 @@ begin if (Result=0) then Exit(EJUSTRETURN); end; +function sys_thr_get_ucontext(tid:Integer;ucp:p_ucontext_t):Integer; +var + tdf:p_kthread; + uc:ucontext_t; +begin + tdf:=tdfind(tid); + + repeat + if (tdf=nil) then Exit(ESRCH); + + PROC_LOCK; + thread_lock(tdf); + + if ((tdf^.td_inhibitors and TDI_SUSP_CTX)=0) and + ((tdf^.td_flags and TDF_SUSP_CTX)=0) then + begin + thread_unlock(tdf); + thread_dec_ref(tdf); + PROC_UNLOCK; + Exit(EINVAL); + end; + + case tdf^.td_state of + TDS_INACTIVE :; //try again? + TDS_INHIBITED: + begin + bzero(@uc,SizeOf(ucontext_t)); + + get_mcontext2(tdf, @uc.uc_mcontext, 0); + + thread_unlock(tdf); + thread_dec_ref(tdf); + PROC_UNLOCK; + + Result:=copyout(@uc,ucp,UC_COPY_SIZE); + Exit; + end + else + begin + Writeln('get_ucontext: an illegal state ',tdf^.td_state); + thread_unlock(tdf); + thread_dec_ref(tdf); + PROC_UNLOCK; + Exit(ESRCH); + end; + end; + + thread_unlock(tdf); + thread_dec_ref(tdf); + PROC_UNLOCK; + + pause('ususp',1); + tdf:=tdfind(tid); + until false; +end; + +function sys_thr_suspend_ucontext(tid:Integer):Integer; +label + _exit; +var + td,tdf,tdf2:p_kthread; +begin + Result:=0; + + td:=curkthread; + if (td=nil) then Exit(-1); + + if (tid=td^.td_tid) then Exit(EDEADLK); + + tdf:=tdfind(tid); + + if (tdf=nil) then Exit(ESRCH); + + PROC_LOCK; + thread_lock(tdf); + + if ((tdf^.td_inhibitors and TDI_SUSP_CTX)=0) and + ((tdf^.td_flags and TDF_SUSP_CTX)=0) then + begin + if ((tdf^.td_inhibitors and TDI_SLEEPING)=0) or + ((tdf^.td_flags and TDF_SINTR)=0) then + begin + tdf^.td_flags:=tdf^.td_flags or (TDF_ASTPENDING or TDF_SUSP_CTX); + + if TD_IS_RUNNING(td) then + begin + forward_signal(td); + end; + + repeat + if (tdf^.td_state<>TDS_RUNQ) and + ((tdf^.td_inhibitors and TDI_SLEEPING)=0) then + begin + Result:=0; + goto _exit; + end; + + thread_unlock(tdf); + thread_dec_ref(tdf); + PROC_UNLOCK; + + pause('ususp',1); + + tdf2:=tdfind(tid); + + if (tdf2=nil) then Exit(ESRCH); + + if (tdf<>tdf2) then + begin + thread_dec_ref(tdf2); + Exit(ESRCH); + end; + + PROC_LOCK; + thread_lock(tdf); + + until not (((tdf^.td_inhibitors and TDI_SLEEPING)=0) or + ((tdf^.td_flags and TDF_SINTR)=0)); + + tdf^.td_flags:=tdf^.td_flags and (not (TDF_ASTPENDING or TDF_SUSP_CTX)); + tdf^.td_state:=TDS_INHIBITED; + tdf^.td_inhibitors:=tdf^.td_inhibitors or TDI_SUSP_CTX; + + Result:=0; + end else + begin + tdf^.td_state:=TDS_INHIBITED; + tdf^.td_inhibitors:=tdf^.td_inhibitors or TDI_SUSP_CTX; + + Result:=0; + end; + end else + begin + Result:=EINVAL; + end; + +_exit: + thread_unlock(tdf); + thread_dec_ref(tdf); + PROC_UNLOCK; +end; + +function sys_thr_resume_ucontext(tid:Integer):Integer; +label + _exit; +var + td,tdf:p_kthread; +begin + Result:=0; + + td:=curkthread; + if (td=nil) then Exit(-1); + + if (tid=td^.td_tid) then Exit(EINVAL); + + tdf:=tdfind(tid); + + if (tdf=nil) then Exit(ESRCH); + + PROC_LOCK; + thread_lock(tdf); + + if ((tdf^.td_inhibitors and TDI_SUSP_CTX)=0) then + begin + if ((tdf^.td_flags and TDF_SUSP_CTX)=0) then + begin + Result:=EINVAL; + goto _exit; + end; + tdf^.td_flags:=tdf^.td_flags and (not TDF_SUSP_CTX); + end else + begin + if ((tdf^.td_flags and TDF_SUSP_CTX)<>0) then + begin + tdf^.td_flags:=tdf^.td_flags and (not TDF_SUSP_CTX); + Result:=0; + goto _exit; + end; + + tdf^.td_inhibitors:=tdf^.td_inhibitors and (not TDI_SUSP_CTX); + + if (tdf^.td_inhibitors=0) then + begin + tdf^.td_state:=TDS_CAN_RUN; + end; + + setrunnable(tdf); + end; + + Result:=0; + +_exit: + thread_unlock(tdf); + thread_dec_ref(tdf); + PROC_UNLOCK; +end; end. diff --git a/sys/kern/kern_sig.pas b/sys/kern/kern_sig.pas index da7640de..5a1e0582 100644 --- a/sys/kern/kern_sig.pas +++ b/sys/kern/kern_sig.pas @@ -79,6 +79,7 @@ procedure tdsigcleanup(td:p_kthread); procedure tdsignal(td:p_kthread;sig:Integer); procedure tdksignal(td:p_kthread;sig:Integer;ksi:p_ksiginfo); +procedure forward_signal(td:p_kthread); procedure sigexit(td:p_kthread;sig:Integer); Function cursig(td:p_kthread;stop_allowed:Integer):Integer; @@ -1732,10 +1733,19 @@ begin td:=curkthread; thread_lock(td); + flags:=td^.td_flags; - td^.td_flags:=td^.td_flags and (not (TDF_ASTPENDING or TDF_NEEDSIGCHK or TDF_NEEDSUSPCHK or - TDF_NEEDRESCHED or TDF_ALRMPEND or TDF_PROFPEND or TDF_MACPEND)); + td^.td_flags:=flags and + (not ( + TDF_ASTPENDING or + TDF_NEEDSUSPCHK or + TDF_NEEDRESCHED or + TDF_NEEDSIGCHK or + TDF_ALRMPEND or + TDF_PROFPEND or + TDF_MACPEND + )); thread_unlock(td); @@ -1759,8 +1769,8 @@ begin begin thread_lock(td); sched_prio(td,td^.td_user_pri); - mi_switch(SW_INVOL or SWT_NEEDRESCHED); thread_unlock(td); + mi_switch(SW_INVOL or SWT_NEEDRESCHED); end; if ((flags and TDF_NEEDSIGCHK)<>0) or @@ -1792,6 +1802,34 @@ begin td^.td_pflags:=td^.td_pflags and (not TDP_OLDMASK); kern_sigprocmask(td,SIG_SETMASK,@td^.td_oldsigmask,nil,0); end; + + if ((flags and TDF_SUSP_CTX)<>0) then + begin + // context suspend + thread_lock(td); + + //recheck? + if ((td^.td_flags and TDF_SUSP_CTX)<>0) then + begin + td^.td_flags:=td^.td_flags and (not TDF_SUSP_CTX); + td^.td_state:=TDS_INHIBITED; + td^.td_inhibitors:=td^.td_inhibitors or TDI_SUSP_CTX; + thread_unlock(td); + + mi_switch(SW_VOL or SWT_SUSPEND); + end else + begin + thread_unlock(td); + end; + end; + + if ((td^.td_flags and TDF_ASTPENDING)=0) then + begin + thread_lock(td); + td^.td_flags:=td^.td_flags and (not TDF_UNUSED09); //sony ext???? + thread_unlock(td); + end; + end; end. diff --git a/sys/kern/kern_synch.pas b/sys/kern/kern_synch.pas index 97b9e72f..1813d690 100644 --- a/sys/kern/kern_synch.pas +++ b/sys/kern/kern_synch.pas @@ -41,6 +41,8 @@ function tsleep(ident :Pointer; wmesg :PChar; timo :Int64):Integer; inline; +function pause(wmesg:PChar;timo:Int64):Integer; + procedure wakeup(ident:Pointer); procedure wakeup_one(ident:Pointer); function mi_switch(flags:Integer):Integer; @@ -59,6 +61,9 @@ uses md_sleep, rtprio; +var + pause_wchan:Integer=0; + function msleep(ident :Pointer; lock :p_mtx; priority:Integer; @@ -76,7 +81,10 @@ begin if (TD_ON_SLEEPQ(td)) then sleepq_remove(td,td^.td_wchan); - flags:=SLEEPQ_SLEEP; + if (ident=@pause_wchan) then + flags:=SLEEPQ_PAUSE + else + flags:=SLEEPQ_SLEEP; if (catch<>0) then flags:=flags or SLEEPQ_INTERRUPTIBLE; @@ -119,6 +127,14 @@ begin Result:=msleep(ident,nil,priority,wmesg,timo); end; +function pause(wmesg:PChar;timo:Int64):Integer; +begin + // silently convert invalid timeouts + if (timo < 1) then timo:=1; + + Result:=(tsleep(@pause_wchan, 0, wmesg, timo)); +end; + procedure wakeup(ident:Pointer); begin sleepq_lock(ident); @@ -156,10 +172,21 @@ begin case (flags and SW_TYPE_MASK) of SWT_RELINQUISH, SWT_NEEDRESCHED: + begin md_yield; + end; SWT_SLEEPQ, SWT_SLEEPQTIMO: + begin + if (td=nil) then Exit(-1); Result:=sched_switch(td); + end; + SWT_SUSPEND: + begin + if (td=nil) then Exit(-1); + td^.td_slptick:=0; //infinite + Result:=sched_switch(td); + end; end; end; diff --git a/sys/kern/kern_thr.pas b/sys/kern/kern_thr.pas index 1735d715..aee8f837 100644 --- a/sys/kern/kern_thr.pas +++ b/sys/kern/kern_thr.pas @@ -95,6 +95,8 @@ const TDI_LOCK =$0008; // Stopped on a lock. TDI_IWAIT =$0010; // Awaiting interrupt. + TDI_SUSP_CTX =$0020; // Sony extension + THR_SUSPENDED =$0001; // These flags are kept in p_flag. @@ -117,6 +119,7 @@ const SWT_REMOTEPREEMPT =11; // Remote processor preempted. SWT_REMOTEWAKEIDLE=12; // Remote processor preempted idle. SWT_COUNT =13; // Number of switch types. + // Flags SW_VOL =$0100; // Voluntary switch. SW_INVOL =$0200; // Involuntary switch. @@ -184,7 +187,7 @@ type ru_nvcsw :Int64; ru_nivcsw :Int64; end; - td_timeo :Int64; + td_slptick :Int64; // td_fpop :Pointer; td_map_def_user :Pointer; diff --git a/sys/kern/machdep.pas b/sys/kern/machdep.pas index 56981596..75084214 100644 --- a/sys/kern/machdep.pas +++ b/sys/kern/machdep.pas @@ -26,6 +26,7 @@ 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 get_mcontext2(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); @@ -224,6 +225,57 @@ begin Result:=0; end; +//sce ext + +function get_mcontext2(td:p_kthread;mcp:p_mcontext_t;flags:Integer):Integer; +var + tp:p_trapframe; +begin + tp:=td^.td_frame; + + mcp^.mc_onstack:=sigonstack(tp^.tf_rsp); + + 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; + mcp^.mc_rax :=tp^.tf_rax; + mcp^.mc_rdx :=tp^.tf_rdx; + 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 + get_fpcontext(td,mcp,@mcp^.mc_fpstate); + //xmm,ymm + + 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; + +//sce ext + function set_mcontext(td:p_kthread;mcp:p_mcontext_t):Integer; var tp:p_trapframe; diff --git a/sys/kern/sched_ule.pas b/sys/kern/sched_ule.pas index 8f1ea547..feaa4f10 100644 --- a/sys/kern/sched_ule.pas +++ b/sys/kern/sched_ule.pas @@ -24,6 +24,7 @@ function setrunnable(td:p_kthread):Integer; implementation uses + atomic, md_sleep, md_thread; @@ -98,12 +99,12 @@ end; function sched_switch(td:p_kthread):Integer; var - td_timeo:Int64; + slptick:Int64; begin - td^.td_flags:=td^.td_flags and (not (TDF_NEEDRESCHED or TDF_SLICEEND)); + atomic_clear_int(@td^.td_flags,TDF_NEEDRESCHED or TDF_SLICEEND); - td_timeo:=System.InterlockedExchange64(td^.td_timeo,0); - Result:=msleep_td(td_timeo); + slptick:=System.InterlockedExchange64(td^.td_slptick,0); + Result:=msleep_td(slptick); end; function setrunnable(td:p_kthread):Integer; diff --git a/sys/kern/subr_sleepqueue.pas b/sys/kern/subr_sleepqueue.pas index d3e67f95..1fa00787 100644 --- a/sys/kern/subr_sleepqueue.pas +++ b/sys/kern/subr_sleepqueue.pas @@ -215,7 +215,7 @@ begin Assert(td^.td_sleepqueue=nil); Assert(wchan<>nil); - td^.td_timeo:=time; + td^.td_slptick:=time; end; function sleepq_sleepcnt(wchan,lock:Pointer;flags,queue:Integer):DWORD; diff --git a/sys/md/md_sleep.pas b/sys/md/md_sleep.pas index a6ccfc93..9c31adb0 100644 --- a/sys/md/md_sleep.pas +++ b/sys/md/md_sleep.pas @@ -12,10 +12,10 @@ uses function _umtxq_alloc:THandle; procedure _umtxq_free(h:THandle); -function msleep_umtxq(h:THandle;timo:Int64):Integer; inline; +function msleep_umtxq(h:THandle;timo:Int64):Integer; function wakeup_umtxq(h:THandle):Integer; inline; -function msleep_td(timo:Int64):Integer; inline; +function msleep_td(timo:Int64):Integer; function wakeup_td(td:p_kthread):Integer; inline; procedure md_yield; inline; @@ -66,7 +66,7 @@ begin NtClose(h); end; -function msleep_umtxq(h:THandle;timo:Int64):Integer; inline; +function msleep_umtxq(h:THandle;timo:Int64):Integer; begin if (timo=0) then begin @@ -85,7 +85,7 @@ begin Result:=ntw2px(NtSetEvent(h,nil)); end; -function msleep_td(timo:Int64):Integer; inline; +function msleep_td(timo:Int64):Integer; begin if (timo=0) then begin