main.c   [plain text]




// BUILD:  $CC foo.c -dynamiclib -o $BUILD_DIR/libfoo.dylib -install_name $RUN_DIR/libfoo.dylib
// BUILD:  $CC main.c $BUILD_DIR/libfoo.dylib -o $BUILD_DIR/thread-local-variables.exe


// RUN:  ./thread-local-variables.exe


#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
#include <unistd.h>

#include "test_support.h"

extern __thread int a;
extern __thread int b;
static __thread int c;
static __thread int d = 5;


static int* sAddr1[4];
static int* sAddr2[4];
static int* sAddr3[4];

static pthread_t sWorker1;
static pthread_t sWorker2;


// verify all initial TLV values are correct
static void checkValues()
{
    assert(a == 0);
    assert(b == 5);
    assert(c == 0);
    assert(d == 5);
}


// return addresses of all TLVs
static void getAddresses(int* array[])
{
    array[0] = &a;
    array[1] = &b;
    array[2] = &c;
    array[3] = &d;
}

static void* work2(void* arg)
{
    checkValues();
    getAddresses(sAddr2);

	return NULL;
}

static void* work1(void* arg)
{
    checkValues();

	if ( pthread_create(&sWorker2, NULL, work2, NULL) != 0 ) {
        FAIL("pthread_create");
	}
 	void* dummy;
	pthread_join(sWorker2, &dummy);

    getAddresses(sAddr1);

	return NULL;
}

static bool someMatch(int* t1, int* t2, int* t3)
{
    if ( t1 == t2 )
        return true;
    if ( t1 == t3 )
        return true;
    if ( t2 == t3 )
        return true;
    return false;
}

int main(int argc, const char* argv[], const char* envp[], const char* apple[]) {
    checkValues();

	if ( pthread_create(&sWorker1, NULL, work1, NULL) != 0 ) {
        FAIL("pthread_create");
	}

    getAddresses(sAddr3);

 	void* dummy;
	pthread_join(sWorker1, &dummy);

    // validate each thread had different addresses for all TLVs
    if ( someMatch(sAddr1[0], sAddr2[0], sAddr3[0]) )
        FAIL("&a is same across some threads");
    else if ( someMatch(sAddr1[1], sAddr2[1], sAddr3[1]) )
        FAIL("&b is same across some threads");
    else if ( someMatch(sAddr1[2], sAddr2[2], sAddr3[2]) )
        FAIL("&c is same across some threads");
    else if ( someMatch(sAddr1[3], sAddr2[3], sAddr3[3]) )
        FAIL("&d is same across some threads");
    else
        PASS("Success");
}