1// TEST_CONFIG
2
3#include "test.h"
4
5#include <stdlib.h>
6#include <pthread.h>
7#include <objc/runtime.h>
8#include <objc/objc-sync.h>
9#include <Foundation/NSObject.h>
10#include <System/pthread_machdep.h>
11
12// synchronized stress test
13// Single locked counter incremented by many threads.
14
15#if defined(__arm__)
16#define THREADS 16
17#define COUNT 1024*24
18#else
19// 64 / 1024*24 test takes about 20s on 4x2.6GHz Mac Pro
20#define THREADS 64
21#define COUNT 1024*24
22#endif
23
24static id lock;
25static int count;
26
27static void *threadfn(void *arg)
28{
29    int n, d;
30    int depth = 1 + (int)(intptr_t)arg % 4;
31
32    objc_registerThreadWithCollector();
33
34    for (n = 0; n < COUNT; n++) {
35        // Lock
36        for (d = 0; d < depth; d++) {
37            int err = objc_sync_enter(lock);
38            testassert(err == OBJC_SYNC_SUCCESS);
39        }
40        
41        // Increment
42        count++;
43        
44        // Unlock
45        for (d = 0; d < depth; d++) {
46            int err = objc_sync_exit(lock);
47            testassert(err == OBJC_SYNC_SUCCESS);
48        }
49    }
50
51    // Verify lack of objc pthread data (should have used sync fast cache)
52#ifdef __PTK_FRAMEWORK_OBJC_KEY5
53    testassert(! pthread_getspecific(__PTK_FRAMEWORK_OBJC_KEY5));
54#endif
55
56    return NULL;
57}
58
59int main()
60{
61    pthread_t threads[THREADS];
62    int t;
63    int err;
64
65    lock = [[NSObject alloc] init];
66
67    // Verify objc pthread data on this thread (from +initialize)
68    // Worker threads shouldn't have any because of sync fast cache.
69#ifdef __PTK_FRAMEWORK_OBJC_KEY5
70    testassert(pthread_getspecific(__PTK_FRAMEWORK_OBJC_KEY5));
71#endif
72
73    // Start the threads
74    for (t = 0; t < THREADS; t++) {
75        pthread_create(&threads[t], NULL, &threadfn, (void*)(intptr_t)t);
76    }
77
78    // Wait for threads to finish
79    for (t = 0; t < THREADS; t++) {
80        pthread_join(threads[t], NULL);
81    }
82    
83    // Verify lock: should be available
84    // Verify count: should be THREADS*COUNT
85    err = objc_sync_enter(lock);
86    testassert(err == OBJC_SYNC_SUCCESS);
87    testassert(count == THREADS*COUNT);
88
89    succeed(__FILE__);
90}
91