BXE: min->MIN, plus an spatch
[akaros.git] / Documentation / plan9.txt
1 We're adding the plan 9 file system to akaros.We're bringing in the
2 name space interface, including the ability to do binds, union mounts,
3 and the like. We will extend it to support things we might need,
4 in particular mmap.  We will use it to add things to Akaros we 
5 need, such as virtio drivers, ethernet drivers, and TCP.
6
7 By bringing this model in, we can make the Akaros interface more powerful,
8 yet simpler. We can remove a number of system calls right away 
9 and yet still have the functions they provide, for example. 
10
11 This is not a from scratch effort but a code translation. The Plan 9 code
12 deals with very subtle situations and has been hardened over time. No need
13 to relearn what they learned from scratch.
14
15 Currently we have a lot of the code in and are testing a first device -- 
16 the regression device from NxM.
17
18 Issues.
19
20 The biggest issue so far is implementing the Plan 9 error handling.
21 In Plan 9, errors are managed via a longjmp-like mechanism. For example,
22 in a call chain such as:
23 a()
24  b()
25   c()
26    d()
27
28 It is possible for 'd' to invoke an error that returns to 'a' directly. 
29 This model has many advantages over the standard model, which looks like
30 this:
31 a{ b();}
32  b{ if c() return OK; else return -1;}
33   c{ if d() return OK; else return -1;}
34    d{ if something return OK; else return -1;}
35
36 In Plan 9 it can look like this:
37
38 a{ b();}
39  b{ c(); something else();}
40   c{ d(); other thing();}
41    d{ if something return OK; else error("bad");}
42
43 Note that the intermediate functions can be written as though nothing
44 went wrong, since anything that goes wrong gets bounced to the first level
45 error handler. 
46
47 The handling is implemented via something called waserror().
48 In a() we do this:
49
50 a(){
51    if (waserror())  { handle error; poperror();}
52    b();
53    poperror();
54 }
55
56 and in d we might have this:
57 d(){
58    do something; 
59    if (bad) error("bad");
60    return 0;
61 }
62
63 What if there's more than one error? There can be multiple invocations
64 of waserror in one function:
65 a(){
66    if (waserror()){ printf("b failed"); poperror(); return -2;}
67    b();
68    if (waserror()) { printf("z failed"); nexterror(); }
69    z();
70    poperror();
71    poperror();
72 }
73
74 Every waserror needs a matching poperror or nexterror in the same function as
75 the waserror, covering every exit from the function.  nexterror is like
76 to poperror() then error("str"), but without resetting errstr.
77
78 Note that the error could have been anywhere in the call chain;
79 we don't care. From the point of view of a(), something failed, and we only
80 know about b() or z(), so we blame them. We also show in this example
81 nexterror(). Nexterror() pops back to the next error in the error stack,
82 which might be in this function or somewhere up the call chain.
83
84 How do we find out the ultimate blame? Recall that error takes a string,
85 and that can be anything. We can tell from that. 
86
87 Where does the string in error() go?
88 In Plan 9, it goes into the proc struct; in Akaros,
89 it's copied to a user-mode buffer via set_errstr(). 
90
91 waserror()/error()/nexterror() manipulate an error call stack, similar to
92 the function call stack. In Plan 9, this stack is maintained in the proc
93 struct. This is cheap in Plan 9, since the compiler has caller-save, and
94 hence each stack entry is a stack and a PC. In a callee-save world, the
95 stack entries are much, much larger; so large that maintaining the stack
96 in the proc struct is impractical.
97
98 Hence, we've had to make changes that add a bit of inconvenience but
99 leave the code mostly intact. The error code in Akaros is tested in every
100 circumstance at this point due to all the bugs we had in our port
101 of the Plan 9 file system code.
102
103 So, we'll go from the easiest case to the hardest.
104
105 Case 1: You're a leaf function that does not use error(). No change.
106
107 Case 2: You're a leaf function that needs error().  Just call error().
108
109 Case 3: You're an intermediate function that calls functions that use error(),
110 even though you do not.  No change.
111
112 Those are in some sense the easier cases. Now it starts to get a
113 bit harder.
114
115 Case 4: you're a leaf or intermediate function that uses waserror().  You need
116 to use a macro which creates an array of errbuf structs as automatics. The
117 waserror() usage does not change.  The macro is ERRSTACK(x), where x is the
118 number of calls to waserror() in your function. See kern/sys/chan.c.  Every call
119 to waserror needs to have a matching poperror.  You cannot call nexterror or
120 poperror unless you are in the same scope as an ERRSTACK that had a waserror
121 call.
122
123 Case 5: you're a root node, i.e. you're the start of a chain of calls
124 via syscall that must do the "root" errbuf setup, so that all error
125 calls eventually return to you. In this case, you need to start the error
126 stack.  This uses the same macro as case 4 (ERRSTACK(x)), for now.
127
128 Finally, if, in a waserror, you are finished and want to pop out to the
129 next error in the chain, either in the same function or up the call stack,
130 just call nexterror().
131
132 This can be handy for debugging: in any function that supports error(), i.e.
133 called from a function that called waserror(), simply call error and it bails
134 you out of wherever you are, doing appropriate cleanup on the way out.  No need
135 to add return value processing to intermediate functions; if you try this out
136 you will likely find it is extremely handy. I really miss it on Linux. It made a
137 lot of the port debugging to Akaros a lot easier.
138
139 There is error checking in error()/waserror()/nexterror().
140 If you overflow or underflow the error stack the kernel will panic.
141 The implementation is in kern/src/error.c, the macros are in
142 kern/include/plan9.h.
143
144
145 For info on the format of Ms (which are part of the kernel interface):
146         http://9p.cat-v.org/documentation/rfc/