📄 proc.c
字号:
07158 return(OK);
07159 }
07160 }
07161
07162 /* No suitable message is available. Block the process trying to receive. */
07163 caller_ptr->p_getfrom = src;
07164 caller_ptr->p_messbuf = m_ptr;
07165 if (caller_ptr->p_flags == 0) unready(caller_ptr);
07166 caller_ptr->p_flags |= RECEIVING;
07167
07168 /* If MM has just blocked and there are kernel signals pending, now is the
07169 * time to tell MM about them, since it will be able to accept the message.
07170 */
07171 if (sig_procs > 0 && proc_number(caller_ptr) == MM_PROC_NR && src == ANY)
07172 inform();
07173 return(OK);
07174 }
07176 /*===========================================================================*
07177 * pick_proc *
07178 *===========================================================================*/
07179 PRIVATE void pick_proc()
07180 {
07181 /* Decide who to run now. A new process is selected by setting 'proc_ptr'.
07182 * When a fresh user (or idle) process is selected, record it in 'bill_ptr',
07183 * so the clock task can tell who to bill for system time.
07184 */
07185
07186 register struct proc *rp; /* process to run */
07187
07188 if ( (rp = rdy_head[TASK_Q]) != NIL_PROC) {
07189 proc_ptr = rp;
07190 return;
07191 }
07192 if ( (rp = rdy_head[SERVER_Q]) != NIL_PROC) {
07193 proc_ptr = rp;
07194 return;
07195 }
07196 if ( (rp = rdy_head[USER_Q]) != NIL_PROC) {
07197 proc_ptr = rp;
07198 bill_ptr = rp;
07199 return;
07200 }
07201 /* No one is ready. Run the idle task. The idle task might be made an
07202 * always-ready user task to avoid this special case.
07203 */
07204 bill_ptr = proc_ptr = proc_addr(IDLE);
07205 }
07207 /*===========================================================================*
07208 * ready *
07209 *===========================================================================*/
07210 PRIVATE void ready(rp)
07211 register struct proc *rp; /* this process is now runnable */
07212 {
07213 /* Add 'rp' to the end of one of the queues of runnable processes. Three
07214 * queues are maintained:
07215 * TASK_Q - (highest priority) for runnable tasks
07216 * SERVER_Q - (middle priority) for MM and FS only
07217 * USER_Q - (lowest priority) for user processes
07218 */
07219
07220 if (istaskp(rp)) {
07221 if (rdy_head[TASK_Q] != NIL_PROC)
07222 /* Add to tail of nonempty queue. */
07223 rdy_tail[TASK_Q]->p_nextready = rp;
07224 else {
07225 proc_ptr = /* run fresh task next */
07226 rdy_head[TASK_Q] = rp; /* add to empty queue */
07227 }
07228 rdy_tail[TASK_Q] = rp;
07229 rp->p_nextready = NIL_PROC; /* new entry has no successor */
07230 return;
07231 }
07232 if (!isuserp(rp)) { /* others are similar */
07233 if (rdy_head[SERVER_Q] != NIL_PROC)
07234 rdy_tail[SERVER_Q]->p_nextready = rp;
07235 else
07236 rdy_head[SERVER_Q] = rp;
07237 rdy_tail[SERVER_Q] = rp;
07238 rp->p_nextready = NIL_PROC;
07239 return;
07240 }
07241 if (rdy_head[USER_Q] == NIL_PROC)
07242 rdy_tail[USER_Q] = rp;
07243 rp->p_nextready = rdy_head[USER_Q];
07244 rdy_head[USER_Q] = rp;
07245 /*
07246 if (rdy_head[USER_Q] != NIL_PROC)
07247 rdy_tail[USER_Q]->p_nextready = rp;
07248 else
07249 rdy_head[USER_Q] = rp;
07250 rdy_tail[USER_Q] = rp;
07251 rp->p_nextready = NIL_PROC;
07252 */
07253 }
07255 /*===========================================================================*
07256 * unready *
07257 *===========================================================================*/
07258 PRIVATE void unready(rp)
07259 register struct proc *rp; /* this process is no longer runnable */
07260 {
07261 /* A process has blocked. */
07262
07263 register struct proc *xp;
07264 register struct proc **qtail; /* TASK_Q, SERVER_Q, or USER_Q rdy_tail */
07265
07266 if (istaskp(rp)) {
07267 /* task stack still ok? */
07268 if (*rp->p_stguard != STACK_GUARD)
07269 panic("stack overrun by task", proc_number(rp));
07270
07271 if ( (xp = rdy_head[TASK_Q]) == NIL_PROC) return;
07272 if (xp == rp) {
07273 /* Remove head of queue */
07274 rdy_head[TASK_Q] = xp->p_nextready;
07275 if (rp == proc_ptr) pick_proc();
07276 return;
07277 }
07278 qtail = &rdy_tail[TASK_Q];
07279 }
07280 else if (!isuserp(rp)) {
07281 if ( (xp = rdy_head[SERVER_Q]) == NIL_PROC) return;
07282 if (xp == rp) {
07283 rdy_head[SERVER_Q] = xp->p_nextready;
07284 pick_proc();
07285 return;
07286 }
07287 qtail = &rdy_tail[SERVER_Q];
07288 } else
07289 {
07290 if ( (xp = rdy_head[USER_Q]) == NIL_PROC) return;
07291 if (xp == rp) {
07292 rdy_head[USER_Q] = xp->p_nextready;
07293 pick_proc();
07294 return;
07295 }
07296 qtail = &rdy_tail[USER_Q];
07297 }
07298
07299 /* Search body of queue. A process can be made unready even if it is
07300 * not running by being sent a signal that kills it.
07301 */
07302 while (xp->p_nextready != rp)
07303 if ( (xp = xp->p_nextready) == NIL_PROC) return;
07304 xp->p_nextready = xp->p_nextready->p_nextready;
07305 if (*qtail == rp) *qtail = xp;
07306 }
07308 /*===========================================================================*
07309 * sched *
07310 *===========================================================================*/
07311 PRIVATE void sched()
07312 {
07313 /* The current process has run too long. If another low priority (user)
07314 * process is runnable, put the current process on the end of the user queue,
07315 * possibly promoting another user to head of the queue.
07316 */
07317
07318 if (rdy_head[USER_Q] == NIL_PROC) return;
07319
07320 /* One or more user processes queued. */
07321 rdy_tail[USER_Q]->p_nextready = rdy_head[USER_Q];
07322 rdy_tail[USER_Q] = rdy_head[USER_Q];
07323 rdy_head[USER_Q] = rdy_head[USER_Q]->p_nextready;
07324 rdy_tail[USER_Q]->p_nextready = NIL_PROC;
07325 pick_proc();
07326 }
07328 /*==========================================================================*
07329 * lock_mini_send *
07330 *==========================================================================*/
07331 PUBLIC int lock_mini_send(caller_ptr, dest, m_ptr)
07332 struct proc *caller_ptr; /* who is trying to send a message? */
07333 int dest; /* to whom is message being sent? */
07334 message *m_ptr; /* pointer to message buffer */
07335 {
07336 /* Safe gateway to mini_send() for tasks. */
07337
07338 int result;
07339
07340 switching = TRUE;
07341 result = mini_send(caller_ptr, dest, m_ptr);
07342 switching = FALSE;
07343 return(result);
07344 }
07346 /*==========================================================================*
07347 * lock_pick_proc *
07348 *==========================================================================*/
07349 PUBLIC void lock_pick_proc()
07350 {
07351 /* Safe gateway to pick_proc() for tasks. */
07352
07353 switching = TRUE;
07354 pick_proc();
07355 switching = FALSE;
07356 }
07358 /*==========================================================================*
07359 * lock_ready *
07360 *==========================================================================*/
07361 PUBLIC void lock_ready(rp)
07362 struct proc *rp; /* this process is now runnable */
07363 {
07364 /* Safe gateway to ready() for tasks. */
07365
07366 switching = TRUE;
07367 ready(rp);
07368 switching = FALSE;
07369 }
07372 /*==========================================================================*
07373 * lock_unready *
07374 *==========================================================================*/
07375 PUBLIC void lock_unready(rp)
07376 struct proc *rp; /* this process is no longer runnable */
07377 {
07378 /* Safe gateway to unready() for tasks. */
07379
07380 switching = TRUE;
07381 unready(rp);
07382 switching = FALSE;
07383 }
07385 /*==========================================================================*
07386 * lock_sched *
07387 *==========================================================================*/
07388 PUBLIC void lock_sched()
07389 {
07390 /* Safe gateway to sched() for tasks. */
07391
07392 switching = TRUE;
07393 sched();
07394 switching = FALSE;
07395 }
07397 /*==========================================================================*
07398 * unhold *
07399 *==========================================================================*/
07400 PUBLIC void unhold()
07401 {
07402 /* Flush any held-up interrupts. k_reenter must be 0. held_head must not
07403 * be NIL_PROC. Interrupts must be disabled. They will be enabled but will
07404 * be disabled when this returns.
07405 */
07406
07407 register struct proc *rp; /* current head of held queue */
07408
07409 if (switching) return;
07410 rp = held_head;
07411 do {
07412 if ( (held_head = rp->p_nextheld) == NIL_PROC) held_tail = NIL_PROC;
07413 rp->p_int_held = FALSE;
07414 unlock(); /* reduce latency; held queue may change! */
07415 interrupt(proc_number(rp));
07416 lock(); /* protect the held queue again */
07417 }
07418 while ( (rp = held_head) != NIL_PROC);
07419 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -