Skip to content

Instantly share code, notes, and snippets.

@kawaii-ghost
Created May 19, 2025 10:58
Show Gist options
  • Save kawaii-ghost/79da6bf3d5ee632b386464e436ddbad8 to your computer and use it in GitHub Desktop.
Save kawaii-ghost/79da6bf3d5ee632b386464e436ddbad8 to your computer and use it in GitHub Desktop.
#include <stdint.h>
#include <linux/futex.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <threads.h>
#include <unistd.h>
#include <stdbool.h>
#include <time.h>
#include <stdatomic.h>
#include <stdbool.h>
static int futex(uint32_t *uaddr, int futex_op, uint32_t val, const struct timespec *timeout, uint32_t *uaddr2, uint32_t val3)
{
return syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3);
}
bool WaitOnAddress(volatile void *Address, void *CompareAddress, size_t AddressSize, int Milliseconds)
{
struct timespec ts;
struct timespec *timeout = NULL;
if (Milliseconds != -1) {
ts.tv_sec = Milliseconds / 1000;
ts.tv_nsec = (Milliseconds % 1000) * 1000000;
timeout = &ts;
}
uint32_t shared_var = atomic_load((atomic_uintptr_t*)Address);
uint32_t val = atomic_load((atomic_uintptr_t*)CompareAddress);
if (shared_var == val) {
return !futex((uint32_t*)Address, FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG, val, timeout, NULL, FUTEX_BITSET_MATCH_ANY);
} else {
return false;
}
}
void WakeByAddressSingle(void *Address)
{
futex((uint32_t*)Address, FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, 1, NULL, NULL, FUTEX_BITSET_MATCH_ANY);
}
atomic_int shared_var = 0;
uint32_t expected_value = 0;
int func(void *arg)
{
puts("Sleep in thread");
sleep(3);
printf("Thread waking up address %p\n", &shared_var);
atomic_store(&shared_var, 1);
WakeByAddressSingle(&shared_var);
return 0;
}
int main(void) {
thrd_t thread;
thrd_create(&thread, func, NULL);
thrd_detach(thread);
printf("Main thread waiting on address %p for value %u\n", &shared_var, expected_value);
if (WaitOnAddress(&shared_var, &expected_value, sizeof(shared_var), 10000)) {
printf("Main thread woke up because the value at address %p changed from %u\n", &shared_var, expected_value);
printf("Current value: %u\n", atomic_load(&shared_var));
} else {
printf("WaitOnAddress failed or the initial value was not as expected.\n");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment