synchronized.m 2.9 KB

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