New NOTIFY trap (IPC call) to send queued notification messages.
The call works. Permission check, restriction of outstanding notifications to be added. Low level code to make it work from within interrupt handlers will be added as well.
This commit is contained in:
parent
129b82d207
commit
307c825515
13 changed files with 151 additions and 30 deletions
|
@ -31,9 +31,6 @@ _PROTOTYPE( int _syscall, (int _who, int _syscallnr, message *_msgptr) );
|
|||
_PROTOTYPE( void _loadname, (const char *_name, message *_msgptr) );
|
||||
_PROTOTYPE( int _len, (const char *_s) );
|
||||
_PROTOTYPE( void panic, (const char *_message, int _errnum) );
|
||||
#if 0
|
||||
_PROTOTYPE( int _sendrec, (int _src_dest, message *_m_ptr) );
|
||||
#endif
|
||||
_PROTOTYPE( void _begsig, (int _dummy) );
|
||||
|
||||
#endif /* _LIB_H */
|
||||
|
|
|
@ -82,7 +82,9 @@
|
|||
#define NR_NOTIFY_TYPES 5 /* nr of bits in mask */
|
||||
|
||||
/* Shorthands for message parameters passed with notifications. */
|
||||
#define NOTIFY_ARG m2_l1 /* passed for some types */
|
||||
#define NOTIFY_TYPE m2_i1
|
||||
#define NOTIFY_FLAGS m2_i2
|
||||
#define NOTIFY_ARG m2_i3
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
@ -143,9 +143,7 @@ _PROTOTYPE( int ttyslot, (void) );
|
|||
_PROTOTYPE( int fttyslot, (int _fd) );
|
||||
_PROTOTYPE( char *crypt, (const char *_key, const char *_salt) );
|
||||
_PROTOTYPE( int getsysinfo, (int who, int what, void *where) );
|
||||
#if ENABLE_MESSAGE_STATS
|
||||
_PROTOTYPE( int mstats, (struct message_statentry *ms, int entries, int reset) );
|
||||
#endif
|
||||
_PROTOTYPE( int getprocnr, (int *proc_nr) );
|
||||
#endif
|
||||
|
||||
_PROTOTYPE( int setcache, (int kb));
|
||||
|
|
141
kernel/proc.c
141
kernel/proc.c
|
@ -14,7 +14,6 @@
|
|||
* unhold: repeat all held-up notifications
|
||||
*
|
||||
* Changes:
|
||||
* Nov 05, 2004 removed lock_mini_send() (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 10, 2004 require BOTH for kernel sys_call() (Jorrit N. Herder)
|
||||
|
@ -23,7 +22,6 @@
|
|||
* Sep 23, 2004 removed PM sig check in mini_rec() (Jorrit N. Herder)
|
||||
* Aug 19, 2004 generalized ready()/unready() (Jorrit N. Herder)
|
||||
* Aug 18, 2004 added notify() function (Jorrit N. Herder)
|
||||
* May 01, 2004 check p_sendmask in mini_send() (Jorrit N. Herder)
|
||||
*/
|
||||
|
||||
#include "kernel.h"
|
||||
|
@ -43,6 +41,8 @@ FORWARD _PROTOTYPE( void ready, (struct proc *rp) );
|
|||
FORWARD _PROTOTYPE( void sched, (void) );
|
||||
FORWARD _PROTOTYPE( void unready, (struct proc *rp) );
|
||||
FORWARD _PROTOTYPE( void pick_proc, (void) );
|
||||
FORWARD _PROTOTYPE( int alloc_notify_buf, (void) );
|
||||
FORWARD _PROTOTYPE( void free_notify_buf, (int index) );
|
||||
|
||||
#if (CHIP == M68000)
|
||||
FORWARD _PROTOTYPE( void cp_mess, (int src, struct proc *src_p, message *src_m,
|
||||
|
@ -66,8 +66,65 @@ FORWARD _PROTOTYPE( void cp_mess, (int src, struct proc *src_p, message *src_m,
|
|||
#define clear_bit(mask, n) ((mask) &= ~(1 << (n)))
|
||||
#define isset_bit(mask, n) ((mask) & (1 << (n)))
|
||||
|
||||
/* Declare buffer space for notifications. */
|
||||
PRIVATE struct notification notify_buf[NR_NOTIFY_BUFS];
|
||||
/* Constants and macros for the notification bit map. */
|
||||
#define BITCHUNK_BITS (sizeof(bitchunk_t) * CHAR_BIT)
|
||||
#define BITMAP_CHUNKS ((NR_NOTIFY_BUFS + BITCHUNK_BITS - 1)/BITCHUNK_BITS)
|
||||
|
||||
#define MAP_CHUNK(map,bit) (map)[((bit)/BITCHUNK_BITS)]
|
||||
#define CHUNK_OFFSET(bit) ((bit)%BITCHUNK_BITS))
|
||||
|
||||
#define GET_BIT(map,bit) ( MAP_CHUNK(map,bit) & (1 << CHUNK_OFFSET(bit) )
|
||||
#define SET_BIT(map,bit) ( MAP_CHUNK(map,bit) |= (1 << CHUNK_OFFSET(bit) )
|
||||
#define UNSET_BIT(map,bit) ( MAP_CHUNK(map,bit) &= ~(1 << CHUNK_OFFSET(bit) )
|
||||
|
||||
/* Declare buffer space for notifications and bit map for administration. */
|
||||
PRIVATE struct notification notify_buffer[NR_NOTIFY_BUFS];
|
||||
PRIVATE bitchunk_t notify_bitmap[BITMAP_CHUNKS];
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* free_notify_buf *
|
||||
*===========================================================================*/
|
||||
PRIVATE void free_notify_buf(buf_index)
|
||||
int buf_index; /* buffer to release */
|
||||
{
|
||||
bitchunk_t *chunk;
|
||||
if (buf_index >= NR_NOTIFY_BUFS) return;
|
||||
chunk = ¬ify_bitmap[(buf_index/BITCHUNK_BITS)];
|
||||
*chunk &= ~(buf_index % BITCHUNK_BITS);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* alloc_notify_buf *
|
||||
*===========================================================================*/
|
||||
PRIVATE int alloc_notify_buf()
|
||||
{
|
||||
bitchunk_t *chunk;
|
||||
int i, bit_nr;
|
||||
|
||||
/* Iterate over the words in block. */
|
||||
for (chunk = ¬ify_bitmap[0];
|
||||
chunk < ¬ify_bitmap[BITMAP_CHUNKS]; chunk++) {
|
||||
|
||||
/* Does this chunk contain a free bit? */
|
||||
if (*chunk == (bitchunk_t) ~0) continue;
|
||||
|
||||
/* Get bit number from the start of the bit map. */
|
||||
for (i = 0; (*chunk & (1 << i)) != 0; ++i) {}
|
||||
bit_nr = (chunk - ¬ify_bitmap[0]) * BITCHUNK_BITS + i;
|
||||
|
||||
/* Don't allocate bits beyond the end of the map. */
|
||||
if (bit_nr >= NR_NOTIFY_BUFS) break;
|
||||
|
||||
*chunk |= 1 << bit_nr % BITCHUNK_BITS;
|
||||
kprintf("Allocated bit %d\n", bit_nr);
|
||||
return(bit_nr);
|
||||
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* lock_notify *
|
||||
|
@ -307,8 +364,8 @@ int may_block; /* (dis)allow blocking */
|
|||
caller_ptr->p_sendto= dest;
|
||||
|
||||
/* Process is now blocked. Put in on the destination's queue. */
|
||||
if ( (next_ptr = dest_ptr->p_callerq) == NIL_PROC)
|
||||
dest_ptr->p_callerq = caller_ptr;
|
||||
if ( (next_ptr = dest_ptr->p_caller_q) == NIL_PROC)
|
||||
dest_ptr->p_caller_q = caller_ptr;
|
||||
else {
|
||||
while (next_ptr->p_sendlink != NIL_PROC)
|
||||
next_ptr = next_ptr->p_sendlink;
|
||||
|
@ -336,21 +393,22 @@ int may_block; /* (dis)allow blocking */
|
|||
*/
|
||||
register struct proc *sender_ptr;
|
||||
register struct proc *previous_ptr;
|
||||
register struct notification **ntf_q_pp;
|
||||
message m;
|
||||
int i;
|
||||
int bit_nr, i;
|
||||
|
||||
/* Check to see if a message from desired source is already available. */
|
||||
if (!(caller_ptr->p_flags & SENDING)) {
|
||||
|
||||
/* Check caller queue. */
|
||||
for (sender_ptr = caller_ptr->p_callerq; 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) {
|
||||
if (src == ANY || src == proc_number(sender_ptr)) {
|
||||
/* An acceptable message has been found. */
|
||||
CopyMess(proc_number(sender_ptr), sender_ptr,
|
||||
sender_ptr->p_messbuf, caller_ptr, m_ptr);
|
||||
if (sender_ptr == caller_ptr->p_callerq)
|
||||
caller_ptr->p_callerq = sender_ptr->p_sendlink;
|
||||
if (sender_ptr == caller_ptr->p_caller_q)
|
||||
caller_ptr->p_caller_q = sender_ptr->p_sendlink;
|
||||
else
|
||||
previous_ptr->p_sendlink = sender_ptr->p_sendlink;
|
||||
if ((sender_ptr->p_flags &= ~SENDING) == 0)
|
||||
|
@ -359,6 +417,26 @@ int may_block; /* (dis)allow blocking */
|
|||
}
|
||||
}
|
||||
|
||||
/* Check if there are pending notifications. */
|
||||
ntf_q_pp = &caller_ptr->p_ntf_q; /* get pointer pointer */
|
||||
while (*ntf_q_pp) {
|
||||
if (src == ANY || src == (*ntf_q_pp)->n_source) {
|
||||
/* Found notification. Assemble and copy message. */
|
||||
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,
|
||||
caller_ptr, m_ptr);
|
||||
/* Remove notification from queue and return. */
|
||||
bit_nr = ((long)(*ntf_q_pp) - (long) ¬ify_buffer[0]) /
|
||||
sizeof(struct notification);
|
||||
*ntf_q_pp = (*ntf_q_pp)->n_next;/* remove from queue */
|
||||
free_notify_buf(bit_nr); /* afterwards: prevent race */
|
||||
return(OK); /* report success */
|
||||
}
|
||||
ntf_q_pp = &(*ntf_q_pp)->n_next; /* proceed to next */
|
||||
}
|
||||
|
||||
/* Check bit mask for blocked notifications. If multiple bits are set,
|
||||
* send the first notification encountered; the rest is handled later.
|
||||
* This effectively prioritizes notifications. Notification also have
|
||||
|
@ -395,12 +473,49 @@ int may_block; /* (dis)allow blocking */
|
|||
* mini_notify *
|
||||
*===========================================================================*/
|
||||
PRIVATE int mini_notify(caller_ptr, dst, m_ptr)
|
||||
register struct proc *caller_ptr; /* process trying to get message */
|
||||
register struct proc *caller_ptr; /* process trying to notify */
|
||||
int dst; /* which process to notify */
|
||||
message *m_ptr; /* pointer to message buffer */
|
||||
{
|
||||
kprintf("Kernel notify from %d", caller_ptr->p_nr);
|
||||
kprintf("for %d\n", dst);
|
||||
register struct proc *dest_ptr = proc_addr(dst);
|
||||
register struct notification *ntf_p ;
|
||||
register struct notification **ntf_q_pp;
|
||||
int ntf_index;
|
||||
message ntf_mess;
|
||||
|
||||
/* Check to see if target is blocked waiting for this message. */
|
||||
if ( (dest_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
|
||||
(dest_ptr->p_getfrom == ANY ||
|
||||
dest_ptr->p_getfrom == proc_number(caller_ptr))) {
|
||||
/* Destination is indeed waiting for this message. */
|
||||
CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dest_ptr,
|
||||
dest_ptr->p_messbuf);
|
||||
dest_ptr->p_flags &= ~RECEIVING; /* deblock destination */
|
||||
if (dest_ptr->p_flags == 0) ready(dest_ptr);
|
||||
} else {
|
||||
|
||||
/* See if there is a free notification buffer. */
|
||||
if ((ntf_index = alloc_notify_buf()) < 0)
|
||||
return(ENOSPC); /* should be atomic! */
|
||||
|
||||
/* Copy details from notification message. */
|
||||
CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr,
|
||||
proc_addr(HARDWARE), &ntf_mess);
|
||||
ntf_p = ¬ify_buffer[ntf_index];
|
||||
ntf_p->n_source = proc_number(caller_ptr);
|
||||
ntf_p->n_type = ntf_mess.NOTIFY_TYPE;
|
||||
ntf_p->n_flags = ntf_mess.NOTIFY_FLAGS;
|
||||
ntf_p->n_arg = ntf_mess.NOTIFY_ARG;
|
||||
|
||||
/* Enqueue the notification message for later. New notifications
|
||||
* are added to the end of the list. First find the NULL pointer,
|
||||
* then add the new pointer to the end.
|
||||
*/
|
||||
ntf_q_pp = &dest_ptr->p_ntf_q;
|
||||
while (*ntf_q_pp) ntf_q_pp = &(*ntf_q_pp)->n_next;
|
||||
*ntf_q_pp = ntf_p;
|
||||
ntf_p->n_next = NULL;
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ struct proc {
|
|||
notify_mask_t p_ntf_held; /* bit mask for held up notify() calls */
|
||||
struct proc *p_ntf_nextheld; /* next in chain of held-up int processes */
|
||||
|
||||
struct notification *p_ntfq; /* queue of pending notifications */
|
||||
struct notification *p_ntf_q; /* queue of pending notifications */
|
||||
|
||||
int p_flags; /* SENDING, RECEIVING, etc. */
|
||||
struct mem_map p_memmap[NR_LOCAL_SEGS]; /* local memory map (T, D, S) */
|
||||
|
@ -55,7 +55,7 @@ struct proc {
|
|||
timer_t p_syncalrm; /* synchronous alarm timer */
|
||||
|
||||
send_mask_t p_sendmask; /* mask indicating to whom proc may send */
|
||||
struct proc *p_callerq; /* 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 */
|
||||
message *p_messbuf; /* pointer to message buffer */
|
||||
int p_getfrom; /* from whom does process want to receive? */
|
||||
|
|
|
@ -198,14 +198,14 @@ int proc_nr; /* slot of process to clean up */
|
|||
if (rc->p_flags & SENDING) {
|
||||
/* Check all proc slots to see if the exiting process is queued. */
|
||||
for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
|
||||
if (rp->p_callerq == NIL_PROC) continue;
|
||||
if (rp->p_callerq == rc) {
|
||||
if (rp->p_caller_q == NIL_PROC) continue;
|
||||
if (rp->p_caller_q == rc) {
|
||||
/* Exiting process is on front of this queue. */
|
||||
rp->p_callerq = rc->p_sendlink;
|
||||
rp->p_caller_q = rc->p_sendlink;
|
||||
break;
|
||||
} else {
|
||||
/* See if exiting process is in middle of queue. */
|
||||
np = rp->p_callerq;
|
||||
np = rp->p_caller_q;
|
||||
while ( ( xp = np->p_sendlink) != NIL_PROC) {
|
||||
if (xp == rc) {
|
||||
np->p_sendlink = xp->p_sendlink;
|
||||
|
|
|
@ -47,8 +47,8 @@ register message *m_ptr; /* pointer to request message */
|
|||
rpc->p_ldt_sel = old_ldt_sel;
|
||||
#endif
|
||||
rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */
|
||||
|
||||
rpc->p_flags |= NO_MAP; /* inhibit the process from running */
|
||||
rpc->p_ntf_q = NULL; /* remove pending notifications */
|
||||
rpc->p_flags |= NO_MAP; /* inhibit process from running */
|
||||
|
||||
rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ struct notification {
|
|||
proc_nr_t n_source; /* sender of notification */
|
||||
notify_type_t n_type; /* notification type */
|
||||
notify_arg_t n_arg; /* notification argument */
|
||||
notify_flags_t n_fags; /* notification flags */
|
||||
notify_flags_t n_flags; /* notification flags */
|
||||
struct notification* n_next; /* pointer to next notification */
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ OBJECTS = \
|
|||
$(LIBRARY)(_seekdir.o) \
|
||||
$(LIBRARY)(_svrctl.o) \
|
||||
$(LIBRARY)(_getsysinfo.o) \
|
||||
$(LIBRARY)(_getprocnr.o) \
|
||||
$(LIBRARY)(asynchio.o) \
|
||||
$(LIBRARY)(configfile.o) \
|
||||
$(LIBRARY)(crypt.o) \
|
||||
|
@ -74,6 +75,9 @@ $(LIBRARY)(_seekdir.o): _seekdir.c
|
|||
$(LIBRARY)(_svrctl.o): _svrctl.c
|
||||
$(CC1) _svrctl.c
|
||||
|
||||
$(LIBRARY)(_getprocnr.o): _getprocnr.c
|
||||
$(CC1) _getprocnr.c
|
||||
|
||||
$(LIBRARY)(_getsysinfo.o): _getsysinfo.c
|
||||
$(CC1) _getsysinfo.c
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <lib.h>
|
||||
#define getsysinfo _getsysinfo
|
||||
#define getsysinfo _getsysinfo
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ OBJECTS = \
|
|||
$(LIBRARY)(getpid.o) \
|
||||
$(LIBRARY)(getppid.o) \
|
||||
$(LIBRARY)(getuid.o) \
|
||||
$(LIBRARY)(getprocnr.o) \
|
||||
$(LIBRARY)(ioctl.o) \
|
||||
$(LIBRARY)(isatty.o) \
|
||||
$(LIBRARY)(kill.o) \
|
||||
|
@ -214,6 +215,9 @@ $(LIBRARY)(getpid.o): getpid.s
|
|||
$(LIBRARY)(getppid.o): getppid.s
|
||||
$(CC1) getppid.s
|
||||
|
||||
$(LIBRARY)(getprocnr.o): getprocnr.s
|
||||
$(CC1) getprocnr.s
|
||||
|
||||
$(LIBRARY)(getuid.o): getuid.s
|
||||
$(CC1) getuid.s
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ PUBLIC int do_getsysinfo()
|
|||
*=====================================================================*/
|
||||
PUBLIC int do_getprocnr()
|
||||
{
|
||||
mp->mp_reply.procnr = who;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#define grp_id m1_i1
|
||||
#define namelen m1_i1
|
||||
#define pid m1_i1
|
||||
#define procnr m1_i1
|
||||
#define seconds m1_i1
|
||||
#define sig m6_i1
|
||||
#define stack_bytes m1_i2
|
||||
|
|
Loading…
Reference in a new issue