Sign in

docs ILE Concepts

Alternate Solution: Using Check Lock Value / Clear Lock Value

Alternate Solution: Using Check Lock Value / Clear Lock Value

Alternate Solution: Using Check Lock Value / Clear Lock Value

Space location locks, like those used in the first solution, are full of features that are not required in this simple example. For instance, space location locks support a time-out value which would allow processing to resume if unable to acquire the lock within some period of time. Space locations locks also support several combinations of shared locks. These are important features, but come at the price of some performance overhead.

An alternative is to use Check Lock Value and Clear Lock Value. Together, these two MI instructions provide a way to implement a very simple and fast locking protocol, particularly if there is not much contention on the lock.

In this solution, the system uses CHKLKVAL to attempt to acquire the lock. If that attempt fails (because the system found the lock already in use), the thread will wait for a while and then try again, repeating until the lock is acquired. After updating the shared data, the system will use CLRLKVAL to release the lock. In this example, assume that, in addition to the shared data items, the threads also share the address of an 8-byte location. This code refers to that location as variable LOCK. Furthermore, assume that the lock was initialized to zero, either through static initialization or some prior synchronized initialization.

              THREAD A                                                     THREAD B
 --------------------------------                            ---------------------------------
 /* Do some work on the shared data */                       /* Do some work on the shared data */
 for (i=0; i<10; ++i) {                                      for (i=0; i<10; ++i) {

   /* Attempt to acquire the lock using                        /* Attempt to acquire the lock using
      CHKLKVAL.  By convention, use value                         CHKLKVAL.  By convention, use value
      1 to indicate locked, 0 to indicate                         1 to indicate locked, 0 to indicate
      unlocked. */                                                unlocked. */
   while (_CHKLKVAL(&LOCK, 0, 1) == 1) {                       while (_CHKLKVAL(&LOCK, 0, 1) == 1) {
     sleep(1);  /* wait a bit and try again */                   sleep(1);  /* wait a bit and try again */
   }                                                           }

   /* Update the shared data */                                /* Update the shared data */
   data1 += 5;                                                 data1 += 4;
   data2 += 10;                                                data2 += 6;

   /* Unlock the shared data.  Use of                          /* Unlock the shared data.  Use of
      CLRLKVAL ensures other jobs/threads                         CLRLKVAL ensures other jobs/threads
      see update to shared data prior to                          see update to shared data prior to
      release of the lock. */                                     release of the lock. */
   _CLRLKVAL(&LOCK, 0);                                        _CLRLKVAL(&LOCK, 0);
 }                                                           }

Here, the threads use Check Lock Value to perform a race-free test and update of the lock variable, and Clear Lock Value to reset the lock variable to the unlocked state. This solves the race condition experienced in the original problem fragments. It also addresses the storage access ordering problem. As noted earlier, used in this fashion, Check Lock Value and Clear Lock Value are synchronizing actions. Using Check Lock Value to set the lock prior to reading the shared data ensures that the threads read the most recently updated data. Using Clear Lock Value to clear the lock after updating the shared data ensures that the updates are available for subsequent reads by any thread after its next synchronizing action.