#include <stdio.h>
#include <stdlib.h>
#include <mach-o/dyld.h>
#include <pthread.h>
#include <unistd.h>
#include <Availability.h>
#include "test.h"
extern void foo();
#if __MAC_OS_X_VERSION_MIN_REQUIRED
static volatile int sBarrier = 0;
static pthread_mutex_t sBarrierMutex;
static pthread_cond_t sBarrierFree;
static void blockUntilBarrier(int n)
{
pthread_mutex_lock(&sBarrierMutex);
while ( sBarrier < n )
pthread_cond_wait(&sBarrierFree, &sBarrierMutex);
pthread_mutex_unlock(&sBarrierMutex);
}
static void advanceToBarrier(int n)
{
pthread_mutex_lock(&sBarrierMutex);
sBarrier = n;
pthread_cond_broadcast(&sBarrierFree);
pthread_mutex_unlock(&sBarrierMutex);
}
static pthread_mutex_t sMyLock;
static void* thread2(void* arg)
{
blockUntilBarrier(1);
pthread_mutex_lock(&sMyLock);
advanceToBarrier(2);
foo();
pthread_mutex_unlock(&sMyLock);
return NULL;
}
static void myImageHandler(const struct mach_header *mh, intptr_t vmaddr_slide)
{
if ( NSLookupSymbolInImage(mh, "_bar", 0) != NULL ) {
advanceToBarrier(1);
blockUntilBarrier(2);
pthread_mutex_lock(&sMyLock);
pthread_mutex_unlock(&sMyLock);
}
}
#endif
int main()
{
#if __MAC_OS_X_VERSION_MIN_REQUIRED
pthread_mutex_init(&sBarrierMutex, NULL);
pthread_cond_init(&sBarrierFree, NULL);
pthread_mutex_init(&sMyLock, NULL);
alarm(2);
advanceToBarrier(0);
pthread_t pthread2;
if ( pthread_create(&pthread2, NULL, thread2, NULL) != 0 ) {
FAIL("pthread_create failed");
exit(0);
}
_dyld_register_func_for_add_image(&myImageHandler);
NSAddImage("bar.dylib", 0);
#endif
PASS("deadlock");
return 0;
}