Skip to content

Commit 00e5711

Browse files
committed
more doc tweaks
1 parent 2c5f7ab commit 00e5711

File tree

4 files changed

+52
-54
lines changed

4 files changed

+52
-54
lines changed

TRICKS

+13-13
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ might be worth pointing out in a longer explanation or in class.
44

55
---
66

7+
[2009/07/12: No longer relevant; forkret1 changed
8+
and this is now cleaner.]
9+
710
forkret1 in trapasm.S is called with a tf argument.
811
In order to use it, forkret1 copies the tf pointer into
912
%esp and then jumps to trapret, which pops the
@@ -45,21 +48,21 @@ always.
4548

4649
There is a (harmless) race in pushcli, which does
4750

48-
eflags = read_eflags();
51+
eflags = readeflags();
4952
cli();
50-
if(cpus[cpu()].ncli++ == 0)
51-
cpus[cpu()].intena = eflags & FL_IF;
53+
if(c->ncli++ == 0)
54+
c->intena = eflags & FL_IF;
5255

5356
Consider a bottom-level pushcli.
5457
If interrupts are disabled already, then the right thing
5558
happens: read_eflags finds that FL_IF is not set,
56-
and intena = 1. If interrupts are enabled, then
59+
and intena = 0. If interrupts are enabled, then
5760
it is less clear that the right thing happens:
58-
the read_eflags can execute, then the process
61+
the readeflags can execute, then the process
5962
can get preempted and rescheduled on another cpu,
6063
and then once it starts running, perhaps with
6164
interrupts disabled (can happen since the scheduler
62-
only disables interrupts once per scheduling loop,
65+
only enables interrupts once per scheduling loop,
6366
not every time it schedules a process), it will
6467
incorrectly record that interrupts *were* enabled.
6568
This doesn't matter, because if it was safe to be
@@ -112,17 +115,13 @@ processors will need it.
112115

113116
---
114117

115-
The code in sys_fork needs to read np->pid before
118+
The code in fork needs to read np->pid before
116119
setting np->state to RUNNABLE.
117120

118121
int
119-
sys_fork(void)
122+
fork(void)
120123
{
121-
int pid;
122-
struct proc *np;
123-
124-
if((np = copyproc(cp)) == 0)
125-
return -1;
124+
...
126125
pid = np->pid;
127126
np->state = RUNNABLE;
128127
return pid;
@@ -134,3 +133,4 @@ get reused for a different process (with a new pid), all
134133
before the return statement. So it's not safe to just do
135134
"return np->pid;".
136135

136+
This works because proc.h marks the pid as volatile.

pipe.c

+20-20
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
#define PIPESIZE 512
1010

1111
struct pipe {
12-
int readopen; // read fd is still open
13-
int writeopen; // write fd is still open
14-
uint writep; // next index to write
15-
uint readp; // next index to read
1612
struct spinlock lock;
1713
char data[PIPESIZE];
14+
uint nread; // number of bytes read
15+
uint nwrite; // number of bytes written
16+
int readopen; // read fd is still open
17+
int writeopen; // write fd is still open
1818
};
1919

2020
int
@@ -30,8 +30,8 @@ pipealloc(struct file **f0, struct file **f1)
3030
goto bad;
3131
p->readopen = 1;
3232
p->writeopen = 1;
33-
p->writep = 0;
34-
p->readp = 0;
33+
p->nwrite = 0;
34+
p->nread = 0;
3535
initlock(&p->lock, "pipe");
3636
(*f0)->type = FD_PIPE;
3737
(*f0)->readable = 1;
@@ -60,10 +60,10 @@ pipeclose(struct pipe *p, int writable)
6060
acquire(&p->lock);
6161
if(writable){
6262
p->writeopen = 0;
63-
wakeup(&p->readp);
63+
wakeup(&p->nread);
6464
} else {
6565
p->readopen = 0;
66-
wakeup(&p->writep);
66+
wakeup(&p->nwrite);
6767
}
6868
if(p->readopen == 0 && p->writeopen == 0) {
6969
release(&p->lock);
@@ -80,19 +80,19 @@ pipewrite(struct pipe *p, char *addr, int n)
8080

8181
acquire(&p->lock);
8282
for(i = 0; i < n; i++){
83-
while(p->writep == p->readp + PIPESIZE) {
83+
while(p->nwrite == p->nread + PIPESIZE) { //DOC: pipewrite-full
8484
if(p->readopen == 0 || cp->killed){
8585
release(&p->lock);
8686
return -1;
8787
}
88-
wakeup(&p->readp);
89-
sleep(&p->writep, &p->lock);
88+
wakeup(&p->nread);
89+
sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep
9090
}
91-
p->data[p->writep++ % PIPESIZE] = addr[i];
91+
p->data[p->nwrite++ % PIPESIZE] = addr[i];
9292
}
93-
wakeup(&p->readp);
93+
wakeup(&p->nread); //DOC: pipewrite-wakeup1
9494
release(&p->lock);
95-
return i;
95+
return n;
9696
}
9797

9898
int
@@ -101,19 +101,19 @@ piperead(struct pipe *p, char *addr, int n)
101101
int i;
102102

103103
acquire(&p->lock);
104-
while(p->readp == p->writep && p->writeopen){
104+
while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty
105105
if(cp->killed){
106106
release(&p->lock);
107107
return -1;
108108
}
109-
sleep(&p->readp, &p->lock);
109+
sleep(&p->nread, &p->lock); //DOC: piperead-sleep
110110
}
111-
for(i = 0; i < n; i++){
112-
if(p->readp == p->writep)
111+
for(i = 0; i < n; i++){ //DOC: piperead-copy
112+
if(p->nread == p->nwrite)
113113
break;
114-
addr[i] = p->data[p->readp++ % PIPESIZE];
114+
addr[i] = p->data[p->nread++ % PIPESIZE];
115115
}
116-
wakeup(&p->writep);
116+
wakeup(&p->nwrite); //DOC: piperead-wakeup
117117
release(&p->lock);
118118
return i;
119119
}

proc.c

+18-20
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,8 @@ sleep(void *chan, struct spinlock *lk)
290290
// guaranteed that we won't miss any wakeup
291291
// (wakeup runs with ptable.lock locked),
292292
// so it's okay to release lk.
293-
if(lk != &ptable.lock){
294-
acquire(&ptable.lock);
293+
if(lk != &ptable.lock){ //DOC: sleeplock0
294+
acquire(&ptable.lock); //DOC: sleeplock1
295295
release(lk);
296296
}
297297

@@ -304,7 +304,7 @@ sleep(void *chan, struct spinlock *lk)
304304
cp->chan = 0;
305305

306306
// Reacquire original lock.
307-
if(lk != &ptable.lock){
307+
if(lk != &ptable.lock){ //DOC: sleeplock2
308308
release(&ptable.lock);
309309
acquire(lk);
310310
}
@@ -393,7 +393,6 @@ exit(void)
393393
}
394394

395395
// Jump into the scheduler, never to return.
396-
cp->killed = 0;
397396
cp->state = ZOMBIE;
398397
sched();
399398
panic("zombie exit");
@@ -412,22 +411,21 @@ wait(void)
412411
// Scan through table looking for zombie children.
413412
havekids = 0;
414413
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
415-
if(p->state == UNUSED)
414+
if(p->parent != cp)
416415
continue;
417-
if(p->parent == cp){
418-
havekids = 1;
419-
if(p->state == ZOMBIE){
420-
// Found one.
421-
kfree(p->mem, p->sz);
422-
kfree(p->kstack, KSTACKSIZE);
423-
pid = p->pid;
424-
p->state = UNUSED;
425-
p->pid = 0;
426-
p->parent = 0;
427-
p->name[0] = 0;
428-
release(&ptable.lock);
429-
return pid;
430-
}
416+
havekids = 1;
417+
if(p->state == ZOMBIE){
418+
// Found one.
419+
pid = p->pid;
420+
kfree(p->mem, p->sz);
421+
kfree(p->kstack, KSTACKSIZE);
422+
p->state = UNUSED;
423+
p->pid = 0;
424+
p->parent = 0;
425+
p->name[0] = 0;
426+
p->killed = 0;
427+
release(&ptable.lock);
428+
return pid;
431429
}
432430
}
433431

@@ -438,7 +436,7 @@ wait(void)
438436
}
439437

440438
// Wait for children to exit. (See wakeup1 call in proc_exit.)
441-
sleep(cp, &ptable.lock);
439+
sleep(cp, &ptable.lock); //DOC: wait-sleep
442440
}
443441
}
444442

web/l-coordination.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ <h2>xv6 code examples</h2>
4747
<h3>Sleep and wakeup - usage</h3>
4848

4949
Let's consider implementing a producer/consumer queue
50-
(like a pipe) that can be used to hold a single non-null char pointer:
50+
(like a pipe) that can be used to hold a single non-null pointer:
5151

5252
<pre>
5353
struct pcq {

0 commit comments

Comments
 (0)