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