X-Git-Url: https://git.saurik.com/apple/objc4.git/blobdiff_plain/7c0e6487d7b67b6bf6c632300ee4b74e8950b051..7af964d1562d70f51a8e9aca24215ac3d83d0624:/test/synchronized.m diff --git a/test/synchronized.m b/test/synchronized.m new file mode 100644 index 0000000..128df3d --- /dev/null +++ b/test/synchronized.m @@ -0,0 +1,101 @@ +#include "test.h" + +#include +#include +#include +#include +#include +#include + +// Basic @synchronized tests. + + +#define WAIT_SEC 3 + +static id obj; +static semaphore_t go; +static semaphore_t stop; + +void *thread(void *arg __unused) +{ + int err; + + objc_registerThreadWithCollector(); + + // non-blocking sync_enter + err = objc_sync_enter(obj); + testassert(err == OBJC_SYNC_SUCCESS); + + semaphore_signal(go); + // main thread: sync_exit of object locked on some other thread + semaphore_wait(stop); + + err = objc_sync_exit(obj); + testassert(err == OBJC_SYNC_SUCCESS); + err = objc_sync_enter(obj); + testassert(err == OBJC_SYNC_SUCCESS); + + semaphore_signal(go); + // main thread: blocking sync_enter + testassert(WAIT_SEC/3*3 == WAIT_SEC); + sleep(WAIT_SEC/3); + // recursive enter while someone waits + err = objc_sync_enter(obj); + testassert(err == OBJC_SYNC_SUCCESS); + sleep(WAIT_SEC/3); + // recursive exit while someone waits + err = objc_sync_exit(obj); + testassert(err == OBJC_SYNC_SUCCESS); + sleep(WAIT_SEC/3); + // sync_exit while someone waits + err = objc_sync_exit(obj); + testassert(err == OBJC_SYNC_SUCCESS); + + return NULL; +} + +int main() +{ + pthread_t th; + int err; + struct timeval start, end; + + obj = [[NSObject alloc] init]; + + // sync_exit of never-locked object + err = objc_sync_exit(obj); + testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR); + + semaphore_create(mach_task_self(), &go, 0, 0); + semaphore_create(mach_task_self(), &stop, 0, 0); + pthread_create(&th, NULL, &thread, NULL); + semaphore_wait(go); + + // sync_exit of object locked on some other thread + err = objc_sync_exit(obj); + testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR); + + semaphore_signal(stop); + semaphore_wait(go); + + // blocking sync_enter + gettimeofday(&start, NULL); + err = objc_sync_enter(obj); + gettimeofday(&end, NULL); + testassert(err == OBJC_SYNC_SUCCESS); + // should have waited more than WAIT_SEC but less than WAIT_SEC+1 + // fixme hack: sleep(1) is ending 500 usec too early on x86_64 buildbot + testassert(end.tv_sec*1000000LL+end.tv_usec >= + start.tv_sec*1000000LL+start.tv_usec + WAIT_SEC*1000000LL + - 3*500 /*hack*/); + testassert(end.tv_sec*1000000LL+end.tv_usec < + start.tv_sec*1000000LL+start.tv_usec + (1+WAIT_SEC)*1000000LL); + + err = objc_sync_exit(obj); + testassert(err == OBJC_SYNC_SUCCESS); + + err = objc_sync_exit(obj); + testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR); + + succeed(__FILE__); +}