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