mirror of https://github.com/red-prig/fpPS4.git
206 lines
4.8 KiB
Plaintext
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.
|
|
|