From 5774f100ce9eab64d7aa49b427941b6da69f40f4 Mon Sep 17 00:00:00 2001 From: Remzi Arpaci-Dusseau Date: Thu, 28 Feb 2019 18:40:59 -0600 Subject: [PATCH] init CAS example --- threads-locks/README.md | 47 ++++++++++++++++++++++++++++++++ threads-locks/compare-and-swap.c | 29 ++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 threads-locks/README.md create mode 100644 threads-locks/compare-and-swap.c diff --git a/threads-locks/README.md b/threads-locks/README.md new file mode 100644 index 0000000..6cd1a1d --- /dev/null +++ b/threads-locks/README.md @@ -0,0 +1,47 @@ + +A simple example of compare-and-swap shown in actual C code (which calls into +assembly). + +The code, in entirety, is shown here: + +```c +#include + +int global = 0; + +char compare_and_swap(int *ptr, int old, int new) { + unsigned char ret; + // Note that sete sets a ’byte’ not the word + __asm__ __volatile__ ( + " lock\n" + " cmpxchgl %2,%1\n" + " sete %0\n" + : "=q" (ret), "=m" (*ptr) + : "r" (new), "m" (*ptr), "a" (old) + : "memory"); + return ret; +} + +int main(int argc, char *argv[]) { + printf("before successful cas: %d\n", global); + int success = compare_and_swap(&global, 0, 100); + printf("after successful cas: %d (success: %d)\n", global, success); + + printf("before failing cas: %d\n", global); + success = compare_and_swap(&global, 0, 200); + printf("after failing cas: %d (old: %d)\n", global, success); + + return 0; +} +``` + +The first call to `compare_and_swap()` succeeds because the old value is +correct; the second call does not because the old value is wrong. + +To compile and run: +```sh +prompt> gcc -o compare_and_swap compare_and_swap.c -Wall +prompt> ./compare_and_swap +``` + + diff --git a/threads-locks/compare-and-swap.c b/threads-locks/compare-and-swap.c new file mode 100644 index 0000000..94a7555 --- /dev/null +++ b/threads-locks/compare-and-swap.c @@ -0,0 +1,29 @@ +#include + +int global = 0; + +char compare_and_swap(int *ptr, int old, int new) { + unsigned char ret; + // Note that sete sets a ’byte’ not the word + __asm__ __volatile__ ( + " lock\n" + " cmpxchgl %2,%1\n" + " sete %0\n" + : "=q" (ret), "=m" (*ptr) + : "r" (new), "m" (*ptr), "a" (old) + : "memory"); + return ret; +} + +int main(int argc, char *argv[]) { + printf("before successful cas: %d\n", global); + int success = compare_and_swap(&global, 0, 100); + printf("after successful cas: %d (success: %d)\n", global, success); + + printf("before failing cas: %d\n", global); + success = compare_and_swap(&global, 0, 200); + printf("after failing cas: %d (old: %d)\n", global, success); + + return 0; +} +