Optimized scheduling code. Old code is still available withing DEAD_CODE

and NEW_SCHED_Q definitions. Some minor problems are being traced at the
moment. This commit is meant to backup my files.
  --- Jorrit
This commit is contained in:
Jorrit Herder 2005-05-26 13:17:57 +00:00
parent dcffa17db2
commit 77c3213948
15 changed files with 321 additions and 198 deletions

View file

@ -869,11 +869,17 @@ message *m;
int r; int r;
/* Try to get a fresh copy of the buffer with kernel messages. */ /* Try to get a fresh copy of the buffer with kernel messages. */
r=0; #if DEAD_CODE
/* During shutdown, the reply is garbled because new notifications arrive
* while the system task makes a copy of the kernel messages buffer.
* Hence, don't check the return value.
*/
if ((r=sys_getkmessages(&kmess)) != OK) { if ((r=sys_getkmessages(&kmess)) != OK) {
printf("TTY: couldn't get copy of kmessages: %d, 0x%x\n", r,r); printf("TTY: couldn't get copy of kmessages: %d, 0x%x\n", r,r);
return; return;
} }
#endif
sys_getkmessages(&kmess);
/* Print only the new part. Determine how many new bytes there are with /* Print only the new part. Determine how many new bytes there are with
* help of the current and previous 'next' index. Note that the kernel * help of the current and previous 'next' index. Note that the kernel

View file

@ -526,13 +526,23 @@ int scode; /* scan code for a function key */
/* See if an observer is registered and send it a message. */ /* See if an observer is registered and send it a message. */
if (observers[index] != NONE) { if (observers[index] != NONE) {
#if DEAD_CODE
m.m_type = FKEY_PRESSED; m.m_type = FKEY_PRESSED;
m.FKEY_NUM = index+1; m.FKEY_NUM = index+1;
m.FKEY_CODE = fkey; m.FKEY_CODE = fkey;
if (OK != (s=nb_send(observers[index], &m))) { if (OK != (s=nb_send(observers[index], &m))) {
printf("WARNING: F%d key notification to process %d failed: %d.\n", printf("WARNING: F%d key nb_send to process %d failed: %d.\n",
index+1, observers[index], s); index+1, observers[index], s);
} }
#else
m.NOTIFY_TYPE = FKEY_PRESSED;
m.NOTIFY_ARG = fkey;
m.NOTIFY_FLAGS = index+1;
if (OK != (s=notify(observers[index], &m))) {
printf("WARNING: F%d key notify to process %d failed: %d.\n",
index+1, observers[index], s);
}
#endif
} }
return(TRUE); return(TRUE);
} }

View file

@ -145,6 +145,7 @@ PUBLIC timer_t *tty_timers; /* queue of TTY timers */
PUBLIC clock_t tty_next_timeout; /* time that the next alarm is due */ PUBLIC clock_t tty_next_timeout; /* time that the next alarm is due */
PUBLIC struct machine machine; /* kernel environment variables */ PUBLIC struct machine machine; /* kernel environment variables */
static int debug = 0;
/*===========================================================================* /*===========================================================================*
* tty_task * * tty_task *
@ -192,6 +193,11 @@ PUBLIC void main(void)
* request and should be handled separately. These extra functions * request and should be handled separately. These extra functions
* do not operate on a device, in constrast to the driver requests. * do not operate on a device, in constrast to the driver requests.
*/ */
if (debug) {
printf("TTY got request from %d, type %d\n",
tty_mess.m_source, tty_mess.m_type);
printf("???\n");
}
switch (tty_mess.m_type) { switch (tty_mess.m_type) {
case SYN_ALARM: /* fall through */ case SYN_ALARM: /* fall through */
case HARD_INT: /* hardware interrupt notification */ case HARD_INT: /* hardware interrupt notification */
@ -204,8 +210,12 @@ PUBLIC void main(void)
case HARD_STOP: { /* MINIX is going down */ case HARD_STOP: { /* MINIX is going down */
static int stop = 0; /* expect two HARD_STOP messages */ static int stop = 0; /* expect two HARD_STOP messages */
if (! stop++) { if (! stop++) {
printf("TTY got first HARD_STOP message\n");
debug = 1;
cons_stop(); /* first switch to primary console */ cons_stop(); /* first switch to primary console */
printf("TTY returned from cons_stop()\n");
} else { } else {
printf("TTY got second HARD_STOP message\n");
if(irq_hook_id != -1) { if(irq_hook_id != -1) {
int r; int r;
r = sys_irqdisable(&irq_hook_id); r = sys_irqdisable(&irq_hook_id);
@ -222,7 +232,9 @@ PUBLIC void main(void)
do_panic_dumps(&tty_mess); do_panic_dumps(&tty_mess);
continue; continue;
case DIAGNOSTICS: /* a server wants to print some */ case DIAGNOSTICS: /* a server wants to print some */
if (debug) printf("TTY get DIAG\n");
do_diagnostics(&tty_mess); do_diagnostics(&tty_mess);
if (debug) printf("TTY finished DIAG\n");
continue; continue;
case FKEY_CONTROL: /* (un)register a fkey observer */ case FKEY_CONTROL: /* (un)register a fkey observer */
do_fkey_ctl(&tty_mess); do_fkey_ctl(&tty_mess);
@ -1302,8 +1314,12 @@ int status; /* reply code */
tty_mess.m_type = code; tty_mess.m_type = code;
tty_mess.REP_PROC_NR = proc_nr; tty_mess.REP_PROC_NR = proc_nr;
tty_mess.REP_STATUS = status; tty_mess.REP_STATUS = status;
if ((status = send(replyee, &tty_mess)) != OK) if (debug)
printf("TTY wanted to send to %d, type %d, status %d\n",
proc_nr, code, status);
if ((status = send(replyee, &tty_mess)) != OK) {
server_panic("TTY","tty_reply failed, status\n", status); server_panic("TTY","tty_reply failed, status\n", status);
}
} }

View file

@ -118,7 +118,7 @@ PUBLIC void clock_task()
result = do_clocktick(&m); /* handle clock tick */ result = do_clocktick(&m); /* handle clock tick */
break; break;
default: /* illegal message type */ default: /* illegal message type */
kprintf("CLOCK got illegal request from %d.\n", m.m_source); kprintf("Warning, illegal CLOCK request from %d.\n", m.m_source);
result = EBADREQUEST; result = EBADREQUEST;
} }
@ -128,7 +128,8 @@ PUBLIC void clock_task()
*/ */
if (result != EDONTREPLY) { if (result != EDONTREPLY) {
m.m_type = result; m.m_type = result;
lock_send(m.m_source, &m); if (OK != lock_send(m.m_source, &m))
kprintf("Warning, CLOCK couldn't reply to %d.\n", m.m_source);
} }
} }
} }
@ -155,9 +156,10 @@ message *m_ptr; /* pointer to request message */
TMR_NEVER : clock_timers->tmr_exp_time; TMR_NEVER : clock_timers->tmr_exp_time;
} }
/* If a user process has been running too long, pick another one. */ /* If a process has been running too long, pick another one. */
if (--sched_ticks == 0) { if (--sched_ticks <= 0) {
if (bill_ptr == prev_ptr) lock_sched(); /* process has run too long */ if (bill_ptr == prev_ptr)
lock_sched(PPRI_USER); /* process has run too long */
sched_ticks = SCHED_RATE; /* reset quantum */ sched_ticks = SCHED_RATE; /* reset quantum */
prev_ptr = bill_ptr; /* new previous process */ prev_ptr = bill_ptr; /* new previous process */
} }
@ -249,7 +251,7 @@ irq_hook_t *hook;
m.NOTIFY_TYPE = HARD_INT; m.NOTIFY_TYPE = HARD_INT;
lock_notify(CLOCK, &m); lock_notify(CLOCK, &m);
} }
else if (--sched_ticks == 0) { else if (--sched_ticks <= 0) {
sched_ticks = SCHED_RATE; /* reset the quantum */ sched_ticks = SCHED_RATE; /* reset the quantum */
prev_ptr = bill_ptr; /* new previous process */ prev_ptr = bill_ptr; /* new previous process */
} }

View file

@ -57,7 +57,7 @@ unsigned vec_nr;
if (k_reenter == 0 && ! istaskp(saved_proc)) { if (k_reenter == 0 && ! istaskp(saved_proc)) {
unlock(); /* this is protected like sys_call() */ unlock(); /* this is protected like sys_call() */
cause_sig(proc_number(saved_proc), ep->signum); cause_sig(proc_nr(saved_proc), ep->signum);
return; return;
} }
@ -66,7 +66,7 @@ unsigned vec_nr;
kprintf("\nIntel-reserved exception %d\n", vec_nr); kprintf("\nIntel-reserved exception %d\n", vec_nr);
else else
kprintf("\n%s\n", karg(ep->msg)); kprintf("\n%s\n", karg(ep->msg));
kprintf("process number %d, ", proc_number(saved_proc)); kprintf("process number %d, ", proc_nr(saved_proc));
kprintf("pc = %d:", (unsigned) saved_proc->p_reg.cs); kprintf("pc = %d:", (unsigned) saved_proc->p_reg.cs);
kprintf("0x%x\n", (unsigned) saved_proc->p_reg.pc); kprintf("0x%x\n", (unsigned) saved_proc->p_reg.pc);

View file

@ -55,7 +55,7 @@ PUBLIC void main()
intr_init(1); intr_init(1);
/* Clear the process table. Anounce each slot as empty and /* Clear the process table. Anounce each slot as empty and
* set up mappings for proc_addr() and proc_number() macros. * set up mappings for proc_addr() and proc_nr() macros.
*/ */
for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) { for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) {
rp->p_type = P_NONE; /* isemptyp() tests on this */ rp->p_type = P_NONE; /* isemptyp() tests on this */
@ -146,7 +146,6 @@ PUBLIC void main()
#if ENABLE_K_DEBUGGING #if ENABLE_K_DEBUGGING
rp->p_ready = 0; rp->p_ready = 0;
#endif #endif
if (rp->p_nr != HARDWARE) lock_ready(rp); if (rp->p_nr != HARDWARE) lock_ready(rp);
rp->p_flags = 0; rp->p_flags = 0;
@ -271,7 +270,6 @@ timer_t *tp;
*/ */
static int level = P_SERVER; /* start at the highest level */ static int level = P_SERVER; /* start at the highest level */
static struct proc *p = NIL_PROC; /* next process to stop */ static struct proc *p = NIL_PROC; /* next process to stop */
static char *types[] = {"task","system","driver","server","user"};
static message m; static message m;
/* See if the last process' shutdown was successful. Else, force exit. */ /* See if the last process' shutdown was successful. Else, force exit. */
@ -291,13 +289,11 @@ timer_t *tp;
if (p == NIL_PROC) p = BEG_PROC_ADDR; if (p == NIL_PROC) p = BEG_PROC_ADDR;
while (TRUE) { while (TRUE) {
if (isalivep(p) && p->p_type == level) { /* found a process */ if (isalivep(p) && p->p_type == level) { /* found a process */
int w; kprintf("- Stopping %s ... ", karg(p->p_name));
kprintf("- Stopping %s ", karg(p->p_name));
kprintf("%s ... ", karg(types[p->p_type]));
shutdown_process = p; /* directly continue if exited */ shutdown_process = p; /* directly continue if exited */
m.NOTIFY_TYPE = HARD_STOP; m.NOTIFY_TYPE = HARD_STOP;
m.NOTIFY_ARG = tmr_arg(tp)->ta_int; /* how */ m.NOTIFY_ARG = tmr_arg(tp)->ta_int; /* how */
lock_notify(proc_number(p), &m); lock_notify(proc_nr(p), &m);
set_timer(tp, get_uptime()+STOP_TICKS, stop_sequence); set_timer(tp, get_uptime()+STOP_TICKS, stop_sequence);
return; /* allow the process to shut down */ return; /* allow the process to shut down */
} }

View file

@ -104,7 +104,6 @@ bit_t nr_bits;
return(bit_nr); return(bit_nr);
} }
kprintf("Warning, all %d bits in map busy\n", nr_bits);
return(-1); return(-1);
} }

View file

