1 /*
2  * Copyright 2011-2015 Samy Al Bahra.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <ck_stack.h>
28 #include <ck_spinlock.h>
29 #include <inttypes.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 
33 #include "../../common.h"
34 
35 #ifndef ENTRIES
36 #define ENTRIES 4096
37 #endif
38 
39 #ifndef STEPS
40 #define STEPS 40000
41 #endif
42 
43 /*
44  * Note the redundant post-increment of r. This is to silence
45  * some irrelevant GCC warnings.
46  */
47 
48 static ck_stack_t stack CK_CC_CACHELINE;
49 
50 int
main(void)51 main(void)
52 {
53 	ck_stack_entry_t entry[ENTRIES];
54 	ck_spinlock_fas_t mutex = CK_SPINLOCK_FAS_INITIALIZER;
55 	volatile ck_stack_entry_t * volatile r;
56 	uint64_t s, e, a;
57 	unsigned int i;
58 	unsigned int j;
59 
60 	a = 0;
61 	for (i = 0; i < STEPS; i++) {
62 		ck_stack_init(&stack);
63 
64 		s = rdtsc();
65 		for (j = 0; j < ENTRIES; j++) {
66 			ck_spinlock_fas_lock(&mutex);
67 			ck_stack_push_spnc(&stack, entry + j);
68 			ck_spinlock_fas_unlock(&mutex);
69 		}
70 		e = rdtsc();
71 
72 		a += e - s;
73 	}
74 	printf("     spinlock_push: %16" PRIu64 "\n", a / STEPS / ENTRIES);
75 
76 	a = 0;
77 	for (i = 0; i < STEPS; i++) {
78 		ck_stack_init(&stack);
79 
80 		for (j = 0; j < ENTRIES; j++)
81 			ck_stack_push_spnc(&stack, entry + j);
82 
83 		s = rdtsc();
84 		for (j = 0; j < ENTRIES; j++) {
85 			ck_spinlock_fas_lock(&mutex);
86 			r = ck_stack_pop_npsc(&stack);
87 			ck_spinlock_fas_unlock(&mutex);
88 		}
89 		e = rdtsc();
90 		a += e - s;
91 	}
92 	printf("      spinlock_pop: %16" PRIu64 "\n", a / STEPS / ENTRIES);
93 	r++;
94 
95 #ifdef CK_F_STACK_PUSH_UPMC
96 	a = 0;
97 	for (i = 0; i < STEPS; i++) {
98 		ck_stack_init(&stack);
99 
100 		s = rdtsc();
101 		for (j = 0; j < ENTRIES; j++)
102 			ck_stack_push_upmc(&stack, entry + j);
103 		e = rdtsc();
104 
105 		a += e - s;
106 	}
107 	printf("ck_stack_push_upmc: %16" PRIu64 "\n", a / STEPS / ENTRIES);
108 #endif /* CK_F_STACK_PUSH_UPMC */
109 
110 #ifdef CK_F_STACK_PUSH_MPMC
111 	a = 0;
112 	for (i = 0; i < STEPS; i++) {
113 		ck_stack_init(&stack);
114 
115 		s = rdtsc();
116 		for (j = 0; j < ENTRIES; j++)
117 			ck_stack_push_mpmc(&stack, entry + j);
118 		e = rdtsc();
119 
120 		a += e - s;
121 	}
122 	printf("ck_stack_push_mpmc: %16" PRIu64 "\n", a / STEPS / ENTRIES);
123 #endif /* CK_F_STACK_PUSH_MPMC */
124 
125 #ifdef CK_F_STACK_PUSH_MPNC
126 	a = 0;
127 	for (i = 0; i < STEPS; i++) {
128 		ck_stack_init(&stack);
129 
130 		s = rdtsc();
131 		for (j = 0; j < ENTRIES; j++)
132 			ck_stack_push_mpnc(&stack, entry + j);
133 		e = rdtsc();
134 
135 		a += e - s;
136 	}
137 	printf("ck_stack_push_mpnc: %16" PRIu64 "\n", a / STEPS / ENTRIES);
138 #endif /* CK_F_STACK_PUSH_MPNC */
139 
140 #if defined(CK_F_STACK_PUSH_UPMC) && defined(CK_F_STACK_POP_UPMC)
141 	a = 0;
142 	for (i = 0; i < STEPS; i++) {
143 		ck_stack_init(&stack);
144 
145 		for (j = 0; j < ENTRIES; j++)
146 			ck_stack_push_upmc(&stack, entry + j);
147 
148 		s = rdtsc();
149 		for (j = 0; j < ENTRIES; j++)
150 			r = ck_stack_pop_upmc(&stack);
151 		e = rdtsc();
152 		a += e - s;
153 	}
154 	printf(" ck_stack_pop_upmc: %16" PRIu64 "\n", a / STEPS / (sizeof(entry) / sizeof(*entry)));
155 #endif /* CK_F_STACK_PUSH_UPMC && CK_F_STACK_POP_UPMC */
156 
157 #if defined(CK_F_STACK_POP_MPMC) && defined(CK_F_STACK_PUSH_MPMC)
158 	a = 0;
159 	for (i = 0; i < STEPS; i++) {
160 		ck_stack_init(&stack);
161 
162 		for (j = 0; j < ENTRIES; j++)
163 			ck_stack_push_mpmc(&stack, entry + j);
164 
165 		s = rdtsc();
166 		for (j = 0; j < ENTRIES; j++)
167 			r = ck_stack_pop_mpmc(&stack);
168 		e = rdtsc();
169 		a += e - s;
170 	}
171 	printf(" ck_stack_pop_mpmc: %16" PRIu64 "\n", a / STEPS / (sizeof(entry) / sizeof(*entry)));
172 	r++;
173 #endif
174 
175 	return 0;
176 }
177