Skip to content

Instantly share code, notes, and snippets.

@michaeljclark
Last active March 28, 2024 23:23
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michaeljclark/31fc67fe41d233a83e9ec8e3702398e8 to your computer and use it in GitHub Desktop.
Save michaeljclark/31fc67fe41d233a83e9ec8e3702398e8 to your computer and use it in GitHub Desktop.
Demonstrates torn loads for misaligned atomics
#include <stdio.h>
#include <stdlib.h>
#include <stdatomic.h>
#include <limits.h>
#include <pthread.h>
/*
* Intel® 64 and IA-32 Architectures Software Developer’s Manual
*
* Volume 3A - 8.1.1 Guaranteed Atomic Operations
*
* Accesses to cacheable memory that are split across cache lines and
* page boundaries are not guaranteed to be atomic by the Intel Core 2 Duo,
* Intel® Atom™, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, P6 family,
* Pentium, and Intel486 processors
*/
typedef struct { atomic_long ub; } misaligned_atomic;
void* detect_misaligned_atomic_torn_load(void *arg)
{
misaligned_atomic *p = arg;
long c1 = 0, c2 = 0;
for (;;) {
/* relaxed "atomic" load */
long val = atomic_load(&p->ub);
if (val == 0) c1++;
else if (val == -1) c2++;
else {
printf("0x%016lx : %ld\n0x%016lx : %ld\n0x%016lx : %ld\n",
0UL, c1, -1UL, c2, val, 1L);
exit(1);
}
}
return NULL;
}
int main()
{
int ret;
pthread_t thr;
long m = (long)malloc(128);
/* arrange for our "atomic" to straddle a cache line */
misaligned_atomic *p = (void*)(((m + 64) & ~63) - (sizeof(atomic_ulong)/2));
atomic_store(&p->ub, 0);
if (pthread_create(&thr, NULL, detect_misaligned_atomic_torn_load, p) < 0) {
perror("pthread_create");
exit(1);
}
for (;;) {
atomic_fetch_add_explicit(&p->ub, -1, memory_order_relaxed);
atomic_fetch_add_explicit(&p->ub, 1, memory_order_relaxed);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment