boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

forktest.c (4128B)


      1 /* Tier 2 demo: parent atomic-spawns "child" with one syscall, waitid's
      2  * for it, reports the result. Mirrors the scheme1 prelude's spawn/wait
      3  * pattern in C. The seed kernel offers sys_spawn (private syscall 1024)
      4  * in place of POSIX clone+execve. */
      5 
      6 typedef long          i64;
      7 typedef unsigned long u64;
      8 typedef int           i32;
      9 
     10 #if defined(__x86_64__)
     11 #define SYS_write       1
     12 #define SYS_exit_group  60
     13 #define SYS_waitid      247
     14 #elif defined(__riscv)
     15 #define SYS_write       64
     16 #define SYS_exit_group  93
     17 #define SYS_waitid      95
     18 #else
     19 #define SYS_write       64
     20 #define SYS_exit_group  93
     21 #define SYS_waitid      95
     22 #endif
     23 #define SYS_spawn      1024
     24 
     25 extern i64 syscall6(u64 nr, u64 a, u64 b, u64 c, u64 d, u64 e, u64 f);
     26 
     27 static i64 sys_write(int fd, const void *buf, u64 n) { return syscall6(SYS_write, (u64)fd, (u64)buf, n, 0,0,0); }
     28 static void sys_exit(int c) { syscall6(SYS_exit_group, (u64)c, 0,0,0,0,0); for(;;); }
     29 static i64 sys_spawn(const char *p, char **argv) { return syscall6(SYS_spawn, (u64)p, (u64)argv, 0, 0, 0, 0); }
     30 static i64 sys_waitid(int id, int pid, void *info, int opts) { return syscall6(SYS_waitid, (u64)id, (u64)pid, (u64)info, (u64)opts, 0, 0); }
     31 
     32 void *memset(void *d, int c, u64 n) {
     33     unsigned char *dd = d; for (u64 i = 0; i < n; i++) dd[i] = (unsigned char)c; return d;
     34 }
     35 
     36 static u64 strlen_(const char *s) { u64 n = 0; while (s[n]) n++; return n; }
     37 static void puts_(const char *s) { sys_write(1, s, strlen_(s)); }
     38 static void put_d(i64 v) {
     39     char buf[24]; int i = 0;
     40     if (v < 0) { sys_write(1, "-", 1); v = -v; }
     41     if (v == 0) buf[i++] = '0';
     42     while (v) { buf[i++] = '0' + (char)(v % 10); v /= 10; }
     43     while (i--) sys_write(1, &buf[i], 1);
     44 }
     45 
     46 void _start_c(long argc, char **argv) {
     47     puts_("[forktest] argc="); put_d(argc); puts_(" argv[0]="); puts_(argv[0]); puts_("\n");
     48 
     49     char *cargv[3];
     50     cargv[0] = "child";
     51     cargv[1] = "from-parent";
     52     cargv[2] = 0;
     53     long pid = sys_spawn("child", cargv);
     54     puts_("[forktest:parent] spawn returned pid="); put_d(pid); puts_("\n");
     55     unsigned char info[128];
     56     memset(info, 0, sizeof info);
     57     long w = sys_waitid(/*P_PID*/1, (int)pid, info, /*WEXITED*/4);
     58     puts_("[forktest:parent] waitid="); put_d(w);
     59     puts_(" si_code="); put_d(*(i32 *)(info + 8));
     60     puts_(" si_status="); put_d(*(i32 *)(info + 24));
     61     puts_("\n");
     62     sys_exit(0);
     63 }
     64 
     65 /* tcc 0.9.26 quirk: in a toplevel asm() block, `.globl name` followed by
     66  * `name:` leaves the symbol UND in the .o symtab. Putting the label
     67  * first and `.globl name` after makes tcc register it as defined. gcc
     68  * accepts both orderings. */
     69 #if defined(__x86_64__)
     70 asm(
     71     "_start: mov (%rsp), %rdi\n"
     72     ".globl _start\n"
     73     ".type  _start, @function\n"
     74     "    lea 8(%rsp), %rsi\n"
     75     "    call _start_c\n"
     76     "\n"
     77     "syscall6:\n"
     78     ".globl syscall6\n"
     79     ".type  syscall6, @function\n"
     80     "    mov %rdi, %rax\n"
     81     "    mov %rsi, %rdi\n"
     82     "    mov %rdx, %rsi\n"
     83     "    mov %rcx, %rdx\n"
     84     "    mov %r8,  %r10\n"
     85     "    mov %r9,  %r8\n"
     86     "    mov 8(%rsp), %r9\n"
     87     "    int $0x80\n"
     88     "    ret\n");
     89 #elif defined(__riscv)
     90 asm(
     91     "_start: ld a0, 0(sp)\n"
     92     ".globl _start\n"
     93     ".type  _start, @function\n"
     94     "    addi a1, sp, 8\n"
     95     "    tail _start_c\n"
     96     "\n"
     97     "syscall6:\n"
     98     ".globl syscall6\n"
     99     ".type  syscall6, @function\n"
    100     "    mv a7, a0\n"
    101     "    mv a0, a1\n"
    102     "    mv a1, a2\n"
    103     "    mv a2, a3\n"
    104     "    mv a3, a4\n"
    105     "    mv a4, a5\n"
    106     "    mv a5, a6\n"
    107     "    ecall\n"
    108     "    ret\n");
    109 #else
    110 asm(
    111     "_start: ldr x0, [sp]\n"
    112     ".globl _start\n"
    113     ".type  _start, %function\n"
    114     "    add x1, sp, #8\n"
    115     "    b   _start_c\n"
    116     "\n"
    117     /* syscall6(nr, a..f) — args land in x0..x6 by SysV ABI. Linux
    118      * arm64 wants the syscall number in x8 and a..f in x0..x5. */
    119     "syscall6:\n"
    120     ".globl syscall6\n"
    121     ".type  syscall6, %function\n"
    122     "    mov x8, x0\n"
    123     "    mov x0, x1\n"
    124     "    mov x1, x2\n"
    125     "    mov x2, x3\n"
    126     "    mov x3, x4\n"
    127     "    mov x4, x5\n"
    128     "    mov x5, x6\n"
    129     "    svc #0\n"
    130     "    ret\n");
    131 #endif