Skip to content

Instantly share code, notes, and snippets.

@david415
Created February 10, 2024 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save david415/05a5e7ed332e90bd7fb78b1f8f0c72cb to your computer and use it in GitHub Desktop.
Save david415/05a5e7ed332e90bd7fb78b1f8f0c72cb to your computer and use it in GitHub Desktop.
promela rwmutex with golang blocking semantics
int counter = 0;
typedef RWLock {
chan writeComplete = [0] of {bit};
chan allowWrite = [0] of {bit};
int readers;
bit writing;
int writeWaiters;
int readWaiters
}
/* RWLock actions */
inline acquire_read(lock) {
do
:: atomic {
if
:: lock.writing == 1 ->
lock.readWaiters++;
lock.writeComplete?0;
lock.readWaiters--;
break
:: else ->
lock.readers++;
break
fi
}
od
}
inline release_read(lock) {
atomic {
lock.readers--;
lock.readers == 0 ->
end: lock.writeComplete!0
}
}
inline acquire_write(lock) {
do
:: atomic {
if
:: lock.writing == 0 ->
lock.writing = 1;
break;
:: else ->
lock.writeWaiters++;
lock.allowWrite?0;
lock.writeWaiters--
fi
}
od
}
inline release_write(lock) {
atomic {
assert(lock.writing == 1);
lock.writing = 0
if
:: lock.writeWaiters > 0 ->
lock.allowWrite!0
:: else ->
skip
fi
if
:: lock.readWaiters > 0 ->
lock.writeComplete!0;
:: else ->
skip
fi
}
}
/* attempt to test the RWLock */
proctype Writer(RWLock lock) {
acquire_write(lock);
counter = counter + 1;
printf("Writer incremented counter to %d\n", counter);
end: release_write(lock);
}
proctype Reader(RWLock lock) {
int localCounter;
acquire_read(lock);
localCounter = counter;
printf("Reader read counter: %d\n", localCounter);
end: release_read(lock);
}
init {
RWLock myLock;
myLock.readers = 0;
myLock.writing = 0;
myLock.writeWaiters = 0;
myLock.readWaiters = 0
run Writer(myLock);
run Reader(myLock)
end: skip
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment