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