FPPS4/sys/kern/kern_sig.pas

1939 lines
37 KiB
Plaintext

unit kern_sig;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
uses
mqueue,
kern_param,
sys_event,
time,
signal,
signalvar,
kern_thr,
kern_proc;
const
SA_KILL =$01; // terminates process by default
SA_CORE =$02; // ditto and coredumps
SA_STOP =$04; // suspend process
SA_TTYSTOP =$08; // ditto, from tty
SA_IGNORE =$10; // ignore by default
SA_CONT =$20; // continue if suspended
SA_CANTMASK=$40; // non-maskable, catchable
SA_PROC =$80; // deliverable to any thread
sigproptbl:array[0..30] of Integer=(
SA_KILL or SA_PROC, // SIGHUP
SA_KILL or SA_PROC, // SIGINT
SA_KILL or SA_CORE or SA_PROC, // SIGQUIT
SA_KILL or SA_CORE, // SIGILL
SA_KILL or SA_CORE, // SIGTRAP
SA_KILL or SA_CORE, // SIGABRT
SA_KILL or SA_CORE or SA_PROC, // SIGEMT
SA_KILL or SA_CORE, // SIGFPE
SA_KILL or SA_PROC, // SIGKILL
SA_KILL or SA_CORE, // SIGBUS
SA_KILL or SA_CORE, // SIGSEGV
SA_KILL or SA_CORE, // SIGSYS
SA_KILL or SA_PROC, // SIGPIPE
SA_KILL or SA_PROC, // SIGALRM
SA_KILL or SA_PROC, // SIGTERM
SA_IGNORE or SA_PROC, // SIGURG
SA_STOP or SA_PROC, // SIGSTOP
SA_STOP or SA_TTYSTOP or SA_PROC, // SIGTSTP
SA_IGNORE or SA_CONT or SA_PROC, // SIGCONT
SA_IGNORE or SA_PROC, // SIGCHLD
SA_STOP or SA_TTYSTOP or SA_PROC, // SIGTTIN
SA_STOP or SA_TTYSTOP or SA_PROC, // SIGTTOU
SA_IGNORE or SA_PROC, // SIGIO
SA_KILL, // SIGXCPU
SA_KILL, // SIGXFSZ
SA_KILL or SA_PROC, // SIGVTALRM
SA_KILL or SA_PROC, // SIGPROF
SA_IGNORE or SA_PROC, // SIGWINCH
SA_IGNORE or SA_PROC, // SIGINFO
SA_KILL or SA_PROC, // SIGUSR1
SA_KILL or SA_PROC // SIGUSR2
);
Function sys_sigaction(sig:Integer;act,oact:Pointer):Integer;
Function sys_sigprocmask(how:Integer;_set,oset:Pointer):Integer;
Function sys_sigpending(oset:Pointer):Integer;
Function sys_sigwait(oset:Pointer;sig:PInteger):Integer;
Function sys_sigtimedwait(oset,info,timeout:Pointer):Integer;
Function sys_sigwaitinfo(oset,info:Pointer):Integer;
Function sys_sigsuspend(sigmask:Pointer):Integer;
Function sys_sigaltstack(ss,oss:Pointer):Integer;
function sys_kill(pid,signum:Integer):Integer;
function sys_sigqueue(pid,signum:Integer;value:Pointer):Integer;
//
Function sigonstack(sp:size_t):Integer;
procedure sigqueue_init(list:p_sigqueue);
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;
Function kern_sigprocmask(td:p_kthread;
how:Integer;
_set:p_sigset_t;
oset:p_sigset_t;
flags:Integer
):Integer;
procedure ast;
procedure ps_mtx_lock;
procedure ps_mtx_unlock;
function sigdeferstop:Integer;
procedure sigallowstop;
procedure siginit; //SYSINIT
//
function filt_sigattach(kn:p_knote):Integer;
procedure filt_sigdetach(kn:p_knote);
function filt_signal(kn:p_knote;hint:QWORD):Integer;
const
sig_filtops:t_filterops=(
f_isfd :0;
f_attach:@filt_sigattach;
f_detach:@filt_sigdetach;
f_event :@filt_signal;
);
implementation
uses
errno,
systm,
kern_mtx,
md_time,
kern_exit,
kern_prot,
kern_synch,
md_context,
machdep,
sched_ule,
sys_sleepqueue;
const
max_pending_per_proc=128;
kern_forcesigexit=1;
var
signal_overflow :Integer=0;
signal_alloc_fail:Integer=0;
function ksiginfo_alloc():p_ksiginfo;
begin
Result:=AllocMem(SizeOf(ksiginfo_t));
end;
procedure ksiginfo_free(ksi:p_ksiginfo);
begin
FreeMem(ksi);
end;
Function ksiginfo_tryfree(ksi:p_ksiginfo):Boolean;
begin
Result:=False;
if ((ksi^.ksi_flags and KSI_EXT)=0) then
begin
FreeMem(ksi);
Result:=True;
end;
end;
procedure sigqueue_init(list:p_sigqueue);
begin
SIGEMPTYSET(@list^.sq_signals);
SIGEMPTYSET(@list^.sq_kill);
TAILQ_INIT(@list^.sq_list);
list^.sq_flags:=SQ_INIT;
end;
Function sigqueue_get(sq:p_sigqueue;signo:Integer;si:p_ksiginfo):Integer;
var
ksi,next:p_ksiginfo;
count:Integer;
begin
count:=0;
Assert((sq^.sq_flags and SQ_INIT)<>0,'sigqueue not inited');
if not SIGISMEMBER(@sq^.sq_signals,signo) then Exit(0);
if SIGISMEMBER(@sq^.sq_kill,signo) then
begin
Inc(count);
SIGDELSET(@sq^.sq_kill,signo);
end;
ksi:=TAILQ_FIRST(@sq^.sq_list);
While (ksi<>nil) do
begin
next:=TAILQ_NEXT(ksi,@ksi^.ksi_link);
if (ksi^.ksi_info.si_signo=signo) then
begin
if (count=0) then
begin
TAILQ_REMOVE(@sq^.sq_list,ksi,@ksi^.ksi_link);
ksi^.ksi_sigq:=nil;
ksiginfo_copy(ksi,si);
if ksiginfo_tryfree(ksi) then
begin
Dec(p_proc.p_pendingcnt);
end;
end;
if (count>1) then
begin
Inc(count);
Break;
end else
begin
Inc(count);
end;
end;
ksi:=next;
end;
if (count<=1) then
begin
SIGDELSET(@sq^.sq_signals,signo);
end;
si^.ksi_info.si_signo:=signo;
Result:=signo;
end;
procedure sigqueue_take(ksi:p_ksiginfo);
var
kp:p_ksiginfo;
sq:p_sigqueue;
begin
if (ksi=nil) or (ksi^.ksi_sigq=nil) then Exit;
sq:=ksi^.ksi_sigq;
TAILQ_REMOVE(@sq^.sq_list,ksi,@ksi^.ksi_link);
ksi^.ksi_sigq:=nil;
if ((ksi^.ksi_flags and KSI_EXT)=0)then
begin
Dec(p_proc.p_pendingcnt);
end;
kp:=TAILQ_FIRST(@sq^.sq_list);
While (kp<>nil) do
begin
if (kp^.ksi_info.si_signo=ksi^.ksi_info.si_signo) then Break;
kp:=TAILQ_NEXT(kp,@kp^.ksi_link);
end;
if (kp=nil) and (not SIGISMEMBER(@sq^.sq_kill,ksi^.ksi_info.si_signo)) then
begin
SIGDELSET(@sq^.sq_signals,ksi^.ksi_info.si_signo);
end;
end;
Function sigqueue_add(sq:p_sigqueue;signo:Integer;si:p_ksiginfo):Integer;
label
out_set_bit;
var
ksi:p_ksiginfo;
begin
Result:=0;
Assert((sq^.sq_flags and SQ_INIT)<>0,'sigqueue not inited');
if (signo=SIGKILL) or (signo=SIGSTOP) or (si=nil) then
begin
SIGADDSET(@sq^.sq_kill,signo);
goto out_set_bit;
end;
if ((si^.ksi_flags and KSI_INS)<>0) then
begin
if ((si^.ksi_flags and KSI_HEAD)<>0) then
TAILQ_INSERT_HEAD(@sq^.sq_list,si,@si^.ksi_link)
else
TAILQ_INSERT_TAIL(@sq^.sq_list,si,@si^.ksi_link);
si^.ksi_sigq:=sq;
goto out_set_bit;
end;
if (p_proc.p_pendingcnt>=max_pending_per_proc) then
begin
Inc(signal_overflow);
Result:=EAGAIN;
end else
begin
ksi:=ksiginfo_alloc;
if (ksi=nil) then
begin
Inc(signal_alloc_fail);
Result:=EAGAIN;
end else
begin
Inc(p_proc.p_pendingcnt);
ksiginfo_copy(si,ksi);
ksi^.ksi_info.si_signo:=signo;
if ((si^.ksi_flags and KSI_HEAD)<>0) then
TAILQ_INSERT_HEAD(@sq^.sq_list,ksi,@ksi^.ksi_link)
else
TAILQ_INSERT_TAIL(@sq^.sq_list,ksi,@ksi^.ksi_link);
ksi^.ksi_sigq:=sq;
end;
end;
if ((si^.ksi_flags and KSI_TRAP)<>0) or
((si^.ksi_flags and KSI_SIGQ) =0) then
begin
if (Result<>0) then
begin
SIGADDSET(@sq^.sq_kill,signo);
end;
Result:=0;
goto out_set_bit;
end;
if (Result<>0) then Exit;
out_set_bit:
SIGADDSET(@sq^.sq_signals,signo);
end;
procedure sigqueue_flush(sq:p_sigqueue);
var
ksi,next:p_ksiginfo;
begin
Assert((sq^.sq_flags and SQ_INIT)<>0,'sigqueue not inited');
ksi:=TAILQ_FIRST(@sq^.sq_list);
while (ksi<>nil) do
begin
next:=TAILQ_NEXT(ksi,@ksi^.ksi_link);
TAILQ_REMOVE(@sq^.sq_list,ksi,@ksi^.ksi_link);
ksi^.ksi_sigq:=nil;
if ksiginfo_tryfree(ksi) then
begin
Dec(p_proc.p_pendingcnt);
end;
ksi:=next;
end;
SIGEMPTYSET(@sq^.sq_signals);
SIGEMPTYSET(@sq^.sq_kill);
end;
procedure sigqueue_move_set(src,dst:p_sigqueue;_set:p_sigset_t);
var
tmp:sigset_t;
ksi,next:p_ksiginfo;
begin
Assert((src^.sq_flags and SQ_INIT)<>0,'sigqueue not inited');
Assert((dst^.sq_flags and SQ_INIT)<>0,'sigqueue not inited');
ksi:=TAILQ_FIRST(@src^.sq_list);
while (ksi<>nil) do
begin
next:=TAILQ_NEXT(ksi,@ksi^.ksi_link);
if SIGISMEMBER(_set,ksi^.ksi_info.si_signo) then
begin
TAILQ_REMOVE(@src^.sq_list,ksi,@ksi^.ksi_link);
TAILQ_INSERT_TAIL(@dst^.sq_list,ksi,@ksi^.ksi_link);
ksi^.ksi_sigq:=dst;
end;
ksi:=next;
end;
tmp:=src^.sq_kill;
SIGSETAND(@tmp,_set);
SIGSETOR(@dst^.sq_kill,@tmp);
SIGSETNAND(@src^.sq_kill,@tmp);
tmp:=src^.sq_signals;
SIGSETAND(@tmp,_set);
SIGSETOR(@dst^.sq_signals,@tmp);
SIGSETNAND(@src^.sq_signals,@tmp);
end;
procedure sigqueue_delete_set(sq:p_sigqueue;_set:p_sigset_t);
var
ksi,next:p_ksiginfo;
begin
Assert((sq^.sq_flags and SQ_INIT)<>0,'sigqueue not inited');
ksi:=TAILQ_FIRST(@sq^.sq_list);
while (ksi<>nil) do
begin
next:=TAILQ_NEXT(ksi,@ksi^.ksi_link);
if SIGISMEMBER(_set,ksi^.ksi_info.si_signo) then
begin
TAILQ_REMOVE(@sq^.sq_list,ksi,@ksi^.ksi_link);
ksi^.ksi_sigq:=nil;
if ksiginfo_tryfree(ksi) then
begin
Dec(p_proc.p_pendingcnt)
end;
end;
ksi:=next;
end;
SIGSETNAND(@sq^.sq_kill,_set);
SIGSETNAND(@sq^.sq_signals,_set);
end;
procedure sigqueue_delete(sq:p_sigqueue;signo:Integer);
var
_set:sigset_t;
begin
SIGEMPTYSET(@_set);
SIGADDSET(@_set,signo);
sigqueue_delete_set(sq,@_set);
end;
procedure sigqueue_delete_set_proc(_set:p_sigset_t);
var
td0:p_kthread;
worklist:sigqueue_t;
begin
sigqueue_init(@worklist);
sigqueue_move_set(@p_proc.p_sigqueue,@worklist,_set);
threads_lock;
td0:=TAILQ_FIRST(get_p_threads);
while (td0<>nil) do
begin
sigqueue_move_set(@td0^.td_sigqueue,@worklist,_set);
td0:=TAILQ_NEXT(td0,@td0^.td_plist)
end;
threads_unlock;
sigqueue_flush(@worklist);
end;
procedure sigqueue_delete_proc(signo:Integer);
var
_set:sigset_t;
begin
SIGEMPTYSET(@_set);
SIGADDSET(@_set,signo);
sigqueue_delete_set_proc(@_set);
end;
procedure sigqueue_delete_stopmask_proc;
var
_set:sigset_t;
begin
SIGEMPTYSET(@_set);
SIGADDSET(@_set,SIGSTOP);
SIGADDSET(@_set,SIGTSTP);
SIGADDSET(@_set,SIGTTIN);
SIGADDSET(@_set,SIGTTOU);
sigqueue_delete_set_proc(@_set);
end;
///
Function issignal(td:p_kthread;stop_allowed:Integer):Integer; forward;
Function cursig(td:p_kthread;stop_allowed:Integer):Integer; public;
begin
Assert((stop_allowed=SIG_STOP_ALLOWED) or (stop_allowed=SIG_STOP_NOT_ALLOWED),'cursig: stop_allowed');
if SIGPENDING(td) then
begin
Result:=issignal(td, stop_allowed);
end else
begin
Result:=0;
end;
end;
procedure signotify(td:p_kthread);
begin
if SIGPENDING(td) then
begin
thread_lock(td);
td^.td_flags:=td^.td_flags or TDF_NEEDSIGCHK or TDF_ASTPENDING;
thread_unlock(td);
end;
end;
Function sigonstack(sp:size_t):Integer; public;
var
td:p_kthread;
begin
Result:=0;
td:=curkthread;
if (td=nil) then Exit;
if ((td^.td_pflags and TDP_ALTSTACK)<>0) then
begin
Result:=ord((sp-size_t(td^.td_sigstk.ss_sp))<td^.td_sigstk.ss_size);
end;
end;
Function sigprop(sig:Integer):Integer;
begin
Result:=0;
if (sig>0) and (sig<NSIG) then
begin
Result:=sigproptbl[_SIG_IDX(sig)];
end;
end;
procedure ps_mtx_lock; public;
begin
mtx_lock(p_sigacts.ps_mtx);
end;
procedure ps_mtx_unlock; public;
begin
mtx_unlock(p_sigacts.ps_mtx);
end;
Function kern_sigaction(sig:Integer;
act,oact:p_sigaction_t):Integer;
begin
if (not _SIG_VALID(sig)) then Exit(EINVAL);
PROC_LOCK;
ps_mtx_lock;
if (oact<>nil) then
begin
oact^.sa_mask :=p_sigacts.ps_catchmask[_SIG_IDX(sig)];
oact^.sa_flags:=0;
if (SIGISMEMBER(@p_sigacts.ps_sigonstack,sig)) then
oact^.sa_flags:=oact^.sa_flags or SA_ONSTACK;
if (not SIGISMEMBER(@p_sigacts.ps_sigintr,sig)) then
oact^.sa_flags:=oact^.sa_flags or SA_RESTART;
if (SIGISMEMBER(@p_sigacts.ps_sigreset,sig)) then
oact^.sa_flags:=oact^.sa_flags or SA_RESETHAND;
if (SIGISMEMBER(@p_sigacts.ps_signodefer,sig)) then
oact^.sa_flags:=oact^.sa_flags or SA_NODEFER;
if (SIGISMEMBER(@p_sigacts.ps_siginfo,sig)) then
begin
oact^.sa_flags:=oact^.sa_flags or SA_SIGINFO;
oact^.u.sa_handler:=p_sigacts.ps_sigact[_SIG_IDX(sig)];
end else
begin
oact^.u.sa_handler:=p_sigacts.ps_sigact[_SIG_IDX(sig)];
end;
if (sig=SIGCHLD and p_sigacts.ps_flag and PS_NOCLDSTOP) then
oact^.sa_flags:=oact^.sa_flags or SA_NOCLDSTOP;
if (sig=SIGCHLD and p_sigacts.ps_flag and PS_NOCLDWAIT) then
oact^.sa_flags:=oact^.sa_flags or SA_NOCLDWAIT;
end;
if (act<>nil) then
begin
if ((sig=SIGKILL) or (sig=SIGSTOP)) and
(act^.u.code<>SIG_DFL) then
begin
ps_mtx_unlock;
PROC_UNLOCK;
Result:=EINVAL;
end;
p_sigacts.ps_catchmask[_SIG_IDX(sig)]:=act^.sa_mask;
SIG_CANTMASK(@p_sigacts.ps_catchmask[_SIG_IDX(sig)]);
if ((act^.sa_flags and SA_SIGINFO)<>0) then
begin
p_sigacts.ps_sigact[_SIG_IDX(sig)]:=act^.u.sa_handler;
SIGADDSET(@p_sigacts.ps_siginfo,sig);
end else
begin
p_sigacts.ps_sigact[_SIG_IDX(sig)]:=act^.u.sa_handler;
SIGDELSET(@p_sigacts.ps_siginfo,sig);
end;
if ((act^.sa_flags and SA_RESTART)=0) then
SIGADDSET(@p_sigacts.ps_sigintr,sig)
else
SIGDELSET(@p_sigacts.ps_sigintr,sig);
if ((act^.sa_flags and SA_ONSTACK)<>0) then
SIGADDSET(@p_sigacts.ps_sigonstack,sig)
else
SIGDELSET(@p_sigacts.ps_sigonstack,sig);
if ((act^.sa_flags and SA_RESETHAND)<>0) then
SIGADDSET(@p_sigacts.ps_sigreset,sig)
else
SIGDELSET(@p_sigacts.ps_sigreset,sig);
if ((act^.sa_flags and SA_NODEFER)<>0) then
SIGADDSET(@p_sigacts.ps_signodefer,sig)
else
SIGDELSET(@p_sigacts.ps_signodefer,sig);
if (sig=SIGCHLD) then
begin
if ((act^.sa_flags and SA_NOCLDSTOP)<>0) then
p_sigacts.ps_flag:=p_sigacts.ps_flag or PS_NOCLDSTOP
else
p_sigacts.ps_flag:=p_sigacts.ps_flag and (not PS_NOCLDSTOP);
if ((act^.sa_flags and SA_NOCLDWAIT)<>0) then
begin
p_sigacts.ps_flag:=p_sigacts.ps_flag or PS_NOCLDWAIT;
end else
p_sigacts.ps_flag:=p_sigacts.ps_flag and (not PS_NOCLDWAIT);
if (p_sigacts.ps_sigact[_SIG_IDX(SIGCHLD)]=sig_t(SIG_IGN)) then
p_sigacts.ps_flag:=p_sigacts.ps_flag or PS_CLDSIGIGN
else
p_sigacts.ps_flag:=p_sigacts.ps_flag and (not PS_CLDSIGIGN);
end;
if (p_sigacts.ps_sigact[_SIG_IDX(sig)]=sig_t(SIG_IGN)) or
(((sigprop(sig) and SA_IGNORE)<>0) and
(p_sigacts.ps_sigact[_SIG_IDX(sig)]=sig_t(SIG_DFL))) then
begin
sigqueue_delete_proc(sig);
if (sig<>SIGCONT) then
begin
SIGADDSET(@p_sigacts.ps_sigignore,sig);
end;
SIGDELSET(@p_sigacts.ps_sigcatch,sig);
end else
begin
SIGDELSET(@p_sigacts.ps_sigignore,sig);
if (p_sigacts.ps_sigact[_SIG_IDX(sig)]=sig_t(SIG_DFL)) then
SIGDELSET(@p_sigacts.ps_sigcatch,sig)
else
SIGADDSET(@p_sigacts.ps_sigcatch,sig);
end;
end;
ps_mtx_unlock;
PROC_UNLOCK;
Result:=0;
end;
Function sys_sigaction(sig:Integer;act,oact:Pointer):Integer;
var
_act,_oact:sigaction_t;
actp,oactp:p_sigaction_t;
begin
actp :=nil;
oactp:=nil;
if (oact<>nil) then oactp:=@_oact;
if (act<>nil) then
begin
actp:=@_act;
Result:=copyin(act,actp,sizeof(sigaction_t));
if (Result<>0) then Exit;
end;
Result:=kern_sigaction(sig,actp,oactp);
if (oact<>nil) and (Result=0) then
begin
Result:=copyout(oactp,oact,sizeof(sigaction_t));
end;
end;
procedure siginit;
var
i:Integer;
begin
mtx_init(p_sigacts.ps_mtx,'sigacts');
For i:=1 to NSIG do
begin
if ((sigprop(i) and SA_IGNORE)<>0) and (i<>SIGCONT) then
begin
SIGADDSET(@p_sigacts.ps_sigignore,i);
end;
end;
sigqueue_init(@p_proc.p_sigqueue);
end;
procedure reschedule_signals(block:sigset_t;flags:Integer); forward;
Function kern_sigprocmask(td:p_kthread;
how:Integer;
_set:p_sigset_t;
oset:p_sigset_t;
flags:Integer
):Integer; public;
label
_out;
var
new_block,oset1:sigset_t;
begin
Result:=0;
if ((flags and SIGPROCMASK_PROC_LOCKED)=0) then
begin
PROC_LOCK;
end;
if (oset<>nil) then
begin
oset^:=td^.td_sigmask;
end;
if (_set<>nil) then
begin
Case how of
SIG_BLOCK:
begin
SIG_CANTMASK(_set);
oset1:=td^.td_sigmask;
SIGSETOR(@td^.td_sigmask, _set);
new_block:=td^.td_sigmask;
SIGSETNAND(@new_block, @oset1);
end;
SIG_UNBLOCK:
begin
SIGSETNAND(@td^.td_sigmask, _set);
signotify(td);
goto _out;
end;
SIG_SETMASK:
begin
SIG_CANTMASK(_set);
oset1:=td^.td_sigmask;
if ((flags and SIGPROCMASK_OLD)<>0) then
SIGSETLO(@td^.td_sigmask, _set)
else
td^.td_sigmask:=_set^;
new_block:=td^.td_sigmask;
SIGSETNAND(@new_block, @oset1);
signotify(td);
end;
else
begin
Result:=EINVAL;
goto _out;
end;
end;
reschedule_signals(new_block, flags);
end;
_out:
if ((flags and SIGPROCMASK_PROC_LOCKED)=0) then
begin
PROC_UNLOCK;
end;
end;
Function sys_sigprocmask(how:Integer;_set,oset:Pointer):Integer;
var
td:p_kthread;
__set,_oset:sigset_t;
setp,osetp:p_sigset_t;
begin
td:=curkthread;
if (td=nil) then Exit(-1);
setp :=nil;
osetp:=nil;
if (oset<>nil) then osetp:=@_oset;
if (_set<>nil) then
begin
setp:=@__set;
Result:=copyin(_set,setp,sizeof(sigset_t));
if (Result<>0) then Exit;
end;
Result:=kern_sigprocmask(td,how,setp,osetp,0);
if (oset<>nil) and (Result=0) then
begin
Result:=copyout(osetp,oset,sizeof(sigset_t));
end;
end;
Function sys_sigpending(oset:Pointer):Integer;
var
td:p_kthread;
pending:sigset_t;
begin
td:=curkthread;
if (td=nil) then Exit(-1);
PROC_LOCK;
pending:=p_proc.p_sigqueue.sq_signals;
SIGSETOR(@pending,@td^.td_sigqueue.sq_signals);
PROC_UNLOCK;
Result:=copyout(@pending,oset,sizeof(sigset_t));
end;
Function kern_sigtimedwait(td:p_kthread;
waitset:sigset_t;
ksi:p_ksiginfo;
timeout:p_timespec
):Integer;
var
saved_mask,new_block:sigset_t;
rts,ets,tv:Int64;
sig,timevalid:Integer;
begin
Result:=0;
timevalid:=0;
ets:=0;
if (timeout<>nil) then
begin
if (timeout^.tv_nsec >= 0) and (timeout^.tv_nsec < 1000000000) then
begin
timevalid:=1;
rts:=get_unit_uptime;
ets:=rts;
ets:=ets+TIMESPEC_TO_UNIT(timeout);
end;
end;
ksiginfo_init(ksi);
SIG_CANTMASK(@waitset);
PROC_LOCK;
saved_mask:=td^.td_sigmask;
SIGSETNAND(@td^.td_sigmask,@waitset);
repeat
ps_mtx_lock;
sig:=cursig(td,SIG_STOP_ALLOWED);
ps_mtx_unlock;
if (sig<>0) and SIGISMEMBER(@waitset,sig) then
begin
if (sigqueue_get(@td^.td_sigqueue,sig,ksi)<>0) or
(sigqueue_get(@p_proc.p_sigqueue,sig,ksi)<>0) then
begin
Result:=0;
break;
end;
end;
if (Result<>0) then Break;
if (timeout<>nil) then
begin
if (timevalid=0) then
begin
Result:=EINVAL;
break;
end;
rts:=get_unit_uptime;
if (rts>=ets) then
begin
Result:=EAGAIN;
break;
end;
tv:=ets-rts;
tv:=tvtohz(tv);
end else
begin
tv:=0;
end;
Result:=msleep(@p_sigacts,@p_proc.p_mtx,PPAUSE or PCATCH,'sigwait',tv);
if (timeout<>nil) then
begin
if (Result=ERESTART) then
begin
Result:=EINTR;
end else
if (Result=EAGAIN) then
begin
Result:=0;
end;
end;
until false;
new_block:=saved_mask;
SIGSETNAND(@new_block,@td^.td_sigmask);
td^.td_sigmask:=saved_mask;
reschedule_signals(new_block,0);
//if (ksi^.ksi_code == SI_TIMER)
// itimer_accept(p, ksi^.ksi_timerid, ksi);
if (sig=SIGKILL) then
begin
sigexit(td,sig);
end;
PROC_UNLOCK;
end;
Function sys_sigwait(oset:Pointer;sig:PInteger):Integer;
var
td:p_kthread;
ksi:ksiginfo_t;
__set:sigset_t;
begin
td:=curkthread;
if (td=nil) then
begin
td^.td_retval[0]:=EFAULT;
Exit(0);
end;
Result:=copyin(oset,@__set,sizeof(sigset_t));
if (Result<>0) then
begin
td^.td_retval[0]:=EFAULT;
Exit(0);
end;
Result:=kern_sigtimedwait(td,__set,@ksi,nil);
if (Result<>0) then
begin
if (Result=EINTR) then
begin
Result:=ERESTART;
end;
if (Result=ERESTART) then
begin
Exit;
end;
td^.td_retval[0]:=Result;
Exit(0);
end;
Result:=copyout(@ksi.ksi_info.si_signo,sig,sizeof(Integer));
td^.td_retval[0]:=Result;
Result:=0;
end;
Function sys_sigtimedwait(oset,info,timeout:Pointer):Integer;
var
td:p_kthread;
ts:timespec;
ksi:ksiginfo_t;
__set:sigset_t;
begin
td:=curkthread;
if (td=nil) then Exit(-1);
if (timeout<>nil) then
begin
Result:=copyin(timeout,@ts,sizeof(timespec));
if (Result<>0) then Exit;
timeout:=@ts;
end;
Result:=copyin(oset,@__set,sizeof(sigset_t));
if (Result<>0) then Exit;
Result:=kern_sigtimedwait(td,__set,@ksi,timeout);
if (Result<>0) then Exit;
if (info<>nil) then
begin
Result:=copyout(@ksi.ksi_info,info,sizeof(siginfo_t));
if (Result<>0) then Exit;
end;
td^.td_retval[0]:=ksi.ksi_info.si_signo;
end;
Function sys_sigwaitinfo(oset,info:Pointer):Integer;
var
td:p_kthread;
ksi:ksiginfo_t;
__set:sigset_t;
begin
td:=curkthread;
if (td=nil) then Exit(-1);
Result:=copyin(oset,@__set,sizeof(sigset_t));
if (Result<>0) then Exit;
Result:=kern_sigtimedwait(td,__set,@ksi,nil);
if (Result<>0) then Exit;
if (info<>nil) then
begin
Result:=copyout(@ksi.ksi_info,info,sizeof(siginfo_t));
if (Result<>0) then Exit;
end;
td^.td_retval[0]:=ksi.ksi_info.si_signo;
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
//PROC_UNLOCK; //
//while (msleep_td(0)=0) do;
//PROC_LOCK; //
while (msleep(@p_sigacts,@p_proc.p_mtx,PPAUSE or PCATCH,'pause',0)=0) do;
//thread_suspend_check(0);
ps_mtx_lock;
repeat
sig:=cursig(td,SIG_STOP_ALLOWED);
if (sig=0) then Break;
has_sig:=has_sig+postsig(sig);
until false;
ps_mtx_unlock;
end;
PROC_UNLOCK;
td^.td_errno:=EINTR;
td^.td_pflags:=td^.td_pflags or TDP_NERRNO;
Result:=EJUSTRETURN;
end;
Function sys_sigsuspend(sigmask:Pointer):Integer;
var
td:p_kthread;
mask:sigset_t;
begin
td:=curkthread;
if (td=nil) then Exit(-1);
Result:=copyin(sigmask,@mask,sizeof(sigset_t));
if (Result<>0) then Exit;
Result:=kern_sigsuspend(td,mask);
end;
Function kern_sigaltstack(td:p_kthread;ss:p_stack_t;oss:p_stack_t):Integer;
var
oonstack:Integer;
begin
oonstack:=sigonstack(cpu_getstack(td));
if (oss<>nil) then
begin
oss^:=td^.td_sigstk;
if ((td^.td_pflags and TDP_ALTSTACK)<>0) then
begin
if (oonstack<>0) then
begin
oss^.ss_flags:=SS_ONSTACK;
end else
begin
oss^.ss_flags:=0;
end;
end else
begin
oss^.ss_flags:=SS_DISABLE;
end;
end;
if (ss<>nil) then
begin
if (oonstack<>0) then Exit(EPERM);
if ((ss^.ss_flags and (not SS_DISABLE))<>0) then Exit(EINVAL);
if ((ss^.ss_flags and SS_DISABLE)=0) then
begin
if (ss^.ss_size<MINSIGSTKSZ) then Exit(ENOMEM);
td^.td_sigstk:=ss^;
td^.td_pflags:=td^.td_pflags or TDP_ALTSTACK;
end else
begin
td^.td_pflags:=td^.td_pflags and (not TDP_ALTSTACK);
end;
end;
Result:=0;
end;
Function sys_sigaltstack(ss,oss:Pointer):Integer;
var
td:p_kthread;
_ss,_oss:stack_t;
p_oss:p_stack_t;
begin
td:=curkthread;
if (td=nil) then Exit(-1);
if (ss<>nil) then
begin
Result:=copyin(ss,@_ss,sizeof(stack_t));
if (Result<>0) then Exit;
ss:=@_ss;
end;
p_oss:=nil;
if (oss<>nil) then
begin
p_oss:=@_oss;
end;
Result:=kern_sigaltstack(td,ss,p_oss);
if (Result<>0) then Exit;
if (oss<>nil) then
begin
Result:=copyout(p_oss,oss,sizeof(stack_t));
end;
end;
function pksignal(sig:Integer;ksi:p_ksiginfo):Integer; forward;
{
* Common code for kill process group/broadcast kill.
* cp is calling process.
}
function killpg1(sig,pgid,all:Integer;ksi:p_ksiginfo):Integer;
var
err:Integer;
begin
Result:=ESRCH;
if (all<>0) then
begin
//broadcast
PROC_LOCK;
err:=p_cansignal(sig);
if (err=0) then
begin
if (sig<>0) then pksignal(sig, ksi);
Result:=err;
end else
if (Result=ESRCH) then
begin
Result:=err;
end;
PROC_UNLOCK;
end else
begin
if (pgid=0) then
begin
//zero pgid means send to my process group.
end else
begin
Exit(ESRCH);
end;
PROC_LOCK;
err:=p_cansignal(sig);
if (err=0) then
begin
if (sig<>0) then pksignal(sig, ksi);
Result:=err;
end else
if (Result=ESRCH) then
begin
Result:=err;
end;
PROC_UNLOCK;
end;
end;
function sys_kill(pid,signum:Integer):Integer;
var
ksi:ksiginfo_t;
error:Integer;
begin
if (signum > _SIG_MAXSIG) then
begin
Exit(EINVAL);
end;
ksiginfo_init(@ksi);
ksi.ksi_info.si_signo:=signum;
ksi.ksi_info.si_code:=SI_USER;
ksi.ksi_info.si_pid :=pid;
if (pid > 0) then
begin
{ kill single process }
if (pid<>p_proc.p_pid) then Exit(ESRCH);
PROC_LOCK;
error:=p_cansignal(signum);
if (error=0) and (signum<>0) then
begin
pksignal(signum, @ksi);
end;
PROC_UNLOCK;
Exit(error);
end;
case pid of
-1: { broadcast signal }
Exit(killpg1(signum, 0, 1, @ksi));
0: { signal own process group }
Exit(killpg1(signum, 0, 0, @ksi));
else { negative explicit process group }
Exit(killpg1(signum, -pid, 0, @ksi));
end;
{ NOTREACHED }
end;
function sys_sigqueue(pid,signum:Integer;value:Pointer):Integer;
var
ksi:ksiginfo_t;
error:Integer;
begin
if (signum > _SIG_MAXSIG) then
begin
Exit(EINVAL);
end;
{
* Specification says sigqueue can only send signal to
* single process.
}
if (pid <= 0) then
begin
Exit(EINVAL);
end;
if (pid<>0) and (pid<>p_proc.p_pid) then
begin
Exit(ESRCH);
end;
error:=p_cansignal(signum);
if (error=0) and (signum<>0) then
begin
ksiginfo_init(@ksi);
ksi.ksi_flags:=KSI_SIGQ;
ksi.ksi_info.si_signo:=signum;
ksi.ksi_info.si_code :=SI_QUEUE;
ksi.ksi_info.si_pid :=p_proc.p_pid;
ksi.ksi_info.si_value.sival_ptr:=value;
PROC_LOCK();
error:=pksignal(signum, @ksi);
PROC_UNLOCK();
end;
Exit(error);
end;
procedure postsig_done(sig:Integer;td:p_kthread);
var
mask:sigset_t;
begin
InterlockedIncrement64(p_proc.p_nsignals);
InterlockedIncrement64(td^.td_ru.ru_nsignals);
mask:=p_sigacts.ps_catchmask[_SIG_IDX(sig)];
if (not SIGISMEMBER(@p_sigacts.ps_signodefer,sig)) then
begin
SIGADDSET(@mask,sig);
end;
kern_sigprocmask(td,SIG_BLOCK,@mask,nil,SIGPROCMASK_PROC_LOCKED or SIGPROCMASK_PS_LOCKED);
if (SIGISMEMBER(@p_sigacts.ps_sigreset,sig)) then
begin
SIGDELSET(@p_sigacts.ps_sigcatch,sig);
if (sig<>SIGCONT) and
((sigprop(sig) and SA_IGNORE)<>0) then
begin
SIGADDSET(@p_sigacts.ps_sigignore,sig);
end;
p_sigacts.ps_sigact[_SIG_IDX(sig)]:=sig_t(SIG_DFL);
end;
end;
function tdsendsignal(td:p_kthread;sig:Integer;ksi:p_ksiginfo):Integer; forward;
procedure trapsignal(td:p_kthread;ksi:p_ksiginfo);
var
sig:Integer;
begin
sig :=ksi^.ksi_info.si_signo;
Assert(_SIG_VALID(sig),'invalid signal');
PROC_LOCK;
ps_mtx_lock;
if SIGISMEMBER(@p_sigacts.ps_sigcatch,sig) and
(not SIGISMEMBER(@td^.td_sigmask,sig)) then
begin
sendsig(p_sigacts.ps_sigact[_SIG_IDX(sig)],ksi,@td^.td_sigmask);
postsig_done(sig,td);
ps_mtx_unlock;
end else
begin
//ignoring?
if (kern_forcesigexit<>0) and
(SIGISMEMBER(@td^.td_sigmask,sig) or
(p_sigacts.ps_sigact[_SIG_IDX(sig)]=sig_t(SIG_IGN))) then
begin
SIGDELSET(@td^.td_sigmask,sig);
SIGDELSET(@p_sigacts.ps_sigcatch,sig);
SIGDELSET(@p_sigacts.ps_sigignore,sig);
p_sigacts.ps_sigact[_SIG_IDX(sig)]:=sig_t(SIG_DFL);
end;
ps_mtx_unlock;
tdsendsignal(td,sig,ksi);
end;
PROC_UNLOCK;
end;
function sigtd(sig,prop:Integer):p_kthread;
var
td:p_kthread;
first_td :p_kthread;
signal_td:p_kthread;
begin
td:=curkthread;
if (td<>nil) then
if not SIGISMEMBER(@td^.td_sigmask,sig) then
begin
Exit(td);
end;
first_td :=nil;
signal_td:=nil;
threads_lock;
td:=TAILQ_FIRST(get_p_threads);
while (td<>nil) do
begin
if (first_td=nil) then
begin
first_td:=td;
end;
if (not SIGISMEMBER(@td^.td_sigmask,sig)) then
begin
signal_td:=td;
Break;
end;
td:=TAILQ_NEXT(td,@td^.td_plist)
end;
threads_unlock;
if (signal_td=nil) then
begin
Result:=first_td;
end else
begin
Result:=signal_td;
end;
end;
procedure kern_psignal(sig:Integer);
var
ksi:ksiginfo_t;
begin
ksiginfo_init(@ksi);
ksi.ksi_info.si_signo:=sig;
ksi.ksi_info.si_code :=SI_KERNEL;
ksi.ksi_info.si_pid :=p_proc.p_pid;
tdsendsignal(nil,sig,@ksi);
end;
function pksignal(sig:Integer;ksi:p_ksiginfo):Integer;
begin
Result:=tdsendsignal(nil,sig,ksi);
end;
procedure tdsigwakeup(td:p_kthread;sig:Integer;action:sig_t;intrval:Integer); forward;
function tdsendsignal(td:p_kthread;sig:Integer;ksi:p_ksiginfo):Integer;
var
sigqueue:p_sigqueue;
action:sig_t;
intrval:Integer;
prop:Integer;
begin
Result:=0;
Writeln('tdsendsignal(',td^.td_tid,':',td^.td_name,',',sig,')');
KNOTE_LOCKED(@p_proc.p_klist, NOTE_SIGNAL or sig);
prop:=sigprop(sig);
if (td=nil) then
begin
td:=sigtd(sig,prop);
sigqueue:=@p_proc.p_sigqueue;
end else
begin
sigqueue:=@td^.td_sigqueue;
end;
ps_mtx_lock;
if (SIGISMEMBER(@p_sigacts.ps_sigignore,sig)) then
begin
ps_mtx_unlock;
if (ksi<>nil) then
if (ksi^.ksi_flags and KSI_INS)<>0 then
begin
ksiginfo_tryfree(ksi);
end;
Exit;
end;
if (SIGISMEMBER(@td^.td_sigmask,sig)) then
action:=sig_t(SIG_HOLD)
else
if (SIGISMEMBER(@p_sigacts.ps_sigcatch,sig)) then
action:=sig_t(SIG_CATCH)
else
action:=sig_t(SIG_DFL);
if (SIGISMEMBER(@p_sigacts.ps_sigintr,sig)) then
begin
intrval:=EINTR;
end else
begin
intrval:=ERESTART;
end;
ps_mtx_unlock;
if ((prop and SA_CONT)<>0) then
begin
sigqueue_delete_stopmask_proc
end else
if ((prop and SA_STOP)<>0) then
begin
sigqueue_delete_proc(SIGCONT);
end;
Result:=sigqueue_add(sigqueue,sig,ksi);
if (Result<>0) then Exit;
signotify(td);
if (action=sig_t(SIG_HOLD)) and ((prop and SA_CONT)=0) then Exit;
tdsigwakeup(td,sig,action,intrval);
end;
procedure tdsignal(td:p_kthread;sig:Integer); public;
var
ksi:ksiginfo_t;
begin
ksiginfo_init(@ksi);
ksi.ksi_info.si_signo:=sig;
ksi.ksi_info.si_code :=SI_KERNEL;
ksi.ksi_info.si_pid :=p_proc.p_pid;
tdsendsignal(td,sig,@ksi);
end;
procedure tdksignal(td:p_kthread;sig:Integer;ksi:p_ksiginfo);
begin
tdsendsignal(td,sig,ksi);
end;
procedure forward_signal(td:p_kthread);
begin
if (td=curkthread) then Exit;
ipi_send_cpu(td);
end;
procedure tdsigwakeup(td:p_kthread;sig:Integer;action:sig_t;intrval:Integer);
label
_out;
var
prop:Integer;
begin
prop:=sigprop(sig);
PROC_LOCK;
thread_lock(td);
if (action=sig_t(SIG_DFL)) and ((prop and SA_KILL)<>0) and (td^.td_priority>PUSER) then
begin
sched_prio(td,PUSER);
end;
if TD_ON_SLEEPQ(td) then
begin
if ((td^.td_flags and TDF_SINTR)=0) then
begin
goto _out;
end;
if ((prop and SA_CONT)<>0) and (action=sig_t(SIG_DFL)) then
begin
thread_unlock(td);
PROC_UNLOCK;
sigqueue_delete(@p_proc.p_sigqueue,sig);
sigqueue_delete(@td^.td_sigqueue,sig);
Exit;
end;
if ((prop and SA_STOP)<>0) and ((td^.td_flags and TDF_SBDRY)<>0) then
begin
goto _out;
end;
if (td^.td_priority>PUSER) then
begin
sched_prio(td,PUSER);
end;
sleepq_abort(td,intrval);
end else
begin
if TD_IS_RUNNING(td) and (td<>curkthread) then
begin
forward_signal(td);
end;
end;
_out:
PROC_UNLOCK;
thread_unlock(td);
end;
procedure reschedule_signals(block:sigset_t;flags:Integer);
var
td:p_kthread;
sig:Integer;
begin
if (SIGISEMPTY(@p_proc.p_sigqueue.sq_signals)) then Exit;
SIGSETAND(@block,@p_proc.p_sigqueue.sq_signals);
repeat
sig:=sig_ffs(@block);
if (sig=0) then Exit;
SIGDELSET(@block,sig);
td:=sigtd(sig,0);
signotify(td);
if ((flags and SIGPROCMASK_PS_LOCKED)=0) then
begin
ps_mtx_lock;
end;
if SIGISMEMBER(@p_sigacts.ps_sigcatch,sig) then
begin
if SIGISMEMBER(@p_sigacts.ps_sigintr,sig) then
begin
tdsigwakeup(td,sig,sig_t(SIG_CATCH),EINTR);
end else
begin
tdsigwakeup(td,sig,sig_t(SIG_CATCH),ERESTART);
end;
end;
if ((flags and SIGPROCMASK_PS_LOCKED)=0) then
begin
ps_mtx_unlock;
end;
until false;
end;
procedure tdsigcleanup(td:p_kthread);
var
unblocked:sigset_t;
begin
sigqueue_flush(@td^.td_sigqueue);
SIGFILLSET(@unblocked);
SIGSETNAND(@unblocked,@td^.td_sigmask);
SIGFILLSET(@td^.td_sigmask);
reschedule_signals(unblocked,0);
end;
function sigdeferstop:Integer; public;
var
td:p_kthread;
begin
td:=curkthread;
if (td^.td_flags and TDF_SBDRY)<>0 then Exit(0);
thread_lock(td);
td^.td_flags:=td^.td_flags or TDF_SBDRY;
thread_unlock(td);
Result:=1;
end;
procedure sigallowstop; public;
var
td:p_kthread;
begin
td:=curkthread;
thread_lock(td);
td^.td_flags:=td^.td_flags and (not TDF_SBDRY);
thread_unlock(td);
end;
Function issignal(td:p_kthread;stop_allowed:Integer):Integer;
var
sigpending:sigset_t;
sig,prop:Integer;
begin
repeat
sigpending:=td^.td_sigqueue.sq_signals;
SIGSETOR(@sigpending,@p_proc.p_sigqueue.sq_signals);
SIGSETNAND(@sigpending,@td^.td_sigmask);
if (td^.td_flags and TDF_SBDRY)<>0 then
begin
SIG_STOPSIGMASK(@sigpending);
end;
if (SIGISEMPTY(@sigpending)) then
begin
Exit(0);
end;
sig:=sig_ffs(@sigpending);
if SIGISMEMBER(@p_sigacts.ps_sigignore,sig) then
begin
sigqueue_delete(@td^.td_sigqueue,sig);
sigqueue_delete(@p_proc.p_sigqueue,sig);
continue;
end;
prop:=sigprop(sig);
Case ptrint(p_sigacts.ps_sigact[_SIG_IDX(sig)]) of
SIG_DFL:
begin
if ((prop and SA_STOP)<>0) then
begin
ps_mtx_unlock;
PROC_LOCK;
//sig_suspend_threads(td, p, 0);
//thread_suspend_switch(td);
PROC_UNLOCK;
ps_mtx_lock;
end else
if ((prop and SA_IGNORE)<>0) then
begin
//ignore
end else
begin
Exit(sig);
end;
end;
SIG_IGN:; //ignore
else
Exit(sig);
end;
sigqueue_delete(@td^.td_sigqueue,sig);
sigqueue_delete(@p_proc.p_sigqueue,sig);
until false;
end;
function postsig(sig:Integer):Integer;
var
td:p_kthread;
action:sig_t;
ksi:ksiginfo_t;
returnmask:sigset_t;
begin
td:=curkthread;
Assert(sig<>0,'postsig');
ksiginfo_init(@ksi);
if (sigqueue_get(@td^.td_sigqueue,sig,@ksi)=0) and
(sigqueue_get(@p_proc.p_sigqueue,sig,@ksi)=0) then
begin
Exit(0);
end;
ksi.ksi_info.si_signo:=sig;
//if (ksi.ksi_code=SI_TIMER)
// itimer_accept(p, ksi.ksi_timerid, &ksi);
action:=p_sigacts.ps_sigact[_SIG_IDX(sig)];
if (action=sig_t(SIG_DFL)) then
begin
ps_mtx_unlock;
sigexit(td,sig);
// NOTREACHED
end else
begin
Assert((action<>sig_t(SIG_IGN)) and (not SIGISMEMBER(@td^.td_sigmask,sig)),'postsig action');
if ((td^.td_pflags and TDP_OLDMASK)<>0) then
begin
returnmask:=td^.td_oldsigmask;
td^.td_pflags:=td^.td_pflags and (not TDP_OLDMASK);
end else
begin
returnmask:=td^.td_sigmask;
end;
sendsig(action,@ksi,@returnmask);
postsig_done(sig,td);
end;
Result:=1;
end;
procedure sigexit(td:p_kthread;sig:Integer); public;
begin
exit1(W_EXITCODE(0,sig));
// NOTREACHED
end;
//
procedure ast; public;
var
td:p_kthread;
flags,sig:Integer;
//
sttop:Pointer;
stack:Pointer;
begin
td:=curkthread;
if (td=nil) then Exit;
Writeln('ast');
//teb stack
if ((td^.pcb_flags and PCB_IS_JIT)=0) then
begin
sttop:=td^.td_teb^.sttop;
stack:=td^.td_teb^.stack;
//
td^.td_teb^.sttop:=td^.td_kstack.sttop;
td^.td_teb^.stack:=td^.td_kstack.stack;
end;
//teb stack
thread_lock(td);
flags:=td^.td_flags;
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);
if ((flags and TDF_ALRMPEND)<>0) then
begin
PROC_LOCK;
kern_psignal(SIGVTALRM);
PROC_UNLOCK;
end;
if ((flags and TDF_PROFPEND)<>0) then
begin
PROC_LOCK;
kern_psignal(SIGPROF);
PROC_UNLOCK;
end;
if ((flags and TDF_NEEDRESCHED)<>0) then
begin
thread_lock(td);
sched_prio(td,td^.td_user_pri);
mi_switch(SW_INVOL or SWT_NEEDRESCHED);
thread_unlock(td);
end;
if ((flags and TDF_NEEDSIGCHK)<>0) or
(p_proc.p_pendingcnt>0) or
(not SIGISEMPTY(@p_proc.p_sigqueue.sq_list)) then
begin
PROC_LOCK;
ps_mtx_lock;
repeat
sig:=cursig(td,SIG_STOP_ALLOWED);
if (sig=0) then Break;
postsig(sig);
until false;
ps_mtx_unlock;
PROC_UNLOCK;
end;
if ((flags and TDF_NEEDSUSPCHK)<>0) then
begin
//PROC_LOCK;
//thread_suspend_check(0);
//PROC_UNLOCK;
end;
if ((td^.td_pflags and TDP_OLDMASK)<>0) then
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;
mi_switch(SW_VOL or SWT_SUSPEND);
thread_unlock(td);
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;
//teb stack
if ((td^.pcb_flags and PCB_IS_JIT)=0) then
begin
td^.td_teb^.sttop:=sttop;
td^.td_teb^.stack:=stack;
end;
//teb stack
end;
//
function filt_sigattach(kn:p_knote):Integer;
begin
kn^.kn_ptr.p_proc:=@p_proc;
kn^.kn_flags:=kn^.kn_flags or EV_CLEAR; // automatically set
knlist_add(@p_proc.p_klist, kn, 0);
Exit(0);
end;
procedure filt_sigdetach(kn:p_knote);
begin
knlist_remove(@p_proc.p_klist, kn, 0);
end;
function filt_signal(kn:p_knote;hint:QWORD):Integer;
begin
if ((hint and NOTE_SIGNAL)<>0) then
begin
hint:=hint and (not NOTE_SIGNAL);
if (kn^.kn_id=hint) then
begin
Inc(kn^.kn_kevent.data);
end;
end;
Exit(ord(kn^.kn_data<>0));
end;
end.