synchronized-grid.m 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // TEST_CONFIG
  2. #include "test.h"
  3. #include <stdlib.h>
  4. #include <pthread.h>
  5. #include <objc/runtime.h>
  6. #include <objc/objc-sync.h>
  7. #include <Foundation/NSObject.h>
  8. // synchronized stress test
  9. // 2-D grid of counters and locks.
  10. // Each thread increments all counters some number of times.
  11. // To increment:
  12. // * thread picks a target [row][col]
  13. // * thread locks all locks [row][0] to [row][col], possibly recursively
  14. // * thread increments counter [row][col]
  15. // * thread unlocks all of the locks
  16. #if defined(__arm__)
  17. // 16 / 4 / 3 / 1024*8 test takes about 30s on 2nd gen iPod touch
  18. #define THREADS 16
  19. #define ROWS 4
  20. #define COLS 3
  21. #define COUNT 1024*8
  22. #else
  23. // 64 / 4 / 3 / 1024*8 test takes about 20s on 4x2.6GHz Mac Pro
  24. #define THREADS 64
  25. #define ROWS 4
  26. #define COLS 3
  27. #define COUNT 1024*8
  28. #endif
  29. static id locks[ROWS][COLS];
  30. static int counts[ROWS][COLS];
  31. static void *threadfn(void *arg)
  32. {
  33. int n, d;
  34. int depth = 1 + (int)(intptr_t)arg % 4;
  35. for (n = 0; n < COUNT; n++) {
  36. int rrr = rand() % ROWS;
  37. int ccc = rand() % COLS;
  38. int rr, cc;
  39. for (rr = 0; rr < ROWS; rr++) {
  40. int r = (rrr+rr) % ROWS;
  41. for (cc = 0; cc < COLS; cc++) {
  42. int c = (ccc+cc) % COLS;
  43. int l;
  44. // Lock [r][0..c]
  45. // ... in that order to prevent deadlock
  46. for (l = 0; l <= c; l++) {
  47. for (d = 0; d < depth; d++) {
  48. int err = objc_sync_enter(locks[r][l]);
  49. testassert(err == OBJC_SYNC_SUCCESS);
  50. }
  51. }
  52. // Increment count [r][c]
  53. counts[r][c]++;
  54. // Unlock [r][0..c]
  55. // ... in that order to increase contention
  56. for (l = 0; l <= c; l++) {
  57. for (d = 0; d < depth; d++) {
  58. int err = objc_sync_exit(locks[r][l]);
  59. testassert(err == OBJC_SYNC_SUCCESS);
  60. }
  61. }
  62. }
  63. }
  64. }
  65. return NULL;
  66. }
  67. int main()
  68. {
  69. pthread_t threads[THREADS];
  70. int r, c, t;
  71. for (r = 0; r < ROWS; r++) {
  72. for (c = 0; c < COLS; c++) {
  73. locks[r][c] = [[NSObject alloc] init];
  74. }
  75. }
  76. // Start the threads
  77. for (t = 0; t < THREADS; t++) {
  78. pthread_create(&threads[t], NULL, &threadfn, (void*)(intptr_t)t);
  79. }
  80. // Wait for threads to finish
  81. for (t = 0; t < THREADS; t++) {
  82. pthread_join(threads[t], NULL);
  83. }
  84. // Verify locks: all should be available
  85. // Verify counts: all should be THREADS*COUNT
  86. for (r = 0; r < ROWS; r++) {
  87. for (c = 0; c < COLS; c++) {
  88. int err = objc_sync_enter(locks[r][c]);
  89. testassert(err == OBJC_SYNC_SUCCESS);
  90. testassert(counts[r][c] == THREADS*COUNT);
  91. }
  92. }
  93. succeed(__FILE__);
  94. }