diff --git a/sys/kern_sig.pas b/sys/kern_sig.pas index b83eb3b4..8a6a497f 100644 --- a/sys/kern_sig.pas +++ b/sys/kern_sig.pas @@ -101,11 +101,11 @@ implementation uses ntapi, systm, - _umtx, kern_mtx, kern_time, vm_machdep, - machdep; + machdep, + trap; const max_pending_per_proc=128; @@ -779,6 +779,27 @@ begin Result:=copyout(@pending,oset,sizeof(sigset_t)); end; +function ntw2px(n:Integer):Integer; +begin + Case DWORD(n) of + STATUS_SUCCESS :Result:=0; + STATUS_ABANDONED :Result:=EPERM; + STATUS_ALERTED :Result:=EINTR; + STATUS_USER_APC :Result:=EINTR; + STATUS_TIMEOUT :Result:=ETIMEDOUT; + STATUS_ACCESS_VIOLATION:Result:=EFAULT; + else + Result:=EINVAL; + end; +end; + +function msleep(timo:Int64):Integer; inline; +begin + sig_set_alterable; + Result:=ntw2px(NtDelayExecution(True,@timo)); + sig_reset_alterable; +end; + Function kern_sigtimedwait(td:p_kthread; waitset:sigset_t; ksi:p_ksiginfo; @@ -849,7 +870,9 @@ begin tv:=NT_INFINITE; end; - //Result:=msleep(ps, &p^.p_mtx, PPAUSE|PCATCH, "sigwait", -tv); + PROC_UNLOCK; // + Result:=msleep(tvtohz(tv)); + PROC_LOCK; // if (timeout<>nil) then begin @@ -989,7 +1012,9 @@ begin has_sig:=0; While (has_sig=0) do begin - //while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "pause",0) == 0) + PROC_UNLOCK; // + while (msleep(T_INFINITE)=0) do; + PROC_LOCK; // //thread_suspend_check(0); diff --git a/sys/kern_thread.pas b/sys/kern_thread.pas index 3dfe8c41..2234bfc4 100644 --- a/sys/kern_thread.pas +++ b/sys/kern_thread.pas @@ -12,6 +12,8 @@ uses ucontext, signal, signalvar, + time, + kern_time, hamt; const @@ -181,6 +183,7 @@ function sys_thr_new(_param:p_thr_param;_size:Integer):Integer; function sys_thr_self(id:PQWORD):Integer; procedure sys_thr_exit(state:PQWORD); function sys_thr_kill(id:QWORD;sig:Integer):Integer; +function sys_thr_suspend(timeout:ptimespec):Integer; procedure thread_inc_ref(td:p_kthread); procedure thread_dec_ref(td:p_kthread); @@ -227,7 +230,8 @@ uses kern_rwlock, kern_mtx, kern_umtx, - kern_sig; + kern_sig, + trap; var p_mtx:Pointer=nil; @@ -268,7 +272,7 @@ end; procedure PROC_UNLOCK; begin - mtx_lock(@p_mtx); + mtx_unlock(@p_mtx); end; procedure threadinit; inline; @@ -809,6 +813,105 @@ begin end; end; +function ntw2px(n:Integer):Integer; +begin + Case DWORD(n) of + STATUS_SUCCESS :Result:=0; + STATUS_ABANDONED :Result:=EPERM; + STATUS_ALERTED :Result:=EINTR; + STATUS_USER_APC :Result:=EINTR; + STATUS_TIMEOUT :Result:=ETIMEDOUT; + STATUS_ACCESS_VIOLATION:Result:=EFAULT; + else + Result:=EINVAL; + end; +end; + +function msleep(timo:Int64):Integer; inline; +begin + sig_set_alterable; + Result:=ntw2px(NtDelayExecution(True,@timo)); + sig_reset_alterable; +end; + +function kern_thr_suspend(td:p_kthread;tsp:ptimespec):Integer; +var + tv:Int64; +begin + if ((td^.td_pflags and TDP_WAKEUP)<>0) then + begin + td^.td_pflags:=td^.td_pflags and (not TDP_WAKEUP); + Exit(0); + end; + + tv:=T_INFINITE; + if (tsp<>nil) then + begin + if (tsp^.tv_sec=0) and (tsp^.tv_nsec=0) then + begin + Result:=EWOULDBLOCK; + end else + begin + tv:=TIMESPEC_TO_UNIT(tsp); + tv:=tvtohz(tv); + end; + end; + + PROC_LOCK; + + if (Result=0) and ((td^.td_flags and TDF_THRWAKEUP)=0) then + begin + PROC_UNLOCK; // + Result:=msleep(tv); + PROC_LOCK; // + end; + + if ((td^.td_flags and TDF_THRWAKEUP)=0) then + begin + thread_lock(td); + td^.td_flags:=td^.td_flags and (not TDF_THRWAKEUP); + thread_unlock(td); + PROC_UNLOCK; + Exit(0); + end; + + PROC_UNLOCK; + + if (Result=EWOULDBLOCK) then + begin + Result:=ETIMEDOUT; + end else + if (Result=ERESTART) then + begin + if (tv<>T_INFINITE) then + begin + Result:=EINTR; + end; + end; +end; + +function sys_thr_suspend(timeout:ptimespec):Integer; +var + td:p_kthread; + ts:timespec; + tsp:ptimespec; +begin + td:=curkthread; + if (td=nil) then Exit(-1); + + tsp:=nil; + if (timeout<>nil) then + begin + Result:=umtx_copyin_timeout(timeout,@ts); + if (Result<>0) then Exit; + tsp:=@ts; + end; + + Result:=kern_thr_suspend(td,tsp); +end; + + + function rtp_to_pri(rtp:p_rtprio;td:p_kthread):Integer; var diff --git a/sys/kern_time.pas b/sys/kern_time.pas index eefeb8e2..9e2d751d 100644 --- a/sys/kern_time.pas +++ b/sys/kern_time.pas @@ -7,8 +7,13 @@ interface uses sys_kernel, + windows, + ntapi, time; +const + T_INFINITE=NT_INFINITE; + function get_unit_uptime:Int64; function kern_clock_gettime_unit(clock_id:Integer;time:PInt64):Integer; function kern_clock_gettime(clock_id:Integer;tp:Ptimespec):Integer; @@ -16,10 +21,6 @@ function kern_clock_getres(clock_id:Integer;tp:Ptimespec):Integer; implementation -uses - windows, - ntapi; - Const UNIT_PER_SEC =10000000; DELTA_EPOCH_IN_UNIT =116444736000000000; diff --git a/sys/kern_umtx.pas b/sys/kern_umtx.pas index dfd22d4c..81b8b5a3 100644 --- a/sys/kern_umtx.pas +++ b/sys/kern_umtx.pas @@ -29,6 +29,8 @@ function _sys_umtx_op(obj:Pointer;op:Integer;val:QWORD;uaddr1,uaddr2:Pointer):I function kern_umtx_wake(td:p_kthread;umtx:p_umtx;n_wake,priv:Integer):Integer; +function umtx_copyin_timeout(addr:Pointer;tsp:ptimespec):Integer; + implementation uses @@ -513,7 +515,7 @@ begin if (timeout=nil) then begin - Result:=_do_lock_umtx(td,umtx,id,NT_INFINITE); + Result:=_do_lock_umtx(td,umtx,id,T_INFINITE); if (Result=EINTR) then begin Result:=ERESTART; @@ -525,7 +527,7 @@ begin ts:=ts+tv; repeat - Result:=_do_lock_umtx(td,umtx,id,-tv); + Result:=_do_lock_umtx(td,umtx,id,tvtohz(tv)); if (Result<>ETIMEDOUT) then Break; ts2:=get_unit_uptime; @@ -636,7 +638,7 @@ begin end else if (timeout=nil) then begin - umtxq_sleep(uq,NT_INFINITE); + umtxq_sleep(uq,T_INFINITE); umtxq_lock(uq^.uq_key); umtxq_remove(uq); @@ -648,7 +650,7 @@ begin ts:=ts+tv; repeat - Result:=umtxq_sleep(uq,-tv); + Result:=umtxq_sleep(uq,tvtohz(tv)); if ((uq^.uq_flags and UQF_UMTXQ)=0) then begin @@ -1465,7 +1467,7 @@ begin if (timeout=nil) then begin - Result:=_do_lock_umutex(td,m,flags,NT_INFINITE,mode); + Result:=_do_lock_umutex(td,m,flags,T_INFINITE,mode); if (Result=EINTR) and (mode<>_UMUTEX_WAIT) then begin Result:=ERESTART; @@ -1477,7 +1479,7 @@ begin ts:=ts+tv; repeat - Result:=_do_lock_umutex(td,m,flags,-tv,mode); + Result:=_do_lock_umutex(td,m,flags,tvtohz(tv),mode); if (Result<>ETIMEDOUT) then Break; ts2:=get_unit_uptime; @@ -1565,7 +1567,7 @@ begin begin if (timeout=nil) then begin - Result:=umtxq_sleep(uq,NT_INFINITE); + Result:=umtxq_sleep(uq,T_INFINITE); end else begin if ((wflags and CVWAIT_ABSTIME)=0) then @@ -1589,7 +1591,7 @@ begin tv:=tts; repeat - Result:=umtxq_sleep(uq,-tv); + Result:=umtxq_sleep(uq,tvtohz(tv)); if (Result<>ETIMEDOUT) then Break; kern_clock_gettime_unit(clockid,@cts); @@ -1826,7 +1828,7 @@ begin tv:=ts; repeat - Result:=do_rw_rdlock(td,rwlock,fflag,-tv); + Result:=do_rw_rdlock(td,rwlock,fflag,tvtohz(tv)); if (Result<>ETIMEDOUT) then Break; @@ -1993,7 +1995,7 @@ begin tv:=ts; repeat - Result:=do_rw_wrlock(td,rwlock,fflag,-tv); + Result:=do_rw_wrlock(td,rwlock,fflag,tvtohz(tv)); if (Result<>ETIMEDOUT) then Break; @@ -2166,7 +2168,7 @@ begin if (timeout=nil) then begin - Result:=umtxq_sleep(uq,NT_INFINITE); + Result:=umtxq_sleep(uq,T_INFINITE); end else begin ets:=get_unit_uptime; @@ -2174,7 +2176,7 @@ begin ets:=ets+tv; repeat - Result:=umtxq_sleep(uq,-tv); + Result:=umtxq_sleep(uq,tvtohz(tv)); if (Result<>ETIMEDOUT) then Break; cts:=get_unit_uptime; @@ -2450,7 +2452,7 @@ begin if (uaddr2=nil) then begin - Result:=do_rw_rdlock(td,obj,val,NT_INFINITE); + Result:=do_rw_rdlock(td,obj,val,T_INFINITE); end else begin Result:=umtx_copyin_timeout(uaddr2,@timeout); @@ -2467,7 +2469,7 @@ begin if (uaddr2=nil) then begin - Result:=do_rw_wrlock(td,obj,val,NT_INFINITE); + Result:=do_rw_wrlock(td,obj,val,T_INFINITE); end else begin Result:=umtx_copyin_timeout(uaddr2,@timeout); diff --git a/sys/sys_sig.pas b/sys/sys_sig.pas new file mode 100644 index 00000000..387001f2 --- /dev/null +++ b/sys/sys_sig.pas @@ -0,0 +1,93 @@ +unit sys_sig; + +{$mode ObjFPC}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +uses + time, + signal, + kern_sig; + +Function sigaction(sig:Integer; + act,oact:p_sigaction_t; + flags:Integer):Integer; + +Function sigprocmask(how:Integer; + _set:p_sigset_t; + oset:p_sigset_t; + flags:Integer):Integer; + +Function sigpending(oset:p_sigset_t):Integer; + +Function sigwait(oset:p_sigset_t;sig:PInteger):Integer; +Function sigtimedwait(oset:p_sigset_t;info:p_siginfo_t;timeout:ptimespec):Integer; +Function sigwaitinfo(oset:p_sigset_t;info:p_siginfo_t):Integer; + +Function sigsuspend(sigmask:p_sigset_t):Integer; + +Function sigaltstack(ss:p_stack_t;oss:p_stack_t):Integer; + +implementation + +uses + trap; + +Function sigaction(sig:Integer; + act,oact:p_sigaction_t; + flags:Integer):Integer; assembler; nostackframe; +asm + movq sys_sigaction,%rax + call fast_syscall +end; + +Function sigprocmask(how:Integer; + _set:p_sigset_t; + oset:p_sigset_t; + flags:Integer):Integer; assembler; nostackframe; +asm + movq sys_sigprocmask,%rax + call fast_syscall +end; + +Function sigpending(oset:p_sigset_t):Integer; assembler; nostackframe; +asm + movq sys_sigpending,%rax + call fast_syscall +end; + +Function sigwait(oset:p_sigset_t;sig:PInteger):Integer; assembler; nostackframe; +asm + movq sys_sigwait,%rax + call fast_syscall +end; + +Function sigtimedwait(oset:p_sigset_t;info:p_siginfo_t;timeout:ptimespec):Integer; assembler; nostackframe; +asm + movq sys_sigtimedwait,%rax + call fast_syscall +end; + +Function sigwaitinfo(oset:p_sigset_t;info:p_siginfo_t):Integer; assembler; nostackframe; +asm + movq sys_sigwaitinfo,%rax + call fast_syscall +end; + +Function sigsuspend(sigmask:p_sigset_t):Integer; assembler; nostackframe; +asm + movq sys_sigsuspend,%rax + call fast_syscall +end; + +Function sigaltstack(ss:p_stack_t;oss:p_stack_t):Integer; assembler; nostackframe; +asm + movq sys_sigaltstack,%rax + call fast_syscall +end; + + +end. + + diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi index 68450ac9..b1d9dc59 100644 --- a/sys/test/project1.lpi +++ b/sys/test/project1.lpi @@ -101,6 +101,10 @@ + + + + diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr index 82175f68..1114a729 100644 --- a/sys/test/project1.lpr +++ b/sys/test/project1.lpr @@ -15,8 +15,8 @@ uses kern_lock, kern_rwlock, thr_private, - kern_sig, trap, + sys_sig, md_psl, sysutils, vulkan, @@ -159,6 +159,8 @@ procedure test_thread; sysv_abi_default; var rax:qword; act:sigaction_t; + _sig:Integer; + oset:sigset_t; begin //SetTlsBase(Pointer(qword(1))); @@ -169,11 +171,19 @@ begin act.u.sa_handler:=sa_handler(@__ex_handler); act.sa_flags:=SA_RESTART; - sys_sigaction(SIGUSR1,@act,nil,0); + sigaction(SIGUSR1,@act,nil,0); - sys_thr_kill(tid,SIGUSR1); + thr_kill(tid,SIGUSR1); end else begin + Writeln('thr_suspend:',thr_suspend(nil)); + { + oset.qwords[0]:=QWORD(-1); + oset.qwords[1]:=QWORD(-1); + Writeln('sigwait:',sigwait(@oset,@_sig)); + Writeln('intr:',_sig); + } + { Writeln('before: sptr:',HexStr(sptr)); repeat asm @@ -182,6 +192,7 @@ begin until (intr<>0); Writeln('intr'); Writeln('after: sptr:',HexStr(sptr)); + } end; sig_lock; diff --git a/sys/thr.pas b/sys/thr.pas index 4f4fc9a1..8cafdf73 100644 --- a/sys/thr.pas +++ b/sys/thr.pas @@ -6,6 +6,7 @@ unit thr; interface uses + time, kern_thread; type @@ -15,14 +16,12 @@ type function thr_new(param:p_thr_param;param_size:Integer):Integer; function thr_self(id:PQWORD):Integer; procedure thr_exit(state:PQWORD); +function thr_kill(id:QWORD;sig:Integer):Integer; +function thr_suspend(timeout:ptimespec):Integer; //int thr_create(ucontext_t *ctx, long *id, int flags); -//int thr_new(struct thr_param *param, int param_size); -//int thr_self(long *id); -//void thr_exit(long *state); -//int thr_kill(long id, int sig); + //int thr_kill2(pid_t pid, long id, int sig); -//int thr_suspend(const struct timespec *timeout); //int thr_wake(long id); //int thr_set_name(long id, const char *name); @@ -55,5 +54,20 @@ asm call fast_syscall end; +function thr_kill(id:QWORD;sig:Integer):Integer; assembler; nostackframe; +asm + movq sys_thr_kill,%rax + call fast_syscall +end; + +function thr_suspend(timeout:ptimespec):Integer; assembler; nostackframe; +asm + movq sys_thr_suspend,%rax + call fast_syscall +end; + + end. + + diff --git a/sys/time.pas b/sys/time.pas index f0334d96..162493fb 100644 --- a/sys/time.pas +++ b/sys/time.pas @@ -55,6 +55,7 @@ type end; function TIMESPEC_TO_UNIT(ts:ptimespec):Int64; inline; //Unit +function tvtohz(time:Int64):Int64; inline; implementation @@ -63,5 +64,10 @@ begin Result:=(QWORD(ts^.tv_sec)*10000000)+(QWORD(ts^.tv_nsec) div 100); end; +function tvtohz(time:Int64):Int64; inline; +begin + Result:=-time; +end; + end.