defined 'test_name' for msg()/vmsg() to work properly
[pintos-anon] / TODO
1 -*- text -*-
2
3 * Reconsider command line arg style--confuses everyone.
4
5 * Internal tests.
6
7 * Godmar: Introduce memory leak robustness tests - both for the
8   well-behaved as well as the mis-behaved case - that tests that the
9   kernel handles low-mem conditions well.
10
11 * Godmar: Another area is concurrency. I noticed that I had passed all
12   tests with bochs 2.2.1 (in reproducibility mode). Then I ran them
13   with qemu and hit two deadlocks (one of them in rox-*,
14   incidentally). After fixing those deadlocks, I upgraded to bochs
15   2.2.5 and hit yet another deadlock in reproducibility mode that
16   didn't show up in 2.2.1. All in all, a standard grading run would
17   have missed 3 deadlocks in my code.  I'm not sure how to exploit
18   that for grading - either run with qemu n times (n=2 or 3), or run
19   it with bochs and a set of -j parameters.  Some of which could be
20   known to the students, some not, depending on preference.  (I ported
21   the -j patch to bochs 2.2.5 -
22   http://people.cs.vt.edu/~gback/pintos/bochs-2.2.5.jitter.patch but I
23   have to admit I never tried it so I don't know if it would have
24   uncovered the deadlocks that qemu and the switch to 2.2.5
25   uncovered.)
26
27 * Godmar: There is also the option to require students to develop test
28   workloads themselves, for instance, to demonstrate the effectiveness
29   of a particular algorithm (page eviction & buffer cache replacement
30   come to mind.) This could involve a problem of the form: develop a
31   workload that you cover well, and develop a "worst-case" load where
32   you algorithm performs poorly, and show the results of your
33   quantitative evaluation in your report - this could then be part of
34   their test score.
35
36 * Threads project:
37
38   - Godmar:
39
40     >> Describe a potential race in thread_set_priority() and explain how
41     >> your implementation avoids it.  Can you use a lock to avoid this race?
42
43     I'm not sure what you're getting at here:
44     If changing the priority of a thread involves accessing the ready
45     list, then of course there's a race with interrupt handlers and locks
46     can't be used to resolve it.
47
48     Changing the priority however also involves a race with respect to
49     accessing a thread's "priority" field - this race is with respect to
50     other threads that attempt to donate priority to the thread that's
51     changing its priority. Since this is a thread-to-thread race, I would
52     tend to believe that locks could be used, although I'm not certain.  [
53     I should point out, though, that lock_acquire currently disables
54     interrupts - the purpose of which I had doubted in an earlier email,
55     since sema_down() sufficiently establishes mutual exclusion. Taking
56     priority donation into account, disabling interrupts prevents the race
57     for the priority field, assuming the priority field of each thread is
58     always updated with interrupts disabled. ]
59
60     What answer are you looking for for this design document question?
61
62   - Godmar:
63
64     >> Did any ambiguities in the scheduler specification make values in the
65     >> table uncertain?  If so, what rule did you use to resolve them?  Does
66     >> this match the behavior of your scheduler?
67
68     My guess is that you're referring to the fact the scheduler
69     specification does not prescribe any order in which the priorities of
70     all threads are updated, so if multiple threads end up with the same
71     priority, it doesn't say which one to pick.  ("round-robin" order
72     would not apply here.)
73
74     Is that correct?
75
76   - Godmar:
77     
78     One of my groups implemented priority donation with these data
79     structures in synch.cc:
80     ---
81     struct value
82     {
83       struct list_elem elem;      /* List element. */
84       int value;                  /* Item value. */
85     };
86
87     static struct value values[10];
88     static int start = 10;
89     static int numNest = 0;
90     ---
91     In their implementation, the "elem" field in their "struct value" is
92     not even used.
93
94     The sad part is that they've passed all tests that are currently in
95     the Pintos base with this implementation. (They do fail the additional
96     tests I added priority-donate-sema & priority-donate-multiple2.)
97
98     Another group managed to pass all tests with this construct:
99     ---
100     struct lock
101       {
102         struct thread *holder;      /* Thread holding lock (for debugging). */
103         struct semaphore semaphore; /* Binary semaphore controlling access. */
104         //*************************************
105         int pri_prev;
106         int pri_delta;              //Used for Priority Donation
107         /**************************************************/
108       };
109     ---
110     where "pri_delta" keeps track of "priority deltas." They even pass
111     priority-donate-multiple2.
112
113     I think we'll need a test where a larger number of threads & locks
114     simultaneously exercise priority donation to weed out those
115     implementations.
116
117     It may also be a good idea to use non-constant deltas for the low,
118     medium, and high priority threads in the tests - otherwise, adding a
119     "priority delta" might give - by coincidence - the proper priority for
120     a thread.
121
122   - Godmar: Another thing: one group passed all tests even though they
123     wake up all waiters on a lock_release(), rather than just
124     one. Since there's never more than one waiter in our tests, they
125     didn't fail anything. Another possible TODO item - this could be
126     part a series of "regression tests" that check that they didn't
127     break basic functionality in project 1. I don't think this would
128     be insulting to the students.
129
130 * Userprog project:
131
132   - Get rid of rox--causes more trouble than it's worth
133
134   - Extra credit: specifics on how to implement sbrk, malloc.
135
136   - Godmar: We're missing tests that pass arguments to system calls
137     that span multiple pages, where some are mapped and some are not.
138     An implementation that only checks the first page, rather than all
139     pages that can be touched during a call to read()/write() passes
140     all tests.
141
142   - Godmar: Need some tests that test that illegal accesses lead to
143     process termination. I have written some, will add them. In P2,
144     obviously, this would require that the students break this
145     functionality since the page directory is initialized for them,
146     still it would be good to have.
147
148   - Godmar: There does not appear to be a test that checks that they
149     close all fd's on exit.  Idea: add statistics & self-diagnostics
150     code to palloc.c and malloc.c.  Self-diagnostics code could be
151     used for debugging.  The statistics code would report how much
152     kernel memory is free.  Add a system call
153     "get_kernel_memory_information".  User programs could engage in a
154     variety of activities and notice leaks by checking the kernel
155     memory statistics.
156
157   - Godmar: is there a test that tests that they properly kill a process that
158     attempts to access an invalid address in user code, e.g. *(void**)0 =
159     42;?
160
161     It seems all of the robustness tests deal with bad pointers passed to
162     system calls (at least judging from test/userprog/Rubric.robustness),
163     but none deals with bad accesses by user code, or I am missing
164     something.
165
166     ps: I found tests/vm/pt-bad-addr, which is in project 3 only, though.
167
168     For completeness, we should probably check read/write/jump to unmapped
169     user virtual address and to mapped kernel address, for a total of 6
170     cases. I wrote up some tests, see
171     http://people.cs.vt.edu/~gback/pintos/bad-pointers/
172
173   - process_death test needs improvement
174
175   - Godmar: In the wait() tests, there's currently no test that tests
176     that a process can only wait for its own children. There's only
177     one test that tests that wait() on an invalid pid returns -1 (or
178     kills the process), but no test where a valid pid is used that is
179     not a child of the current process.
180
181     The current tests also do not ensure that both scenarios (parent waits
182     first vs. child exits first) are exercised. In this context, I'm
183     wondering if we should add a sleep() system call that would export
184     timer_sleep() to user processes; this would allow the construction of
185     such a test. It would also make it easier to construct a test for the
186     valid-pid, but not-a-child scenario.
187
188     As in Project 4, the baseline implementation of timer_sleep() should
189     suffice, so this would not necessarily require basing Project 2 on
190     Project 1. [ A related thought: IMO it would not be entirely
191     unreasonable to require timer_sleep() and priority scheduling sans
192     donation from Project 1 working for subsequent projects. ]
193
194 * VM project:
195
196   - Godmar: Get rid of mmap syscall, add sbrk.
197
198   - Godmar: page-linear, page-shuffle VM tests do not use enough
199     memory to force eviction.  Should increase memory consumption.
200
201   - Godmar: fix the page* tests to require swapping
202
203   - Godmar: make sure the filesystem fails if not properly
204     concurrency-protected in project 3.
205
206   - Godmar: Another area in which tests could be created are for
207     project 3: tests that combine mmap with a paging workload to see
208     their kernel pages properly while mmapping pages - I don't think
209     the current tests test that, do they?
210
211 * Filesys project:
212
213   - Need a better way to measure performance improvement of buffer
214     cache.  Some students reported that their system was slower with
215     cache--likely, Bochs doesn't simulate a disk with a realistic
216     speed.
217
218     (Perhaps we should count disk reads and writes, not time.)
219
220   - Need lots more tests.
221
222   - Detect implementations that represent the cwd as a string, by
223     removing a directory that is the cwd of another process, then
224     creating a new directory of the same name and putting some files
225     in it, then checking whether the process that had it as cwd sees
226     them.
227
228   - dir-rm-cwd should have a related test that uses a separate process
229     to try to pin the directory as its cwd.
230
231   - Godmar: I'm not sure if I mentioned that already, but I passed all
232     tests for the filesys project without having implemented inode
233     deallocation. A test is needed that checks that blocks are
234     reclaimed when files are deleted.
235
236   - Godmar: I'm in the middle of project 4, I've started by
237     implementing a buffer cache and plugging it into the existing
238     filesystem.  Along the way I was wondering how we could test the
239     cache.
240
241     Maybe one could adopt a similar testing strategy as in project 1
242     for the MLQFS scheduler: add a function that reads
243     "get_cache_accesses()" and a function "get_cache_hits()".  Then
244     create a version of pintos that creates access traces for a
245     to-be-determined workload.  Run an off-line analysis that would
246     determine how many hits a perfect cache would have (MAX), and how
247     much say an LRU strategy would give (MIN).  Then add a fudge
248     factor to account for different index strategies and test that the
249     reported number of cache hits/accesses is within (MIN, MAX) +/-
250     fudge factor.
251
252     (As an aside - I am curious why you chose to use a clock-style
253     algorithm rather than the more straightforward LRU for your buffer
254     cache implementation in your sample solution. Is there a reason
255     for that?  I was curious to see if it made a difference, so I
256     implemented LRU for your cache implementation and ran the test
257     workload of project 4 and printed cache hits/accesses.  I found
258     that for that workload, the clock-based algorithm performs almost
259     identical to LRU (within about 1%, but I ran nondeterministally
260     with QEMU). I then reduced the cache size to 32 blocks and found
261     again the same performance, which raises the suspicion that the
262     test workload might not force any cache replacement, so the
263     eviction strategy doesn't matter.)
264
265   - Godmar: I haven't analyzed the tests for project 4 yet, but I'm
266     wondering if the fairness requirements your specification has for
267     readers/writers are covered in the tests or not.
268
269
270 * Documentation:
271
272   - Add "Digging Deeper" sections that describe the nitty-gritty x86
273     details for the benefit of those interested.
274
275   - Add explanations of what "real" OSes do to give students some
276     perspective.
277
278 * To add partition support:
279
280   - Find four partition types that are more or less unused and choose
281     to use them for Pintos.  (This is implemented.)
282
283   - Bootloader reads partition tables of all BIOS devices to find the
284     first that has the "Pintos kernel" partition type.  (This is
285     implemented.)  Ideally the bootloader would make sure there is
286     exactly one such partition, but I didn't implement that yet.
287
288   - Bootloader reads kernel into memory at 1 MB using BIOS calls.
289     (This is implemented.)
290
291   - Kernel arguments have to go into a separate sector because the
292     bootloader is otherwise too big to fit now?  (I don't recall if I
293     did anything about this.)
294
295   - Kernel at boot also scans partition tables of all the disks it can
296     find to find the ones with the four Pintos partition types
297     (perhaps not all exist).  After that, it makes them available to
298     the rest of the kernel (and doesn't allow access to other devices,
299     for safety).
300
301   - "pintos" and "pintos-mkdisk" need to write a partition table to
302     the disks that they create.  "pintos-mkdisk" will need to take a
303     new parameter specifying the type.  (I might have partially
304     implemented this, don't remember.)
305
306   - "pintos" should insist on finding a partition header on disks
307     handed to it, for safety.
308
309   - Need some way for "pintos" to assemble multiple disks or
310     partitions into a single image that can be copied directly to a
311     USB block device.  (I don't know whether I came up with a good
312     solution yet or not, or whether I implemented any of it.)
313
314 * To add USB support:
315
316     - Needs to be able to scan PCI bus for UHCI controller.  (I
317       implemented this partially.)
318
319     - May want to be able to initialize USB controllers over CardBus
320       bridges.  I don't know whether this requires additional work or
321       if it's useful enough to warrant extra work.  (It's of special
322       interest for me because I have a laptop that only has USB via
323       CardBus.)
324
325     - There are many protocol layers involved: SCSI over USB-Mass
326       Storage over USB over UHCI over PCI.  (I may be forgetting one.)
327       I don't know yet whether it's best to separate the layers or to
328       merge (some of) them.  I think that a simple and clean
329       organization should be a priority.
330
331     - VMware can likely be used for testing because it can expose host
332       USB devices as guest USB devices.  This is safer and more
333       convenient than using real hardware for testing.
334
335     - Should test with a variety of USB keychain devices because there
336       seems to be wide variation among them, especially in the SCSI
337       protocols they support.  Should try to use a "lowest-common
338       denominator" SCSI protocol if any such thing really exists.
339
340     - Might want to add a feature whereby kernel arguments can be
341       given interactively, rather than passed on-disk.  Needs some
342       though.