[M3devel] SIGCHLD diff

Tony Hosking hosking at cs.purdue.edu
Sun Feb 13 21:18:03 CET 2011


Hi Mika, Why was this change needed (I haven't looked closely)?  I don't think we diverged much from previous implementations of user threads, which presumably used to work for you.

On Feb 12, 2011, at 3:44 PM, Mika Nystrom wrote:

> 
> 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