]> git.saurik.com Git - apple/objc4.git/blobdiff - test/synchronized-grid.m
objc4-437.tar.gz
[apple/objc4.git] / test / synchronized-grid.m
diff --git a/test/synchronized-grid.m b/test/synchronized-grid.m
new file mode 100644 (file)
index 0000000..3988306
--- /dev/null
@@ -0,0 +1,104 @@
+#include "test.h"
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <objc/runtime.h>
+#include <objc/objc-sync.h>
+#include <Foundation/Foundation.h>
+
+// synchronized stress test
+// 2-D grid of counters and locks. 
+// Each thread increments all counters some number of times.
+// To increment:
+// * thread picks a target [row][col]
+// * thread locks all locks [row][0] to [row][col], possibly recursively
+// * thread increments counter [row][col]
+// * thread unlocks all of the locks
+
+// 64 / 4 / 3 / 1024*8 test takes about 20s on 4x2.6GHz Mac Pro
+#define THREADS 64
+#define ROWS 4
+#define COLS 3
+#define COUNT 1024*8
+
+static id locks[ROWS][COLS];
+static int counts[ROWS][COLS];
+
+
+static void *threadfn(void *arg)
+{
+    int n, d;
+    int depth = 1 + (int)(intptr_t)arg % 4;
+
+    objc_registerThreadWithCollector();
+
+    for (n = 0; n < COUNT; n++) {
+        int rrr = rand() % ROWS;
+        int ccc = rand() % COLS;
+        int rr, cc;
+        for (rr = 0; rr < ROWS; rr++) {
+            int r = (rrr+rr) % ROWS;
+            for (cc = 0; cc < COLS; cc++) {
+                int c = (ccc+cc) % COLS;
+                int l;
+
+                // Lock [r][0..c]
+                // ... in that order to prevent deadlock
+                for (l = 0; l <= c; l++) {
+                    for (d = 0; d < depth; d++) {
+                        int err = objc_sync_enter(locks[r][l]);
+                        testassert(err == OBJC_SYNC_SUCCESS);
+                    }
+                }
+                
+                // Increment count [r][c]
+                counts[r][c]++;
+                
+                // Unlock [r][0..c]
+                // ... in that order to increase contention
+                for (l = 0; l <= c; l++) {
+                    for (d = 0; d < depth; d++) {
+                        int err = objc_sync_exit(locks[r][l]);
+                        testassert(err == OBJC_SYNC_SUCCESS);
+                    }
+                }
+            }
+        }
+    }
+    
+    return NULL;
+}
+
+int main()
+{
+    pthread_t threads[THREADS];
+    int r, c, t;
+
+    for (r = 0; r < ROWS; r++) {
+        for (c = 0; c < COLS; c++) {
+            locks[r][c] = [[NSObject alloc] init];
+        }
+    }
+
+    // Start the threads
+    for (t = 0; t < THREADS; t++) {
+        pthread_create(&threads[t], NULL, &threadfn, (void*)(intptr_t)t);
+    }
+
+    // Wait for threads to finish
+    for (t = 0; t < THREADS; t++) {
+        pthread_join(threads[t], NULL);
+    }
+    
+    // Verify locks: all should be available
+    // Verify counts: all should be THREADS*COUNT
+    for (r = 0; r < ROWS; r++) {
+        for (c = 0; c < COLS; c++) {
+            int err = objc_sync_enter(locks[r][c]);
+            testassert(err == OBJC_SYNC_SUCCESS);
+            testassert(counts[r][c] == THREADS*COUNT);
+        }
+    }
+
+    succeed(__FILE__);
+}