diff --git a/include/lib.h b/include/lib.h index 948739a47..d00eda7cf 100755 --- a/include/lib.h +++ b/include/lib.h @@ -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 */ diff --git a/include/minix/com.h b/include/minix/com.h index a00c761ca..f04c220f2 100755 --- a/include/minix/com.h +++ b/include/minix/com.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 /*===========================================================================* diff --git a/include/unistd.h b/include/unistd.h index 22c0f9bee..a5921db6e 100755 --- a/include/unistd.h +++ b/include/unistd.h @@ -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)); diff --git a/kernel/proc.c b/kernel/proc.c index c271268a0..54d977864 100755 --- a/kernel/proc.c +++ b/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); } diff --git a/kernel/proc.h b/kernel/proc.h index 633259d14..db69a2e57 100755 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -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? */ diff --git a/kernel/system.c b/kernel/system.c index 0d93e7fb8..84e429b74 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -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; diff --git a/kernel/system/proctl.c b/kernel/system/proctl.c index 31493b838..c35b6248f 100644 --- a/kernel/system/proctl.c +++ b/kernel/system/proctl.c @@ -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); diff --git a/kernel/type.h b/kernel/type.h index 80a38ae26..598ad4198 100755 --- a/kernel/type.h +++ b/kernel/type.h @@ -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 */ }; diff --git a/lib/other/Makefile b/lib/other/Makefile index 1654def69..c05c91a73 100755 --- a/lib/other/Makefile +++ b/lib/other/Makefile @@ -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 diff --git a/lib/other/_getsysinfo.c b/lib/other/_getsysinfo.c index d98b8833f..19675ab18 100644 --- a/lib/other/_getsysinfo.c +++ b/lib/other/_getsysinfo.c @@ -1,6 +1,5 @@ #include #define getsysinfo _getsysinfo -#define getsysinfo _getsysinfo #include diff --git a/lib/syscall/Makefile b/lib/syscall/Makefile index 1b179c2e0..41bee90db 100755 --- a/lib/syscall/Makefile +++ b/lib/syscall/Makefile @@ -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 diff --git a/servers/pm/misc.c b/servers/pm/misc.c index 983435e38..32aa327d5 100644 --- a/servers/pm/misc.c +++ b/servers/pm/misc.c @@ -36,6 +36,7 @@ PUBLIC int do_getsysinfo() *=====================================================================*/ PUBLIC int do_getprocnr() { + mp->mp_reply.procnr = who; return(OK); } diff --git a/servers/pm/param.h b/servers/pm/param.h index e5764812c..c39752fbd 100644 --- a/servers/pm/param.h +++ b/servers/pm/param.h @@ -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