Home | History | Annotate | Line # | Download | only in benchmark
      1 // SPDX-FileCopyrightText: 2009 Mathieu Desnoyers <mathieu.desnoyers (at) efficios.com>
      2 //
      3 // SPDX-License-Identifier: GPL-2.0-or-later
      4 
      5 /*
      6  * Userspace RCU library - test program
      7  */
      8 
      9 #include <stdio.h>
     10 #include <pthread.h>
     11 #include <stdlib.h>
     12 #include <string.h>
     13 #include <sys/types.h>
     14 #include <sys/wait.h>
     15 #include <unistd.h>
     16 #include <stdio.h>
     17 #include <pthread.h>
     18 #include <errno.h>
     19 
     20 #include <urcu/arch.h>
     21 #include <urcu/assert.h>
     22 
     23 #include "thread-id.h"
     24 
     25 #include <urcu.h>
     26 
     27 struct test_array {
     28 	int a;
     29 };
     30 
     31 /*
     32  * static rwlock initializer is broken on Cygwin. Use runtime
     33  * initialization.
     34  */
     35 pthread_rwlock_t lock;
     36 
     37 static struct test_array test_array = { 8 };
     38 
     39 #define OUTER_READ_LOOP	200U
     40 #define INNER_READ_LOOP	100000U
     41 #define READ_LOOP ((unsigned long long)OUTER_READ_LOOP * INNER_READ_LOOP)
     42 
     43 #define OUTER_WRITE_LOOP 10U
     44 #define INNER_WRITE_LOOP 200U
     45 #define WRITE_LOOP ((unsigned long long)OUTER_WRITE_LOOP * INNER_WRITE_LOOP)
     46 
     47 static int num_read;
     48 static int num_write;
     49 
     50 #define NR_READ num_read
     51 #define NR_WRITE num_write
     52 
     53 static caa_cycles_t __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *reader_time;
     54 static caa_cycles_t __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *writer_time;
     55 
     56 static
     57 void *thr_reader(void *arg)
     58 {
     59 	unsigned int i, j;
     60 	int ret;
     61 	caa_cycles_t time1, time2;
     62 
     63 	printf("thread_begin %s, tid %lu\n",
     64 		"reader", urcu_get_thread_id());
     65 	sleep(2);
     66 
     67 	time1 = caa_get_cycles();
     68 	for (i = 0; i < OUTER_READ_LOOP; i++) {
     69 		for (j = 0; j < INNER_READ_LOOP; j++) {
     70 			ret = pthread_rwlock_rdlock(&lock);
     71 			if (ret) {
     72 				fprintf(stderr, "reader pthread_rwlock_rdlock: %s\n", strerror(ret));
     73 				abort();
     74 			}
     75 
     76 			urcu_posix_assert(test_array.a == 8);
     77 
     78 			ret = pthread_rwlock_unlock(&lock);
     79 			if (ret) {
     80 				fprintf(stderr, "reader pthread_rwlock_unlock: %s\n", strerror(ret));
     81 				abort();
     82 			}
     83 		}
     84 	}
     85 	time2 = caa_get_cycles();
     86 
     87 	reader_time[(unsigned long)arg] = time2 - time1;
     88 
     89 	sleep(2);
     90 	printf("thread_end %s, tid %lu\n",
     91 		"reader", urcu_get_thread_id());
     92 	return ((void*)1);
     93 
     94 }
     95 
     96 static
     97 void *thr_writer(void *arg)
     98 {
     99 	unsigned int i, j;
    100 	int ret;
    101 	caa_cycles_t time1, time2;
    102 
    103 	printf("thread_begin %s, tid %lu\n",
    104 		"writer", urcu_get_thread_id());
    105 	sleep(2);
    106 
    107 	for (i = 0; i < OUTER_WRITE_LOOP; i++) {
    108 		for (j = 0; j < INNER_WRITE_LOOP; j++) {
    109 			time1 = caa_get_cycles();
    110 			ret = pthread_rwlock_wrlock(&lock);
    111 			if (ret) {
    112 				fprintf(stderr, "writer pthread_rwlock_wrlock: %s\n", strerror(ret));
    113 				abort();
    114 			}
    115 
    116 			test_array.a = 8;
    117 
    118 			ret = pthread_rwlock_unlock(&lock);
    119 			if (ret) {
    120 				fprintf(stderr, "writer pthread_rwlock_unlock: %s\n", strerror(ret));
    121 				abort();
    122 			}
    123 
    124 			time2 = caa_get_cycles();
    125 			writer_time[(unsigned long)arg] += time2 - time1;
    126 			usleep(1);
    127 		}
    128 	}
    129 
    130 	printf("thread_end %s, tid %lu\n",
    131 		"writer", urcu_get_thread_id());
    132 	return ((void*)2);
    133 }
    134 
    135 int main(int argc, char **argv)
    136 {
    137 	int err;
    138 	pthread_t *tid_reader, *tid_writer;
    139 	void *tret;
    140 	int i;
    141 	caa_cycles_t tot_rtime = 0;
    142 	caa_cycles_t tot_wtime = 0;
    143 
    144 	if (argc < 2) {
    145 		printf("Usage : %s nr_readers nr_writers\n", argv[0]);
    146 		exit(-1);
    147 	}
    148 	num_read = atoi(argv[1]);
    149 	num_write = atoi(argv[2]);
    150 
    151 	err = pthread_rwlock_init(&lock, NULL);
    152 	if (err != 0) {
    153 		fprintf(stderr, "pthread_rwlock_init: (%d) %s\n", err, strerror(err));
    154 		exit(1);
    155 	}
    156 
    157 	reader_time = calloc(num_read, sizeof(*reader_time));
    158 	writer_time = calloc(num_write, sizeof(*writer_time));
    159 	tid_reader = calloc(num_read, sizeof(*tid_reader));
    160 	tid_writer = calloc(num_write, sizeof(*tid_writer));
    161 
    162 	printf("thread %-6s, tid %lu\n",
    163 		"main", urcu_get_thread_id());
    164 
    165 	for (i = 0; i < NR_READ; i++) {
    166 		err = pthread_create(&tid_reader[i], NULL, thr_reader,
    167 				     (void *)(long)i);
    168 		if (err != 0)
    169 			exit(1);
    170 	}
    171 	for (i = 0; i < NR_WRITE; i++) {
    172 		err = pthread_create(&tid_writer[i], NULL, thr_writer,
    173 				     (void *)(long)i);
    174 		if (err != 0)
    175 			exit(1);
    176 	}
    177 
    178 	sleep(10);
    179 
    180 	for (i = 0; i < NR_READ; i++) {
    181 		err = pthread_join(tid_reader[i], &tret);
    182 		if (err != 0)
    183 			exit(1);
    184 		tot_rtime += reader_time[i];
    185 	}
    186 	for (i = 0; i < NR_WRITE; i++) {
    187 		err = pthread_join(tid_writer[i], &tret);
    188 		if (err != 0)
    189 			exit(1);
    190 		tot_wtime += writer_time[i];
    191 	}
    192 	printf("Time per read : %g cycles\n",
    193 	       (double)tot_rtime / ((double)NR_READ * (double)READ_LOOP));
    194 	printf("Time per write : %g cycles\n",
    195 	       (double)tot_wtime / ((double)NR_WRITE * (double)WRITE_LOOP));
    196 
    197 	err = pthread_rwlock_destroy(&lock);
    198 	if (err != 0) {
    199 		fprintf(stderr, "pthread_rwlock_destroy: (%d) %s\n", err, strerror(err));
    200 		exit(1);
    201 	}
    202 	free(reader_time);
    203 	free(writer_time);
    204 	free(tid_reader);
    205 	free(tid_writer);
    206 
    207 	return 0;
    208 }
    209