feat: extend stopchldtarget with syscall4 and syscall6
This commit is contained in:
1 parent
2709025a74
commit
fa03edc4a5
2 files changed
+113
No files matched your search
@@ -0,0 +1,68 @@
|
||||
#include "ulib.h"
|
||||
|
||||
/*
|
||||
* Only ever spawned by stopchldtest.c, with two shared pipe handles as
|
||||
* argv[1] (the "ready" pipe, this process writes) and argv[2] (the "go"
|
||||
* pipe, this process reads) -- identical shape to user/jobtarget.c, reused
|
||||
* here so stopchldtest.c can stop/continue a target genuinely Blocked
|
||||
* mid-syscall while ALSO watching for the new SIGCHLD-on-stop/
|
||||
* SIGCHLD-on-continue notifications (sched.c's threadStop/threadContinue)
|
||||
* against itself, something jobtest.c/jobtarget.c never needed since
|
||||
* neither side there installs a sigChld handler. A distinct exit code (66,
|
||||
* not jobtarget.c's 55) keeps the two pairs' needles/asserts from ever
|
||||
* being confusable in the serial log.
|
||||
*/
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
print("stopchldtarget: start, pid=");
|
||||
printDec(userGetpid());
|
||||
print("\n");
|
||||
|
||||
if (argc != 3) {
|
||||
print("stopchldtarget: FAIL expected two argv (ready handle, go handle)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
long readyHandle = parseDec(argv[1]);
|
||||
long goHandle = parseDec(argv[2]);
|
||||
|
||||
long goFd = userPipeAttach(goHandle, 0);
|
||||
if (goFd < 0) {
|
||||
print("stopchldtarget: FAIL attach go pipe as reader\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
long readyFd = userPipeAttach(readyHandle, 1);
|
||||
if (readyFd < 0) {
|
||||
print("stopchldtarget: FAIL attach ready pipe as writer\n");
|
||||
return 1;
|
||||
}
|
||||
if (userWrite((int)readyFd, "r", 1) != 1) {
|
||||
print("stopchldtarget: FAIL write ready byte\n");
|
||||
return 1;
|
||||
}
|
||||
userClose((int)readyFd);
|
||||
print("stopchldtarget: ready, blocking on go pipe\n");
|
||||
|
||||
char goByte = 0;
|
||||
/* Real blocking read: parks this thread (threadBlocked) until a byte is
|
||||
actually available. stopchldtest.c raises SIGSTOP against this exact
|
||||
blocking read, waits for its own SIGCHLD-on-stop notification, writes
|
||||
the byte, raises SIGCONT, waits for its own SIGCHLD-on-continue
|
||||
notification, and only then this read can return -- the same
|
||||
restart-syscall retry contract user/jobtarget.c already relies on. */
|
||||
if (userRead((int)goFd, &goByte, 1) != 1) {
|
||||
print("stopchldtarget: FAIL read go byte\n");
|
||||
return 1;
|
||||
}
|
||||
userClose((int)goFd);
|
||||
|
||||
if (goByte != 'g') {
|
||||
print("stopchldtarget: FAIL wrong go byte\n");
|
||||
return 1;
|
||||
}
|
||||
print("stopchldtarget: received go\n");
|
||||
|
||||
return 66;
|
||||
}
|
||||
+45
@@ -11,6 +11,41 @@ static long syscall3(long number, long a1, long a2, long a3)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Same trap as syscall3, with a 4th argument -- passed in r10, not rcx,
|
||||
the same choice the real Linux x86-64 syscall ABI makes (rcx is already
|
||||
spoken for by the `int $0x80`/syscall instruction's own use, so a fourth
|
||||
argument needs a register the trap does not otherwise touch). Only
|
||||
userSigAction needs one today. */
|
||||
static long syscall4(long number, long a1, long a2, long a3, long a4)
|
||||
{
|
||||
long ret;
|
||||
register long a4Reg __asm__("r10") = a4;
|
||||
__asm__ volatile(
|
||||
"int $0x80"
|
||||
: "=a"(ret)
|
||||
: "a"(number), "D"(a1), "S"(a2), "d"(a3), "r"(a4Reg)
|
||||
: "memory", "rcx", "r11");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Same trap again, with a 5th and 6th argument in r8/r9 -- the same real
|
||||
Linux x86-64 syscall ABI register order this file's own 4th-argument
|
||||
choice (r10) already follows, continued one register further. Only
|
||||
userMmap needs this many today. */
|
||||
static long syscall6(long number, long a1, long a2, long a3, long a4, long a5, long a6)
|
||||
{
|
||||
long ret;
|
||||
register long a4Reg __asm__("r10") = a4;
|
||||
register long a5Reg __asm__("r8") = a5;
|
||||
register long a6Reg __asm__("r9") = a6;
|
||||
__asm__ volatile(
|
||||
"int $0x80"
|
||||
: "=a"(ret)
|
||||
: "a"(number), "D"(a1), "S"(a2), "d"(a3), "r"(a4Reg), "r"(a5Reg), "r"(a6Reg)
|
||||
: "memory", "rcx", "r11");
|
||||
return ret;
|
||||
}
|
||||
|
||||
long userWrite(int fd, const char* buffer, unsigned long length)
|
||||
{
|
||||
return syscall3(sysWrite, fd, (long)buffer, (long)length);
|
||||
@@ -46,6 +81,16 @@ void userSleep(unsigned long milliseconds)
|
||||
syscall3(sysSleep, (long)milliseconds, 0, 0);
|
||||
}
|
||||
|
||||
unsigned long userAlarm(unsigned long seconds)
|
||||
{
|
||||
return (unsigned long)syscall3(sysAlarm, (long)seconds, 0, 0);
|
||||
}
|
||||
|
||||
long userPoll(PollFd* fds, unsigned long nfds, long timeoutMs)
|
||||
{
|
||||
return syscall3(sysPoll, (long)fds, (long)nfds, timeoutMs);
|
||||
}
|
||||
|
||||
long userOpen(const char* path, unsigned int flags)
|
||||
{
|
||||
return syscall3(sysOpen, (long)path, (long)flags, 0);
|
||||
|
||||
Reference in new issue
Block a user