diff options
Diffstat (limited to 'user/progR.c')
-rw-r--r-- | user/progR.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/user/progR.c b/user/progR.c new file mode 100644 index 0000000..1d47f6b --- /dev/null +++ b/user/progR.c @@ -0,0 +1,99 @@ +#include <common.h> + +/** +** User function R: exit, sleep, write, fork, getpid, getppid, +** +** Reports itself and its sequence number, along with its PID and +** its parent's PID. It then delays, forks, delays, reports again, +** and exits. +** +** Invoked as: userR x n [ s ] +** where x is the ID character +** n is the sequence number of the initial incarnation +** s is the initial delay time (defaults to 10) +*/ + +USERMAIN( main ) { + char ch = 'r'; // default character to print + int delay = 10; // initial delay count + int seq = 99; // my sequence number + char buf[128]; + + // process the command-line arguments + switch( argc ) { + case 4: delay = str2int( argv[3], 10 ); + // FALL THROUGH + case 3: seq = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "userR: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + /* + ** C oddity: a label cannot immediately precede a declaration. + ** + ** Declarations are not considered "statements" in C. Prior to + ** C99, all declarations had to precede any statements inside a + ** block. Labels can only appear before statements. C99 allowed + ** the mixing of declarations and statements, but did not relax + ** the requirement that labels precede only statements. + ** + ** That's why the declarations of these variables occur before the + ** label, but their initializations occur after the label. + ** + ** As the PSA says on TV, "The more you know..." :-) + */ + + int32_t pid; + int32_t ppid; + + restart: + + // announce our presence + pid = getpid(); + ppid = getppid(); + + sprint( buf, " %c[%d,%d,%d]", ch, seq, pid, ppid ); + swrites( buf ); + + sleep( SEC_TO_MS(delay) ); + + // create the next child in sequence + if( seq < 5 ) { + ++seq; + int32_t n = fork(); + switch( n ) { + case -1: + // failure? + sprint( buf, "** R[%d] fork code %d\n", pid, n ); + cwrites( buf ); + break; + case 0: + // child + goto restart; + default: + // parent + --seq; + sleep( SEC_TO_MS(delay) ); + } + } + + // final report - PPID may change, but PID and seq shouldn't + pid = getpid(); + ppid = getppid(); + sprint( buf, " %c[%d,%d,%d]", ch, seq, pid, ppid ); + swrites( buf ); + + exit( 0 ); + + return( 42 ); // shut the compiler up! + +} |