;;; -*- Mode:Lisp; Readtable:CL; Package:USER; Base:10; Patch-File:T -*- ;;; Patch file for System version 124.8 ;;; Reason: ;;; The TCP background process depends on variable *background-wakeup-time* ;;; to tell it that timeouts are armed. Setting of this is not interlocked. ;;; I noticed a TCP socket that was hung because it had a timeout armed but ;;; the variable was NIL. Hence, the background process did nothing. ;;; Don't let this happen... ;;; Written 26-May-88 19:09:18 by pld (Peter L. DeWolf) at site Gigamos Cambridge ;;; while running on Azathoth from band 2 ;;; with Experimental System 124.6, Experimental Local-File 74.0, Experimental File-Server 23.0, Experimental Unix-Interface 12.0, Experimental ZMail 72.0, Experimental Tape 23.0, Experimental Lambda-Diag 16.0, microcode 1756, SDU Boot Tape 3.14, SDU ROM 8. ; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; TCP.LISP#291 at 26-May-88 19:09:52 #10R TCP#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TCP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; TCP  " (defun tcp-background-process-wait (int-pkt now) (and (tcp-enabled *tcp-stream*) (or (and (or (not (fifo-empty-p *send-blocked-control-packets*)) (not (fifo-empty-p *send-blocked-sockets*))) (or (cdr int-pkt) (setf (cdr int-pkt) (net:allocate-packet nil)))) (and *background-wakeup-time* (not (time-lessp (setf (cdr now) (zl:time)) *background-wakeup-time*)))))) (defun tcp-background-process () (loop (let (int-pkt now) (process-wait "Timeout" 'tcp-background-process-wait (locf int-pkt) (locf now)) (tcp-background-process-1 int-pkt now)))) (defun tcp-background-process-1 (int-pkt now) (let (elt socket) (cond ((not (tcp-enabled *tcp-stream*))) ;tcp disabled -- do nothing (int-pkt ;send blocked stream or packet -- send it (cond ((setq elt (pop-fifo *send-blocked-control-packets*)) (apply 'send-control-packet (nconc elt (ncons int-pkt)))) ((setq socket (pop-fifo *send-blocked-sockets*)) (tcp-log :unblock socket) (send-tcp-packets socket t int-pkt)) (t (net:free-packet int-pkt)))) (t ;generic timeout ;;Do the global timeouts (do ((list *global-timeouts* (cdr list)) (result nil)) ((null list) (setq *global-timeouts* result)) (let* ((elt (car list)) (time (first elt))) (if (time-lessp time now) (funcall (second elt) (third elt) now) (push elt result)))) ;;And the socket specific timeouts (do ((list (tcp-user-socket-alist *tcp-stream*) (cdr list))) ((null list)) (let* ((socket (cdar list)) (passed (mapcan #'(lambda (x) (if (time-lessp (cdr x) now) (ncons x))) (tcp-user-timeout-alist socket)))) (when passed (setf (tcp-user-timeout-alist socket) (nset-difference (tcp-user-timeout-alist socket) passed)) (dolist (x passed) (funcall (car x) socket now))))) ;;Reset next wakeup time (without-interrupts (let ((next-wakeup-time nil)) (dolist (x *global-timeouts*) (when (or (null next-wakeup-time) (time-lessp (first x) next-wakeup-time)) (setq next-wakeup-time (first x)))) (dolist (elt (tcp-user-socket-alist *tcp-stream*)) (dolist (x (tcp-user-timeout-alist (cdr elt))) (when (or (null next-wakeup-time) (time-lessp (cdr x) next-wakeup-time)) (setq next-wakeup-time (cdr x))))) (setq *background-wakeup-time* next-wakeup-time))))))) )) ;;Reset the background process to use the new function. (when tcp:*tcp-background-process* (send tcp:*tcp-background-process* :reset)) ; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; TCP.LISP#291 at 26-May-88 19:13:07 #10R TCP#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TCP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; TCP  " (defun start-timeout (interval function socket) (without-interrupts (let* ((now (zl:time)) (time (time-increment now (floor (* 60 interval)))) (elt (assoc function (tcp-user-timeout-alist socket) :test #'eq))) (if elt (setf (cdr elt) time) (push (cons function time) (tcp-user-timeout-alist socket))) (if (or (null *background-wakeup-time*) (time-lessp time *background-wakeup-time*)) (setq *background-wakeup-time* time))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; TCP.LISP#291 at 26-May-88 19:13:11 #10R TCP#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TCP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; TCP  " (defun start-global-timeout (interval function arg) (without-interrupts (let ((time (time-increment (zl:time) (floor (* 60 interval))))) (push (list time function arg) *global-timeouts*) (if (or (null *background-wakeup-time*) (time-lessp time *background-wakeup-time*)) (setq *background-wakeup-time* time))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; TCP.LISP#291 at 26-May-88 19:13:15 #10R TCP#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TCP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; TCP  " (defun cancel-timeout (socket &optional function) (without-interrupts (cond (function ;;Cancelling a specific timeout (let ((elt (assoc function (tcp-user-timeout-alist socket) :test #'eq))) (when elt (tcp-log :cancel socket function) (setf (tcp-user-timeout-alist socket) (delete elt (tcp-user-timeout-alist socket)))))) ((tcp-user-timeout-alist socket) ;;Cancelling all timeouts and some are set (tcp-log :cancel socket nil) (setf (tcp-user-timeout-alist socket) nil)) (t ;;timeout not set... nil)))) ))