Skip to content

Instantly share code, notes, and snippets.

@aprell
Created March 7, 2019 19:13
Show Gist options
  • Select an option

  • Save aprell/0e26c731e6a0c41e5539d88a3ddbda5f to your computer and use it in GitHub Desktop.

Select an option

Save aprell/0e26c731e6a0c41e5539d88a3ddbda5f to your computer and use it in GitHub Desktop.

Revisions

  1. aprell created this gist Mar 7, 2019.
    13 changes: 13 additions & 0 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    CC := gcc
    CFLAGS += -Wall -Wextra -std=c99
    LDLIBS += -lpthread

    all: test_wrap

    test_wrap: LDFLAGS += -Wl,--wrap=pthread_create -Wl,--wrap=pthread_join
    test_wrap: test_wrap.c wrap.c

    clean:
    rm -rf test_wrap

    .PHONY: all clean
    34 changes: 34 additions & 0 deletions test_wrap.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,34 @@
    #include <assert.h>
    #include <pthread.h>
    #include <stdlib.h>

    unsigned int num_threads;

    static void *thread_entry_fn(void *arg)
    {
    (void)arg;
    return NULL;
    }

    int main(int argc, char *argv[])
    {
    unsigned int n = argc > 1 && atoi(argv[1]) >= 0 ? atoi(argv[1]) : 4;
    pthread_t *threads = malloc(n * sizeof(pthread_t));
    if (!threads) return EXIT_FAILURE;

    for (unsigned int i = 0; i < n; i++) {
    pthread_create(&threads[i], NULL, thread_entry_fn, NULL);
    }

    assert(num_threads == n);

    for (unsigned int i = 0; i < n; i++) {
    pthread_join(threads[i], NULL);
    }

    assert(num_threads == 0);

    free(threads);

    return 0;
    }
    26 changes: 26 additions & 0 deletions wrap.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,26 @@
    #include <pthread.h>

    extern unsigned int num_threads;

    // From the docs:
    // Any undefined reference to `symbol` will be resolved to `__wrap_symbol`. Any
    // undefined reference to `__real_symbol` will be resolved to `symbol`. This
    // can be used to provide a wrapper for a system function. The wrapper function
    // should be called `__wrap_symbol`. If it wishes to call the system function,
    // it should call `__real_symbol`.

    extern int __real_pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);

    extern int __real_pthread_join(pthread_t, void **);

    int __wrap_pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
    {
    num_threads++;
    return __real_pthread_create(thread, attr, start_routine, arg);
    }

    int __wrap_pthread_join(pthread_t thread, void **retval)
    {
    num_threads--;
    return __real_pthread_join(thread, retval);
    }