599 lines
13 KiB
C
599 lines
13 KiB
C
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
|
|
#include "psxmsg.h"
|
|
#include <signal.h>
|
|
#include <errno.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
#include <sys/times.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
|
|
#include "tsttmp.h" // defines DbgPrint as printf
|
|
|
|
extern int errno;
|
|
|
|
VOID p0(VOID);
|
|
VOID p1(VOID);
|
|
VOID ex0(VOID);
|
|
VOID a0(VOID);
|
|
VOID s0(VOID);
|
|
VOID call0(VOID);
|
|
VOID f1(VOID);
|
|
VOID f2(VOID);
|
|
VOID p0foo(VOID);
|
|
|
|
CONTEXT a0JumpBuff;
|
|
|
|
int __cdecl main(int argc, char *argv[])
|
|
{
|
|
|
|
pid_t self;
|
|
PCH p,t;
|
|
PTEB ThreadInfo;
|
|
|
|
ThreadInfo = NtCurrentTeb();
|
|
|
|
self = getpid();
|
|
|
|
DbgPrint("tstfork: My pid is %lx Argc = %lx\n",self,argc);
|
|
DbgPrint("tstfork: StackBase %lx\n",ThreadInfo->NtTib.StackBase);
|
|
DbgPrint("tstfork: StackLimit %lx\n",ThreadInfo->NtTib.StackLimit);
|
|
DbgPrint("tstfork: ClientId %lx.%lx\n",ThreadInfo->ClientId.UniqueProcess,ThreadInfo->ClientId.UniqueThread);
|
|
|
|
while(argc--){
|
|
p = *argv++;
|
|
t = p;
|
|
while(*t++);
|
|
DbgPrint("Argv --> %s\n",p);
|
|
}
|
|
|
|
|
|
p0();
|
|
p1();
|
|
ex0();
|
|
a0();
|
|
s0();
|
|
call0();
|
|
f1();
|
|
f2();
|
|
|
|
_exit(2);
|
|
return 1;
|
|
|
|
}
|
|
|
|
VOID
|
|
p0foo(){}
|
|
|
|
ULONG
|
|
p0touch(
|
|
IN PUCHAR pch,
|
|
IN ULONG nb
|
|
)
|
|
{
|
|
ULONG ct = 0;
|
|
|
|
DbgPrint("p0touch: pch %lx nb %lx\n",pch,nb);
|
|
|
|
while (nb--) {
|
|
ct += *pch++;
|
|
}
|
|
return ct;
|
|
}
|
|
|
|
VOID
|
|
p0()
|
|
{
|
|
int fildes[2];
|
|
int psxst;
|
|
UCHAR buffer[525];
|
|
UCHAR buf[525];
|
|
int i;
|
|
|
|
for(i=0;i<525;i++){
|
|
buf[i] = (char)(i&255);
|
|
}
|
|
|
|
DbgPrint("p0:++\n");
|
|
|
|
//
|
|
// Create a pipe
|
|
//
|
|
|
|
psxst = pipe(fildes);
|
|
|
|
if ( psxst ) {
|
|
DbgPrint("p0: pipe() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
|
|
DbgPrint("p0: fildes[0] = %lx filedes[1] = %lx\n",fildes[0],fildes[1]);
|
|
|
|
//
|
|
// Test write followed by read
|
|
//
|
|
|
|
psxst = write(fildes[1],"Hello World\n",13);
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p0: write() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
|
|
DbgPrint("p0: write() success transfered %lx bytes to fd %lx\n",psxst,fildes[1]);
|
|
|
|
psxst = read(fildes[0],buffer,32);
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p0: read() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
|
|
p0touch(buffer,psxst);
|
|
DbgPrint("p0: read() success transfered %lx bytes from fd %lx %s\n",psxst,fildes[1],buffer);
|
|
//
|
|
// End write followed by read
|
|
//
|
|
|
|
|
|
//
|
|
// assume parents read will happen before childs write.
|
|
// parents first read blocks testing write unblocks read
|
|
//
|
|
|
|
if ( !fork() ) {
|
|
|
|
|
|
DbgPrint("p0:child pid %lx\n",getpid());
|
|
DbgPrint("p0:child writing\n");
|
|
|
|
sleep(8);
|
|
|
|
psxst = write(fildes[1],"From Child\n\0",12);
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p0:child write() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
DbgPrint("p0:child write() success transfered %lx bytes to fd %lx\n",psxst,fildes[1]);
|
|
|
|
psxst = write(fildes[1],"Small Write\n\0",13);
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p0:child write() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
DbgPrint("p0:child write() success transfered %lx bytes to fd %lx\n",psxst,fildes[1]);
|
|
|
|
//
|
|
// this write should block and get unblocked when read of
|
|
// previous write completes
|
|
//
|
|
p0foo();
|
|
psxst = write(fildes[1],buf,514);
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p0:child write() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
DbgPrint("p0:child write() success transfered %lx bytes to fd %lx\n",psxst,fildes[1]);
|
|
|
|
_exit(1);
|
|
}
|
|
|
|
DbgPrint("p0:parent reading\n");
|
|
psxst = read(fildes[0],buffer,12);
|
|
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p0:parent read() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
p0touch(buffer,psxst);
|
|
DbgPrint("p0:parent read() success transfered %lx bytes from fd %lx %s\n",psxst,fildes[1],buffer);
|
|
|
|
DbgPrint("p0:parent sleeping\n");
|
|
sleep(12);
|
|
DbgPrint("p0:parent back from sleep\n");
|
|
|
|
DbgPrint("p0:parent reading\n");
|
|
psxst = read(fildes[0],buffer,13);
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p0:parent read() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
p0touch(buffer,psxst);
|
|
DbgPrint("p0:parent read() success transfered %lx bytes from fd %lx %s\n",psxst,fildes[1],buffer);
|
|
|
|
psxst = read(fildes[0],buffer,512);
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p0:parent read() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
DbgPrint("p0:parent read() success transfered %lx bytes from fd %lx\n",psxst,fildes[1]);
|
|
|
|
for(i=0;i<psxst;i++){
|
|
if ( buf[i] != buffer[i] ) {
|
|
DbgPrint("p0: Compare failed. i %lx master %lx vs. %lx\n",i,buf[i],buffer[i]);
|
|
}
|
|
}
|
|
|
|
psxst = read(fildes[0],buffer,512);
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p0:parent read() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
DbgPrint("p0:parent read() success transfered %lx bytes from fd %lx\n",psxst,fildes[1]);
|
|
|
|
for(i=0;i<psxst;i++){
|
|
if ( buf[i] != buffer[i] ) {
|
|
DbgPrint("p0: Compare failed. i %lx master %lx vs. %lx\n",i,buf[i],buffer[i]);
|
|
}
|
|
}
|
|
wait(NULL);
|
|
|
|
close(fildes[0]);
|
|
close(fildes[1]);
|
|
|
|
DbgPrint("p0:--\n");
|
|
|
|
}
|
|
|
|
VOID
|
|
p1()
|
|
{
|
|
int fildes[2];
|
|
int psxst;
|
|
UCHAR buffer[525];
|
|
UCHAR buf[525];
|
|
int i;
|
|
|
|
for(i=0;i<525;i++){
|
|
buf[i] = (char)(i&255);
|
|
}
|
|
|
|
DbgPrint("p1:++\n");
|
|
|
|
//
|
|
// Create a pipe
|
|
//
|
|
|
|
psxst = pipe(fildes);
|
|
|
|
if ( psxst ) {
|
|
DbgPrint("p1: pipe() failed st = %lx errno %lx\n",psxst,errno);
|
|
return;
|
|
}
|
|
|
|
DbgPrint("p1: fildes[0] = %lx filedes[1] = %lx\n",fildes[0],fildes[1]);
|
|
|
|
//
|
|
// Test write to readonly fd
|
|
//
|
|
|
|
psxst = write(fildes[0],"Hello World\n",13);
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p1: write test NT_SUCCESS %lx errno %lx\n",psxst,errno);
|
|
}
|
|
|
|
//
|
|
// Test read to writeonly fd
|
|
//
|
|
|
|
psxst = read(fildes[1],buf,13);
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("p1: read test NT_SUCCESS %lx errno %lx\n",psxst,errno);
|
|
}
|
|
|
|
|
|
//
|
|
// Close Write Handle
|
|
//
|
|
|
|
close(fildes[1]);
|
|
|
|
//
|
|
// Test read w/ no writers
|
|
//
|
|
|
|
psxst = read(fildes[0],buffer,32);
|
|
if ( psxst == 0 ) {
|
|
DbgPrint("p1: read test NT_SUCCESS %lx\n",psxst);
|
|
}
|
|
|
|
close(fildes[0]);
|
|
|
|
DbgPrint("p1:--\n");
|
|
|
|
}
|
|
|
|
VOID
|
|
ex0()
|
|
{
|
|
PCH Arg[3], Env[4];
|
|
struct tms TimeBuffer;
|
|
clock_t TimesRtn;
|
|
int fildes[2];
|
|
int rc;
|
|
|
|
DbgPrint("ex0:++\n");
|
|
|
|
rc = pipe(fildes);
|
|
ASSERT(rc==0 && fildes[0] == 0 && fildes[1] == 1);
|
|
|
|
if ( !fork() ) {
|
|
|
|
if ( !fork() ) {
|
|
|
|
Arg[0]="tsthello.n10";
|
|
Arg[1]=(PCH)NULL;
|
|
Env[0]="NTUSER=MARKL";
|
|
Env[1]=(PCH)NULL;
|
|
|
|
//
|
|
// We should not have any accumulated child times
|
|
//
|
|
|
|
TimesRtn = times(&TimeBuffer);
|
|
ASSERT(TimesRtn != 0);
|
|
ASSERT(TimeBuffer.tms_cstime == 0 && TimeBuffer.tms_cutime == 0);
|
|
|
|
write(1,&TimeBuffer,sizeof(TimeBuffer));
|
|
execve("\\DosDevices\\D:\\PSX\\TSTHELLO.exe",Arg,Env);
|
|
|
|
DbgPrint("ex0:child returned from exec ? errno %lx\n",errno);
|
|
|
|
_exit(1);
|
|
}
|
|
|
|
wait(NULL);
|
|
|
|
//
|
|
// We should not have any accumulated child times
|
|
//
|
|
|
|
TimesRtn = times(&TimeBuffer);
|
|
ASSERT(TimesRtn != 0);
|
|
DbgPrint("tms_cstime %lx tms_cutime %lx\n",TimeBuffer.tms_cstime,TimeBuffer.tms_cutime);
|
|
ASSERT(TimeBuffer.tms_cstime != 0 || TimeBuffer.tms_cutime != 0);
|
|
|
|
_exit(2);
|
|
}
|
|
|
|
wait(NULL);
|
|
|
|
DbgPrint("ex0:parent wait satisfied \n");
|
|
|
|
close(fildes[0]);
|
|
close(fildes[1]);
|
|
|
|
DbgPrint("ex0:--\n");
|
|
|
|
}
|
|
|
|
VOID
|
|
call0()
|
|
{
|
|
VOID PdxNullPosixApi();
|
|
|
|
#ifdef SIMULATOR
|
|
for(i=0;i<10;i++) {
|
|
begin = rnuminstr();
|
|
PdxNullPosixApi();
|
|
end = rnuminstr();
|
|
|
|
DbgPrint("Call Time 0x%lx 0x%lx 0x%lx dec %ld\n",begin, end, end - begin,end-begin);
|
|
}
|
|
#endif // SIMULATOR
|
|
|
|
}
|
|
|
|
VOID
|
|
f1()
|
|
{
|
|
pid_t child,wchild;
|
|
|
|
DbgPrint("f1:+++\n");
|
|
|
|
child = fork();
|
|
|
|
if ( child == 0 ) {
|
|
DbgPrint("tstfork_child: I am the child %lx\n",getpid());
|
|
_exit(1);
|
|
}
|
|
|
|
DbgPrint("tstfork_parent: My child is %lx\n",child);
|
|
|
|
wchild = wait(NULL);
|
|
|
|
DbgPrint("tstfork_parent: Wait on child %lx satisfied %lx errno %lx\n",
|
|
child,
|
|
wchild,
|
|
errno
|
|
);
|
|
DbgPrint("f1:---\n");
|
|
}
|
|
|
|
void
|
|
__cdecl
|
|
f2catcher(
|
|
IN int sig
|
|
)
|
|
{
|
|
DbgPrint("f2catcher, signal == %lx\n",sig);
|
|
}
|
|
|
|
VOID
|
|
f2()
|
|
{
|
|
struct sigaction act, oact;
|
|
pid_t child,wchild,parent;
|
|
int psxst;
|
|
|
|
|
|
//
|
|
// Send signal to parent which sould be in wait. Parent should
|
|
// get EINTR from wait. If it retries, then wait will succeed.
|
|
//
|
|
|
|
DbgPrint("f2:+++\n");
|
|
|
|
act.sa_handler = f2catcher;
|
|
sigfillset(&act.sa_mask);
|
|
act.sa_flags = 0;
|
|
|
|
if (sigaction(SIGUSR1, &act ,&oact) ) {
|
|
DbgPrint("f2: fail sigaction errno %lx\n",errno);
|
|
_exit(-1);
|
|
}
|
|
|
|
child = fork();
|
|
if( !child ) {
|
|
|
|
DbgPrint("tstfork_child: I am the child %lx parent %lx\n",
|
|
getpid(),
|
|
(parent = getppid())
|
|
);
|
|
|
|
DbgPrint("tstfork_child: Killing SIGUSR1 parent %lx\n",parent);
|
|
|
|
psxst = kill(parent,SIGUSR1);
|
|
|
|
if ( psxst < 0 ) {
|
|
DbgPrint("tstfork_child: kill failed %lx errno %lx\n",psxst,errno);
|
|
_exit(errno);
|
|
}
|
|
|
|
_exit(1);
|
|
}
|
|
|
|
DbgPrint("tstfork_parent: My child is %lx\n",child);
|
|
|
|
wchild = wait(NULL);
|
|
|
|
DbgPrint("tstfork_parent: Wait on child %lx satisfied %lx errno %lx\n",
|
|
child,
|
|
wchild,
|
|
errno
|
|
);
|
|
|
|
if ( wchild < 0 && errno == EINTR ) {
|
|
DbgPrint("tstfork_parent: wait interrupted by SIGUSR1. Rewait\n");
|
|
|
|
wchild = wait(NULL);
|
|
|
|
DbgPrint("tstfork_parent: Wait on child %lx satisfied %lx errno %lx\n",
|
|
child,
|
|
wchild,
|
|
errno
|
|
);
|
|
}
|
|
|
|
DbgPrint("f2:---\n");
|
|
}
|
|
|
|
void
|
|
__cdecl
|
|
a0catcher(
|
|
IN int sig
|
|
)
|
|
{
|
|
DbgPrint("a0catcher, signal == %lx long jumping...\n",sig);
|
|
NtContinue(&a0JumpBuff,FALSE);
|
|
}
|
|
|
|
VOID
|
|
a0()
|
|
{
|
|
struct sigaction act, oact;
|
|
unsigned int previous;
|
|
NTSTATUS st;
|
|
sigset_t eset;
|
|
|
|
//
|
|
// Call alarm and then sit in a loop
|
|
//
|
|
|
|
DbgPrint("a0:+++\n");
|
|
|
|
act.sa_handler = a0catcher;
|
|
sigfillset(&act.sa_mask);
|
|
act.sa_flags = 0;
|
|
|
|
if (sigaction(SIGALRM, &act ,&oact) ) {
|
|
DbgPrint("a0: fail sigaction errno %lx\n",errno);
|
|
_exit(-1);
|
|
}
|
|
|
|
a0JumpBuff.ContextFlags = CONTEXT_FULL;
|
|
|
|
st = NtGetContextThread(NtCurrentThread(),&a0JumpBuff);
|
|
|
|
#ifdef MIPS
|
|
a0JumpBuff.IntV0 = 0x12345678;
|
|
#endif
|
|
|
|
#ifdef i386
|
|
a0JumpBuff.Eax = 0x12345678;
|
|
#endif
|
|
|
|
if (st == STATUS_SUCCESS) {
|
|
previous = alarm(2);
|
|
for(;;);
|
|
}
|
|
|
|
sigemptyset(&eset);
|
|
sigprocmask(SIG_SETMASK,&eset,NULL);
|
|
|
|
DbgPrint("a0: Longjumpp st = %lx\n",st);
|
|
|
|
//
|
|
// start a 10 second alarm and then cancel it
|
|
//
|
|
|
|
a0JumpBuff.ContextFlags = CONTEXT_FULL;
|
|
|
|
st = NtGetContextThread(NtCurrentThread(),&a0JumpBuff);
|
|
|
|
#ifdef MIPS
|
|
a0JumpBuff.IntV0 = 0x12345678;
|
|
#endif
|
|
|
|
#ifdef i386
|
|
a0JumpBuff.Eax = 0x12345678;
|
|
#endif
|
|
|
|
if (st == STATUS_SUCCESS) {
|
|
previous = alarm(10);
|
|
sleep(1);
|
|
previous = alarm(0);
|
|
DbgPrint("Previous = %lx\n",previous);
|
|
}
|
|
|
|
sigemptyset(&eset);
|
|
sigprocmask(SIG_SETMASK,&eset,NULL);
|
|
|
|
DbgPrint("a0:---\n");
|
|
}
|
|
|
|
VOID
|
|
s0()
|
|
{
|
|
|
|
LARGE_INTEGER BeginTime,EndTime;
|
|
unsigned int psxst;
|
|
|
|
DbgPrint("s0:+++\n");
|
|
|
|
NtQuerySystemTime(&BeginTime);
|
|
|
|
DbgPrint("s0: sleeping\n");
|
|
|
|
psxst = sleep(1);
|
|
|
|
NtQuerySystemTime(&EndTime);
|
|
|
|
DbgPrint("s0: sleep(1) returned %lx\n",psxst);
|
|
DbgPrint("s0: BeginTime %lx %lx\n",BeginTime.HighPart,BeginTime.LowPart);
|
|
DbgPrint("s0: EndTime %lx %lx\n",EndTime.HighPart,EndTime.LowPart);
|
|
|
|
DbgPrint("s0:---\n");
|
|
|
|
}
|