1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2014 Los Alamos National Security, LLC. All rights
4 * reserved.
5 * $COPYRIGHT$
6 *
7 * Additional copyrights may follow
8 *
9 * $HEADER$
10 */
11
12 #include "opal_config.h"
13 #include <assert.h>
14
15 #include "support.h"
16 #include "opal/class/opal_lifo.h"
17 #include "opal/runtime/opal.h"
18 #include "opal/constants.h"
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stddef.h>
23
24 #include <sys/time.h>
25
26 #define OPAL_LIFO_TEST_THREAD_COUNT 8
27 #define ITERATIONS 1000000
28 #define ITEM_COUNT 100
29
30 #if !defined(timersub)
31 #define timersub(a, b, r) \
32 do { \
33 (r)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
34 if ((a)->tv_usec < (b)->tv_usec) { \
35 (r)->tv_sec--; \
36 (a)->tv_usec += 1000000; \
37 } \
38 (r)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
39 } while (0)
40 #endif
41
thread_test(void * arg)42 static void *thread_test (void *arg) {
43 opal_lifo_t *lifo = (opal_lifo_t *) arg;
44 opal_list_item_t *item;
45 struct timeval start, stop, total;
46 double timing;
47
48 gettimeofday (&start, NULL);
49 for (int i = 0 ; i < ITERATIONS ; ++i) {
50 item = opal_lifo_pop_atomic (lifo);
51 if (NULL != item) {
52 (void) opal_lifo_push_atomic (lifo, item);
53 }
54 }
55 gettimeofday (&stop, NULL);
56
57 timersub(&stop, &start, &total);
58
59 timing = ((double) total.tv_sec + (double) total.tv_usec * 1e-6) / (double) ITERATIONS;
60
61 printf ("Atomics thread finished. Time: %d s %d us %d nsec/poppush\n", (int) total.tv_sec,
62 (int)total.tv_usec, (int)(timing / 1e-9));
63
64 return NULL;
65 }
66
check_lifo_consistency(opal_lifo_t * lifo,int expected_count)67 static bool check_lifo_consistency (opal_lifo_t *lifo, int expected_count)
68 {
69 opal_list_item_t *item;
70 int count;
71
72 for (count = 0, item = lifo->opal_lifo_head.data.item ; item != &lifo->opal_lifo_ghost ;
73 item = opal_list_get_next(item), count++);
74
75 return count == expected_count;
76 }
77
main(int argc,char * argv[])78 int main (int argc, char *argv[]) {
79 pthread_t threads[OPAL_LIFO_TEST_THREAD_COUNT];
80 opal_list_item_t *item, *prev, *item2;
81 struct timeval start, stop, total;
82 opal_lifo_t lifo;
83 bool success;
84 double timing;
85 int rc;
86
87 rc = opal_init_util (&argc, &argv);
88 test_verify_int(OPAL_SUCCESS, rc);
89 if (OPAL_SUCCESS != rc) {
90 test_finalize();
91 exit (1);
92 }
93
94 test_init("opal_lifo_t");
95
96 OBJ_CONSTRUCT(&lifo, opal_lifo_t);
97
98 item = OBJ_NEW(opal_list_item_t);
99 prev = opal_lifo_push_st (&lifo, item);
100 if (&lifo.opal_lifo_ghost == prev) {
101 test_success ();
102 } else {
103 test_failure (" opal_lifo_push_st on empty lifo");
104 }
105
106 item2 = opal_lifo_pop_st (&lifo);
107 if (item == item2) {
108 test_success ();
109 } else {
110 test_failure (" opal_lifo_pop_st");
111 }
112
113 OBJ_RELEASE(item);
114
115 for (int i = 0 ; i < ITEM_COUNT ; ++i) {
116 item = OBJ_NEW(opal_list_item_t);
117 item->item_free = 0;
118 opal_lifo_push_st (&lifo, item);
119 }
120
121 if (check_lifo_consistency (&lifo, ITEM_COUNT)) {
122 test_success ();
123 } else {
124 test_failure (" opal_lifo_push_st(multiple items)");
125 }
126
127 gettimeofday (&start, NULL);
128 for (int i = 0 ; i < ITERATIONS ; ++i) {
129 item = opal_lifo_pop_st (&lifo);
130 (void) opal_lifo_push_st (&lifo, item);
131 }
132 gettimeofday (&stop, NULL);
133
134 timersub(&stop, &start, &total);
135
136 timing = ((double) total.tv_sec + (double) total.tv_usec * 1e-6) / (double) ITERATIONS;
137
138 if (check_lifo_consistency (&lifo, ITEM_COUNT)) {
139 test_success ();
140 } else {
141 test_failure (" lifo push/pop");
142 }
143
144 printf ("Single thread test. Time: %d s %d us %d nsec/poppush\n", (int) total.tv_sec,
145 (int)total.tv_usec, (int)(timing / 1e-9));
146
147 thread_test (&lifo);
148
149 if (check_lifo_consistency (&lifo, ITEM_COUNT)) {
150 test_success ();
151 } else {
152 test_failure (" lifo push/pop single-threaded with atomics");
153 }
154
155 gettimeofday (&start, NULL);
156 for (int i = 0 ; i < OPAL_LIFO_TEST_THREAD_COUNT ; ++i) {
157 pthread_create (threads + i, NULL, thread_test, &lifo);
158 }
159
160 for (int i = 0 ; i < OPAL_LIFO_TEST_THREAD_COUNT ; ++i) {
161 void *ret;
162
163 pthread_join (threads[i], &ret);
164 }
165 gettimeofday (&stop, NULL);
166
167 timersub(&stop, &start, &total);
168
169 timing = ((double) total.tv_sec + (double) total.tv_usec * 1e-6) / (double) (ITERATIONS * OPAL_LIFO_TEST_THREAD_COUNT);
170
171 if (check_lifo_consistency (&lifo, ITEM_COUNT)) {
172 test_success ();
173 } else {
174 test_failure (" lifo push/pop multi-threaded with atomics");
175 }
176
177 printf ("All threads finished. Thread count: %d Time: %d s %d us %d nsec/poppush\n",
178 OPAL_LIFO_TEST_THREAD_COUNT, (int) total.tv_sec, (int)total.tv_usec, (int)(timing / 1e-9));
179
180 success = true;
181 for (int i = 0 ; i < ITEM_COUNT ; ++i) {
182 item = opal_lifo_pop_st (&lifo);
183 if (NULL == item) {
184 success = false;
185 break;
186 }
187 OBJ_RELEASE(item);
188 }
189
190 if (success) {
191 test_success ();
192 } else {
193 test_failure (" list pop all items");
194 }
195
196 OBJ_DESTRUCT(&lifo);
197
198 opal_finalize_util ();
199
200 return test_finalize ();
201 }
202