xv6, line by line
user/usys.pl

user/usys.pl

Perl · 45 lines · annotated 100% · user program / library · upstream

About this file

A small Perl program that writes the assembly file user/usys.S: one system call stub for each of xv6’s 22 system calls. The stubs are the only place where a user program makes a system call (the only ecall instructions in user code); everything in user/user.h that is a system call is defined by one of them.

The stubs are identical apart from two names, so writing them by hand would be 110 lines of copy and paste in which a typo (a stub loading the wrong number) would be easy to miss. Generating them from a list keeps each call to one line. The Makefile runs the script with perl user/usys.pl > user/usys.S and assembles the result (Makefile:111).

Perl is used here only as a text printer: each print writes one line of the output. You can see the result, with notes, at user/usys.S.

Read next: user/usys.S, then kernel/syscall.c for the kernel side.

1#!/usr/bin/perl -w
3# Generate usys.S, the stubs for syscalls.
5print "# generated by usys.pl - do not edit\n";
7print "#include \"kernel/syscall.h\"\n";
9sub entry {
10 my $prefix = "sys_";
11 my $name = shift;
12 if ($name eq "sbrk") {
13 print ".global $prefix$name\n";
14 print "$prefix$name:\n";
15 } else {
16 print ".global $name\n";
17 print "$name:\n";
18 }
19 print " li a7, SYS_${name}\n";
20 print " ecall\n";
21 print " ret\n";
24entry("fork");
25entry("exit");
26entry("wait");
27entry("pipe");
28entry("read");
29entry("write");
30entry("close");
31entry("kill");
32entry("exec");
33entry("open");
34entry("mknod");
35entry("unlink");
36entry("fstat");
37entry("link");
38entry("mkdir");
39entry("chdir");
40entry("dup");
41entry("getpid");
42entry("sbrk");
43entry("pause");
44entry("uptime");
45entry("sync");