[M3devel] SIGCHLD diff

Mika Nystrom mika at async.caltech.edu
Sat Feb 12 21:44:06 CET 2011


Index: ThreadPosix.i3
===================================================================
RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/POSIX/ThreadPosix.i3,v
retrieving revision 1.16
diff -c -r1.16 ThreadPosix.i3
*** ThreadPosix.i3	14 Apr 2010 09:53:34 -0000	1.16
--- ThreadPosix.i3	12 Feb 2011 20:43:26 -0000
***************
*** 39,42 ****
--- 39,45 ----
  
  (*---------------------------------------------------------------------------*)
  
+ <*EXTERNAL ThreadPosix__value_of_SIGCHLD*>
+ PROCEDURE ValueOfSIGCHLD(): int;
+ 
  END ThreadPosix.
Index: ThreadPosix.m3
===================================================================
RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/POSIX/ThreadPosix.m3,v
retrieving revision 1.73
diff -c -r1.73 ThreadPosix.m3
*** ThreadPosix.m3	28 Dec 2010 10:13:46 -0000	1.73
--- ThreadPosix.m3	12 Feb 2011 20:43:26 -0000
***************
*** 97,102 ****
--- 97,105 ----
      (* if state = pausing, the time at which we can restart *)
      waitingForTime: Time.T;
  
+     (* if state = pausing, the signal that truncates the pause *)
+     waitingForSig: int := -1;
+ 
      (* true if we are waiting during an AlertWait or AlertJoin 
         or AlertPause *)
      alertable: BOOLEAN := FALSE;
***************
*** 147,152 ****
--- 150,160 ----
  
    defaultStackSize := 3000;
  
+   (* note that even though the "heavy machinery" is only used for 
+      multipleThreads, we still need to set up the signal handler so
+      that we can catch signals from other sources than thread switching.
+      e.g., we use SIGCHLD to speed up Process.Wait *)
+ 
  VAR
    stats: RECORD
             n_forks := 0;
***************
*** 511,527 ****
      XPause(until, FALSE);
    END Pause;
  
  PROCEDURE AlertPause(n: LONGREAL) RAISES {Alerted}=
    VAR until := n + Time.Now ();
    BEGIN
      XPause(until, TRUE);
    END AlertPause;
  
! PROCEDURE XPause (READONLY until: Time.T; alertable := FALSE) RAISES {Alerted} =
    BEGIN
      INC (inCritical);
        self.waitingForTime := until;
        self.alertable := alertable;
        ICannotRun (State.pausing);
      DEC (inCritical);
      InternalYield ();
--- 519,546 ----
      XPause(until, FALSE);
    END Pause;
  
+ PROCEDURE SigPause(n: LONGREAL; sig: int)=
+   <*FATAL Alerted*>
+   VAR until := n + Time.Now ();
+   BEGIN
+     XPause(until, FALSE, sig);
+   END SigPause;
+ 
  PROCEDURE AlertPause(n: LONGREAL) RAISES {Alerted}=
    VAR until := n + Time.Now ();
    BEGIN
      XPause(until, TRUE);
    END AlertPause;
  
! PROCEDURE XPause (READONLY until: Time.T; alertable := FALSE; sig:int := -1) 
!   RAISES {Alerted} =
    BEGIN
      INC (inCritical);
        self.waitingForTime := until;
        self.alertable := alertable;
+       IF sig # -1 THEN
+         self.waitingForSig := sig
+       END;
        ICannotRun (State.pausing);
      DEC (inCritical);
      InternalYield ();
***************
*** 703,712 ****
      END;
    END StartSwitching;
  
! PROCEDURE switch_thread (<*UNUSED*> sig: int) RAISES {Alerted} =
    BEGIN
      allow_sigvtalrm ();
!     IF inCritical = 0 AND heapState.inCritical = 0 THEN InternalYield () END;
    END switch_thread;
  
  (*------------------------------------------------------------- scheduler ---*)
--- 722,750 ----
      END;
    END StartSwitching;
  
! CONST MaxSigs = 64;
! TYPE Sig = [ 0..MaxSigs-1 ];
! 
! (* in order to listen to other signals, they have to be enabled in
!    allow_sigvtalrm as well *)
! VAR (*CONST*) SIGCHLD := ValueOfSIGCHLD();
!               
!     gotSigs := SET OF Sig { };
! 
! PROCEDURE switch_thread (sig: int) RAISES {Alerted} =
    BEGIN
      allow_sigvtalrm ();
