123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- // TEST_CONFIG
- #include "test.h"
- #include <Foundation/NSObject.h>
- #include <mach/mach.h>
- #include <pthread.h>
- #include <sys/time.h>
- #include <objc/runtime.h>
- #include <objc/objc-sync.h>
- // 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;
- BOOL locked;
- // non-blocking sync_enter
- err = objc_sync_enter(obj);
- testassert(err == OBJC_SYNC_SUCCESS);
- // recursive try_sync_enter
- locked = objc_sync_try_enter(obj);
- testassert(locked);
- err = objc_sync_exit(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;
- BOOL locked;
- 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);
- // contended try_sync_enter
- locked = objc_sync_try_enter(obj);
- testassert(!locked);
- // 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
- // (rdar://6456975)
- 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__);
- }
|