|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2018 [email protected]
4: //
5:
1.1.1.2 ! root 6: #include "config-nono.h"
1.1 root 7: #include <atomic>
8: #include <cstdio>
9: #include <inttypes.h>
10: #include <pthread.h>
11: #include <sys/time.h>
12: #if defined(__NetBSD__)
13: #include <atomic.h>
14: #endif
15:
16: volatile uint64_t shared;
17: volatile uint32_t terminate;
18: uint64_t result;
19: const uint64_t loopcnt = 10000000;
20:
21: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
22:
23: std::atomic<uint64_t> shared5(0);
24: std::atomic<uint32_t> terminate5(0);
25:
26: // test1: なにもしない
27: void
28: test1_init()
29: {
30: }
31:
32: void *
33: test1_prod(void *arg)
34: {
35: for (uint64_t i = 0; i < loopcnt; i++) {
36: shared++;
37: }
38: terminate = 1;
39: return NULL;
40: }
41:
42: void *
43: test1_cons(void *arg)
44: {
45: do {
46: result += shared;
47: shared = 0;
48: } while (terminate == 0);
49: return NULL;
50: }
51:
52: // test2: pthread_mutex
53: void
54: test2_init()
55: {
56: }
57:
58: void *
59: test2_prod(void *arg)
60: {
61: for (uint64_t i = 0; i < loopcnt; i++) {
62: pthread_mutex_lock(&mutex);
63: shared++;
64: pthread_mutex_unlock(&mutex);
65: }
66: terminate = 1;
67: return NULL;
68: }
69:
70: void *
71: test2_cons(void *arg)
72: {
73: uint32_t t;
74: do {
75: pthread_mutex_lock(&mutex);
76: result += shared;
77: shared = 0;
78: t = terminate;
79: pthread_mutex_unlock(&mutex);
80: } while (t == 0);
81: result += shared;
82: return NULL;
83: }
84:
85: #if defined(__NetBSD__)
86: // test3: atomic.h
87: void
88: test3_init()
89: {
90: }
91:
92: void *
93: test3_prod(void *arg)
94: {
95: for (uint64_t i = 0; i < loopcnt; i++) {
96: atomic_add_64(&shared, 1);
97: }
98: terminate = 1;
99: return NULL;
100: }
101:
102: void *
103: test3_cons(void *arg)
104: {
105: do {
106: result += atomic_swap_64(&shared, 0);
107: } while (terminate == 0);
108: // 見落とした分
109: result += atomic_swap_64(&shared, 0);
110: return NULL;
111: }
112: #endif
113:
114: #if defined(__clang_version__)
115: // test4: clang's builtin
116:
117: #else
118:
119: // test4: GCC's builtin atomic
120: void
121: test4_init()
122: {
123: }
124:
125: #define ATOMIC_TYPE __ATOMIC_SEQ_CST
126:
127: void *
128: test4_prod(void *arg)
129: {
130: for (uint64_t i = 0; i < loopcnt; i++) {
131: __atomic_add_fetch(&shared, 1, ATOMIC_TYPE);
132: }
133: terminate = 1;
134: return NULL;
135: }
136:
137: void *
138: test4_cons(void *arg)
139: {
140: do {
141: result += __atomic_exchange_8(&shared, 0, ATOMIC_TYPE);
142: } while (terminate == 0);
143: //
144: result += __atomic_exchange_8(&shared, 0, ATOMIC_TYPE);
145: return NULL;
146: }
147: #endif // __GNUC__
148:
149: // test5: std::atomic
150: void
151: test5_init()
152: {
153: }
154:
155: void *
156: test5_prod(void *arg)
157: {
158: for (uint64_t i = 0; i < loopcnt; i++) {
159: shared5.fetch_add(1);
160: }
161: terminate = 1;
162: return NULL;
163: }
164:
165: void *
166: test5_cons(void *arg)
167: {
168: do {
169: result += shared5.exchange(0);
170: } while (terminate == 0);
171: //
172: result += shared5.exchange(0);
173: return NULL;
174: }
175:
176: // メインルーチン
177: int
178: test(const char *name,
179: void (*init)(), void *(*prod)(void *), void *(*cons)(void *))
180: {
181: pthread_t t1;
182: pthread_t t2;
183: struct timeval start, end, tv;
184:
185: printf("%-20s: ", name); fflush(stdout);
186: result = 0;
187: shared = 0;
188: terminate = false;
189: init();
190:
191: gettimeofday(&start, NULL);
192: pthread_create(&t1, NULL, prod, NULL);
193: pthread_create(&t2, NULL, cons, NULL);
194: pthread_join(t1, NULL);
195: pthread_join(t2, NULL);
196: gettimeofday(&end, NULL);
197:
198: timersub(&end, &start, &tv);
199: printf("time=%d.%06d, ", (int)tv.tv_sec, (int)tv.tv_usec);
200: printf("result=%" PRIu64 "\n", result);
201: return 0;
202: }
203:
204: int
205: main(int ac, char *av[])
206: {
207: printf("compiled by ");
208: #if defined(__clang_version__)
209: printf("clang %s", __clang_version__);
210: #elif defined(__GNUC__) && defined(__VERSION__)
211: printf("gcc %s", __VERSION__);
212: #else
213: printf("unknown compiler");
214: #endif
215: printf("\n");
216:
217: test("test1(no atomics)", test1_init, test1_prod, test1_cons);
218: #if defined(__NetBSD__)
219: test("test3(atomic.h)", test3_init, test3_prod, test3_cons);
220: #endif
221: #if defined(__clang_version__)
222: #else
223: test("test4(gcc builtin)", test4_init, test4_prod, test4_cons);
224: #endif
225: test("test5(std::atomic)", test5_init, test5_prod, test5_cons);
226: test("test2(pthread_mutex)",test2_init, test2_prod, test2_cons);
227: return 0;
228: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.