Skip to content

Support for FUTEX_REQUEUE #183

@zyedidia

Description

@zyedidia

It looks like Blink's system call emulation for futex(2) doesn't support the FUTEX_REQUEUE flag. This flag is sometimes used by musl libc (specifically here: https://git.musl-libc.org/cgit/musl/tree/src/thread/pthread_cond_timedwait.c#n48). This can cause multithreaded programs built with musl to misbehave when run inside of Blink.

Here's a simple example that makes direct use of FUTEX_REQUEUE as a test:

#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <pthread.h>

#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define FUTEX_REQUEUE 3

int futex1 = 0;  // Initial futex
int futex2 = 0;  // Destination futex for requeued threads

static int futex_wait(int *addr, int val) {
    return syscall(SYS_futex, addr, FUTEX_WAIT, val, NULL, NULL, 0);
}

static int futex_wake(int *addr, int num) {
    return syscall(SYS_futex, addr, FUTEX_WAKE, num, NULL, NULL, 0);
}

static int futex_requeue(int *futex1, int *futex2, int wake_count, int requeue_count) {
    return syscall(SYS_futex, futex1, FUTEX_REQUEUE, wake_count, requeue_count, futex2, 0);
}

void *worker_thread(void *arg) {
    int id = *(int *)arg;
    printf("Thread %d waiting on futex1\n", id);

    futex_wait(&futex1, 0);

    return NULL;
}

int main() {
    pthread_t thread1, thread2;
    int id1 = 1, id2 = 2;

    // Start two worker threads
    pthread_create(&thread1, NULL, worker_thread, &id1);
    pthread_create(&thread2, NULL, worker_thread, &id2);
    sleep(1); // Ensure both threads are waiting

    // Wake one thread and requeue the other to futex2
    printf("Main thread: Waking 1 thread and requeuing 1 thread\n");
    futex_requeue(&futex1, &futex2, 1, 1);

    sleep(1); // Give time for one thread to wake up

    // Wake the remaining thread from futex2
    printf("Main thread: Waking the remaining thread from futex2\n");
    futex_wake(&futex2, 1);

    // Join threads
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    printf("All threads completed.\n");
    return 0;
}
$ musl-clang -O2 -static main.c

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions