|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2018 [email protected] ! 4: // ! 5: ! 6: #include "config.h" ! 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.