FPPS4/sys/kern/kern_exit.pas

206 lines
4.8 KiB
Plaintext

unit kern_exit;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
uses
sys_resource;
const
WCOREFLAG=&0200;
_WSTOPPED=&0177; { _WSTATUS if process is stopped }
{
* Option bits for the third argument of wait4. WNOHANG causes the
* wait to not hang if there are no stopped or terminated processes, rather
* returning an error indication in this case (pid==0). WUNTRACED
* indicates that the caller should receive status about untraced children
* which stop due to signals. If children are stopped and a wait without
* this option is done, it is as though they were still running... nothing
* about them is returned. WNOWAIT only request information about zombie,
* leaving the proc around, available for later waits.
}
WNOHANG =1; { Don't hang in wait. }
WUNTRACED =2; { Tell about stopped, untraced children. }
WSTOPPED =WUNTRACED; { SUS compatibility }
WCONTINUED=4; { Report a job control continued process. }
WNOWAIT =8; { Poll only. Don't delete the proc entry. }
WEXITED =16; { Wait for exited processes. }
WTRAPPED =32; { Wait for a process to hit a trap or a breakpoint. }
WLINUXCLONE=$80000000; { Wait for kthread spawned from linux_clone. }
{
* Tokens for special values of the "pid" parameter to wait4.
* Extended struct __wrusage to collect rusage for both the target
* process and its children within one wait6() call.
}
WAIT_ANY =(-1); { any process }
WAIT_MYPGRP=0; { any process in my process group }
type
_W_INT=Integer;
function _WSTATUS(x:Integer):Integer; inline;
function WIFSTOPPED(x:Integer):Boolean; inline;
function WSTOPSIG(x:Integer):Integer; inline;
function WIFSIGNALED(x:Integer):Boolean; inline;
function WTERMSIG(x:Integer):Integer; inline;
function WIFEXITED(x:Integer):Boolean; inline;
function WEXITSTATUS(x:Integer):Integer; inline;
function WIFCONTINUED(x:Integer):Boolean; inline; { 0x13=SIGCONT }
function WCOREDUMP(x:Integer):Boolean; inline;
function W_STOPCODE(sig:Integer):Integer; inline;
function W_EXITCODE(ret,sig:Integer):Integer; inline;
procedure exit1(rv:Integer);
procedure sys_sys_exit(rval:Integer);
function sys_wait4(pid:Integer;status:PInteger;options:Integer;rusage:Pointer):Integer;
implementation
uses
errno,
systm,
sys_bootparam,
kern_proc,
sys_event,
md_sleep,
md_proc;
function _WSTATUS(x:Integer):Integer; inline;
begin
Result:=(_W_INT(x) and &0177);
end;
function WIFSTOPPED(x:Integer):Boolean; inline;
begin
Result:=(_WSTATUS(x)=_WSTOPPED);
end;
function WSTOPSIG(x:Integer):Integer; inline;
begin
Result:=(_W_INT(x) shr 8) ;
end;
function WIFSIGNALED(x:Integer):Boolean; inline;
begin
Result:=(_WSTATUS(x)<>_WSTOPPED) and (_WSTATUS(x)<>0);
end;
function WTERMSIG(x:Integer):Integer; inline;
begin
Result:=(_WSTATUS(x));
end;
function WIFEXITED(x:Integer):Boolean; inline;
begin
Result:=(_WSTATUS(x)=0);
end;
function WEXITSTATUS(x:Integer):Integer; inline;
begin
Result:=(_W_INT(x) shr 8);
end;
function WIFCONTINUED(x:Integer):Boolean; inline; { 0x13=SIGCONT }
begin
Result:=(x=$13);
end;
function WCOREDUMP(x:Integer):Boolean; inline;
begin
Result:=(_W_INT(x) and WCOREFLAG)<>0;
end;
function W_STOPCODE(sig:Integer):Integer; inline;
begin
Result:=(sig shl 8) or _WSTOPPED;
end;
function W_EXITCODE(ret,sig:Integer):Integer; inline;
begin
Result:=(ret shl 8) or sig;
end;
procedure thread_suspend_all(exclude:Pointer); external;
procedure exit1(rv:Integer);
begin
//Notify interested parties of our demise.
KNOTE_UNLOCKED(@p_proc.p_klist, NOTE_EXIT);
//
if (p_halt_on_exit) then
begin
md_halt(rv);
end else
begin
thread_suspend_all(p_host_ipc_td);
msleep_td(0);
end;
end;
procedure sys_sys_exit(rval:Integer);
begin
exit1(W_EXITCODE(rval, 0));
// NOTREACHED
end;
function kern_wait(pid:Integer;status:PInteger;options:Integer;rusage:p_rusage):Integer;
begin
options:=options or WEXITED or WTRAPPED;
{ If we don't know the option, just return. }
if ((options and (not (WUNTRACED or WNOHANG or WCONTINUED or WNOWAIT or
WEXITED or WTRAPPED or WLINUXCLONE)))<>0) then
begin
Exit(EINVAL);
end;
if ((options and (WEXITED or WUNTRACED or WCONTINUED or WTRAPPED))=0) then
begin
{
* We will be unable to find any matching processes,
* because there are no known events to look for.
* Prefer to Exiterror instead of blocking
* indefinitely.
}
Exit(EINVAL);
end;
Exit(ECHILD);
end;
{
* The dirty work is handled by kern_wait().
}
function sys_wait4(pid:Integer;status:PInteger;options:Integer;rusage:Pointer):Integer;
var
ru:t_rusage;
rup:p_rusage;
error,_status:Integer;
begin
if (rusage<>nil) then
rup:=@ru
else
rup:=nil;
error:=kern_wait(pid, @_status, options, rup);
if (status<>nil) and (error=0) then
error:=copyout(@_status, status, sizeof(_status));
if (rusage<>nil) and (error=0) then
error:=copyout(@ru, rusage, sizeof(t_rusage));
Exit(error);
end;
end.