Some suggestions from "Waqar Mohsin" <wmohsin@gmail.com>
[pintos-anon] / TODO
1 -*- text -*-
2
3 From: "Waqar Mohsin" <wmohsin@gmail.com>
4 Subject: 3 questions about switch_threads() in switch.S
5 To: blp@cs.stanford.edu, joshwise@stanford.edu
6 Date: Fri, 3 Mar 2006 17:09:21 -0800
7
8 QUESTION 1
9  
10 In the section
11  
12   # Save current stack pointer to old thread's stack, if any.
13   movl SWITCH_CUR(%esp), %eax
14   test %eax, %eax
15   jz 1f
16   movl %esp, (%eax,%edx,1)
17 1:
18
19   # Restore stack pointer from new thread's stack.
20   movl SWITCH_NEXT(%esp), %ecx
21   movl (%ecx,%edx,1), %esp
22
23 why are we saving the current stack pointer only if the "cur" thread pointer
24 is non-NULL ? Isn't it gauranteed to be non-NULL because switch_threads() is
25 only called form schedule(), where we have
26
27   struct thread *cur = running_thread ();
28
29 which should always be non-NULL (given the way kernel pool is laid out).
30
31 QUESTION 2
32
33   # This stack frame must match the one set up by thread_create().
34   pushl %ebx
35   pushl %ebp
36   pushl %esi
37   pushl %edi
38
39 I find the comment confusing. thread_create() is a special case: the set of
40 registers popped from switch_threads stack frame for a newly created thread
41 are all zero, so their order shouldn't dictate the order above.
42
43 I think all that matters is that the order of pops at the end of
44 switch_threads() is the opposite of the pushes at the beginning (as shown
45 above).
46
47 QUESTION 3
48
49 Is it true that struct switch_threads_frame does NOT strictly require
50
51     struct thread *cur;         /* 20: switch_threads()'s CUR argument. */
52     struct thread *next;        /* 24: switch_threads()'s NEXT argument. */
53 at the end ?
54
55 When a newly created thread's stack pointer is installed in switch_threads(),
56 all we do is pop the saved registers and return to switch_entry() which pops
57 off and discards the above two simulated (and not used) arguments to
58 switch_threads().
59
60 If we remove these two from struct switch_threads_frame and don't do a
61
62   # Discard switch_threads() arguments.
63   addl $8, %esp
64 in switch_entry(), things should still work. Am I right ?
65
66 Thanks
67 Waqar
68
69 From: "Godmar Back" <godmar@gmail.com>
70 Subject: thread_yield in irq handler
71 To: "Ben Pfaff" <blp@cs.stanford.edu>
72 Date: Wed, 22 Feb 2006 22:18:50 -0500
73
74 Ben,
75
76 you write in your Tour of Pintos:
77
78 "Second, an interrupt handler must not call any function that can
79 sleep, which rules out thread_yield(), lock_acquire(), and many
80 others. This is because external interrupts use space on the stack of
81 the kernel thread that was running at the time the interrupt occurred.
82 If the interrupt handler tried to sleep and that thread resumed, then
83 the two uses of the single stack would interfere, which cannot be
84 allowed."
85
86 Is the last sentence really true?
87
88 I thought the reason that you couldn't sleep is that you would put
89 effectively a random thread/process to sleep, but I don't think it
90 would cause problems with the kernel stack.  After all, it doesn't
91 cause this problem if you call thread_yield at the end of
92 intr_handler(), so why would it cause this problem earlier.
93
94 As for thread_yield(), my understanding is that the reason it's called
95 at the end is to ensure it's done after the interrupt is acknowledged,
96 which you can't do until the end because Pintos doesn't handle nested
97 interrupts.
98
99  - Godmar
100
101 From: "Godmar Back" <godmar@gmail.com>
102
103 For reasons I don't currently understand, some of our students seem
104 hesitant to include each thread in a second "all-threads" list and are
105 looking for ways to implement the advanced scheduler without one.
106
107 Currently, I believe, all tests for the mlfqs are such that all
108 threads are either ready or sleeping in timer_sleep(). This allows for
109 an incorrect implementation in which recent-cpu and priorities are
110 updated only for those threads that are on the alarm list or the ready
111 list.
112
113 The todo item would be a test where a thread is blocked on a
114 semaphore, lock or condition variable and have its recent_cpu decay to
115 zero, and check that it's scheduled right after the unlock/up/signal.
116
117 From: "Godmar Back" <godmar@gmail.com>
118 Subject: set_priority & donation - a TODO item
119 To: "Ben Pfaff" <blp@cs.stanford.edu>
120 Date: Mon, 20 Feb 2006 22:20:26 -0500
121
122 Ben,
123
124 it seems that there are currently no tests that check the proper
125 behavior of thread_set_priority() when called by a thread that is
126 running under priority donation.  The proper behavior, I assume, is to
127 temporarily drop the donation if the set priority is higher, and to
128 reassume the donation should the thread subsequently set its own
129 priority again to a level that's lower than a still active donation.
130
131  - Godmar
132
133 From: Godmar Back <godmar@gmail.com>
134 Subject: project 4 question/comment regarding caching inode data
135 To: Ben Pfaff <blp@cs.stanford.edu>
136 Date: Sat, 14 Jan 2006 15:59:33 -0500
137
138 Ben,
139
140 in section 6.3.3 in the P4 FAQ, you write:
141
142 "You can store a pointer to inode data in struct inode, if you want,"
143
144 Should you point out that if they indeed do that, they likely wouldn't
145 be able to support more than 64 open inodes systemwide at any given
146 point in time.
147
148 (This seems like a rather strong limitation; do your current tests
149 open more than 64 files?
150 It would also point to an obvious way to make the projects harder by
151 specifically disallowing that inode data be locked in memory during
152 the entire time an inode is kept open.)
153
154  - Godmar
155
156 From: Godmar Back <godmar@gmail.com>
157 Subject: on caching in project 4
158 To: Ben Pfaff <blp@cs.stanford.edu>
159 Date: Mon, 9 Jan 2006 20:58:01 -0500
160
161 here's an idea for future semesters.
162
163 I'm in the middle of project 4, I've started by implementing a buffer
164 cache and plugging it into the existing filesystem.  Along the way I
165 was wondering how we could test the cache.
166
167 Maybe one could adopt a similar testing strategy as in project 1 for
168 the MLQFS scheduler: add a function that reads "get_cache_accesses()"
169 and a function "get_cache_hits()".  Then create a version of pintos
170 that creates access traces for a to-be-determined workload.  Run an
171 off-line analysis that would determine how many hits a perfect cache
172 would have (MAX), and how much say an LRU strategy would give (MIN).
173 Then add a fudge factor to account for different index strategies and
174 test that the reported number of cache hits/accesses is within (MIN,
175 MAX) +/- fudge factor.
176
177 (As an aside - I am curious why you chose to use a clock-style
178 algorithm rather than the more straightforward LRU for your buffer
179 cache implementation in your sample solution. Is there a reason for
180 that?  I was curious to see if it made a difference, so I implemented
181 LRU for your cache implementation and ran the test workload of project
182 4 and printed cache hits/accesses.
183 I found that for that workload, the clock-based algorithm performs
184 almost identical to LRU (within about 1%, but I ran nondeterministally
185 with QEMU). I then reduced the cache size to 32 blocks and found again
186 the same performance, which raises the suspicion that the test
187 workload might not force any cache replacement, so the eviction
188 strategy doesn't matter.)
189
190 Godmar Back <godmar@gmail.com> writes:
191
192 > in your sample solution to P4, dir_reopen does not take any locks when
193 > changing a directory's open_cnt. This looks like a race condition to
194 > me, considering that dir_reopen is called from execute_process without
195 > any filesystem locks held.
196
197 * Get rid of rox--causes more trouble than it's worth
198
199 * Reconsider command line arg style--confuses everyone.
200
201 * Finish writing tour.
202
203 * Introduce a "yield" system call to speed up the syn-* tests.
204
205 via Godmar Back:
206
207 * Project 3 solution needs FS lock.
208
209 * Get rid of mmap syscall, add sbrk.
210
211 * Make backtrace program accept multiple object file arguments,
212   e.g. add -u option to allow backtracing user program also.
213
214 * page-linear, page-shuffle VM tests do not use enough memory to force
215   eviction.  Should increase memory consumption.
216
217 * Add FS persistence test(s).
218
219 * lock_acquire(), lock_release() don't need additional intr_dis/enable
220   calls, because the semaphore protects lock->holder.
221
222
223
224 * process_death test needs improvement
225
226 * Internal tests.
227
228 * Improve automatic interpretation of exception messages.
229
230 * Userprog project:
231
232   - Mark read-only pages as actually read-only in the page table.  Or,
233     since this was consistently rated as the easiest project by the
234     students, require them to do it.
235
236   - Don't provide per-process pagedir implementation but only
237     single-process implementation and require students to implement
238     the separation?  This project was rated as the easiest after all.
239     Alternately we could just remove the synchronization on pid
240     selection and check that students fix it.
241
242 * Filesys project:
243
244   - Need a better way to measure performance improvement of buffer
245     cache.  Some students reported that their system was slower with
246     cache--likely, Bochs doesn't simulate a disk with a realistic
247     speed.
248
249 * Documentation:
250
251   - Add "Digging Deeper" sections that describe the nitty-gritty x86
252     details for the benefit of those interested.
253
254   - Add explanations of what "real" OSes do to give students some
255     perspective.
256
257 * Assignments:
258
259   - Add extra credit:
260
261     . Low-level x86 stuff, like paged page tables.
262
263     . Specifics on how to implement sbrk, malloc.
264
265     . Other good ideas.
266
267     . opendir/readdir/closedir
268
269     . everything needed for getcwd()