Created
May 19, 2025 10:58
-
-
Save kawaii-ghost/79da6bf3d5ee632b386464e436ddbad8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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