diff --git a/rtl/gtailq.pas b/rtl/gtailq.pas
index 9b7ef0b5..b0fd718c 100644
--- a/rtl/gtailq.pas
+++ b/rtl/gtailq.pas
@@ -25,8 +25,85 @@ type
procedure Remove(Node:PNODE);
end;
+procedure TAILQ_INIT (head:Pointer); inline;
+function TAILQ_FIRST (head:Pointer):Pointer; inline;
+function TAILQ_NEXT (elm,field:Pointer):Pointer; inline;
+procedure TAILQ_INSERT_HEAD(head,elm,field:Pointer); inline;
+procedure TAILQ_INSERT_TAIL(head,elm,field:Pointer); inline;
+procedure TAILQ_REMOVE (head,elm,field:Pointer); inline;
+
implementation
+type
+ p_tailq_list=^_tailq_list;
+ _tailq_list=packed record
+ pFirst,pLast:Pointer;
+ end;
+
+ p_tailq_entry=^_tailq_entry;
+ _tailq_entry=packed record
+ pNext,pPrev:Pointer;
+ end;
+
+procedure TAILQ_INIT(head:Pointer); inline;
+begin
+ p_tailq_list(head)^.pFirst:=nil;
+ p_tailq_list(head)^.pLast :=@p_tailq_list(head)^.pFirst;
+end;
+
+function TAILQ_FIRST(head:Pointer):Pointer; inline;
+begin
+ Result:=p_tailq_list(head)^.pFirst;
+end;
+
+function TAILQ_NEXT(elm,field:Pointer):Pointer; inline;
+begin
+ Result:=p_tailq_entry(field)^.pNext;
+end;
+
+procedure TAILQ_INSERT_HEAD(head,elm,field:Pointer); inline;
+var
+ offset:ptruint;
+begin
+ offset:=ptruint(field-elm);
+ if (p_tailq_entry(field)^.pNext=p_tailq_list(head)^.pFirst) and
+ (p_tailq_list(head)^.pFirst<>nil) then
+ begin
+ p_tailq_entry(p_tailq_list(head)^.pFirst+offset)^.pPrev:=@p_tailq_entry(field)^.pNext;
+ end else
+ begin
+ p_tailq_list(head)^.pLast:=@p_tailq_entry(field)^.pNext;
+ end;
+ p_tailq_list(head)^.pFirst:=elm;
+ p_tailq_entry(field)^.pPrev:=@p_tailq_list(head)^.pFirst;
+end;
+
+procedure TAILQ_INSERT_TAIL(head,elm,field:Pointer); inline;
+var
+ offset:ptruint;
+begin
+ offset:=ptruint(field-elm);
+ p_tailq_entry(field)^.pNext:=nil;
+ p_tailq_entry(field)^.pPrev:=p_tailq_list(head)^.pLast;
+ PPointer(p_tailq_list(head)^.pLast)^:=elm;
+ p_tailq_list(head)^.pLast:=@p_tailq_entry(field)^.pNext;
+end;
+
+procedure TAILQ_REMOVE(head,elm,field:Pointer); inline;
+var
+ offset:ptruint;
+begin
+ offset:=ptruint(field-elm);
+ if (p_tailq_entry(field)^.pNext<>nil) then
+ begin
+ p_tailq_entry(p_tailq_entry(field)^.pNext+offset)^.pPrev:=p_tailq_entry(field)^.pPrev;
+ end else
+ begin
+ p_tailq_list(head)^.pLast:=p_tailq_entry(field)^.pPrev;
+ end;
+ PPointer(p_tailq_entry(field)^.pPrev)^:=p_tailq_entry(field)^.pNext;
+end;
+
procedure TAILQ_HEAD.Insert_head(Node:PNODE);
begin
if (pHead=nil) then
diff --git a/sys/kern_sig.pas b/sys/kern_sig.pas
new file mode 100644
index 00000000..fd945e8d
--- /dev/null
+++ b/sys/kern_sig.pas
@@ -0,0 +1,338 @@
+unit kern_sig;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ gtailq,
+ sys_kernel,
+ signal,
+ signalvar;
+
+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
+);
+
+
+implementation
+
+const
+ max_pending_per_proc=128;
+
+var
+ p_pendingcnt :Integer=0;
+ 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: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
+ 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_pendingcnt);
+ end;
+ end;
+ if (count>1) then
+ begin
+ Inc(count);
+ Break;
+ end else
+ begin
+ Inc(count);
+ end;
+ end;
+ ksi:=TAILQ_NEXT(ksi,@ksi^.ksi_link);
+ 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_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_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_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: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
+ TAILQ_REMOVE(@sq^.sq_list,ksi,@ksi^.ksi_link);
+ ksi^.ksi_sigq:=nil;
+ if ksiginfo_tryfree(ksi) then
+ begin
+ Dec(p_pendingcnt);
+ end;
+ ksi:=TAILQ_NEXT(ksi,@ksi^.ksi_link);
+ 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: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
+ 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:=TAILQ_NEXT(ksi,@ksi^.ksi_link);
+ 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: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
+ 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_pendingcnt)
+ end;
+ end;
+
+ ksi:=TAILQ_NEXT(ksi,@ksi^.ksi_link);
+ 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;
+
+
+
+
+end.
+
diff --git a/sys/kern_thread.pas b/sys/kern_thread.pas
index 9d256a29..2500bdbf 100644
--- a/sys/kern_thread.pas
+++ b/sys/kern_thread.pas
@@ -8,7 +8,9 @@ interface
uses
ntapi,
windows,
- sys_kernel;
+ sys_kernel,
+ signal,
+ signalvar;
const
PRI_ITHD =1; // Interrupt thread.
@@ -38,7 +40,7 @@ type
td_umtxq :Pointer; //p_umtx_q
td_handle :THandle; //nt thread
td_lock :Pointer;
- td_tid :DWORD;
+ td_tid :QWORD;
td_ref :Integer;
td_priority :Word;
td_pri_class :Word;
@@ -50,6 +52,8 @@ type
//
td_fsbase :Pointer;
td_cpuset :Ptruint;
+ td_sigmask :sigset_t;
+ td_sigqueue :sigqueue_t;
end;
p_rtprio=^rtprio;
@@ -66,8 +70,8 @@ type
stack_size:Ptruint;
tls_base :Pointer;
tls_size :Ptruint;
- child_tid :PDWORD;
- parent_tid:PDWORD;
+ child_tid :PQWORD;
+ parent_tid:PQWORD;
flags :Integer;
align :Integer;
rtp :p_rtprio;
@@ -92,14 +96,15 @@ function create_thread(td :p_kthread; //calling thread
stack_base:Pointer;
stack_size:QWORD;
tls_base :Pointer;
- child_tid :PDWORD;
- parent_tid:PDWORD;
+ child_tid :PQWORD;
+ parent_tid:PQWORD;
flags :Integer;
rtp :p_rtprio;
name :PChar
):Integer;
-function sys_thr_new(td:p_kthread;_param:p_thr_param;_size:Integer):Integer;
+function sys_thr_new(_param:p_thr_param;_size:Integer):Integer;
+function sys_thr_self(id:PQWORD):Integer;
procedure thread_exit;
@@ -112,6 +117,8 @@ function tdfind(tid:DWORD):p_kthread;
function curkthread:p_kthread; assembler;
procedure set_curkthread(td:p_kthread); assembler;
+function SIGPENDING(td:p_kthread):Boolean; inline;
+
implementation
{
@@ -159,6 +166,12 @@ asm
movqq td,%gs:(0x700)
end;
+function SIGPENDING(td:p_kthread):Boolean; inline;
+begin
+ Result:=SIGNOTEMPTY(@td^.td_sigqueue.sq_signals) and
+ sigsetmasked(@td^.td_sigqueue.sq_signals,@td^.td_sigmask);
+end;
+
procedure threadinit; inline;
begin
FillChar(tidhashtbl,SizeOf(tidhashtbl),0);
@@ -352,8 +365,8 @@ function create_thread(td :p_kthread; //calling thread
stack_base:Pointer;
stack_size:QWORD;
tls_base :Pointer;
- child_tid :PDWORD;
- parent_tid:PDWORD;
+ child_tid :PQWORD;
+ parent_tid:PQWORD;
flags :Integer;
rtp :p_rtprio;
name :PChar
@@ -455,17 +468,21 @@ begin
if (child_tid<>nil) then
begin
- n:=suword32(child_tid^,newtd^.td_tid);
+ n:=suword64(child_tid^,newtd^.td_tid);
if (n<>0) then Goto _term;
end;
if (parent_tid<>nil) then
begin
- n:=suword32(parent_tid^,newtd^.td_tid);
+ n:=suword64(parent_tid^,newtd^.td_tid);
if (n<>0) then Goto _term;
end;
- //newtd->td_sigmask = td->td_sigmask;
+ if (td<>nil) then
+ begin
+ newtd^.td_sigmask:=td^.td_sigmask;
+ end;
+
thread_link(newtd);
if (name<>nil) then
@@ -537,12 +554,16 @@ begin
@name);
end;
-function sys_thr_new(td:p_kthread;_param:p_thr_param;_size:Integer):Integer;
+function sys_thr_new(_param:p_thr_param;_size:Integer):Integer;
var
+ td:p_kthread;
param:thr_param;
begin
if (_size<0) or (_size>Sizeof(thr_param)) then Exit(EINVAL);
+ td:=curkthread;
+ if (td=nil) then Exit(EFAULT);
+
param:=Default(thr_param);
Result:=copyin(_param,@param,_size);
@@ -562,6 +583,9 @@ begin
//td^.td_state:=TDS_INACTIVE;
+ tidhash_remove(td);
+ thread_unlink(td);
+
umtx_thread_exit(td);
thread_dec_ref(td);
@@ -569,11 +593,39 @@ begin
RtlExitUserThread(0);
end;
+function sys_thr_self(id:PQWORD):Integer;
+var
+ td:p_kthread;
+begin
+ if (id=nil) then Exit(EINVAL);
+ td:=curkthread;
+ if (td=nil) then Exit(EFAULT);
+ Result:=suword64(id^,td^.td_tid);
+ if (Result<>0) then Exit(EFAULT);
+ Result:=0;
+end;
+function sys_thr_exit(state:PQWORD):Integer;
+var
+ td:p_kthread;
+begin
+ td:=curkthread;
+ if (td=nil) then Exit(EFAULT);
+
+ if (state<>nil) then
+ begin
+ kern_umtx_wake(td,Pointer(state),High(Integer),0);
+ end;
+
+ //tdsigcleanup(td);
+ //thread_stopped(p);
+ thread_exit();
+ // NOTREACHED
+end;
function rtp_to_pri(rtp:p_rtprio;td:p_kthread):Integer;
var
diff --git a/sys/kern_umtx.pas b/sys/kern_umtx.pas
index 27725311..2f5fa11a 100644
--- a/sys/kern_umtx.pas
+++ b/sys/kern_umtx.pas
@@ -25,6 +25,10 @@ function _sys_umtx_lock(mtx:p_umtx):Integer;
function _sys_umtx_unlock(mtx:p_umtx):Integer;
function _sys_umtx_op(obj:Pointer;op:Integer;val:QWORD;uaddr1,uaddr2:Pointer):Integer;
+//
+
+function kern_umtx_wake(td:p_kthread;umtx:p_umtx;n_wake,priv:Integer):Integer;
+
implementation
uses
@@ -2459,7 +2463,7 @@ var
begin
if (mtx=nil) then Exit(EINVAL);
td:=curkthread;
- if (td=nil) then Exit(EINVAL);
+ if (td=nil) then Exit(EFAULT);
Result:=_do_lock_umtx(td,mtx,td^.td_tid,0);
end;
@@ -2469,7 +2473,7 @@ var
begin
if (mtx=nil) then Exit(EINVAL);
td:=curkthread;
- if (td=nil) then Exit(EINVAL);
+ if (td=nil) then Exit(EFAULT);
Result:=do_unlock_umtx(td,mtx,td^.td_tid);
end;
@@ -2501,7 +2505,7 @@ var
begin
if (obj=nil) then Exit(EINVAL);
td:=curkthread;
- if (td=nil) then Exit(EINVAL);
+ if (td=nil) then Exit(EFAULT);
Case op of
UMTX_OP_LOCK :Result:=__umtx_op_lock_umtx (td,obj,val,uaddr1,uaddr2);
UMTX_OP_UNLOCK :Result:=__umtx_op_unlock_umtx (td,obj,val,uaddr1,uaddr2);
diff --git a/sys/signal.pas b/sys/signal.pas
index dd252463..ffcfd1f2 100644
--- a/sys/signal.pas
+++ b/sys/signal.pas
@@ -204,6 +204,8 @@ const
function _SIG_IDX(sig:Integer):DWORD; inline;
function _SIG_VALID(sig:Integer):Boolean; inline;
function _SIG_VALID_32(sig:Integer):Boolean; inline;
+function _SIG_WORD(sig:Integer):DWORD; inline;
+function _SIG_BIT(sig:Integer):DWORD; inline;
function _get_sig_str(signum:Integer):RawByteString;
@@ -224,6 +226,16 @@ begin
Result:=(sig<=32) and (sig>0);
end;
+function _SIG_WORD(sig:Integer):DWORD; inline;
+begin
+ Result:=_SIG_IDX(sig) shr 5;
+end;
+
+function _SIG_BIT(sig:Integer):DWORD; inline;
+begin
+ Result:=1 shl (_SIG_IDX(sig) and 31);
+end;
+
function _get_sig_str(signum:Integer):RawByteString;
begin
case signum of
diff --git a/sys/signalvar.pas b/sys/signalvar.pas
new file mode 100644
index 00000000..e3ce5be3
--- /dev/null
+++ b/sys/signalvar.pas
@@ -0,0 +1,176 @@
+unit signalvar;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+ signal;
+
+type
+ p_sigacts=^sigacts;
+ sigacts=packed record
+ ps_sigact :array[0.._SIG_MAXSIG-1] of sig_t;
+ ps_catchmask :array[0.._SIG_MAXSIG-1] of sigset_t;
+ ps_sigonstack:sigset_t;
+ ps_sigintr :sigset_t;
+ ps_sigreset :sigset_t;
+ ps_signodefer:sigset_t;
+ ps_siginfo :sigset_t;
+ ps_sigignore :sigset_t;
+ ps_sigcatch :sigset_t;
+ end;
+
+const
+ PS_NOCLDWAIT=$0001; // No zombies if child dies
+ PS_NOCLDSTOP=$0002; // No SIGCHLD when children stop.
+ PS_CLDSIGIGN=$0004; // The SIGCHLD handler is SIG_IGN.
+
+ SIG_CATCH=2;
+
+type
+ p_ksiginfo=^ksiginfo_t;
+ p_sigqueue=^sigqueue_t;
+
+ ksiginfo_list=packed record
+ pFirst:p_ksiginfo;
+ pLast:^p_ksiginfo;
+ end;
+
+ ksiginfo_entry=packed record
+ pNext:p_ksiginfo;
+ pPrev:^p_ksiginfo;
+ end;
+
+ ksiginfo_t=packed record
+ ksi_link :ksiginfo_entry;
+ ksi_info :siginfo_t;
+ ksi_flags:Integer;
+ _align :Integer;
+ ksi_sigq :p_sigqueue;
+ end;
+
+ sigqueue_t=packed record
+ sq_signals:sigset_t;
+ sq_kill :sigset_t;
+ sq_list :ksiginfo_list;
+ sq_flags :Integer;
+ end;
+
+const
+ //bits for ksi_flags
+ KSI_TRAP =$01; // Generated by trap.
+ KSI_EXT =$02; // Externally managed ksi.
+ KSI_INS =$04; // Directly insert ksi, not the copy
+ KSI_SIGQ =$08; // Generated by sigqueue, might ret EGAIN.
+ KSI_HEAD =$10; // Insert into head, not tail.
+ KSI_COPYMASK=(KSI_TRAP or KSI_SIGQ);
+
+ // Flags for ksi_flags
+ SQ_INIT=$01;
+
+function SIGACTION (p:p_sigacts;sig:Integer):sig_t; inline;
+procedure SIGADDSET (p:p_sigset_t;signo:Integer); inline;
+procedure SIGDELSET (p:p_sigset_t;signo:Integer); inline;
+procedure SIGEMPTYSET(p:p_sigset_t); inline;
+procedure SIGFILLSET (p:p_sigset_t); inline;
+function SIGISMEMBER(p:p_sigset_t;signo:Integer):Boolean; inline;
+function SIGISEMPTY (p:p_sigset_t):Boolean; inline;
+function SIGNOTEMPTY(p:p_sigset_t):Boolean; inline;
+function SIGSETEQ (p1,p2:p_sigset_t):Boolean; inline;
+function SIGSETNEQ (p1,p2:p_sigset_t):Boolean; inline;
+procedure SIGSETOR (p1,p2:p_sigset_t); inline;
+procedure SIGSETAND (p1,p2:p_sigset_t); inline;
+procedure SIGSETNAND (p1,p2:p_sigset_t); inline;
+
+function sigsetmasked(p,mask:p_sigset_t):Boolean; inline;
+
+procedure ksiginfo_copy(src,dst:p_ksiginfo); inline;
+
+implementation
+
+function SIGACTION(p:p_sigacts;sig:Integer):sig_t; inline;
+begin
+ Result:=p^.ps_sigact[_SIG_IDX(sig)];
+end;
+
+procedure SIGADDSET(p:p_sigset_t;signo:Integer); inline;
+begin
+ p^.bits[_SIG_WORD(signo)]:=p^.bits[_SIG_WORD(signo)] or _SIG_BIT(signo);
+end;
+
+procedure SIGDELSET(p:p_sigset_t;signo:Integer); inline;
+begin
+ p^.bits[_SIG_WORD(signo)]:=p^.bits[_SIG_WORD(signo)] and (not _SIG_BIT(signo));
+end;
+
+procedure SIGEMPTYSET(p:p_sigset_t); inline;
+begin
+ p^.qwords[0]:=0;
+ p^.qwords[1]:=0;
+end;
+
+procedure SIGFILLSET(p:p_sigset_t); inline;
+begin
+ p^.qwords[0]:=QWORD(-1);
+ p^.qwords[1]:=QWORD(-1);
+end;
+
+function SIGISMEMBER(p:p_sigset_t;signo:Integer):Boolean; inline;
+begin
+ Result:=(p^.bits[_SIG_WORD(signo)] and _SIG_BIT(signo))<>0;
+end;
+
+function SIGISEMPTY(p:p_sigset_t):Boolean; inline;
+begin
+ Result:=(p^.qwords[0]=0) and (p^.qwords[1]=0)
+end;
+
+function SIGNOTEMPTY(p:p_sigset_t):Boolean; inline;
+begin
+ Result:=not SIGISEMPTY(P);
+end;
+
+function SIGSETEQ(p1,p2:p_sigset_t):Boolean; inline;
+begin
+ Result:=(p1^.qwords[0]=p2^.qwords[0]) and (p1^.qwords[1]=p2^.qwords[1]);
+end;
+
+function SIGSETNEQ(p1,p2:p_sigset_t):Boolean; inline;
+begin
+ Result:=not SIGSETEQ(p1,p2);
+end;
+
+procedure SIGSETOR(p1,p2:p_sigset_t); inline;
+begin
+ p1^.qwords[0]:=p1^.qwords[0] or p2^.qwords[0];
+ p1^.qwords[1]:=p1^.qwords[1] or p2^.qwords[1];
+end;
+
+procedure SIGSETAND(p1,p2:p_sigset_t); inline;
+begin
+ p1^.qwords[0]:=p1^.qwords[0] and p2^.qwords[0];
+ p1^.qwords[1]:=p1^.qwords[1] and p2^.qwords[1];
+end;
+
+procedure SIGSETNAND(p1,p2:p_sigset_t); inline;
+begin
+ p1^.qwords[0]:=p1^.qwords[0] and (not p2^.qwords[0]);
+ p1^.qwords[1]:=p1^.qwords[1] and (not p2^.qwords[1]);
+end;
+
+function sigsetmasked(p,mask:p_sigset_t):Boolean; inline;
+begin
+ Result:=((p^.qwords[0] and (not mask^.qwords[0]))<>0) or
+ ((p^.qwords[1] and (not mask^.qwords[1]))<>0);
+end;
+
+procedure ksiginfo_copy(src,dst:p_ksiginfo); inline;
+begin
+ dst^.ksi_info :=src^.ksi_info;
+ dst^.ksi_flags:=src^.ksi_flags and KSI_COPYMASK;
+end;
+
+
+end.
+
diff --git a/sys/systm.pas b/sys/systm.pas
index 80a733f3..73ae4fad 100644
--- a/sys/systm.pas
+++ b/sys/systm.pas
@@ -16,6 +16,7 @@ function fuword64(var base:QWORD):QWORD; inline;
function casuword32(var base:DWORD;oldval,newval:DWORD):DWORD; inline;
function casuword64(var base:QWORD;oldval,newval:QWORD):QWORD; inline;
function suword32(var base:DWORD;word:DWORD):DWORD; inline;
+function suword64(var base:QWORD;word:QWORD):DWORD; inline;
implementation
@@ -101,6 +102,16 @@ begin
end;
end;
+function suword64(var base:QWORD;word:QWORD):DWORD; inline;
+begin
+ if (NtWriteVirtualMemory(NtCurrentProcess,@base,@word,SizeOf(QWORD),nil)=0) then
+ begin
+ Result:=0;
+ end else
+ begin
+ Result:=DWORD(-1);
+ end;
+end;
end.
diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi
index f2652b97..fe5d3801 100644
--- a/sys/test/project1.lpi
+++ b/sys/test/project1.lpi
@@ -69,6 +69,14 @@
+
+
+
+
+
+
+
+
diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr
index 4fa34303..574d7cc4 100644
--- a/sys/test/project1.lpr
+++ b/sys/test/project1.lpr
@@ -14,6 +14,7 @@ uses
kern_lock,
kern_rwlock,
thr_private,
+ kern_sig,
sysutils,
vulkan,
vDevice;
@@ -515,7 +516,7 @@ var
prio:rtprio;
- tid:DWORD;
+ tid:QWORD;
ktd:p_kthread;
_time:Int64;
@@ -567,8 +568,8 @@ begin
ktd:=tdfind(tid);
- NtSuspendThread(ktd^.td_handle,nil);
- NtResumeThread(ktd^.td_handle,nil);
+ //NtSuspendThread(ktd^.td_handle,nil);
+ //NtResumeThread(ktd^.td_handle,nil);
kunlock(lock);