! 
!     INC(inCritical);
!     (* mark signal as being delivered *)
!     IF sig >= 0 AND sig < MaxSigs THEN
!       gotSigs := gotSigs + SET OF Sig { sig }
!     END;
!     DEC(inCritical);
! 
!     IF inCritical = 0 AND heapState.inCritical = 0 THEN 
!       InternalYield () 
!     END;
    END switch_thread;
  
  (*------------------------------------------------------------- scheduler ---*)
***************
*** 782,792 ****
              IF t.alertable AND t.alertPending THEN
                CanRun (t);
                EXIT;
  
              ELSIF t.waitingForTime <= now THEN
                CanRun (t);
                EXIT;
!   
              ELSIF NOT somePausing THEN
                earliest := t.waitingForTime;
                somePausing := TRUE;
--- 820,835 ----
              IF t.alertable AND t.alertPending THEN
                CanRun (t);
                EXIT;
+               
+             ELSIF t.waitingForSig IN gotSigs THEN
+               t.waitingForSig := -1;
+               CanRun(t);
+               EXIT;
  
              ELSIF t.waitingForTime <= now THEN
                CanRun (t);
                EXIT;
! 
              ELSIF NOT somePausing THEN
                earliest := t.waitingForTime;
                somePausing := TRUE;
***************
*** 886,891 ****
--- 929,936 ----
        END;
      END;
  
+     gotSigs := SET OF Sig {};
+ 
      IF t.state = State.alive AND (scanned OR NOT someBlocking) THEN
        IF perfOn THEN PerfRunning (t.id); END;
        (* At least one thread wants to run; transfer to it *)
***************
*** 948,960 ****
  
  PROCEDURE WaitProcess (pid: int; VAR status: int): int =
    (* ThreadPThread.m3 and ThreadPosix.m3 are very similar. *)
!   CONST Delay = 0.1D0;
    BEGIN
      LOOP
        WITH r = Uexec.waitpid(pid, ADR(status), Uexec.WNOHANG) DO
          IF r # 0 THEN RETURN r END;
        END;
!       Pause(Delay);
      END;
    END WaitProcess;
  
--- 993,1005 ----
  
  PROCEDURE WaitProcess (pid: int; VAR status: int): int =
    (* ThreadPThread.m3 and ThreadPosix.m3 are very similar. *)
!   CONST Delay = 10.0D0;
    BEGIN
      LOOP
        WITH r = Uexec.waitpid(pid, ADR(status), Uexec.WNOHANG) DO
          IF r # 0 THEN RETURN r END;
        END;
!       SigPause(Delay,SIGCHLD);
      END;
    END WaitProcess;
  
***************
*** 1361,1364 ****
--- 1406,1412 ----
  VAR debug := RTParams.IsPresent ("debugthreads");
  
  BEGIN
+   (* we need to call set up the signal handler for other reasons than
+      just thread switching now *)
+   setup_sigvtalrm (switch_thread);
  END ThreadPosix.
Index: ThreadPosixC.c
===================================================================
RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/POSIX/ThreadPosixC.c,v
retrieving revision 1.59
diff -c -r1.59 ThreadPosixC.c
*** ThreadPosixC.c	12 Feb 2011 00:56:32 -0000	1.59
--- ThreadPosixC.c	12 Feb 2011 20:43:26 -0000
***************
*** 78,88 ****
--- 78,97 ----
  
    sigemptyset(&ThreadSwitchSignal);
    sigaddset(&ThreadSwitchSignal, SIG_TIMESLICE);
+   sigaddset(&ThreadSwitchSignal, SIGCHLD);
  
    act.sa_handler = handler;
    act.sa_flags = SA_RESTART;
    sigemptyset(&(act.sa_mask));
    if (sigaction (SIG_TIMESLICE, &act, NULL)) abort();
+   if (sigaction (SIGCHLD, &act, NULL)) abort();
+ }
+ 
+ int
+ __cdecl
+ ThreadPosix__value_of_SIGCHLD(void)
+ {
+ 	return SIGCHLD;
  }
  
  void



More information about the M3devel mailing list