1// TEST_CONFIG 2 3#include "test.h" 4 5#include <Foundation/NSObject.h> 6#include <mach/mach.h> 7#include <pthread.h> 8#include <sys/time.h> 9#include <objc/runtime.h> 10#include <objc/objc-sync.h> 11 12// Basic @synchronized tests. 13 14 15#define WAIT_SEC 3 16 17static id obj; 18static semaphore_t go; 19static semaphore_t stop; 20 21void *thread(void *arg __unused) 22{ 23 int err; 24 25 objc_registerThreadWithCollector(); 26 27 // non-blocking sync_enter 28 err = objc_sync_enter(obj); 29 testassert(err == OBJC_SYNC_SUCCESS); 30 31 semaphore_signal(go); 32 // main thread: sync_exit of object locked on some other thread 33 semaphore_wait(stop); 34 35 err = objc_sync_exit(obj); 36 testassert(err == OBJC_SYNC_SUCCESS); 37 err = objc_sync_enter(obj); 38 testassert(err == OBJC_SYNC_SUCCESS); 39 40 semaphore_signal(go); 41 // main thread: blocking sync_enter 42 testassert(WAIT_SEC/3*3 == WAIT_SEC); 43 sleep(WAIT_SEC/3); 44 // recursive enter while someone waits 45 err = objc_sync_enter(obj); 46 testassert(err == OBJC_SYNC_SUCCESS); 47 sleep(WAIT_SEC/3); 48 // recursive exit while someone waits 49 err = objc_sync_exit(obj); 50 testassert(err == OBJC_SYNC_SUCCESS); 51 sleep(WAIT_SEC/3); 52 // sync_exit while someone waits 53 err = objc_sync_exit(obj); 54 testassert(err == OBJC_SYNC_SUCCESS); 55 56 return NULL; 57} 58 59int main() 60{ 61 pthread_t th; 62 int err; 63 struct timeval start, end; 64 65 obj = [[NSObject alloc] init]; 66 67 // sync_exit of never-locked object 68 err = objc_sync_exit(obj); 69 testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR); 70 71 semaphore_create(mach_task_self(), &go, 0, 0); 72 semaphore_create(mach_task_self(), &stop, 0, 0); 73 pthread_create(&th, NULL, &thread, NULL); 74 semaphore_wait(go); 75 76 // sync_exit of object locked on some other thread 77 err = objc_sync_exit(obj); 78 testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR); 79 80 semaphore_signal(stop); 81 semaphore_wait(go); 82 83 // blocking sync_enter 84 gettimeofday(&start, NULL); 85 err = objc_sync_enter(obj); 86 gettimeofday(&end, NULL); 87 testassert(err == OBJC_SYNC_SUCCESS); 88 // should have waited more than WAIT_SEC but less than WAIT_SEC+1 89 // fixme hack: sleep(1) is ending 500 usec too early on x86_64 buildbot 90 // (rdar://6456975) 91 testassert(end.tv_sec*1000000LL+end.tv_usec >= 92 start.tv_sec*1000000LL+start.tv_usec + WAIT_SEC*1000000LL 93 - 3*500 /*hack*/); 94 testassert(end.tv_sec*1000000LL+end.tv_usec < 95 start.tv_sec*1000000LL+start.tv_usec + (1+WAIT_SEC)*1000000LL); 96 97 err = objc_sync_exit(obj); 98 testassert(err == OBJC_SYNC_SUCCESS); 99 100 err = objc_sync_exit(obj); 101 testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR); 102 103 succeed(__FILE__); 104} 105