#68106: Mutex starvation fixed - enable another reader to proceed chained mutex in case readers have got it before. testdep_54161_root
authorpnejedly@netbeans.org
Fri, 26 May 2006 15:00:50 +0000
changeset 166154df46b44cd
parent 165 542f8c5e67b2
child 167 bad1db674ebe
#68106: Mutex starvation fixed - enable another reader to proceed chained mutex in case readers have got it before.
openide.util/src/org/openide/util/Mutex.java
     1.1 --- a/openide.util/src/org/openide/util/Mutex.java	Fri May 26 07:38:45 2006 +0000
     1.2 +++ b/openide.util/src/org/openide/util/Mutex.java	Fri May 26 15:00:50 2006 +0000
     1.3 @@ -138,6 +138,9 @@
     1.4  
     1.5      /** granted mode */
     1.6      private int grantedMode = NONE;
     1.7 +    
     1.8 +    /** The mode the mutex was in before it started chaining */
     1.9 +    private int origMode;
    1.10  
    1.11      /** protects internal data structures */
    1.12      private /*final*/ Object LOCK;
    1.13 @@ -189,15 +192,6 @@
    1.14          }
    1.15      }
    1.16  
    1.17 -    /** Decides whether two locks are compatible.?
    1.18 -     * @param granted?
    1.19 -     * @param requested?
    1.20 -     * @return <tt>true</tt> iff they are compatible?
    1.21 -     */
    1.22 -    private static boolean compatibleLocks(int granted, int requested) {
    1.23 -        return cmatrix[requested][granted];
    1.24 -    }
    1.25 -
    1.26      /** Initiates this Mutex */
    1.27      private void init(Object lock) {
    1.28          this.LOCK = lock;
    1.29 @@ -605,7 +599,7 @@
    1.30                          info.rsnapshot = info.counts[S];
    1.31  
    1.32                          if (grantedMode == S) {
    1.33 -                            grantedMode = X;
    1.34 +                            setGrantedMode(X);
    1.35                          } else if (grantedMode == X) {
    1.36                              // defensive
    1.37                              throw new IllegalStateException();
    1.38 @@ -630,7 +624,7 @@
    1.39                  } else { // first acquisition
    1.40  
    1.41                      if (isCompatible(requested)) { // NONE -> S,X or S -> S
    1.42 -                        grantedMode = requested;
    1.43 +                        setGrantedMode(requested);
    1.44                          registeredThreads.put(t, info = new ThreadInfo(t, requested));
    1.45  
    1.46                          if (requested == S) {
    1.47 @@ -646,7 +640,7 @@
    1.48                      return false;
    1.49                  }
    1.50  
    1.51 -                grantedMode = CHAIN;
    1.52 +                setGrantedMode(CHAIN);
    1.53                  cell = chain(requested, t, 0);
    1.54              }
    1.55               // sync
    1.56 @@ -655,7 +649,7 @@
    1.57          }
    1.58           // for
    1.59      }
    1.60 -
    1.61 +    
    1.62      /** privilegedEnter serves for processing posted requests */
    1.63      private boolean reenter(Thread t, int mode) {
    1.64          boolean log = LOG.isLoggable(Level.FINE);
    1.65 @@ -707,7 +701,7 @@
    1.66              readersNo += 2;
    1.67  
    1.68              // prevent from new readers
    1.69 -            grantedMode = CHAIN;
    1.70 +            setGrantedMode(CHAIN);
    1.71  
    1.72              return true;
    1.73          }
    1.74 @@ -735,7 +729,7 @@
    1.75                  // always chain this thread
    1.76                  // since there can be another one
    1.77                  // in the queue with higher priority
    1.78 -                grantedMode = CHAIN;
    1.79 +                setGrantedMode(CHAIN);
    1.80                  cell = chain(mode, t, Integer.MAX_VALUE);
    1.81  
    1.82                  if (readersNo == 0) { // seems I may enter
    1.83 @@ -746,7 +740,7 @@
    1.84  
    1.85                          return;
    1.86                      } else {
    1.87 -                        grantedMode = NONE;
    1.88 +                        setGrantedMode(NONE);
    1.89                          wakeUpOthers();
    1.90                      }
    1.91                  }
    1.92 @@ -875,9 +869,11 @@
    1.93  
    1.94                  // downgrade the lock
    1.95                  if (info.counts[S] > 0) {
    1.96 -                    info.mode = grantedMode = S;
    1.97 +                    info.mode = S;
    1.98 +                    setGrantedMode(S);
    1.99                  } else {
   1.100 -                    info.mode = grantedMode = NONE;
   1.101 +                    info.mode = NONE;
   1.102 +                    setGrantedMode(NONE);
   1.103                      registeredThreads.remove(info.t);
   1.104                  }
   1.105  
   1.106 @@ -937,7 +933,7 @@
   1.107                  // set grantedMode to NONE
   1.108                  // and then wakeUp others - either immediately 
   1.109                  // or in privelegedEnter()
   1.110 -                grantedMode = NONE;
   1.111 +                setGrantedMode(NONE);
   1.112  
   1.113                  if (info.getRunnableCount(X) > 0) {
   1.114                      return X;
   1.115 @@ -968,7 +964,7 @@
   1.116                                  }
   1.117  
   1.118                                  if (waiters.size() == 1) {
   1.119 -                                    grantedMode = X;
   1.120 +                                    setGrantedMode(X);
   1.121                                  }
   1.122                                   // else let CHAIN
   1.123  
   1.124 @@ -1061,10 +1057,10 @@
   1.125                      continue;
   1.126                  }
   1.127  
   1.128 -                if (compatibleLocks(grantedMode, qc.mode)) { // woken S -> should I wake X? -> no
   1.129 +                if (isCompatible(qc.mode)) { // woken S -> should I wake X? -> no
   1.130                      waiters.remove(i--);
   1.131                      qc.wakeMeUp();
   1.132 -                    grantedMode = qc.mode;
   1.133 +                    setGrantedMode(qc.mode);
   1.134  
   1.135                      if (getThreadInfo(qc.t) == null) {
   1.136                          // force to have a record since recorded threads
   1.137 @@ -1079,7 +1075,7 @@
   1.138                          registeredThreads.put(qc.t, ti);
   1.139                      }
   1.140                  } else {
   1.141 -                    grantedMode = CHAIN;
   1.142 +                    setGrantedMode(CHAIN);
   1.143  
   1.144                      break;
   1.145                  }
   1.146 @@ -1109,7 +1105,7 @@
   1.147                  if (qc.mode == S) { // readers only
   1.148                      waiters.remove(i--);
   1.149                      qc.wakeMeUp();
   1.150 -                    grantedMode = S;
   1.151 +                    setGrantedMode(S);
   1.152  
   1.153                      if (getThreadInfo(qc.t) == null) {
   1.154                          // force to have a record since recorded threads
   1.155 @@ -1181,7 +1177,9 @@
   1.156      * @return <tt>true</tt> if and only if current mode and requested mode are compatible
   1.157      */
   1.158      private boolean isCompatible(int requested) {
   1.159 -        return compatibleLocks(grantedMode, requested);
   1.160 +        // allow next reader in even in chained mode, if it was read access before
   1.161 +        if (requested == S && grantedMode == CHAIN && origMode == S) return true;
   1.162 +        return cmatrix[requested][grantedMode];
   1.163      }
   1.164  
   1.165      private ThreadInfo getThreadInfo(Thread t) {
   1.166 @@ -1523,4 +1521,11 @@
   1.167              parent.leave(Thread.currentThread());
   1.168          }
   1.169      }
   1.170 +
   1.171 +    private void setGrantedMode(int mode) {
   1.172 +        if (grantedMode != CHAIN && mode == CHAIN) {
   1.173 +            origMode = grantedMode;
   1.174 +        }
   1.175 +        grantedMode = mode;
   1.176 +    }
   1.177  }