Improved NOTIFY system: fixed a minor error, ignore pending notifications
on SENDREC system calls. To be done: resource (buffer pool) management; make it structurally impossible to run out of buffers.
This commit is contained in:
parent
77c3213948
commit
c2be104821
11 changed files with 110 additions and 102 deletions
|
@ -145,7 +145,6 @@ 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 *
|
||||||
|
@ -193,11 +192,6 @@ 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 */
|
||||||
|
@ -210,12 +204,8 @@ 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);
|
||||||
|
@ -232,9 +222,7 @@ 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);
|
||||||
|
@ -267,6 +255,8 @@ PUBLIC void main(void)
|
||||||
|
|
||||||
/* If the device doesn't exist or is not configured return ENXIO. */
|
/* If the device doesn't exist or is not configured return ENXIO. */
|
||||||
if (tp == NULL || ! tty_active(tp)) {
|
if (tp == NULL || ! tty_active(tp)) {
|
||||||
|
printf("Warning, TTY got illegal request %d from %d\n",
|
||||||
|
tty_mess.m_type, tty_mess.m_source);
|
||||||
tty_reply(TASK_REPLY, tty_mess.m_source,
|
tty_reply(TASK_REPLY, tty_mess.m_source,
|
||||||
tty_mess.PROC_NR, ENXIO);
|
tty_mess.PROC_NR, ENXIO);
|
||||||
continue;
|
continue;
|
||||||
|
@ -280,7 +270,10 @@ PUBLIC void main(void)
|
||||||
case DEV_OPEN: do_open(tp, &tty_mess); break;
|
case DEV_OPEN: do_open(tp, &tty_mess); break;
|
||||||
case DEV_CLOSE: do_close(tp, &tty_mess); break;
|
case DEV_CLOSE: do_close(tp, &tty_mess); break;
|
||||||
case CANCEL: do_cancel(tp, &tty_mess); break;
|
case CANCEL: do_cancel(tp, &tty_mess); break;
|
||||||
default: tty_reply(TASK_REPLY, tty_mess.m_source,
|
default:
|
||||||
|
printf("Warning, TTY got unexpected request %d from %d\n",
|
||||||
|
tty_mess.m_type, tty_mess.m_source);
|
||||||
|
tty_reply(TASK_REPLY, tty_mess.m_source,
|
||||||
tty_mess.PROC_NR, EINVAL);
|
tty_mess.PROC_NR, EINVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1314,9 +1307,6 @@ 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 (debug)
|
|
||||||
printf("TTY wanted to send to %d, type %d, status %d\n",
|
|
||||||
proc_nr, code, status);
|
|
||||||
if ((status = send(replyee, &tty_mess)) != OK) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,14 @@
|
||||||
/* Masks and flags for system calls. */
|
/* Masks and flags for system calls. */
|
||||||
#define SYSCALL_FUNC 0x0F /* mask for system call function */
|
#define SYSCALL_FUNC 0x0F /* mask for system call function */
|
||||||
#define SYSCALL_FLAGS 0xF0 /* mask for system call flags */
|
#define SYSCALL_FLAGS 0xF0 /* mask for system call flags */
|
||||||
#define NON_BLOCKING 0x10 /* don't block, but return */
|
#define NON_BLOCKING 0x10 /* prevent blocking, return error */
|
||||||
|
#define FRESH_ANSWER 0x20 /* ignore pending notifications as answer */
|
||||||
|
/* default behaviour for SENDREC calls */
|
||||||
|
|
||||||
/* System calls (numbers passed when trapping to the kernel) */
|
/* System calls (numbers passed when trapping to the kernel) */
|
||||||
#define SEND 1 /* function code for sending messages */
|
#define SEND 1 /* function code for sending messages */
|
||||||
#define RECEIVE 2 /* function code for receiving messages */
|
#define RECEIVE 2 /* function code for receiving messages */
|
||||||
#define BOTH 3 /* function code for SEND + RECEIVE */
|
#define SENDREC 3 /* function code for SEND + RECEIVE */
|
||||||
#define NOTIFY 4 /* function code for notifications */
|
#define NOTIFY 4 /* function code for notifications */
|
||||||
#define NB_SEND (SEND | NON_BLOCKING) /* non-blocking SEND */
|
#define NB_SEND (SEND | NON_BLOCKING) /* non-blocking SEND */
|
||||||
#define NB_RECEIVE (RECEIVE | NON_BLOCKING) /* non-blocking RECEIVE */
|
#define NB_RECEIVE (RECEIVE | NON_BLOCKING) /* non-blocking RECEIVE */
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#define NR_IRQ_HOOKS 16
|
#define NR_IRQ_HOOKS 16
|
||||||
|
|
||||||
/* How many buffers for notification messages should there be? */
|
/* How many buffers for notification messages should there be? */
|
||||||
#define NR_NOTIFY_BUFS 64
|
#define NR_NOTIFY_BUFS 32
|
||||||
|
|
||||||
/* Constants and macros for bit map manipulation. */
|
/* Constants and macros for bit map manipulation. */
|
||||||
#define BITCHUNK_BITS (sizeof(bitchunk_t) * CHAR_BIT)
|
#define BITCHUNK_BITS (sizeof(bitchunk_t) * CHAR_BIT)
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
/* Prototype declarations for PRIVATE functions. */
|
/* Prototype declarations for PRIVATE functions. */
|
||||||
FORWARD _PROTOTYPE( void announce, (void));
|
FORWARD _PROTOTYPE( void announce, (void));
|
||||||
FORWARD _PROTOTYPE( void shutdown, (int how));
|
FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
|
||||||
|
|
||||||
#define STOP_TICKS (5*HZ) /* time allowed to stop */
|
#define STOP_TICKS (5*HZ) /* time allowed to stop */
|
||||||
|
|
||||||
|
@ -248,10 +248,10 @@ int how; /* 0 = halt, 1 = reboot, 2 = panic!, ... */
|
||||||
tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */
|
tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */
|
||||||
if (skip_stop_sequence) { /* set in exception() */
|
if (skip_stop_sequence) { /* set in exception() */
|
||||||
kprintf("\nAn exception occured; skipping stop sequence.\n", NO_ARG);
|
kprintf("\nAn exception occured; skipping stop sequence.\n", NO_ARG);
|
||||||
shutdown(how); /* TTY isn't scheduled */
|
shutdown(&shutdown_timer); /* TTY isn't scheduled */
|
||||||
} else {
|
} else {
|
||||||
kprintf("\nNotifying system services about MINIX shutdown.\n", NO_ARG);
|
kprintf("\nNotifying system services about MINIX shutdown.\n", NO_ARG);
|
||||||
stop_sequence(&shutdown_timer);
|
set_timer(&shutdown_timer, get_uptime(), stop_sequence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ timer_t *tp;
|
||||||
p = BEG_PROC_ADDR;
|
p = BEG_PROC_ADDR;
|
||||||
level = level - 1;
|
level = level - 1;
|
||||||
if (level == P_TASK) { /* done; tasks must remain alive */
|
if (level == P_TASK) { /* done; tasks must remain alive */
|
||||||
shutdown(tmr_arg(tp)->ta_int);
|
shutdown(tp);
|
||||||
/* no return */
|
/* no return */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -313,13 +313,15 @@ timer_t *tp;
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
* shutdown *
|
* shutdown *
|
||||||
*==========================================================================*/
|
*==========================================================================*/
|
||||||
PRIVATE void shutdown(int how)
|
PRIVATE void shutdown(tp)
|
||||||
|
timer_t *tp;
|
||||||
{
|
{
|
||||||
/* This function is called from prepare_shutdown or stop_sequence to bring
|
/* This function is called from prepare_shutdown or stop_sequence to bring
|
||||||
* down MINIX. How to shutdown is in the argument: RBT_REBOOT, RBT_HALT,
|
* down MINIX. How to shutdown is in the argument: RBT_REBOOT, RBT_HALT,
|
||||||
* RBT_RESET.
|
* RBT_RESET.
|
||||||
*/
|
*/
|
||||||
static u16_t magic = STOP_MEM_CHECK;
|
static u16_t magic = STOP_MEM_CHECK;
|
||||||
|
int how = tmr_arg(tp)->ta_int;
|
||||||
|
|
||||||
/* Now mask all interrupts, including the clock, and stop the clock. */
|
/* Now mask all interrupts, including the clock, and stop the clock. */
|
||||||
outb(INT_CTLMASK, ~0);
|
outb(INT_CTLMASK, ~0);
|
||||||
|
|
148
kernel/proc.c
148
kernel/proc.c
|
@ -1,4 +1,6 @@
|
||||||
#define NEW_SCHED_Q 1
|
#define NEW_SCHED_Q 1
|
||||||
|
#define OLD_SEND 1
|
||||||
|
#define OLD_RECV 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:
|
||||||
*
|
*
|
||||||
|
@ -18,7 +20,7 @@
|
||||||
* 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)
|
||||||
* Oct 10, 2004 require BOTH for kernel sys_call() (Jorrit N. Herder)
|
* Oct 10, 2004 require SENDREC for kernel sys_call() (Jorrit N. Herder)
|
||||||
* (to protect kernel tasks from being blocked)
|
* (to protect kernel tasks from being blocked)
|
||||||
* Aug 19, 2004 generalized ready()/unready() (Jorrit N. Herder)
|
* Aug 19, 2004 generalized ready()/unready() (Jorrit N. Herder)
|
||||||
*/
|
*/
|
||||||
|
@ -35,9 +37,9 @@
|
||||||
* 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 flags) );
|
message *m_ptr, unsigned 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 flags) );
|
message *m_ptr, unsigned 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 ) );
|
||||||
|
|
||||||
|
@ -73,7 +75,7 @@ PRIVATE bitchunk_t notify_bitmap[BITMAP_CHUNKS(NR_NOTIFY_BUFS)];
|
||||||
* sys_call *
|
* sys_call *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int sys_call(call_nr, src_dst, m_ptr)
|
PUBLIC int sys_call(call_nr, src_dst, m_ptr)
|
||||||
int call_nr; /* (NB_)SEND, (NB_)RECEIVE, BOTH */
|
int call_nr; /* (NB_)SEND, (NB_)RECEIVE, SENDREC */
|
||||||
int src_dst; /* src to receive from or dst to send to */
|
int src_dst; /* src to receive from or dst to send to */
|
||||||
message *m_ptr; /* pointer to message in the caller's space */
|
message *m_ptr; /* pointer to message in the caller's space */
|
||||||
{
|
{
|
||||||
|
@ -83,7 +85,7 @@ 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 flags = call_nr & SYSCALL_FLAGS; /* get flags */
|
unsigned 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_bytes vb; /* message buffer pointer as vir_bytes */
|
||||||
|
@ -93,8 +95,8 @@ message *m_ptr; /* pointer to message in the caller's space */
|
||||||
* 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 (iskernel(src_dst) && function != BOTH)
|
if (iskernel(src_dst) && function != SENDREC)
|
||||||
return(ECALLDENIED); /* BOTH was required */
|
return(ECALLDENIED); /* SENDREC was required */
|
||||||
|
|
||||||
/* Verify that requested source and/ or destination is a valid process. */
|
/* Verify that requested source and/ or destination is a valid process. */
|
||||||
if (! isoksrc_dst(src_dst))
|
if (! isoksrc_dst(src_dst))
|
||||||
|
@ -125,9 +127,10 @@ message *m_ptr; /* pointer to message in the caller's space */
|
||||||
* mask and whether the destination is alive.
|
* mask and whether the destination is alive.
|
||||||
*/
|
*/
|
||||||
switch(function) {
|
switch(function) {
|
||||||
case SEND:
|
case SENDREC:
|
||||||
/* fall through, SEND is done in BOTH */
|
flags |= FRESH_ANSWER; /* ignore pending notifications */
|
||||||
case BOTH:
|
/* fall through */
|
||||||
|
case SEND:
|
||||||
if (! isalive(src_dst)) {
|
if (! isalive(src_dst)) {
|
||||||
result = EDEADDST; /* cannot send to the dead */
|
result = EDEADDST; /* cannot send to the dead */
|
||||||
break;
|
break;
|
||||||
|
@ -140,14 +143,12 @@ message *m_ptr; /* pointer to message in the caller's space */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = mini_send(caller_ptr, src_dst, m_ptr,
|
result = mini_send(caller_ptr, src_dst, m_ptr, flags);
|
||||||
! (flags & NON_BLOCKING) );
|
|
||||||
if (function == SEND || result != OK) {
|
if (function == SEND || result != OK) {
|
||||||
break; /* done, or SEND failed */
|
break; /* done, or SEND failed */
|
||||||
} /* fall through for BOTH */
|
} /* fall through for SENDREC */
|
||||||
case RECEIVE:
|
case RECEIVE:
|
||||||
result = mini_rec(caller_ptr, src_dst, m_ptr,
|
result = mini_rec(caller_ptr, src_dst, m_ptr, flags);
|
||||||
! (flags & NON_BLOCKING) );
|
|
||||||
break;
|
break;
|
||||||
case NOTIFY:
|
case NOTIFY:
|
||||||
result = mini_notify(caller_ptr, src_dst, m_ptr);
|
result = mini_notify(caller_ptr, src_dst, m_ptr);
|
||||||
|
@ -168,21 +169,23 @@ 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 flags; /* system call flags */
|
unsigned 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;
|
register struct proc *dst_ptr;
|
||||||
#if DEAD_CODE
|
#if OLD_SEND
|
||||||
register struct proc *next_ptr;
|
register struct proc *next_ptr;
|
||||||
#endif
|
|
||||||
register struct proc *xp;
|
register struct proc *xp;
|
||||||
|
#else
|
||||||
register struct proc **xpp;
|
register struct proc **xpp;
|
||||||
|
#endif
|
||||||
|
|
||||||
dst_ptr = proc_addr(dst); /* pointer to destination's proc entry */
|
dst_ptr = proc_addr(dst); /* pointer to destination's proc entry */
|
||||||
|
|
||||||
|
|
||||||
/* Check for deadlock by 'caller_ptr' and 'dst' sending to each other.
|
/* Check for deadlock by 'caller_ptr' and 'dst' sending to each other.
|
||||||
* This check is rare, so overhead is acceptable.
|
* This check is rare, so overhead is acceptable.
|
||||||
*/
|
*/
|
||||||
|
@ -198,16 +201,16 @@ int flags; /* system call flags */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if 'dst' is blocked waiting for this message. The destination's
|
/* 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.
|
* SENDING flag may be set when SENDREC 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 == caller_ptr->p_nr)) {
|
(dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) {
|
||||||
/* Destination is indeed waiting for this message. */
|
/* Destination is indeed waiting for this message. */
|
||||||
CopyMess(caller_ptr->p_nr, 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 */
|
if ((dst_ptr->p_flags &= ~RECEIVING) == 0)
|
||||||
if (dst_ptr->p_flags == 0) ready(dst_ptr);
|
ready(dst_ptr);
|
||||||
} else if (flags) {
|
} else if ( ! (flags & NON_BLOCKING)) {
|
||||||
/* 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);
|
||||||
|
@ -215,7 +218,7 @@ int flags; /* system call flags */
|
||||||
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 OLD_SEND
|
||||||
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 {
|
||||||
|
@ -230,6 +233,7 @@ int flags; /* system call flags */
|
||||||
#endif
|
#endif
|
||||||
caller_ptr->p_q_link = NIL_PROC;
|
caller_ptr->p_q_link = NIL_PROC;
|
||||||
} else {
|
} else {
|
||||||
|
kprintf("Didn't block... ;-), flags: 0x%x\n", flags);
|
||||||
return(ENOTREADY);
|
return(ENOTREADY);
|
||||||
}
|
}
|
||||||
return(OK);
|
return(OK);
|
||||||
|
@ -242,29 +246,30 @@ 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 flags; /* system call flags */
|
unsigned 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
|
#if OLD_RECV
|
||||||
register struct proc *sender_ptr;
|
register struct proc *sender_ptr;
|
||||||
register struct proc *previous_ptr;
|
register struct proc *previous_ptr;
|
||||||
#endif
|
#else
|
||||||
register struct proc **xpp;
|
register struct proc **xpp;
|
||||||
|
#endif
|
||||||
register struct notification **ntf_q_pp;
|
register struct notification **ntf_q_pp;
|
||||||
message m;
|
message m;
|
||||||
int bit_nr;
|
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
|
* The caller's SENDING flag may be set if SENDREC couldn't send. If it is
|
||||||
* set, the process should be blocked.
|
* set, the process should be blocked.
|
||||||
*/
|
*/
|
||||||
if (!(caller_ptr->p_flags & SENDING)) {
|
if (!(caller_ptr->p_flags & SENDING)) {
|
||||||
|
|
||||||
/* Check caller queue. Use pointer pointers to keep code simple. */
|
/* Check caller queue. Use pointer pointers to keep code simple. */
|
||||||
#if DEAD_CODE /* to hairy, unreadable */
|
#if OLD_RECV /* 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_q_link) {
|
previous_ptr = sender_ptr, sender_ptr = sender_ptr->p_q_link) {
|
||||||
if (src == ANY || src == proc_nr(sender_ptr)) {
|
if (src == ANY || src == proc_nr(sender_ptr)) {
|
||||||
|
@ -297,8 +302,9 @@ int flags; /* system call flags */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Check if there are pending notifications. */
|
/* Check if there are pending notifications. */
|
||||||
|
if (! (flags & FRESH_ANSWER)) {
|
||||||
|
|
||||||
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 != NULL) {
|
while (*ntf_q_pp != NULL) {
|
||||||
if (src == ANY || src == (*ntf_q_pp)->n_source) {
|
if (src == ANY || src == (*ntf_q_pp)->n_source) {
|
||||||
|
@ -307,20 +313,21 @@ int flags; /* system call flags */
|
||||||
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 bit map. */
|
/* Remove notification from queue and bit map. */
|
||||||
bit_nr = ((long)(*ntf_q_pp) - (long) ¬ify_buffer[0]) /
|
bit_nr = (int) (*ntf_q_pp - ¬ify_buffer[0]);
|
||||||
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);
|
||||||
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 or the caller couldn't send in BOTH.
|
/* No suitable message is available or the caller couldn't send in SENDREC.
|
||||||
* Block the process trying to receive, unless the flags tell otherwise.
|
* Block the process trying to receive, unless the flags tell otherwise.
|
||||||
*/
|
*/
|
||||||
if (flags) {
|
if ( ! (flags & NON_BLOCKING)) {
|
||||||
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);
|
||||||
|
@ -347,9 +354,9 @@ message *m_ptr; /* pointer to message buffer */
|
||||||
message ntf_mess;
|
message ntf_mess;
|
||||||
|
|
||||||
/* Check to see if target is blocked waiting for this message. A process
|
/* Check to see if target is blocked waiting for this message. A process
|
||||||
* can be both sending and receiving during a BOTH system call.
|
* can be both sending and receiving during a SENDREC 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 == caller_ptr->p_nr)) {
|
(dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) {
|
||||||
|
|
||||||
/* Destination is indeed waiting for this message. */
|
/* Destination is indeed waiting for this message. */
|
||||||
|
@ -357,43 +364,44 @@ message *m_ptr; /* pointer to message buffer */
|
||||||
dst_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);
|
||||||
|
return(OK);
|
||||||
}
|
}
|
||||||
/* Destination is not ready. Add the notification to the pending queue. */
|
|
||||||
else {
|
|
||||||
/* Get pointer to notification message. Don't copy for kernel. */
|
|
||||||
if (! iskernelp(caller_ptr)) {
|
|
||||||
CopyMess(proc_nr(caller_ptr), caller_ptr, m_ptr,
|
|
||||||
proc_addr(HARDWARE), &ntf_mess);
|
|
||||||
m_ptr = &ntf_mess;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enqueue the message. Existing notifications with the same source
|
/* Destination is not ready. Add the notification to the pending queue.
|
||||||
* and type are overwritten with newer ones. New notifications that
|
* Get pointer to notification message. Don't copy for the kernel.
|
||||||
* are not yet on the list are added to the end.
|
*/
|
||||||
*/
|
if (! iskernelp(caller_ptr)) {
|
||||||
ntf_q_pp = &dst_ptr->p_ntf_q;
|
CopyMess(proc_nr(caller_ptr), caller_ptr, m_ptr,
|
||||||
while (*ntf_q_pp != NULL) {
|
proc_addr(HARDWARE), &ntf_mess);
|
||||||
/* Replace notifications with same source and type. */
|
m_ptr = &ntf_mess;
|
||||||
if ((*ntf_q_pp)->n_type == m_ptr->NOTIFY_TYPE &&
|
|
||||||
(*ntf_q_pp)->n_source == proc_nr(caller_ptr)) {
|
|
||||||
(*ntf_q_pp)->n_flags = m_ptr->NOTIFY_FLAGS;
|
|
||||||
(*ntf_q_pp)->n_arg = m_ptr->NOTIFY_ARG;
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
ntf_q_pp = &(*ntf_q_pp)->n_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add to end of queue. Get a free notification buffer. */
|
|
||||||
if ((ntf_index = alloc_bit(notify_bitmap, NR_NOTIFY_BUFS)) < 0)
|
|
||||||
return(ENOSPC);
|
|
||||||
ntf_p = ¬ify_buffer[ntf_index];
|
|
||||||
ntf_p->n_source = proc_nr(caller_ptr);
|
|
||||||
ntf_p->n_type = m_ptr->NOTIFY_TYPE;
|
|
||||||
ntf_p->n_flags = m_ptr->NOTIFY_FLAGS;
|
|
||||||
ntf_p->n_arg = m_ptr->NOTIFY_ARG;
|
|
||||||
*ntf_q_pp = ntf_p; /* add to end of queue */
|
|
||||||
ntf_p->n_next = NULL; /* mark new end of queue */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enqueue the message. Existing notifications with the same source
|
||||||
|
* 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;
|
||||||
|
while (*ntf_q_pp != NULL) {
|
||||||
|
/* Replace notifications with same source and type. */
|
||||||
|
if ((*ntf_q_pp)->n_type == m_ptr->NOTIFY_TYPE &&
|
||||||
|
(*ntf_q_pp)->n_source == proc_nr(caller_ptr)) {
|
||||||
|
(*ntf_q_pp)->n_flags = m_ptr->NOTIFY_FLAGS;
|
||||||
|
(*ntf_q_pp)->n_arg = m_ptr->NOTIFY_ARG;
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
ntf_q_pp = &(*ntf_q_pp)->n_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add to end of queue (found above). Get a free notification buffer. */
|
||||||
|
if ((ntf_index = alloc_bit(notify_bitmap, NR_NOTIFY_BUFS)) < 0)
|
||||||
|
return(ENOSPC);
|
||||||
|
ntf_p = ¬ify_buffer[ntf_index];
|
||||||
|
*ntf_q_pp = ntf_p; /* add to end of queue */
|
||||||
|
ntf_p->n_next = NULL; /* mark new end of queue */
|
||||||
|
ntf_p->n_source = proc_nr(caller_ptr);
|
||||||
|
ntf_p->n_type = m_ptr->NOTIFY_TYPE;
|
||||||
|
ntf_p->n_flags = m_ptr->NOTIFY_FLAGS;
|
||||||
|
ntf_p->n_arg = m_ptr->NOTIFY_ARG;
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,7 +631,7 @@ message *m_ptr; /* pointer to message buffer */
|
||||||
/* Safe gateway to mini_send() for tasks. */
|
/* Safe gateway to mini_send() for tasks. */
|
||||||
int result;
|
int result;
|
||||||
lock();
|
lock();
|
||||||
result = mini_send(proc_ptr, dst, m_ptr, FALSE);
|
result = mini_send(proc_ptr, dst, m_ptr, NON_BLOCKING);
|
||||||
unlock();
|
unlock();
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,8 +72,8 @@ struct proc {
|
||||||
|
|
||||||
/* Bits for p_flags in proc[]. A process is runnable iff p_flags == 0. */
|
/* Bits for p_flags in proc[]. A process is runnable iff p_flags == 0. */
|
||||||
#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 /* process blocked trying to SEND */
|
||||||
#define RECEIVING 0x04 /* set when process blocked trying to recv */
|
#define RECEIVING 0x04 /* process blocked trying to RECEIVE */
|
||||||
#define PENDING 0x10 /* set when inform() of signal pending */
|
#define PENDING 0x10 /* set when inform() of signal pending */
|
||||||
#define SIG_PENDING 0x20 /* keeps to-be-signalled proc from running */
|
#define SIG_PENDING 0x20 /* keeps to-be-signalled proc from running */
|
||||||
#define P_STOP 0x40 /* set when process is being traced */
|
#define P_STOP 0x40 /* set when process is being traced */
|
||||||
|
|
|
@ -33,7 +33,7 @@ _PROTOTYPE( void kprintf, (const char *fmt, karg_t arg) );
|
||||||
|
|
||||||
/* main.c */
|
/* main.c */
|
||||||
_PROTOTYPE( void main, (void) );
|
_PROTOTYPE( void main, (void) );
|
||||||
_PROTOTYPE( void prepare_shutdown, (int) );
|
_PROTOTYPE( void prepare_shutdown, (int how) );
|
||||||
_PROTOTYPE( void stop_sequence, (struct timer *tp) );
|
_PROTOTYPE( void stop_sequence, (struct timer *tp) );
|
||||||
|
|
||||||
/* misc.c */
|
/* misc.c */
|
||||||
|
|
|
@ -66,7 +66,7 @@ PUBLIC void sys_task()
|
||||||
{
|
{
|
||||||
/* Main entry point of sys_task. Get the message and dispatch on type. */
|
/* Main entry point of sys_task. Get the message and dispatch on type. */
|
||||||
static message m;
|
static message m;
|
||||||
register int result;
|
register int result, debug;
|
||||||
|
|
||||||
/* Initialize the system task. */
|
/* Initialize the system task. */
|
||||||
initialize();
|
initialize();
|
||||||
|
@ -88,9 +88,12 @@ PUBLIC void sys_task()
|
||||||
* is known to be blocked waiting for a message.
|
* is known to be blocked waiting for a message.
|
||||||
*/
|
*/
|
||||||
if (result != EDONTREPLY) {
|
if (result != EDONTREPLY) {
|
||||||
|
debug = m.m_type;
|
||||||
m.m_type = result; /* report status of call */
|
m.m_type = result; /* report status of call */
|
||||||
if (OK != 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);
|
kprintf("Warning, SYSTASK couldn't reply to request %d", debug);
|
||||||
|
kprintf(" from %d\n", m.m_source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ struct memory {
|
||||||
|
|
||||||
typedef unsigned long notify_mask_t; /* bit mask for notifications */
|
typedef unsigned long notify_mask_t; /* bit mask for notifications */
|
||||||
typedef short notify_type_t; /* notification type */
|
typedef short notify_type_t; /* notification type */
|
||||||
typedef short notify_flags_t; /* notification flags */
|
typedef char notify_flags_t; /* notification flags */
|
||||||
typedef int notify_arg_t; /* notification argument */
|
typedef int notify_arg_t; /* notification argument */
|
||||||
|
|
||||||
struct notification {
|
struct notification {
|
||||||
|
|
|
@ -74,7 +74,7 @@ PUBLIC int do_fkey_pressed(message *m)
|
||||||
printf("IS: unhandled notification for F%d\n", m->FKEY_NUM);
|
printf("IS: unhandled notification for F%d\n", m->FKEY_NUM);
|
||||||
#else
|
#else
|
||||||
printf("IS: unhandled notify for F%d (code %d)\n",
|
printf("IS: unhandled notify for F%d (code %d)\n",
|
||||||
m->NOTIFY_ARG, m->NOTIFY_FLAGS);
|
m->NOTIFY_FLAGS, m->NOTIFY_ARG);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ PUBLIC void main(void)
|
||||||
* sending the reply. The loop never terminates, unless a panic occurs.
|
* sending the reply. The loop never terminates, unless a panic occurs.
|
||||||
*/
|
*/
|
||||||
int result;
|
int result;
|
||||||
|
static long count;
|
||||||
|
|
||||||
/* Initialize the server, then go to work. */
|
/* Initialize the server, then go to work. */
|
||||||
init_server();
|
init_server();
|
||||||
|
@ -66,6 +67,8 @@ PUBLIC void main(void)
|
||||||
/* never reached */
|
/* never reached */
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
|
printf("Warning %u, IS got unexpected request %d from %d\n",
|
||||||
|
++count, m_in.m_type, m_in.m_source);
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue