This commit is contained in:
Pavel 2023-06-08 12:59:17 +03:00
parent e68bf7838b
commit fce9f80df0
8 changed files with 338 additions and 14 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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