File:  [Isaki's NoNo m68k/m88k emulator] / nono / lib / testatomic.cpp
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:04:49 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v010, v009, HEAD
nono 0.1.5

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

#include "config-nono.h"
#include <atomic>
#include <cstdio>
#include <inttypes.h>
#include <pthread.h>
#include <sys/time.h>
#if defined(__NetBSD__)
#include <atomic.h>
#endif

volatile uint64_t shared;
volatile uint32_t terminate;
uint64_t result;
const uint64_t loopcnt = 10000000;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

std::atomic<uint64_t> shared5(0);
std::atomic<uint32_t> terminate5(0);

// test1: なにもしない
void
test1_init()
{
}

void *
test1_prod(void *arg)
{
	for (uint64_t i = 0; i < loopcnt; i++) {
		shared++;
	}
	terminate = 1;
	return NULL;
}

void *
test1_cons(void *arg)
{
	do {
		result += shared;
		shared = 0;
	} while (terminate == 0);
	return NULL;
}

// test2: pthread_mutex
void
test2_init()
{
}

void *
test2_prod(void *arg)
{
	for (uint64_t i = 0; i < loopcnt; i++) {
		pthread_mutex_lock(&mutex);
		shared++;
		pthread_mutex_unlock(&mutex);
	}
	terminate = 1;
	return NULL;
}

void *
test2_cons(void *arg)
{
	uint32_t t;
	do {
		pthread_mutex_lock(&mutex);
		result += shared;
		shared = 0;
		t = terminate;
		pthread_mutex_unlock(&mutex);
	} while (t == 0);
	result += shared;
	return NULL;
}

#if defined(__NetBSD__)
// test3: atomic.h
void
test3_init()
{
}

void *
test3_prod(void *arg)
{
	for (uint64_t i = 0; i < loopcnt; i++) {
		atomic_add_64(&shared, 1);
	}
	terminate = 1;
	return NULL;
}

void *
test3_cons(void *arg)
{
	do {
		result += atomic_swap_64(&shared, 0);
	} while (terminate == 0);
	// 見落とした分
	result += atomic_swap_64(&shared, 0);
	return NULL;
}
#endif

#if defined(__clang_version__)
// test4: clang's builtin

#else

// test4: GCC's builtin atomic
void
test4_init()
{
}

#define ATOMIC_TYPE __ATOMIC_SEQ_CST

void *
test4_prod(void *arg)
{
	for (uint64_t i = 0; i < loopcnt; i++) {
		__atomic_add_fetch(&shared, 1, ATOMIC_TYPE);
	}
	terminate = 1;
	return NULL;
}

void *
test4_cons(void *arg)
{
	do {
		result += __atomic_exchange_8(&shared, 0, ATOMIC_TYPE);
	} while (terminate == 0);
	//
	result += __atomic_exchange_8(&shared, 0, ATOMIC_TYPE);
	return NULL;
}
#endif // __GNUC__

// test5: std::atomic
void
test5_init()
{
}

void *
test5_prod(void *arg)
{
	for (uint64_t i = 0; i < loopcnt; i++) {
		shared5.fetch_add(1);
	}
	terminate = 1;
	return NULL;
}

void *
test5_cons(void *arg)
{
	do {
		result += shared5.exchange(0);
	} while (terminate == 0);
	//
	result += shared5.exchange(0);
	return NULL;
}

// メインルーチン
int
test(const char *name,
	void (*init)(), void *(*prod)(void *), void *(*cons)(void *))
{
	pthread_t t1;
	pthread_t t2;
	struct timeval start, end, tv;

	printf("%-20s: ", name); fflush(stdout);
	result = 0;
	shared = 0;
	terminate = false;
	init();

	gettimeofday(&start, NULL);
	pthread_create(&t1, NULL, prod, NULL);
	pthread_create(&t2, NULL, cons, NULL);
	pthread_join(t1, NULL);
	pthread_join(t2, NULL);
	gettimeofday(&end, NULL);

	timersub(&end, &start, &tv);
	printf("time=%d.%06d, ", (int)tv.tv_sec, (int)tv.tv_usec);
	printf("result=%" PRIu64 "\n", result);
	return 0;
}

int
main(int ac, char *av[])
{
	printf("compiled by ");
#if defined(__clang_version__)
	printf("clang %s", __clang_version__);
#elif defined(__GNUC__) && defined(__VERSION__)
	printf("gcc %s", __VERSION__);
#else
	printf("unknown compiler");
#endif
	printf("\n");

	test("test1(no atomics)",	test1_init, test1_prod, test1_cons);
#if defined(__NetBSD__)
	test("test3(atomic.h)",		test3_init, test3_prod, test3_cons);
#endif
#if defined(__clang_version__)
#else
	test("test4(gcc builtin)",	test4_init, test4_prod, test4_cons);
#endif
	test("test5(std::atomic)",	test5_init, test5_prod, test5_cons);
	test("test2(pthread_mutex)",test2_init, test2_prod, test2_cons);
	return 0;
}

unix.superglobalmegacorp.com

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