[M3devel] win32 threads/alert/race

Jay K jay.krell at cornell.edu
Mon Oct 5 16:33:05 CEST 2009


e.g. does this help:

 

PROCEDURE Alert(t: T) =
    VAR prev, next: T;
  BEGIN
    IF t = NIL THEN Die(ThisLine(), "Alert called from non-Modula-3 thread") END;
(* remove this *)    EnterCriticalSection_giant(); 

(* make next two lines one interlocked *)
    t.alerted := TRUE;
    IF t.alertable THEN
(* add this *)    EnterCriticalSection_giant();

      (* Dequeue from any CV and unblock from the semaphore *)
      IF t.waitingOn # NIL THEN
        next := t.waitingOn.waiters; prev := NIL;
        WHILE next # t DO
          <* ASSERT(next#NIL) *>
          prev := next; next := next.nextWaiter;
        END;
        IF prev = NIL THEN
          t.waitingOn.waiters := t.nextWaiter
        ELSE
          prev.nextWaiter := t.nextWaiter;
        END;
        t.nextWaiter := NIL;
        t.waitingOn := NIL;
      END;
      t.alertable := FALSE;
      IF ReleaseSemaphore(t.waitSema, 1, NIL) = 0 THEN
        Choke(ThisLine());
      END;
    END;
    LeaveCriticalSection_giant(); (* this moves up obviously *)
  END Alert;



 


From: jay.krell at cornell.edu
To: hosking at cs.purdue.edu; m3devel at elegosoft.com
Subject: win32 threads/alert/race
Date: Mon, 5 Oct 2009 14:27:14 +0000



Tony can you clarify/confirm where you think the race is?
 
 
Is it here:
 
 
PROCEDURE InnerWait(m: Mutex; c: Condition; self: T) =
    (* LL = giant+m on entry; LL = m on exit *)
  BEGIN
    <* ASSERT( (self.waitingOn=NIL) AND (self.nextWaiter=NIL) ) *>
    self.waitingOn := c;
    self.nextWaiter := c.waiters;
    c.waiters := self;
    m.release();
    LeaveCriticalSection_giant();
 
     ** here ** ?

    IF perfOn THEN PerfChanged(State.waiting) END;
    IF WaitForSingleObject(self.waitSema, INFINITE) # 0 THEN
      Choke(ThisLine());
    END;
    m.acquire();
  END InnerWait;

Btw..just in case.. alerted and alertable could be "interlocked", even share bits in the same long.
If that helps.
 
Another thing to consider is that Win32 reserves the lower two bits of handles for users.
So you can imagine something even like where waitSema is in two places.
One place where it isn't used, always there.
Another place where if it is non-null it is going to be waited on.
You could merge setting of that copy of waitSema with the two bits alerted and alertable.
And set all three in one fell interlocked swoop.
Does that help?
 
 
I'm just mentioning random tricks, without understanding where the race is.
 
 
I'm just hoping you don't need a lock free manipulation of the waiters list.
That I have no good ideas on.
There is the slist stuff but I'm not keen on it, and I don't think it buys anything.
 
 
  - Jay





 
 		 	   		  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20091005/cf7cc65e/attachment-0002.html>


More information about the M3devel mailing list