diff --git a/sys/kern_sig.pas b/sys/kern_sig.pas index 3c474ae4..8a8eded8 100644 --- a/sys/kern_sig.pas +++ b/sys/kern_sig.pas @@ -8,6 +8,7 @@ interface uses gtailq, sys_kernel, + time, signal, signalvar; @@ -66,12 +67,16 @@ Function sys_sigprocmask(how:Integer; Function sys_sigpending(oset:p_sigset_t):Integer; +Function sys_sigwait(oset:p_sigset_t;sig:PInteger):Integer; +Function sys_sigtimedwait(oset:p_sigset_t;info:p_siginfo_t;timeout:ptimespec):Integer; +Function sys_sigwaitinfo(oset:p_sigset_t;info:p_siginfo_t):Integer; + implementation uses ntapi, systm, - time, + md_psl, _umtx, kern_umtx, kern_time, @@ -81,8 +86,6 @@ const max_pending_per_proc=128; var - p_p_sigqueue:sigqueue_t; - p_pendingcnt :Integer=0; signal_overflow :Integer=0; signal_alloc_fail:Integer=0; @@ -687,8 +690,7 @@ begin if (td=nil) then Exit(EFAULT); PROC_LOCK; - pending:=p_p_sigqueue.sq_signals; - SIGSETOR(@pending,@td^.td_sigqueue.sq_signals); + pending:=td^.td_sigqueue.sq_signals; PROC_UNLOCK; Result:=copyout(@pending,oset,sizeof(sigset_t)); @@ -738,7 +740,7 @@ begin if (sig<>0) and SIGISMEMBER(@waitset,sig) then begin - if (sigqueue_get(@td^.td_sigqueue, sig, ksi) <> 0) then + if (sigqueue_get(@td^.td_sigqueue,sig,ksi)<>0) then begin Result:=0; break; @@ -799,19 +801,170 @@ begin PROC_UNLOCK; end; +Function sys_sigwait(oset:p_sigset_t;sig:PInteger):Integer; +var + td:p_kthread; + ksi:ksiginfo_t; + __set:sigset_t; +begin + td:=curkthread; + if (td=nil) then Exit(EFAULT); + + Result:=copyin(oset,@__set,sizeof(sigset_t)); + if (Result<>0) then Exit(EFAULT); + + Result:=kern_sigtimedwait(td,__set,@ksi,nil); + if (Result<>0) then + begin + if (Result=EINTR) then + begin + Result:=ERESTART; + end; + Exit; + end; + + Result:=copyout(@ksi.ksi_info.si_signo,sig,sizeof(Integer)); +end; + +Function sys_sigtimedwait(oset:p_sigset_t;info:p_siginfo_t;timeout:ptimespec):Integer; +var + td:p_kthread; + ts:timespec; + ksi:ksiginfo_t; + __set:sigset_t; +begin + td:=curkthread; + if (td=nil) then Exit(-EFAULT); + + if (timeout<>nil) then + begin + Result:=copyin(timeout,@ts,sizeof(timespec)); + if (Result<>0) then Exit(-EFAULT); + timeout:=@ts; + end; + + Result:=copyin(oset,@__set,sizeof(sigset_t)); + if (Result<>0) then Exit(-EFAULT); + + Result:=kern_sigtimedwait(td,__set,@ksi,timeout); + if (Result<>0) then Exit(-Result); + + if (info<>nil) then + begin + Result:=copyout(@ksi.ksi_info,info,sizeof(siginfo_t)); + if (Result<>0) then Exit(-EFAULT); + end; + + Result:=ksi.ksi_info.si_signo; +end; + +Function sys_sigwaitinfo(oset:p_sigset_t;info:p_siginfo_t):Integer; +var + td:p_kthread; + ksi:ksiginfo_t; + __set:sigset_t; +begin + td:=curkthread; + if (td=nil) then Exit(-EFAULT); + + Result:=copyin(oset,@__set,sizeof(sigset_t)); + if (Result<>0) then Exit(-EFAULT); + + Result:=kern_sigtimedwait(td,__set,@ksi,nil); + if (Result<>0) then Exit(-Result); + + if (info<>nil) then + begin + Result:=copyout(@ksi.ksi_info,info,sizeof(siginfo_t)); + if (Result<>0) then Exit(-EFAULT); + end; + + Result:=ksi.ksi_info.si_signo; +end; + +procedure cpu_set_syscall_retval(td:p_kthread;error:Integer); +begin + Case error of + 0:With td^.td_frame^ do + begin + tf_rax:=td^.td_retval[0]; + tf_rdx:=td^.td_retval[1]; + tf_rflags:=tf_rflags and (not PSL_C); + end; + ERESTART: + With td^.td_frame^ do + begin + //tf_err = size of syscall cmd + tf_rip:=tf_rip-td^.td_frame^.tf_err; + tf_r10:=tf_rcx; + //set_pcb_flags(td->td_pcb, PCB_FULL_IRET); + end; + EJUSTRETURN:; + else + With td^.td_frame^ do + begin + tf_rax:=error; + tf_rflags:=tf_rflags or PSL_C; + end; + end; +end; + +function postsig(sig:Integer):Integer; forward; + +Function kern_sigsuspend(td:p_kthread;mask:sigset_t):Integer; +var + has_sig,sig:Integer; +begin + PROC_LOCK; + kern_sigprocmask(td,SIG_SETMASK,@mask,@td^.td_oldsigmask,SIGPROCMASK_PROC_LOCKED); + td^.td_pflags:=td^.td_pflags or TDP_OLDMASK; + + cpu_set_syscall_retval(td,EINTR); + + has_sig:=0; + While (has_sig=0) do + begin + //while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "pause",0) == 0) + + //thread_suspend_check(0); + + mtx_lock(@p_sigacts.ps_mtx); + + repeat + sig:=cursig(td,SIG_STOP_ALLOWED); + if (sig=0) then Break; + has_sig:=has_sig+postsig(sig); + until false; + + mtx_unlock(@p_sigacts.ps_mtx); + end; + + PROC_UNLOCK; + td^.td_errno:=EINTR; + td^.td_pflags:=td^.td_pflags or TDP_NERRNO; + Result:=EJUSTRETURN; +end; + +//TODO check td_errno,td_oldsigmask,td_retval + +function postsig(sig:Integer):Integer; +begin + //TODO +end; + procedure sigexit(td:p_kthread;sig:Integer); begin - // + //TODO end; Function issignal(td:p_kthread;stop_allowed:Integer):Integer; begin - // + //TODO end; procedure reschedule_signals(block:sigset_t;flags:Integer); begin - // + //TODO end; initialization diff --git a/sys/kern_thread.pas b/sys/kern_thread.pas index 1077e35a..282c2e19 100644 --- a/sys/kern_thread.pas +++ b/sys/kern_thread.pas @@ -114,6 +114,7 @@ type td_sigstk :stack_t; td_pflags :Integer; td_flags :Integer; + td_errno :Integer; td_ref :Integer; td_priority :Word; td_pri_class :Word; @@ -126,8 +127,10 @@ type td_fsbase :Pointer; td_cpuset :Ptruint; td_sigmask :sigset_t; + td_oldsigmask :sigset_t; td_sigqueue :sigqueue_t; td_frame :p_trapframe; + td_retval :array[0..1] of QWORD; td_kstack :Pointer; end; diff --git a/sys/md_psl.pas b/sys/md_psl.pas new file mode 100644 index 00000000..00a1dbc6 --- /dev/null +++ b/sys/md_psl.pas @@ -0,0 +1,33 @@ +unit md_psl; + +{$mode ObjFPC}{$H+} + +interface + +const + PSL_C =$00000001; // carry bit + PSL_PF =$00000004; // parity bit + PSL_AF =$00000010; // bcd carry bit + PSL_Z =$00000040; // zero bit + PSL_N =$00000080; // negative bit + PSL_T =$00000100; // trace enable bit + PSL_I =$00000200; // interrupt enable bit + PSL_D =$00000400; // string instruction direction bit + PSL_V =$00000800; // overflow bit + PSL_IOPL=$00003000; // i/o privilege level + PSL_NT =$00004000; // nested task bit + PSL_RF =$00010000; // resume flag bit + PSL_AC =$00040000; // alignment checking + PSL_ID =$00200000; // identification bit + + PSL_RESERVED_DEFAULT=$00000002; + + PSL_KERNEL=PSL_RESERVED_DEFAULT; + PSL_USER =(PSL_RESERVED_DEFAULT or PSL_I); + + PSL_USERCHANGE=(PSL_C or PSL_PF or PSL_AF or PSL_Z or PSL_N or PSL_T or PSL_D or PSL_V or PSL_NT or PSL_RF or PSL_AC or PSL_ID); + +implementation + +end. + diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi index a94b9657..14b37a2e 100644 --- a/sys/test/project1.lpi +++ b/sys/test/project1.lpi @@ -81,6 +81,10 @@ + + + + diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr index ee0c9f85..a4a9c958 100644 --- a/sys/test/project1.lpr +++ b/sys/test/project1.lpr @@ -15,7 +15,7 @@ uses kern_rwlock, thr_private, kern_sig, - trap, + trap, md_psl, sysutils, vulkan, vDevice;