Annotation of nono/lib/testatomic.cpp, revision 1.1.1.4

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);
1.1.1.4 ! root      144:        //
1.1       root      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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.