ast@cs.vu.nl (Andy Tanenbaum) (03/10/88)
While working on the Atari port, Johan Stevenson found and fixed the deadlocks in MINIX that have been reported here repeatedly. The same problems occurred on both the PC and ST. Below are diff listings to apply to the original V1.2 sources to generate the fixed files. For example, do fix pipe.c pipe.diff >pipe.new to make a new version of pipe. The 7 files included here are: h/com.h fs/device.c fs/pipe.c fs/putc.c kernel/proc.c kernel/system.c lib/syslib.c If any problems appear with these fixes, please post them. These fixes make the ASYNC task that Jim Paradis put into his tty driver unnecessary. This is a much better solution to the problem and is the one that will be used in both Atari MINIX and 1.3 for the PC. Andy Tanenbaum : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin:/usr/ucb echo Extracting 'com.diff' sed 's/^X//' > 'com.diff' << '+ END-OF-FILE ''com.diff' X20d19 X< # define SYS_KILL 11 /* fcn code for sys_kill(proc, sig) */ X37c36 X< # define DISKINT 1 /* fcn code for disk interrupt */ X--- X> # define DISKINT 1 /* fcn code for disk interupt */ X51,57d49 X< #define ETHERNET -9 /* Ethernet I/O class */ X< # define ETHER_ARRIV 1 /* fcn code for packet arrival */ X< # define ETHER_SENT 2 /* fcn code for LANCE interrupt on send */ X< # define ETHER_READ 3 /* fcn code for reading from Ethernet */ X< # define ETHER_WRITE 4 /* fcn code for writing to Ethernet */ X< # define ETHER_IOCTL 5 /* fcn code for ioctl */ X< X95c87 X< #define CHILD_STIME m4_l4 /* sys time consumed by process' children */ X--- X> #define CHILD_STIME m4_l4 /* system time consumed by proces children */ + END-OF-FILE com.diff chmod 'u=rw,g=rw,o=rw' 'com.diff' set `wc -c 'com.diff'` count=$1 case $count in 729) :;; *) echo 'Bad character count in ''com.diff' >&2 echo 'Count should be 729' >&2 esac echo Extracting 'device.diff' sed 's/^X//' > 'device.diff' << '+ END-OF-FILE ''device.diff' X153c153,154 X< int proc_nr; X--- X> int r; X> message m; X155,160c156,159 X< proc_nr = mess_ptr->PROC_NR; X< X< if (sendrec(task_nr, mess_ptr) != OK) panic("rw_dev: can't send", NO_NUM); X< while (mess_ptr->REP_PROC_NR != proc_nr) { X< /* Instead of the reply to this request, we got a message for an X< * earlier request. Handle it and go receive again. X--- X> while ((r = sendrec(task_nr, mess_ptr)) == E_LOCKED) { X> /* sendrec() failed to avoid deadlock. The task 'task_nr' is X> * trying to send a REVIVE message for an earlier request. X> * Handle it and go try again. X162,163c161,162 X< revive(mess_ptr->REP_PROC_NR, mess_ptr->REP_STATUS); X< receive(task_nr, mess_ptr); X--- X> if (receive(task_nr, &m) != OK) panic("rw_dev: can't receive", NO_NUM); X> revive(m.REP_PROC_NR, m.REP_STATUS); X164a164 X> if (r != OK) panic("rw_dev: can't send", NO_NUM); X175c175 X< /* This routine is only called for one device, namely /dev/tty. It's job X--- X> /* This routine is only called for one device, namely /dev/tty. Its job + END-OF-FILE device.diff chmod 'u=rw,g=rw,o=rw' 'device.diff' set `wc -c 'device.diff'` count=$1 case $count in 1031) :;; *) echo 'Bad character count in ''device.diff' >&2 echo 'Count should be 1031' >&2 esac echo Extracting 'pipe.diff' sed 's/^X//' > 'pipe.diff' << '+ END-OF-FILE ''pipe.diff' X116,120c116,117 X< /* Tell MM to generate a SIGPIPE signal. */ X< mess.m_type = KSIG; X< mess.PROC1 = fp - fproc; X< mess.SIG_MAP = 1 << (SIGPIPE - 1); X< send(MM_PROC_NR, &mess); X--- X> /* Tell kernel to generate a SIGPIPE signal. */ X> sys_kill((int)(fp - fproc), SIGPIPE); X251,255c248 X< if (sendrec(task, &mess) != OK) panic("unpause err 3", NO_NUM); X< while (mess.REP_PROC_NR != proc_nr) { X< revive(mess.REP_PROC_NR, mess.REP_STATUS); X< if (receive(task, &m) != OK) panic("unpause err 4", NO_NUM); X< } X--- X> rw_dev(task, &mess); + END-OF-FILE pipe.diff chmod 'u=rw,g=rw,o=rw' 'pipe.diff' set `wc -c 'pipe.diff'` count=$1 case $count in 548) :;; *) echo 'Bad character count in ''pipe.diff' >&2 echo 'Count should be 548' >&2 esac echo Extracting 'proc.diff' sed 's/^X//' > 'proc.diff' << '+ END-OF-FILE ''proc.diff' X153a154,163 X> /* Check for deadlock by 'caller' and 'dest' sending to each other. */ X> if (dest_ptr->p_flags & SENDING) { X> next_ptr = caller_ptr->p_callerq; X> while (next_ptr) { X> if (next_ptr == dest_ptr) X> return(E_LOCKED); X> next_ptr = next_ptr->p_sendlink; X> } X> } X> X155,156c165,166 X< if ( (dest_ptr->p_flags & RECEIVING) && X< (dest_ptr->p_getfrom == ANY || dest_ptr->p_getfrom == caller) ) { X--- X> if ( (dest_ptr->p_flags & RECEIVING) && (dest_ptr->p_flags & SENDING) == 0 && X> (dest_ptr->p_getfrom == ANY || dest_ptr->p_getfrom == caller)){ X205c215,216 X< while (sender_ptr != NIL_PROC) { X--- X> if ((caller_ptr->p_flags & SENDING) == 0) { X> while (sender_ptr != NIL_PROC) { X220a232 X> } X253c265 X< * deposit the registers when a interrupt occurs on an idle machine. X--- X> * deposit the registers when an interrupt occurs on an idle machine. X256c268 X< * clock task is running, 'cur_proc' = CLOCKTASK. In addition, set 'bill_ptr' X--- X> * clock task is running, 'cur_proc' = CLOCKTASK.) In addition, set 'bill_ptr' + END-OF-FILE proc.diff chmod 'u=rw,g=rw,o=rw' 'proc.diff' set `wc -c 'proc.diff'` count=$1 case $count in 1067) :;; *) echo 'Bad character count in ''proc.diff' >&2 echo 'Count should be 1067' >&2 esac echo Extracting 'putc.diff' sed 's/^X//' > 'putc.diff' << '+ END-OF-FILE ''putc.diff' X49c49 X< sendrec(TTY, &putchmsg); X--- X> rw_dev(TTY, &putchmsg); + END-OF-FILE putc.diff chmod 'u=rw,g=rw,o=rw' 'putc.diff' set `wc -c 'putc.diff'` count=$1 case $count in 67) :;; *) echo 'Bad character count in ''putc.diff' >&2 echo 'Count should be 67' >&2 esac echo Extracting 'syslib.diff' sed 's/^X//' > 'syslib.diff' << '+ END-OF-FILE ''syslib.diff' X132a133,145 X> X> X> PUBLIC sys_kill(proc, sig) X> int proc; /* which proc has exited */ X> int sig; /* signal number: 1 - 16 */ X> { X> /* A proc has to be signaled via MM. Tell the kernel. */ X> X> M.m6_i1 = proc; X> M.m6_i2 = sig; X> callx(SYSTASK, SYS_KILL); X> } X> + END-OF-FILE syslib.diff chmod 'u=rw,g=rw,o=rw' 'syslib.diff' set `wc -c 'syslib.diff'` count=$1 case $count in 274) :;; *) echo 'Bad character count in ''syslib.diff' >&2 echo 'Count should be 274' >&2 esac echo Extracting 'system.diff' sed 's/^X//' > 'system.diff' << '+ END-OF-FILE ''system.diff' X15a16 X> * SYS_KILL cause a signal to be sent via MM X42a44,45 X> * | SYS_KILL | proc_nr | sig | | | X> * ------------------------------------------------------ X95a99 X> case SYS_KILL: r = do_kill(&m); break; X372a377,395 X> * do_kill * X> *===========================================================================*/ X> PRIVATE int do_kill(m_ptr) X> message *m_ptr; /* pointer to request message */ X> { X> /* Handle sys_kill(). Cause a signal to be sent to a process via MM. */ X> X> int proc_nr; /* process number */ X> int sig; /* signal number 1-16 */ X> X> proc_nr = m_ptr->PR; /* process being signalled */ X> sig = m_ptr->SIGNUM; /* signal number, 1 to 16 */ X> if (proc_nr < LOW_USER || proc_nr >= NR_PROCS) return(E_BAD_PROC); X> cause_sig(proc_nr, sig); X> return(OK); X> } X> X> X> /*===========================================================================* X504c527 X< seg_base = seg_base << CLICK_SHIFT; /* segment orgin in bytes */ X--- X> seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */ + END-OF-FILE system.diff chmod 'u=rw,g=rw,o=rw' 'system.diff' set `wc -c 'system.diff'` count=$1 case $count in 1075) :;; *) echo 'Bad character count in ''system.diff' >&2 echo 'Count should be 1075' >&2 esac exit 0