[M3devel] SIGCHLD diff

Mika Nystrom mika at async.caltech.edu
Sun Feb 13 21:37:26 CET 2011


Tony,

The old user threads has an old problem with Process.Wait.  It has a 
Thread.Pause(0.1d0) in it.  This causes the compiler to run three times
slower than it should.  The m3build I've been using for years has
that Thread.Pause removed (so it uses 100% CPU instead, busy-waiting...)

But yeah user threads works the same as it used to (except for 
now calling pthread_atfork, which I'll return to in another email...)

     Mika

Tony Hosking writes:
>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:
>
>>=20
>> Index: ThreadPosix.i3
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>> 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 ----
>>=20
>>  =
>(*------------------------------------------------------------------------=
>---*)
>>=20
>> + <*EXTERNAL ThreadPosix__value_of_SIGCHLD*>
>> + PROCEDURE ValueOfSIGCHLD(): int;
>> +=20
>>  END ThreadPosix.
>> Index: ThreadPosix.m3
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>> 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 =3D pausing, the time at which we can restart *)
>>      waitingForTime: Time.T;
>>=20
>> +     (* if state =3D pausing, the signal that truncates the pause *)
>> +     waitingForSig: int :=3D -1;
>> +=20
>>      (* true if we are waiting during an AlertWait or AlertJoin=20
>>         or AlertPause *)
>>      alertable: BOOLEAN :=3D FALSE;
>> ***************
>> *** 147,152 ****
>> --- 150,160 ----
>>=20
>>    defaultStackSize :=3D 3000;
>>=20
>> +   (* note that even though the "heavy machinery" is only used for=20
>> +      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 *)
>> +=20
>>  VAR
>>    stats: RECORD
>>             n_forks :=3D 0;
>> ***************
>> *** 511,527 ****
>>      XPause(until, FALSE);
>>    END Pause;
>>=20
>>  PROCEDURE AlertPause(n: LONGREAL) RAISES {Alerted}=3D
>>    VAR until :=3D n + Time.Now ();
>>    BEGIN
>>      XPause(until, TRUE);
>>    END AlertPause;
>>=20
>> ! PROCEDURE XPause (READONLY until: Time.T; alertable :=3D FALSE) =
>RAISES {Alerted} =3D
>>    BEGIN
>>      INC (inCritical);
>>        self.waitingForTime :=3D until;
>>        self.alertable :=3D alertable;
>>        ICannotRun (State.pausing);
>>      DEC (inCritical);
>>      InternalYield ();
>> --- 519,546 ----
>>      XPause(until, FALSE);
>>    END Pause;
>>=20
>> + PROCEDURE SigPause(n: LONGREAL; sig: int)=3D
>> +   <*FATAL Alerted*>
>> +   VAR until :=3D n + Time.Now ();
>> +   BEGIN
>> +     XPause(until, FALSE, sig);
>> +   END SigPause;
>> +=20
>>  PROCEDURE AlertPause(n: LONGREAL) RAISES {Alerted}=3D
>>    VAR until :=3D n + Time.Now ();
>>    BEGIN
>>      XPause(until, TRUE);
>>    END AlertPause;
>>=20
>> ! PROCEDURE XPause (READONLY until: Time.T; alertable :=3D FALSE; =
>sig:int :=3D -1)=20
>> !   RAISES {Alerted} =3D
>>    BEGIN
>>      INC (inCritical);
>>        self.waitingForTime :=3D until;
>>        self.alertable :=3D alertable;
>> +       IF sig # -1 THEN
>> +         self.waitingForSig :=3D sig
>> +       END;
>>        ICannotRun (State.pausing);
>>      DEC (inCritical);
>>      InternalYield ();
>> ***************
>> *** 703,712 ****
>>      END;
>>    END StartSwitching;
>>=20
>> ! PROCEDURE switch_thread (<*UNUSED*> sig: int) RAISES {Alerted} =3D
>>    BEGIN
>>      allow_sigvtalrm ();
>> !     IF inCritical =3D 0 AND heapState.inCritical =3D 0 THEN =
>InternalYield () END;
>>    END switch_thread;
>>=20
>>  (*------------------------------------------------------------- =
>scheduler ---*)
>> --- 722,750 ----
>>      END;
>>    END StartSwitching;
>>=20
>> ! CONST MaxSigs =3D 64;
>> ! TYPE Sig =3D [ 0..MaxSigs-1 ];
>> !=20
>> ! (* in order to listen to other signals, they have to be enabled in
>> !    allow_sigvtalrm as well *)
>> ! VAR (*CONST*) SIGCHLD :=3D ValueOfSIGCHLD();
>> !              =20
>> !     gotSigs :=3D SET OF Sig { };
>> !=20
>> ! PROCEDURE switch_thread (sig: int) RAISES {Alerted} =3D
>>    BEGIN
>>      allow_sigvtalrm ();
>> !=20
>> !     INC(inCritical);
>> !     (* mark signal as being delivered *)
>> !     IF sig >=3D 0 AND sig < MaxSigs THEN
>> !       gotSigs :=3D gotSigs + SET OF Sig { sig }
>> !     END;
>> !     DEC(inCritical);
>> !=20
>> !     IF inCritical =3D 0 AND heapState.inCritical =3D 0 THEN=20
>> !       InternalYield ()=20
>> !     END;
>>    END switch_thread;
>>=20
>>  (*------------------------------------------------------------- =
>scheduler ---*)
>> ***************
>> *** 782,792 ****
>>              IF t.alertable AND t.alertPending THEN
>>                CanRun (t);
>>                EXIT;
>>=20
>>              ELSIF t.waitingForTime <=3D now THEN
>>                CanRun (t);
>>                EXIT;
>> !  =20
>>              ELSIF NOT somePausing THEN
>>                earliest :=3D t.waitingForTime;
>>                somePausing :=3D TRUE;
>> --- 820,835 ----
>>              IF t.alertable AND t.alertPending THEN
>>                CanRun (t);
>>                EXIT;
>> +              =20
>> +             ELSIF t.waitingForSig IN gotSigs THEN
>> +               t.waitingForSig :=3D -1;
>> +               CanRun(t);
>> +               EXIT;
>>=20
>>              ELSIF t.waitingForTime <=3D now THEN
>>                CanRun (t);
>>                EXIT;
>> !=20
>>              ELSIF NOT somePausing THEN
>>                earliest :=3D t.waitingForTime;
>>                somePausing :=3D TRUE;
>> ***************
>> *** 886,891 ****
>> --- 929,936 ----
>>        END;
>>      END;
>>=20
>> +     gotSigs :=3D SET OF Sig {};
>> +=20
>>      IF t.state =3D 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 ****
>>=20
>>  PROCEDURE WaitProcess (pid: int; VAR status: int): int =3D
>>    (* ThreadPThread.m3 and ThreadPosix.m3 are very similar. *)
>> !   CONST Delay =3D 0.1D0;
>>    BEGIN
>>      LOOP
>>        WITH r =3D Uexec.waitpid(pid, ADR(status), Uexec.WNOHANG) DO
>>          IF r # 0 THEN RETURN r END;
>>        END;
>> !       Pause(Delay);
>>      END;
>>    END WaitProcess;
>>=20
>> --- 993,1005 ----
>>=20
>>  PROCEDURE WaitProcess (pid: int; VAR status: int): int =3D
>>    (* ThreadPThread.m3 and ThreadPosix.m3 are very similar. *)
>> !   CONST Delay =3D 10.0D0;
>>    BEGIN
>>      LOOP
>>        WITH r =3D Uexec.waitpid(pid, ADR(status), Uexec.WNOHANG) DO
>>          IF r # 0 THEN RETURN r END;
>>        END;
>> !       SigPause(Delay,SIGCHLD);
>>      END;
>>    END WaitProcess;
>>=20
>> ***************
>> *** 1361,1364 ****
>> --- 1406,1412 ----
>>  VAR debug :=3D RTParams.IsPresent ("debugthreads");
>>=20
>>  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
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>> 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 ----
>>=20
>>    sigemptyset(&ThreadSwitchSignal);
>>    sigaddset(&ThreadSwitchSignal, SIG_TIMESLICE);
>> +   sigaddset(&ThreadSwitchSignal, SIGCHLD);
>>=20
>>    act.sa_handler =3D handler;
>>    act.sa_flags =3D SA_RESTART;
>>    sigemptyset(&(act.sa_mask));
>>    if (sigaction (SIG_TIMESLICE, &act, NULL)) abort();
>> +   if (sigaction (SIGCHLD, &act, NULL)) abort();
>> + }
>> +=20
>> + int
>> + __cdecl
>> + ThreadPosix__value_of_SIGCHLD(void)
>> + {
>> + 	return SIGCHLD;
>>  }
>>=20
>>  void



More information about the M3devel mailing list