weakrace.m 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // TEST_CONFIG MEM=mrc
  2. #include "test.h"
  3. #include <objc/NSObject.h>
  4. static semaphore_t go1;
  5. static semaphore_t go2;
  6. static semaphore_t done;
  7. #define VARCOUNT 100000
  8. static id obj;
  9. static id vars[VARCOUNT];
  10. void *destroyer(void *arg __unused)
  11. {
  12. while (1) {
  13. semaphore_wait(go1);
  14. for (int i = 0; i < VARCOUNT; i++) {
  15. objc_destroyWeak(&vars[i]);
  16. }
  17. semaphore_signal(done);
  18. }
  19. }
  20. void *deallocator(void *arg __unused)
  21. {
  22. while (1) {
  23. semaphore_wait(go2);
  24. [obj release];
  25. semaphore_signal(done);
  26. }
  27. }
  28. void cycle(void)
  29. {
  30. // rdar://12896779 objc_destroyWeak() versus weak clear in dealloc
  31. // Clean up from previous cycle - objc_destroyWeak() doesn't set var to nil
  32. for (int i = 0; i < VARCOUNT; i++) {
  33. vars[i] = nil;
  34. }
  35. obj = [NSObject new];
  36. for (int i = 0; i < VARCOUNT; i++) {
  37. objc_storeWeak(&vars[i], obj);
  38. }
  39. // let destroyer start before deallocator runs
  40. semaphore_signal(go1);
  41. sched_yield();
  42. semaphore_signal(go2);
  43. semaphore_wait(done);
  44. semaphore_wait(done);
  45. }
  46. int main()
  47. {
  48. semaphore_create(mach_task_self(), &go1, 0, 0);
  49. semaphore_create(mach_task_self(), &go2, 0, 0);
  50. semaphore_create(mach_task_self(), &done, 0, 0);
  51. pthread_t th[2];
  52. pthread_create(&th[1], NULL, deallocator, NULL);
  53. pthread_create(&th[1], NULL, destroyer, NULL);
  54. for (int i = 0; i < 100; i++) {
  55. cycle();
  56. }
  57. succeed(__FILE__);
  58. }