@ -1,3 +1,4 @@
#define NEW_SCHED_Q 1
/* This file contains essentially all of the process and message handling. /* This file contains essentially all of the process and message handling.
* It has one main entry point from the outside: * It has one main entry point from the outside:
* *
@ -13,6 +14,7 @@
* lock_pick_proc: pick a process to run (used by system initialization) * lock_pick_proc: pick a process to run (used by system initialization)
* *
* Changes: * Changes:
* May 26, 2005 optimized message passing functions (Jorrit N. Herder)
* May 24, 2005 new, queued NOTIFY system call (Jorrit N. Herder) * May 24, 2005 new, queued NOTIFY system call (Jorrit N. Herder)
* Oct 28, 2004 non-blocking SEND and RECEIVE (Jorrit N. Herder) * Oct 28, 2004 non-blocking SEND and RECEIVE (Jorrit N. Herder)
* Oct 28, 2004 rewrite of sys_call() (Jorrit N. Herder) * Oct 28, 2004 rewrite of sys_call() (Jorrit N. Herder)
@ -33,21 +35,22 @@
* interrupts to prevent race conditions. * interrupts to prevent race conditions.
*/ */
FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst, FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst,
message *m_ptr, int may_block) ); message *m_ptr, int flags) );
FORWARD _PROTOTYPE( int mini_rec, (struct proc *caller_ptr, int src, FORWARD _PROTOTYPE( int mini_rec, (struct proc *caller_ptr, int src,
message *m_ptr, int may_block) ); message *m_ptr, int flags) );
FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst, FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst,
message *m_ptr ) ); message *m_ptr ) );
FORWARD _PROTOTYPE( void ready, (struct proc *rp) ); FORWARD _PROTOTYPE( void ready, (struct proc *rp) );
FORWARD _PROTOTYPE( void sched, (void) ); FORWARD _PROTOTYPE( void sched, (int queue) );
FORWARD _PROTOTYPE( void unready, (struct proc *rp) ); FORWARD _PROTOTYPE( void unready, (struct proc *rp) );
FORWARD _PROTOTYPE( void pick_proc, (void) ); FORWARD _PROTOTYPE( void pick_proc, (void) );
#if (CHIP == M68000) #define BuildMess(m,n) \
FORWARD _PROTOTYPE( void cp_mess, (int src, struct proc *src_p, message *src_m, (m).NOTIFY_SOURCE = (n)->n_source, \
struct proc *dst_p, message *dst_m) ); (m).NOTIFY_TYPE = (n)->n_type, \
#endif (m).NOTIFY_FLAGS = (n)->n_flags, \
(m).NOTIFY_ARG = (n)->n_arg;
#if (CHIP == INTEL) #if (CHIP == INTEL)
#define CopyMess(s,sp,sm,dp,dm) \ #define CopyMess(s,sp,sm,dp,dm) \
@ -80,61 +83,77 @@ message *m_ptr; /* pointer to message in the caller's space */
*/ */
register struct proc *caller_ptr = proc_ptr; /* get pointer to caller */ register struct proc *caller_ptr = proc_ptr; /* get pointer to caller */
int function = call_nr & SYSCALL_FUNC; /* get system call function */ int function = call_nr & SYSCALL_FUNC; /* get system call function */
int may_block = ! (call_nr & NON_BLOCKING); /* (dis)allow blocking? */ int flags = call_nr & SYSCALL_FLAGS; /* get flags */
int mask_entry; /* bit to check in send mask */ int mask_entry; /* bit to check in send mask */
int result; /* the system call's result */ int result; /* the system call's result */
vir_bytes vb; /* message buffer pointer as vir_bytes */
vir_clicks vlo, vhi; /* virtual clicks containing message to send */
/* Calls directed to the kernel may only be sendrec(), because tasks always /* Calls directed to the kernel may only be sendrec(), because tasks always
* reply and may not block if the caller doesn't do receive(). Users also * reply and may not block if the caller doesn't do receive(). Users also
* may only use sendrec() to protect the process manager and file system. * may only use sendrec() to protect the process manager and file system.
*/ */
#if DEAD_CODE if (iskernel(src_dst) && function != BOTH)
if ((iskernel(src_dst) || isuserp(caller_ptr)) && function != BOTH) { return(ECALLDENIED); /* BOTH was required */
#else
if (iskernel(src_dst) && function != BOTH) {
#endif
result = ECALLDENIED; /* BOTH was required */
}
/* Verify that requested source and/ or destination is a valid process. */ /* Verify that requested source and/ or destination is a valid process. */
else if (! isoksrc_dst(src_dst)) { if (! isoksrc_dst(src_dst))
result = EBADSRCDST; /* invalid process number */ return(EBADSRCDST);
}
/* Check validity of message pointer. */
vb = (vir_bytes) m_ptr;
vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */
vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* vir click for top of msg */
#if ALLOW_GAP_MESSAGES
/* This check allows a message to be anywhere in data or stack or gap.
* It will have to be made more elaborate later for machines which
* don't have the gap mapped.
*/
if (vlo < caller_ptr->p_memmap[D].mem_vir || vlo > vhi ||
vhi >= caller_ptr->p_memmap[S].mem_vir + caller_ptr->p_memmap[S].mem_len)
return(EFAULT);
#else
/* Check for messages wrapping around top of memory or outside data seg. */
if (vhi < vlo ||
vhi - caller_ptr->p_memmap[D].mem_vir >= caller_ptr->p_memmap[D].mem_len)
return(EFAULT);
#endif
/* Now check if the call is known and try to perform the request. The only /* Now check if the call is known and try to perform the request. The only
* system calls that exist in MINIX are sending and receiving messages. * system calls that exist in MINIX are sending and receiving messages.
* Receiving is straightforward. Sending requires to check caller's send * Receiving is straightforward. Sending requires to check caller's send
* mask and whether the destination is alive. * mask and whether the destination is alive.
*/ */
else { switch(function) {
switch(function) { case SEND:
case SEND: /* fall through, SEND is done in BOTH */
/* fall through, SEND is done in BOTH */ case BOTH:
case BOTH: if (! isalive(src_dst)) {
if (! isalive(src_dst)) { result = EDEADDST; /* cannot send to the dead */
result = EDEADDST; /* cannot send to the dead */
break;
}
mask_entry = isuser(src_dst) ? USER_PROC_NR : src_dst;
if (! isallowed(caller_ptr->p_sendmask, mask_entry)) {
kprintf("WARNING: sys_call denied %d ", caller_ptr->p_nr);
kprintf("sending to %d\n", proc_addr(src_dst)->p_nr);
result = ECALLDENIED; /* call denied by send mask */
break;
}
result = mini_send(caller_ptr, src_dst, m_ptr, may_block);
if (function == SEND || result != OK) {
break; /* done, or SEND failed */
} /* fall through for BOTH */
case RECEIVE:
result = mini_rec(caller_ptr, src_dst, m_ptr, may_block);
break; break;
case NOTIFY:
result = mini_notify(caller_ptr, src_dst, m_ptr);
break;
default:
result = EBADCALL; /* illegal system call */
} }
mask_entry = isuser(src_dst) ? USER_PROC_NR : src_dst;
if (! isallowed(caller_ptr->p_sendmask, mask_entry)) {
kprintf("WARNING: sys_call denied %d ", caller_ptr->p_nr);
kprintf("sending to %d\n", proc_addr(src_dst)->p_nr);
result = ECALLDENIED; /* call denied by send mask */
break;
}
result = mini_send(caller_ptr, src_dst, m_ptr,
! (flags & NON_BLOCKING) );
if (function == SEND || result != OK) {
break; /* done, or SEND failed */
} /* fall through for BOTH */
case RECEIVE:
result = mini_rec(caller_ptr, src_dst, m_ptr,
! (flags & NON_BLOCKING) );
break;
case NOTIFY:
result = mini_notify(caller_ptr, src_dst, m_ptr);
break;
default:
result = EBADCALL; /* illegal system call */
} }
/* Now, return the result of the system call to the caller. */ /* Now, return the result of the system call to the caller. */
@ -145,44 +164,28 @@ message *m_ptr; /* pointer to message in the caller's space */
/*===========================================================================* /*===========================================================================*
* mini_send * * mini_send *
*===========================================================================*/ *===========================================================================*/
PRIVATE int mini_send(caller_ptr, dst, m_ptr, may_block) PRIVATE int mini_send(caller_ptr, dst, m_ptr, flags)
register struct proc *caller_ptr; /* who is trying to send a message? */ register struct proc *caller_ptr; /* who is trying to send a message? */
int dst; /* to whom is message being sent? */ int dst; /* to whom is message being sent? */
message *m_ptr; /* pointer to message buffer */ message *m_ptr; /* pointer to message buffer */
int may_block; /* (dis)allow blocking */ int flags; /* system call flags */
{ {
/* Send a message from 'caller_ptr' to 'dst'. If 'dst' is blocked waiting /* Send a message from 'caller_ptr' to 'dst'. If 'dst' is blocked waiting
* for this message, copy the message to it and unblock 'dst'. If 'dst' is * for this message, copy the message to it and unblock 'dst'. If 'dst' is
* not waiting at all, or is waiting for another source, queue 'caller_ptr'. * not waiting at all, or is waiting for another source, queue 'caller_ptr'.
*/ */
register struct proc *dst_ptr, *next_ptr; register struct proc *dst_ptr;
vir_bytes vb; /* message buffer pointer as vir_bytes */ #if DEAD_CODE
vir_clicks vlo, vhi; /* virtual clicks containing message to send */ register struct proc *next_ptr;
#endif
register struct proc *xp;
register struct proc **xpp;
dst_ptr = proc_addr(dst); /* pointer to destination's proc entry */ dst_ptr = proc_addr(dst); /* pointer to destination's proc entry */
#if ALLOW_GAP_MESSAGES /* Check for deadlock by 'caller_ptr' and 'dst' sending to each other.
/* This check allows a message to be anywhere in data or stack or gap. * This check is rare, so overhead is acceptable.
* It will have to be made more elaborate later for machines which
* don't have the gap mapped.
*/ */
vb = (vir_bytes) m_ptr;
vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */
vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* vir click for top of msg */
if (vlo < caller_ptr->p_memmap[D].mem_vir || vlo > vhi ||
vhi >= caller_ptr->p_memmap[S].mem_vir + caller_ptr->p_memmap[S].mem_len)
return(EFAULT);
#else
/* Check for messages wrapping around top of memory or outside data seg. */
vb = (vir_bytes) m_ptr;
vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */
vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* vir click for top of msg */
if (vhi < vlo ||
vhi - caller_ptr->p_memmap[D].mem_vir >= caller_ptr->p_memmap[D].mem_len)
return(EFAULT);
#endif
/* Check for deadlock by 'caller_ptr' and 'dst' sending to each other. */
if (dst_ptr->p_flags & SENDING) { if (dst_ptr->p_flags & SENDING) {
next_ptr = proc_addr(dst_ptr->p_sendto); next_ptr = proc_addr(dst_ptr->p_sendto);
while (TRUE) { while (TRUE) {
@ -194,16 +197,17 @@ int may_block; /* (dis)allow blocking */
} }
} }
/* Check to see if 'dst' is blocked waiting for this message. */ /* Check if 'dst' is blocked waiting for this message. The destination's
* SENDING flag may be set when BOTH couldn't send. Await a pure RECEIVE.
*/
if ( (dst_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING && if ( (dst_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
(dst_ptr->p_getfrom == ANY || (dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) {
dst_ptr->p_getfrom == proc_number(caller_ptr))) {
/* Destination is indeed waiting for this message. */ /* Destination is indeed waiting for this message. */
CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dst_ptr, CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr,
dst_ptr->p_messbuf); dst_ptr->p_messbuf);
dst_ptr->p_flags &= ~RECEIVING; /* deblock destination */ dst_ptr->p_flags &= ~RECEIVING; /* deblock destination */
if (dst_ptr->p_flags == 0) ready(dst_ptr); if (dst_ptr->p_flags == 0) ready(dst_ptr);
} else if (may_block) { } else if (flags) {
/* Destination is not waiting. Block and queue caller. */ /* Destination is not waiting. Block and queue caller. */
caller_ptr->p_messbuf = m_ptr; caller_ptr->p_messbuf = m_ptr;
if (caller_ptr->p_flags == 0) unready(caller_ptr); if (caller_ptr->p_flags == 0) unready(caller_ptr);
@ -211,14 +215,20 @@ int may_block; /* (dis)allow blocking */
caller_ptr->p_sendto = dst; caller_ptr->p_sendto = dst;
/* Process is now blocked. Put in on the destination's queue. */ /* Process is now blocked. Put in on the destination's queue. */
#if DEAD_CODE
if ( (next_ptr = dst_ptr->p_caller_q) == NIL_PROC) if ( (next_ptr = dst_ptr->p_caller_q) == NIL_PROC)
dst_ptr->p_caller_q = caller_ptr; dst_ptr->p_caller_q = caller_ptr;
else { else {
while (next_ptr->p_sendlink != NIL_PROC) while (next_ptr->p_q_link != NIL_PROC)
next_ptr = next_ptr->p_sendlink; next_ptr = next_ptr->p_q_link;
next_ptr->p_sendlink = caller_ptr; next_ptr->p_q_link = caller_ptr;
} }
caller_ptr->p_sendlink = NIL_PROC; #else
xpp = &dst_ptr->p_caller_q;
while (*xpp != NIL_PROC) xpp = &(*xpp)->p_q_link;
*xpp = caller_ptr;
#endif
caller_ptr->p_q_link = NIL_PROC;
} else { } else {
return(ENOTREADY); return(ENOTREADY);
} }
@ -228,69 +238,89 @@ int may_block; /* (dis)allow blocking */
/*===========================================================================* /*===========================================================================*
* mini_rec * * mini_rec *
*===========================================================================*/ *===========================================================================*/
PRIVATE int mini_rec(caller_ptr, src, m_ptr, may_block) PRIVATE int mini_rec(caller_ptr, src, m_ptr, flags)
register struct proc *caller_ptr; /* process trying to get message */ register struct proc *caller_ptr; /* process trying to get message */
int src; /* which message source is wanted */ int src; /* which message source is wanted */
message *m_ptr; /* pointer to message buffer */ message *m_ptr; /* pointer to message buffer */
int may_block; /* (dis)allow blocking */ int flags; /* system call flags */
{ {
/* A process or task wants to get a message. If one is already queued, /* A process or task wants to get a message. If one is already queued,
* acquire it and deblock the sender. If no message from the desired source * acquire it and deblock the sender. If no message from the desired source
* is available, block the caller. * is available, block the caller.
*/ */
#if DEAD_CODE
register struct proc *sender_ptr; register struct proc *sender_ptr;
register struct proc *previous_ptr; register struct proc *previous_ptr;
#endif
register struct proc **xpp;
register struct notification **ntf_q_pp; register struct notification **ntf_q_pp;
message m; message m;
int bit_nr, i; int bit_nr;
/* Check to see if a message from desired source is already available. */ /* Check to see if a message from desired source is already available.
* The caller's SENDING flag may be set if BOTH couldn't send. If it is
* set, the process should be blocked.
*/
if (!(caller_ptr->p_flags & SENDING)) { if (!(caller_ptr->p_flags & SENDING)) {
/* Check caller queue. */ /* Check caller queue. Use pointer pointers to keep code simple. */
#if DEAD_CODE /* to hairy, unreadable */
for (sender_ptr = caller_ptr->p_caller_q; sender_ptr != NIL_PROC; for (sender_ptr = caller_ptr->p_caller_q; sender_ptr != NIL_PROC;
previous_ptr = sender_ptr, sender_ptr = sender_ptr->p_sendlink) { previous_ptr = sender_ptr, sender_ptr = sender_ptr->p_q_link) {
if (src == ANY || src == proc_number(sender_ptr)) { if (src == ANY || src == proc_nr(sender_ptr)) {
/* An acceptable message has been found. */ /* An acceptable message has been found. */
CopyMess(proc_number(sender_ptr), sender_ptr, CopyMess(sender_ptr->p_nr, sender_ptr,
sender_ptr->p_messbuf, caller_ptr, m_ptr); sender_ptr->p_messbuf, caller_ptr, m_ptr);
if (sender_ptr == caller_ptr->p_caller_q) if (sender_ptr == caller_ptr->p_caller_q)
caller_ptr->p_caller_q = sender_ptr->p_sendlink; caller_ptr->p_caller_q = sender_ptr->p_q_link;
else else
previous_ptr->p_sendlink = sender_ptr->p_sendlink; previous_ptr->p_q_link = sender_ptr->p_q_link;
if ((sender_ptr->p_flags &= ~SENDING) == 0) if ((sender_ptr->p_flags &= ~SENDING) == 0)
ready(sender_ptr); /* deblock sender */ ready(sender_ptr); /* deblock sender */
return(OK); return(OK);
} }
} }
#else
xpp = &caller_ptr->p_caller_q;
while (*xpp != NIL_PROC) {
if (src == ANY || src == proc_nr(*xpp)) {
/* An acceptable source has been found. Copy the message to the
* caller, update the sender's status, and remove the sender from
* the caller's queue.
*/
CopyMess((*xpp)->p_nr, *xpp, (*xpp)->p_messbuf, caller_ptr, m_ptr);
if (((*xpp)->p_flags &= ~SENDING) == 0) ready(*xpp);
*xpp = (*xpp)->p_q_link; /* remove from queue */
return(OK);
}
xpp = &(*xpp)->p_q_link; /* proceed to next */
}
#endif
/* Check if there are pending notifications. */ /* Check if there are pending notifications. */
ntf_q_pp = &caller_ptr->p_ntf_q; /* get pointer pointer */ ntf_q_pp = &caller_ptr->p_ntf_q; /* get pointer pointer */
while (*ntf_q_pp) { while (*ntf_q_pp != NULL) {
if (src == ANY || src == (*ntf_q_pp)->n_source) { if (src == ANY || src == (*ntf_q_pp)->n_source) {
/* Found notification. Assemble and copy message. */ /* Found notification. Assemble and copy message. */
m.NOTIFY_SOURCE = (*ntf_q_pp)->n_source; BuildMess(m, *ntf_q_pp);
m.NOTIFY_TYPE = (*ntf_q_pp)->n_type;
m.NOTIFY_FLAGS = (*ntf_q_pp)->n_flags;
m.NOTIFY_ARG = (*ntf_q_pp)->n_arg;
CopyMess((*ntf_q_pp)->n_source, proc_addr(HARDWARE), &m, CopyMess((*ntf_q_pp)->n_source, proc_addr(HARDWARE), &m,
caller_ptr, m_ptr); caller_ptr, m_ptr);
/* Remove notification from queue and return. */ /* Remove notification from queue and bit map. */
bit_nr = ((long)(*ntf_q_pp) - (long) &notify_buffer[0]) / bit_nr = ((long)(*ntf_q_pp) - (long) &notify_buffer[0]) /
sizeof(struct notification); sizeof(struct notification);
*ntf_q_pp = (*ntf_q_pp)->n_next;/* remove from queue */ *ntf_q_pp = (*ntf_q_pp)->n_next;/* remove from queue */
free_bit(bit_nr, notify_bitmap, NR_NOTIFY_BUFS); free_bit(bit_nr, notify_bitmap, NR_NOTIFY_BUFS);
kinfo.nr_ntf_pending --;
return(OK); /* report success */ return(OK); /* report success */
} }
ntf_q_pp = &(*ntf_q_pp)->n_next; /* proceed to next */ ntf_q_pp = &(*ntf_q_pp)->n_next; /* proceed to next */
} }
} }
/* No suitable message is available. Block the process trying to receive, /* No suitable message is available or the caller couldn't send in BOTH.
* unless this is not allowed by the system call. * Block the process trying to receive, unless the flags tell otherwise.
*/ */
if (may_block) { if (flags) {
caller_ptr->p_getfrom = src; caller_ptr->p_getfrom = src;
caller_ptr->p_messbuf = m_ptr; caller_ptr->p_messbuf = m_ptr;
if (caller_ptr->p_flags == 0) unready(caller_ptr); if (caller_ptr->p_flags == 0) unready(caller_ptr);
@ -316,51 +346,53 @@ message *m_ptr; /* pointer to message buffer */
int ntf_index; int ntf_index;
message ntf_mess; message ntf_mess;
/* Check to see if target is blocked waiting for this message. */ /* Check to see if target is blocked waiting for this message. A process
* can be both sending and receiving during a BOTH system call.
*/
if ( (dst_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING && if ( (dst_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
(dst_ptr->p_getfrom == ANY || (dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) {
dst_ptr->p_getfrom == proc_number(caller_ptr))) {
/* Destination is indeed waiting for this message. */ /* Destination is indeed waiting for this message. */
CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dst_ptr, CopyMess(proc_nr(caller_ptr), caller_ptr, m_ptr,
dst_ptr->p_messbuf); dst_ptr, dst_ptr->p_messbuf);
dst_ptr->p_flags &= ~RECEIVING; /* deblock destination */ dst_ptr->p_flags &= ~RECEIVING; /* deblock destination */
if (dst_ptr->p_flags == 0) ready(dst_ptr); if (dst_ptr->p_flags == 0) ready(dst_ptr);
} }
/* Destination is not ready. Add the notification to the pending queue. */ /* Destination is not ready. Add the notification to the pending queue. */
else { else {
/* Get pointer to notification message. */ /* Get pointer to notification message. Don't copy for kernel. */
if (! istaskp(caller_ptr)) { if (! iskernelp(caller_ptr)) {
CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, CopyMess(proc_nr(caller_ptr), caller_ptr, m_ptr,
proc_addr(HARDWARE), &ntf_mess); proc_addr(HARDWARE), &ntf_mess);
m_ptr = &ntf_mess; m_ptr = &ntf_mess;
} }
/* Enqueue the message. Existing notifications are overwritten with /* Enqueue the message. Existing notifications with the same source
* the newer one. New notifications are added to the end of the list. * and type are overwritten with newer ones. New notifications that
* are not yet on the list are added to the end.
*/ */
ntf_q_pp = &dst_ptr->p_ntf_q; ntf_q_pp = &dst_ptr->p_ntf_q;
while (*ntf_q_pp) { while (*ntf_q_pp != NULL) {
/* Replace notifications with same source and type. */ /* Replace notifications with same source and type. */
if ((*ntf_q_pp)->n_type == m_ptr->m_type && if ((*ntf_q_pp)->n_type == m_ptr->NOTIFY_TYPE &&
(*ntf_q_pp)->n_source == m_ptr->m_source) { (*ntf_q_pp)->n_source == proc_nr(caller_ptr)) {
(*ntf_q_pp)->n_flags = m_ptr->NOTIFY_FLAGS; (*ntf_q_pp)->n_flags = m_ptr->NOTIFY_FLAGS;
(*ntf_q_pp)->n_arg = m_ptr->NOTIFY_ARG; (*ntf_q_pp)->n_arg = m_ptr->NOTIFY_ARG;
break; return(OK);
} }
return(OK); ntf_q_pp = &(*ntf_q_pp)->n_next;
} }
/* Add to end of queue. Get a free notification buffer. */ /* Add to end of queue. Get a free notification buffer. */
if ((ntf_index = alloc_bit(notify_bitmap, NR_NOTIFY_BUFS)) < 0) if ((ntf_index = alloc_bit(notify_bitmap, NR_NOTIFY_BUFS)) < 0)
return(ENOSPC); /* should be atomic! */ return(ENOSPC);
kinfo.nr_ntf_pending ++;
ntf_p = &notify_buffer[ntf_index]; ntf_p = &notify_buffer[ntf_index];
ntf_p->n_source = proc_number(caller_ptr); ntf_p->n_source = proc_nr(caller_ptr);
ntf_p->n_type = m_ptr->NOTIFY_TYPE; ntf_p->n_type = m_ptr->NOTIFY_TYPE;
ntf_p->n_flags = m_ptr->NOTIFY_FLAGS; ntf_p->n_flags = m_ptr->NOTIFY_FLAGS;
ntf_p->n_arg = m_ptr->NOTIFY_ARG; ntf_p->n_arg = m_ptr->NOTIFY_ARG;
*ntf_q_pp = ntf_p; *ntf_q_pp = ntf_p; /* add to end of queue */
ntf_p->n_next = NULL; /* mark new end of queue */
} }
return(OK); return(OK);
} }
@ -374,16 +406,13 @@ message *m_ptr; /* pointer to message buffer */
{ {
/* Safe gateway to mini_notify() for tasks and interrupt handlers. This /* Safe gateway to mini_notify() for tasks and interrupt handlers. This
* function checks if it is called from an interrupt handler and makes sure * function checks if it is called from an interrupt handler and makes sure
* that the correct message source is put on the notification. All kernel * that the correct message source is put on the notification.
* generated notifications share the same pseudo-process number, to prevent
* conflicts with SENDREC calls to the kernel task.
*/ */
int result; int result;
struct proc *caller_ptr; struct proc *caller_ptr;
lock(); lock();
caller_ptr = (k_reenter >= 0 || istaskp(proc_ptr)) ? caller_ptr = (k_reenter >= 0) ? proc_addr(HARDWARE) : proc_ptr;
proc_addr(KERNEL) : proc_ptr;
result = mini_notify(caller_ptr, dst, m_ptr); result = mini_notify(caller_ptr, dst, m_ptr);
unlock(); unlock();
return(result); return(result);
@ -423,6 +452,7 @@ register struct proc *rp; /* this process is now runnable */
{ {
/* Add 'rp' to one of the queues of runnable processes. */ /* Add 'rp' to one of the queues of runnable processes. */
register int q = rp->p_priority; /* scheduling queue to use */ register int q = rp->p_priority; /* scheduling queue to use */
register struct proc **xpp; /* iterate over queue */
#if ENABLE_K_DEBUGGING #if ENABLE_K_DEBUGGING
if(rp->p_ready) { if(rp->p_ready) {
@ -435,6 +465,18 @@ register struct proc *rp; /* this process is now runnable */
* user processes are added in front of the queue, because this is a bit * user processes are added in front of the queue, because this is a bit
* fairer to I/O bound processes. * fairer to I/O bound processes.
*/ */
#if NEW_SCHED_Q
if (isuserp(rp)) { /* add to front of queue */
rp->p_nextready = rdy_head[q]; /* chain current front */
rdy_head[q] = rp; /* ready process becomes front */
}
else { /* add to end of queue */
xpp = &rdy_head[q]; /* find pointer to end of queue */
while (*xpp != NIL_PROC) xpp = &(*xpp)->p_nextready;
*xpp = rp; /* replace end with ready process */
rp->p_nextready = NIL_PROC; /* mark end of queue */
}
#else
if (isuserp(rp)) { /* add to front of queue */ if (isuserp(rp)) { /* add to front of queue */
if (rdy_head[q] == NIL_PROC) if (rdy_head[q] == NIL_PROC)
rdy_tail[q] = rp; rdy_tail[q] = rp;
@ -449,6 +491,7 @@ register struct proc *rp; /* this process is now runnable */
rdy_tail[q] = rp; rdy_tail[q] = rp;
rp->p_nextready = NIL_PROC; rp->p_nextready = NIL_PROC;
} }
#endif
/* Run 'rp' next if it has a higher priority than 'proc_ptr' or 'next_ptr'. /* Run 'rp' next if it has a higher priority than 'proc_ptr' or 'next_ptr'.
* This actually should be done via pick_proc(), but the message passing * This actually should be done via pick_proc(), but the message passing
@ -456,10 +499,6 @@ register struct proc *rp; /* this process is now runnable */
*/ */
if (next_ptr && next_ptr->p_priority > rp->p_priority) next_ptr = rp; if (next_ptr && next_ptr->p_priority > rp->p_priority) next_ptr = rp;
else if (proc_ptr->p_priority > rp->p_priority) next_ptr = rp; else if (proc_ptr->p_priority > rp->p_priority) next_ptr = rp;
#if DEAD_CODE
if (rp->p_priority < proc_ptr->p_priority) proc_ptr = rp;
#endif
} }
/*===========================================================================* /*===========================================================================*
@ -470,9 +509,13 @@ register struct proc *rp; /* this process is no longer runnable */
{ {
/* A process has blocked. See ready for a description of the queues. */ /* A process has blocked. See ready for a description of the queues. */
register struct proc *xp;
register struct proc **qtail; /* queue's rdy_tail */
register int q = rp->p_priority; /* queue to use */ register int q = rp->p_priority; /* queue to use */
#if NEW_SCHED_Q
register struct proc **xpp; /* iterate over queue */
#else
register struct proc **qtail; /* queue's rdy_tail */
register struct proc *xp;
#endif
#if ENABLE_K_DEBUGGING #if ENABLE_K_DEBUGGING
if(!rp->p_ready) { if(!rp->p_ready) {
@ -484,13 +527,25 @@ register struct proc *rp; /* this process is no longer runnable */
/* Side-effect for tasks: check if the task's stack still is ok? */ /* Side-effect for tasks: check if the task's stack still is ok? */
if (istaskp(rp)) { if (istaskp(rp)) {
if (*rp->p_stguard != STACK_GUARD) if (*rp->p_stguard != STACK_GUARD)
panic("stack overrun by task", proc_number(rp)); panic("stack overrun by task", proc_nr(rp));
} }
/* Now make sure that the process is not in its ready queue. Remove the /* Now make sure that the process is not in its ready queue. Remove the
* process if it is found. A process can be made unready even if it is not * process if it is found. A process can be made unready even if it is not
* running by being sent a signal that kills it. * running by being sent a signal that kills it.
*/ */
#if NEW_SCHED_Q
xpp = &rdy_head[q];
while (*xpp != NIL_PROC) { /* check entire queue */
if (*xpp == rp) { /* lookup unready process */
*xpp = (*xpp)->p_nextready; /* replace it with next */
if (rp == proc_ptr || rp == next_ptr) /* current process removed */
pick_proc(); /* pick new process to run */
break;
}
xpp = &(*xpp)->p_nextready; /* proceed to next */
}
#else
if ( (xp = rdy_head[q]) != NIL_PROC) { /* ready queue is empty */ if ( (xp = rdy_head[q]) != NIL_PROC) { /* ready queue is empty */
if (xp == rp) { /* check head of queue */ if (xp == rp) { /* check head of queue */
rdy_head[q] = xp->p_nextready; /* new head of queue */ rdy_head[q] = xp->p_nextready; /* new head of queue */
@ -508,25 +563,41 @@ register struct proc *rp; /* this process is no longer runnable */
rdy_tail[q] = xp; rdy_tail[q] = xp;
} }
} }
#endif
} }
/*===========================================================================* /*===========================================================================*
* sched * * sched *
*===========================================================================*/ *===========================================================================*/
PRIVATE void sched() PRIVATE void sched(queue)
int queue;
{ {
/* The current process has run too long. If another low priority (user) /* The current process has run too long. If another low priority (user)
* process is runnable, put the current process on the end of the user queue, * process is runnable, put the current process on the end of the user queue,
* possibly promoting another user to head of the queue. * possibly promoting another user to head of the queue.
*/ */
if (rdy_head[PPRI_USER] == NIL_PROC) return; register struct proc **xpp;
register struct proc *xp;
if (rdy_head[queue] == NIL_PROC) return;
/* One or more user processes queued. */ /* One or more user processes queued. */
rdy_tail[PPRI_USER]->p_nextready = rdy_head[PPRI_USER]; #if NEW_SCHED_Q
rdy_tail[PPRI_USER] = rdy_head[PPRI_USER];
rdy_head[PPRI_USER] = rdy_head[PPRI_USER]->p_nextready; xp = rdy_head[queue]; /* save expired process */
rdy_tail[PPRI_USER]->p_nextready = NIL_PROC; rdy_head[queue] = xp->p_nextready; /* advance to next process */
xpp = &rdy_head[queue]; /* find end of queue */
while (*xpp != NIL_PROC) xpp = &(*xpp)->p_nextready;
*xpp = xp; /* add expired to end */
xp->p_nextready = NIL_PROC; /* mark end of queue */
#else
rdy_tail[queue]->p_nextready = rdy_head[queue];
rdy_tail[queue] = rdy_head[queue];
rdy_head[queue] = rdy_head[queue]->p_nextready;
rdy_tail[queue]->p_nextready = NIL_PROC;
#endif
pick_proc(); pick_proc();
} }
@ -585,11 +656,12 @@ struct proc *rp; /* this process is no longer runnable */
/*==========================================================================* /*==========================================================================*
* lock_sched * * lock_sched *
*==========================================================================*/ *==========================================================================*/
PUBLIC void lock_sched() PUBLIC void lock_sched(queue)
int queue;
{ {
/* Safe gateway to sched() for tasks. */ /* Safe gateway to sched() for tasks. */
lock(); lock();
sched(); sched(queue);
unlock(); unlock();
} }

View file

@ -35,7 +35,7 @@ struct proc {
struct mem_map p_memmap[NR_LOCAL_SEGS]; /* local memory map (T, D, S) */ struct mem_map p_memmap[NR_LOCAL_SEGS]; /* local memory map (T, D, S) */
struct far_mem p_farmem[NR_REMOTE_SEGS]; /* remote memory map */ struct far_mem p_farmem[NR_REMOTE_SEGS]; /* remote memory map */
short p_flags; /* SENDING, RECEIVING, etc. */ char p_flags; /* SENDING, RECEIVING, etc. */
char p_type; /* task, system, driver, server, user, idle */ char p_type; /* task, system, driver, server, user, idle */
char p_priority; /* scheduling priority */ char p_priority; /* scheduling priority */
@ -51,7 +51,7 @@ struct proc {
struct proc *p_nextready; /* pointer to next ready process */ struct proc *p_nextready; /* pointer to next ready process */
struct notification *p_ntf_q; /* queue of pending notifications */ struct notification *p_ntf_q; /* queue of pending notifications */
struct proc *p_caller_q; /* head of list of procs wishing to send */ struct proc *p_caller_q; /* head of list of procs wishing to send */
struct proc *p_sendlink; /* link to next proc wishing to send */ struct proc *p_q_link; /* link to next proc wishing to send */
message *p_messbuf; /* pointer to message buffer */ message *p_messbuf; /* pointer to message buffer */
proc_nr_t p_getfrom; /* from whom does process want to receive? */ proc_nr_t p_getfrom; /* from whom does process want to receive? */
proc_nr_t p_sendto; /* to whom does process want to send? */ proc_nr_t p_sendto; /* to whom does process want to send? */
@ -74,9 +74,9 @@ struct proc {
#define NO_MAP 0x01 /* keeps unmapped forked child from running */ #define NO_MAP 0x01 /* keeps unmapped forked child from running */
#define SENDING 0x02 /* set when process blocked trying to send */ #define SENDING 0x02 /* set when process blocked trying to send */
#define RECEIVING 0x04 /* set when process blocked trying to recv */ #define RECEIVING 0x04 /* set when process blocked trying to recv */
#define PENDING 0x08 /* set when inform() of signal pending */ #define PENDING 0x10 /* set when inform() of signal pending */
#define SIG_PENDING 0x10 /* keeps to-be-signalled proc from running */ #define SIG_PENDING 0x20 /* keeps to-be-signalled proc from running */
#define P_STOP 0x20 /* set when process is being traced */ #define P_STOP 0x40 /* set when process is being traced */
/* Values for p_type. Non-negative values represent active process types. /* Values for p_type. Non-negative values represent active process types.
* Process types are important to model inter-process relationships. When * Process types are important to model inter-process relationships. When
@ -120,9 +120,6 @@ struct proc {
#define isalive(n) (proc_addr(n)->p_type > P_NONE) #define isalive(n) (proc_addr(n)->p_type > P_NONE)
#define isalivep(p) ((p)->p_type > P_NONE) #define isalivep(p) ((p)->p_type > P_NONE)
#define isrxhardware(n) ((n) == ANY || (n) == HARDWARE) #define isrxhardware(n) ((n) == ANY || (n) == HARDWARE)
#define iskernel(n) ((n) == CLOCK || (n) == SYSTASK)
#define issysentn(n) ((n) == FS_PROC_NR || (n) == PM_PROC_NR)
#define issysentp(p) (issysentn((p)->p_nr))
#define isreservedp(p) ((p)->p_type == P_RESERVED) #define isreservedp(p) ((p)->p_type == P_RESERVED)
#define isemptyp(p) ((p)->p_type == P_NONE) #define isemptyp(p) ((p)->p_type == P_NONE)
#define istaskp(p) ((p)->p_type == P_TASK) #define istaskp(p) ((p)->p_type == P_TASK)
@ -131,12 +128,11 @@ struct proc {
#define isuserp(p) ((p)->p_type == P_USER) #define isuserp(p) ((p)->p_type == P_USER)
#define isuser(n) (proc_addr(n)->p_type == P_USER) #define isuser(n) (proc_addr(n)->p_type == P_USER)
#define isidlep(p) ((p)->p_type == P_IDLE) #define isidlep(p) ((p)->p_type == P_IDLE)
#define proc_addr(n) (pproc_addr + NR_TASKS)[(n)]
#define cproc_addr(n) (&(proc + NR_TASKS)[(n)]) #define cproc_addr(n) (&(proc + NR_TASKS)[(n)])
#define proc_number(p) ((p)->p_nr) #define proc_addr(n) (pproc_addr + NR_TASKS)[(n)]
#define proc_vir2phys(p, vir) \ #define proc_nr(p) ((p)->p_nr)
(((phys_bytes)(p)->p_map[D].mem_phys << CLICK_SHIFT) \ #define iskernelp(p) ((p)->p_nr < 0)
+ (vir_bytes) (vir)) #define iskernel(n) ((n) == CLOCK || (n) == SYSTASK)
/* The process table and pointers to process table slots. The pointers allow /* The process table and pointers to process table slots. The pointers allow
* faster access because now a process entry can be found by indexing the * faster access because now a process entry can be found by indexing the

View file

@ -48,7 +48,7 @@ _PROTOTYPE( int lock_notify, (int dst, message *m_ptr) );
_PROTOTYPE( int lock_send, (int dst, message *m_ptr) ); _PROTOTYPE( int lock_send, (int dst, message *m_ptr) );
_PROTOTYPE( void lock_pick_proc, (void) ); _PROTOTYPE( void lock_pick_proc, (void) );
_PROTOTYPE( void lock_ready, (struct proc *rp) ); _PROTOTYPE( void lock_ready, (struct proc *rp) );
_PROTOTYPE( void lock_sched, (void) ); _PROTOTYPE( void lock_sched, (int queue) );
_PROTOTYPE( void lock_unready, (struct proc *rp) ); _PROTOTYPE( void lock_unready, (struct proc *rp) );
/* start.c */ /* start.c */

View file

@ -79,7 +79,7 @@ PUBLIC void sys_task()
if ((unsigned) m.m_type < NR_SYS_CALLS) { if ((unsigned) m.m_type < NR_SYS_CALLS) {
result = (*call_vec[m.m_type])(&m); /* do system call */ result = (*call_vec[m.m_type])(&m); /* do system call */
} else { } else {
kprintf("SYS task got illegal request from %d.\n", m.m_source); kprintf("Warning, illegal SYSTASK request from %d.\n", m.m_source);
result = EBADREQUEST; /* illegal message type */ result = EBADREQUEST; /* illegal message type */
} }
@ -89,7 +89,8 @@ PUBLIC void sys_task()
*/ */
if (result != EDONTREPLY) { if (result != EDONTREPLY) {
m.m_type = result; /* report status of call */ m.m_type = result; /* report status of call */
lock_send(m.m_source, &m); if (OK != lock_send(m.m_source, &m))
kprintf("Warning, SYSTASK couldn't reply to %d\n", m.m_source);
} }
} }
} }
@ -177,7 +178,11 @@ PUBLIC void clear_proc(proc_nr)
int proc_nr; /* slot of process to clean up */ int proc_nr; /* slot of process to clean up */
{ {
register struct proc *rp, *rc; register struct proc *rp, *rc;
#if DEAD_CODE
struct proc *np, *xp; struct proc *np, *xp;
#else
register struct proc **xpp; /* iterate over caller queue */
#endif
/* Get a pointer to the process that exited. */ /* Get a pointer to the process that exited. */
rc = proc_addr(proc_nr); rc = proc_addr(proc_nr);
@ -199,22 +204,34 @@ int proc_nr; /* slot of process to clean up */
/* Check all proc slots to see if the exiting process is queued. */ /* Check all proc slots to see if the exiting process is queued. */
for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) { for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
if (rp->p_caller_q == NIL_PROC) continue; if (rp->p_caller_q == NIL_PROC) continue;
#if DEAD_CODE
if (rp->p_caller_q == rc) { if (rp->p_caller_q == rc) {
/* Exiting process is on front of this queue. */ /* Exiting process is on front of this queue. */
rp->p_caller_q = rc->p_sendlink; rp->p_caller_q = rc->p_q_link;
break; break;
} else { } else {
/* See if exiting process is in middle of queue. */ /* See if exiting process is in middle of queue. */
np = rp->p_caller_q; np = rp->p_caller_q;
while ( ( xp = np->p_sendlink) != NIL_PROC) { while ( ( xp = np->p_q_link) != NIL_PROC) {
if (xp == rc) { if (xp == rc) {
np->p_sendlink = xp->p_sendlink; np->p_q_link = xp->p_q_link;
break; break;
} else { } else {
np = xp; np = xp;
} }
} }
} }
#else
/* Make sure that the exiting process is not on the queue. */
xpp = &rp->p_caller_q;
while (*xpp != NIL_PROC) { /* check entire queue */
if (*xpp == rc) { /* process is on the queue */
*xpp = (*xpp)->p_q_link; /* replace by next process */
break;
}
xpp = &(*xpp)->p_q_link; /* proceed to next queued */
}
#endif
} }
} }

View file

@ -165,7 +165,6 @@ timer_t *tp;
* process given with a SYN_ALARM message. * process given with a SYN_ALARM message.
*/ */
message m; message m;
m.NOTIFY_SOURCE = SYSTASK;
m.NOTIFY_TYPE = SYN_ALARM; m.NOTIFY_TYPE = SYN_ALARM;
m.NOTIFY_ARG = get_uptime(); m.NOTIFY_ARG = get_uptime();
m.NOTIFY_FLAGS = 0; m.NOTIFY_FLAGS = 0;

View file

@ -35,7 +35,7 @@ message *m_ptr; /* pointer to request message */
/* Find the next process with pending signals. */ /* Find the next process with pending signals. */
for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) { for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
if (rp->p_flags & PENDING) { if (rp->p_flags & PENDING) {
m_ptr->SIG_PROC = proc_number(rp); m_ptr->SIG_PROC = rp->p_nr;
m_ptr->SIG_MAP = rp->p_pending; m_ptr->SIG_MAP = rp->p_pending;
sigemptyset(&rp->p_pending); /* ball is in PM's court */ sigemptyset(&rp->p_pending); /* ball is in PM's court */
rp->p_flags &= ~PENDING; /* blocked by SIG_PENDING */ rp->p_flags &= ~PENDING; /* blocked by SIG_PENDING */

View file

@ -67,11 +67,11 @@ PUBLIC struct system_image image[] = {
{ HARDWARE, 0, P_TASK, PPRI_TASK, HARDWARE_STACK,HARDWARE_SENDMASK,"HARDWAR" }, { HARDWARE, 0, P_TASK, PPRI_TASK, HARDWARE_STACK,HARDWARE_SENDMASK,"HARDWAR" },
{ PM_PROC_NR, 0, P_SERVER, PPRI_NORMAL, 0, PM_SENDMASK, "PM" }, { PM_PROC_NR, 0, P_SERVER, PPRI_NORMAL, 0, PM_SENDMASK, "PM" },
{ FS_PROC_NR, 0, P_SERVER, PPRI_NORMAL, 0, FS_SENDMASK, "FS" }, { FS_PROC_NR, 0, P_SERVER, PPRI_NORMAL, 0, FS_SENDMASK, "FS" },
{ IS_PROC_NR, 0, P_SYSTEM, PPRI_HIGHER, 0, IS_SENDMASK, "IS" }, { IS_PROC_NR, 0, P_SYSTEM, PPRI_HIGH, 0, IS_SENDMASK, "IS" },
{ TTY, 0, P_SYSTEM, PPRI_HIGHER, 0, TTY_SENDMASK, "TTY" }, { TTY, 0, P_SYSTEM, PPRI_HIGHER, 0, TTY_SENDMASK, "TTY" },
{ MEMORY, 0, P_DRIVER, PPRI_HIGH, 0, MEM_SENDMASK, "MEMORY" }, { MEMORY, 0, P_DRIVER, PPRI_HIGH, 0, MEM_SENDMASK, "MEMORY" },
#if ENABLE_AT_WINI #if ENABLE_AT_WINI
{ AT_WINI, 0, P_DRIVER, PPRI_HIGHER, 0, AT_SENDMASK, "AT_WINI" }, { AT_WINI, 0, P_DRIVER, PPRI_HIGH, 0, AT_SENDMASK, "AT_WINI" },
#endif #endif
#if ENABLE_FLOPPY #if ENABLE_FLOPPY
{ FLOPPY, 0, P_DRIVER, PPRI_HIGH, 0, FLOPPY_SENDMASK, "FLOPPY" }, { FLOPPY, 0, P_DRIVER, PPRI_HIGH, 0, FLOPPY_SENDMASK, "FLOPPY" },

View file

@ -51,8 +51,13 @@ struct system_image image[IMAGE_SIZE];
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_fkey_pressed(message *m) PUBLIC int do_fkey_pressed(message *m)
{ {
#if DEAD_CODE
if (F1 <= m->FKEY_CODE && m->FKEY_CODE <= F12) { if (F1 <= m->FKEY_CODE && m->FKEY_CODE <= F12) {
switch(m->FKEY_CODE) { switch(m->FKEY_CODE) {
#else
if (F1 <= m->NOTIFY_ARG && m->NOTIFY_ARG <= F12) {
switch(m->NOTIFY_ARG) {
#endif
case F1: proctab_dmp(); break; case F1: proctab_dmp(); break;
case F2: memmap_dmp(); break; case F2: memmap_dmp(); break;
case F3: image_dmp(); break; case F3: image_dmp(); break;
@ -65,7 +70,12 @@ PUBLIC int do_fkey_pressed(message *m)
case F11: memchunks_dmp(); break; case F11: memchunks_dmp(); break;
case F12: sched_dmp(); break; case F12: sched_dmp(); break;
default: default:
#if DEAD_CODE
printf("IS: unhandled notification for F%d\n", m->FKEY_NUM); printf("IS: unhandled notification for F%d\n", m->FKEY_NUM);
#else
printf("IS: unhandled notify for F%d (code %d)\n",
m->NOTIFY_ARG, m->NOTIFY_FLAGS);
#endif
} }
} }
return(EDONTREPLY); return(EDONTREPLY);
@ -376,7 +386,7 @@ PRIVATE void sendmask_dmp()
printf("\n\n"); printf("\n\n");
printf(" "); printf(" ");
for (j=proc_number(BEG_PROC_ADDR); j< INIT_PROC_NR+1; j++) { for (j=proc_nr(BEG_PROC_ADDR); j< INIT_PROC_NR+1; j++) {
printf("%3d", j); printf("%3d", j);
} }
printf(" *\n"); printf(" *\n");
@ -386,17 +396,17 @@ PRIVATE void sendmask_dmp()
if (++n > 20) break; if (++n > 20) break;
printf("%8s ", rp->p_name); printf("%8s ", rp->p_name);
j = proc_number(rp); j = proc_nr(rp);
switch(rp->p_type) { switch(rp->p_type) {
case P_IDLE: printf("/%3d/ ", proc_number(rp)); break; case P_IDLE: printf("/%3d/ ", proc_nr(rp)); break;
case P_TASK: printf("[%3d] ", proc_number(rp)); break; case P_TASK: printf("[%3d] ", proc_nr(rp)); break;
case P_SYSTEM: printf("<%3d> ", proc_number(rp)); break; case P_SYSTEM: printf("<%3d> ", proc_nr(rp)); break;
case P_DRIVER: printf("{%3d} ", proc_number(rp)); break; case P_DRIVER: printf("{%3d} ", proc_nr(rp)); break;
case P_SERVER: printf("(%3d) ", proc_number(rp)); break; case P_SERVER: printf("(%3d) ", proc_nr(rp)); break;
default: printf(" %3d ", proc_number(rp)); default: printf(" %3d ", proc_nr(rp));
} }
for (j=proc_number(BEG_PROC_ADDR); j<INIT_PROC_NR+2; j++) { for (j=proc_nr(BEG_PROC_ADDR); j<INIT_PROC_NR+2; j++) {
if (isallowed(rp->p_sendmask, j)) printf(" 1 "); if (isallowed(rp->p_sendmask, j)) printf(" 1 ");
else printf(" 0 "); else printf(" 0 ");
} }
@ -438,12 +448,12 @@ PRIVATE void proctab_dmp()
size = rp->p_memmap[T].mem_len size = rp->p_memmap[T].mem_len
+ ((rp->p_memmap[S].mem_phys + rp->p_memmap[S].mem_len) - data); + ((rp->p_memmap[S].mem_phys + rp->p_memmap[S].mem_len) - data);
switch(rp->p_type) { switch(rp->p_type) {
case P_IDLE: printf("/%3d/ ", proc_number(rp)); break; case P_IDLE: printf("/%3d/ ", proc_nr(rp)); break;
case P_TASK: printf("[%3d] ", proc_number(rp)); break; case P_TASK: printf("[%3d] ", proc_nr(rp)); break;
case P_SYSTEM: printf("<%3d> ", proc_number(rp)); break; case P_SYSTEM: printf("<%3d> ", proc_nr(rp)); break;
case P_DRIVER: printf("{%3d} ", proc_number(rp)); break; case P_DRIVER: printf("{%3d} ", proc_nr(rp)); break;
case P_SERVER: printf("(%3d) ", proc_number(rp)); break; case P_SERVER: printf("(%3d) ", proc_nr(rp)); break;
default: printf(" %3d ", proc_number(rp)); default: printf(" %3d ", proc_nr(rp));
} }
printf("%3u %7lx%7lx %6lu%6lu%6uK%6uK%6uK %3x", printf("%3u %7lx%7lx %6lu%6lu%6uK%6uK%6uK %3x",
rp->p_priority, rp->p_priority,
@ -493,7 +503,7 @@ PRIVATE void memmap_dmp()
+ ((rp->p_memmap[S].mem_phys + rp->p_memmap[S].mem_len) + ((rp->p_memmap[S].mem_phys + rp->p_memmap[S].mem_len)
- rp->p_memmap[D].mem_phys); - rp->p_memmap[D].mem_phys);
printf("%3d %-7.7s %4x %4x %4x %4x %4x %4x %4x %4x %4x %5uK\n", printf("%3d %-7.7s %4x %4x %4x %4x %4x %4x %4x %4x %4x %5uK\n",
proc_number(rp), proc_nr(rp),
rp->p_name, rp->p_name,
rp->p_memmap[T].mem_vir, rp->p_memmap[T].mem_phys, rp->p_memmap[T].mem_len, rp->p_memmap[T].mem_vir, rp->p_memmap[T].mem_phys, rp->p_memmap[T].mem_len,
rp->p_memmap[D].mem_vir, rp->p_memmap[D].mem_phys, rp->p_memmap[D].mem_len, rp->p_memmap[D].mem_vir, rp->p_memmap[D].mem_phys, rp->p_memmap[D].mem_len,