Skip to content

Instantly share code, notes, and snippets.

@sssgun
Created March 29, 2018 07:05
Show Gist options
  • Save sssgun/f8047b3de1ced38e6829fe0f6826fbc7 to your computer and use it in GitHub Desktop.
Save sssgun/f8047b3de1ced38e6829fe0f6826fbc7 to your computer and use it in GitHub Desktop.

Revisions

  1. sssgun created this gist Mar 29, 2018.
    17 changes: 17 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,17 @@
    #ifdef __cplusplus
    extern "C" {
    #endif
    struct simplefu_semaphore {
    int avail;
    int waiters;
    };

    typedef struct simplefu_semaphore *simplefu;

    void simplefu_down(simplefu who);
    void simplefu_up(simplefu who);


    #ifdef __cplusplus
    }
    #endif
    34 changes: 34 additions & 0 deletions main_futex.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,34 @@
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <stdlib.h>
    #include <assert.h>

    #include "simple_futex.h"

    int main()
    {
    int lockfile = open("ipc_lock", O_RDWR);
    assert(lockfile != -1);
    simplefu sema = mmap(NULL, sizeof(*sema), PROT_READ|PROT_WRITE,
    MAP_SHARED, lockfile, 0);
    assert(sema != MAP_FAILED);

    int pid = fork();
    assert(pid != -1);
    if( pid == 0 ) { // child
    printf("Initializing...\n");
    sleep(10);
    printf("Done initializing\n");
    simplefu_up(sema);
    exit(0);
    }
    sleep(15);
    printf("Waiting for child...\n");
    simplefu_down(sema);
    printf("Child done initializing\n");

    return 0;
    }
    25 changes: 25 additions & 0 deletions simple_futex.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    #include "simple_futex.h"
    #include <linux/futex.h>
    #include <sys/syscall.h>

    void simplefu_down(simplefu who)
    {
    int val;
    do {
    val = who->avail;
    if( val > 0 && __sync_bool_compare_and_swap(&who->avail, val, val - 1) )
    return;
    __sync_fetch_and_add(&who->waiters, 1);
    syscall(__NR_futex, &who->avail, FUTEX_WAIT, val, NULL, 0, 0);
    __sync_fetch_and_sub(&who->waiters, 1);
    } while(1);
    }

    void simplefu_up(simplefu who)
    {
    int nval = __sync_add_and_fetch(&who->avail, 1);
    if( who->waiters > 0 )
    {
    syscall(__NR_futex, &who->avail, FUTEX_WAKE, nval, NULL, 0, 0);
    }
    }