/* kern_synch.c 3.13 %G% */
#define SQSIZE 0100 /* Must be power of 2 */
#define HASH(x) (( (int) x >> 5) & (SQSIZE-1))
struct proc
*slpque
[SQSIZE
];
* Give up the processor till a wakeup occurs
* on chan, at which time the process
* enters the scheduling queue at priority pri.
* The most important effect of pri is that when
* pri<=PZERO a signal cannot disturb the sleep;
* if pri>PZERO signals will be processed.
* Callers of this routine must be prepared for
* premature return, and check that the reason for
* sleeping has gone away.
register struct proc
*rp
, **hp
;
if (chan
==0 || rp
->p_stat
!= SRUN
|| rp
->p_rlink
)
hp
= &slpque
[HASH(chan
)];
* If priority was low (>PZERO) and
* there has been a signal,
* execute non-local goto to
* Return in no more than the indicated number of seconds.
* (If seconds==0, no timeout implied)
* Return TS_OK if chan was awakened normally
* TS_TIME if timeout occurred
* TS_SIG if asynchronous signal occurred
tsleep(chan
, pri
, seconds
)
register struct proc
*pp
;
if (pp
->p_clktim
&& pp
->p_clktim
<seconds
)
sec
= pp
->p_clktim
-seconds
;
bcopy((caddr_t
)u
.u_qsav
, (caddr_t
)lqsav
, sizeof (label_t
));
if ((pp
->p_flag
&STIMO
)==0 && seconds
)
bcopy((caddr_t
)lqsav
, (caddr_t
)u
.u_qsav
, sizeof (label_t
));
* Remove a process from its wait queue
register struct proc
**hp
;
hp
= &slpque
[HASH(p
->p_wchan
)];
* Wake up all processes sleeping on chan.
register struct proc
*p
, **q
, **h
;
if (p
->p_rlink
|| p
->p_stat
!= SSLEEP
&& p
->p_stat
!= SSTOP
)
if (p
->p_stat
== SSLEEP
) {
/* OPTIMIZED INLINE EXPANSION OF setrun(p) */
if(runout
!= 0 && (p
->p_flag
&SLOAD
) == 0) {
wakeup((caddr_t
)&runout
);
/* END INLINE EXPANSION */
* Initialize the (doubly-linked) run queues
for (i
= 0; i
< NQS
; i
++)
qs
[i
].ph_link
= qs
[i
].ph_rlink
= (struct proc
*)&qs
[i
];
* Set the process running;
* arrange for it to be swapped in if necessary.
unsleep(p
); /* e.g. when sending signals */
if(runout
!= 0 && (p
->p_flag
&SLOAD
) == 0) {
wakeup((caddr_t
)&runout
);
* The rescheduling flag (runrun)
* is set if the priority is better
* than the currently running process.
register struct proc
*pp
;
p
= (pp
->p_cpu
& 0377)/16;
p
+= PUSER
+ pp
->p_nice
- NZERO
;
* Create a new process-- the internal version of
* It returns 1 in the new process, 0 in the old.
register struct proc
*rpp
, *rip
;
* First, just locate a slot for a process
* and copy the useful info from this process into it.
* The panic "cannot happen" because fork has already
* checked for the existence of a slot.
for(rpp
= &proc
[0]; rpp
< &proc
[NPROC
]; rpp
++) {
if(rpp
->p_stat
== NULL
&& p
==NULL
)
if (rpp
->p_pid
==mpid
|| rpp
->p_pgrp
==mpid
)
* make proc entry for new proc
rpp
->p_flag
= SLOAD
| (rip
->p_flag
& (SPAGI
|SDETACH
));
rpp
->p_pgrp
= rip
->p_pgrp
;
rpp
->p_nice
= rip
->p_nice
;
rpp
->p_textp
= isvfork
? 0 : rip
->p_textp
;
rpp
->p_ppid
= rip
->p_pid
;
rpp
->p_siga0
= rip
->p_siga0
;
rpp
->p_siga1
= rip
->p_siga1
;
/* take along any pending signals, like stops? */
rpp
->p_tsize
= rpp
->p_dsize
= rpp
->p_ssize
= 0;
rpp
->p_szpt
= clrnd(ctopt(UPAGES
));
forkstat
.sizvfork
+= rip
->p_dsize
+ rip
->p_ssize
;
rpp
->p_tsize
= rip
->p_tsize
;
rpp
->p_dsize
= rip
->p_dsize
;
rpp
->p_ssize
= rip
->p_ssize
;
rpp
->p_szpt
= rip
->p_szpt
;
forkstat
.sizfork
+= rip
->p_dsize
+ rip
->p_ssize
;
rpp
->p_aveflt
= rip
->p_aveflt
;
p
->p_idhash
= pidhash
[n
];
if(u
.u_ofile
[n
] != NULL
) {
if(!isvfork
&& u
.u_vrpages
[n
])
u
.u_ofile
[n
]->f_inode
->i_vfdcnt
++;
* Partially simulate the environment
* of the new process so that when it is actually
* created (by copying) it will look right.
rip
->p_flag
|= SKEEP
; /* prevent parent from being swapped */
if (procdup(rpp
, isvfork
))
/* SSWAP NOT NEEDED IN THIS CASE AS u.u_pcb.pcb_sswap SUFFICES */
/* rpp->p_flag |= SSWAP; */
u
.u_procp
->p_xlink
= rpp
;
u
.u_procp
->p_flag
|= SNOVM
;
while (rpp
->p_flag
& SVFORK
)
sleep((caddr_t
)rpp
, PZERO
- 1);
if ((rpp
->p_flag
& SLOAD
) == 0)
uaccess(rpp
, Vfmap
, &vfutl
);
vpassvm(rpp
, u
.u_procp
, &vfutl
, &u
, Vfmap
);
for (n
= 0; n
< NOFILE
; n
++)
if (vfutl
.u_vrpages
[n
]) {
if ((u
.u_vrpages
[n
] = vfutl
.u_vrpages
[n
] - 1) == 0)
if (--u
.u_ofile
[n
]->f_inode
->i_vfdcnt
< 0)
panic("newproc i_vfdcnt");
u
.u_procp
->p_flag
&= ~SNOVM
;