1 /** @file
2
3 A brief file description
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 #include <unistd.h>
25 #include <cstdlib>
26 #include <ctime>
27 #include <poll.h>
28 #include <pthread.h>
29
30 #include "tscore/ink_atomic.h"
31 #include "tscore/ink_queue.h"
32 #include "tscore/ink_thread.h"
33
34 #ifndef LONG_ATOMICLIST_TEST
35
36 #define MAX_ALIST_TEST 10
37 #define MAX_ALIST_ARRAY 100000
38 InkAtomicList al[MAX_ALIST_TEST];
39 void *al_test[MAX_ALIST_TEST][MAX_ALIST_ARRAY];
40 int al_done = 0;
41
42 void *
testalist(void * ame)43 testalist(void *ame)
44 {
45 int me = static_cast<int>((uintptr_t)ame);
46 int j, k;
47 for (k = 0; k < MAX_ALIST_ARRAY; k++) {
48 ink_atomiclist_push(&al[k % MAX_ALIST_TEST], &al_test[me][k]);
49 }
50 void *x;
51 for (j = 0; j < 1000000; j++) {
52 if ((x = ink_atomiclist_pop(&al[me]))) {
53 ink_atomiclist_push(&al[rand() % MAX_ALIST_TEST], x);
54 }
55 }
56 ink_atomic_increment(&al_done, 1);
57 return nullptr;
58 }
59 #endif // !LONG_ATOMICLIST_TEST
60
61 #ifdef LONG_ATOMICLIST_TEST
62 /************************************************************************/
63 #define MAX_ATOMIC_LISTS (4 * 1024)
64 #define MAX_ITEMS_PER_LIST (1 * 1024)
65 #define MAX_TEST_THREADS 64
66 static InkAtomicList alists[MAX_ATOMIC_LISTS];
67 struct listItem *items[MAX_ATOMIC_LISTS * MAX_ITEMS_PER_LIST];
68
69 struct listItem {
70 int data1;
71 int data2;
72 void *link;
73 int data3;
74 int data4;
75 int check;
76 };
77
78 void
init_data()79 init_data()
80 {
81 int j;
82 int ali;
83 struct listItem l;
84 struct listItem *plistItem;
85
86 for (ali = 0; ali < MAX_ATOMIC_LISTS; ali++)
87 ink_atomiclist_init(&alists[ali], "alist", ((char *)&l.link - (char *)&l));
88
89 for (ali = 0; ali < MAX_ATOMIC_LISTS; ali++) {
90 for (j = 0; j < MAX_ITEMS_PER_LIST; j++) {
91 plistItem = (struct listItem *)malloc(sizeof(struct listItem));
92 items[ali + j] = plistItem;
93 plistItem->data1 = ali + j;
94 plistItem->data2 = ali + rand();
95 plistItem->link = 0;
96 plistItem->data3 = j + rand();
97 plistItem->data4 = ali + j + rand();
98 plistItem->check = (plistItem->data1 ^ plistItem->data2 ^ plistItem->data3 ^ plistItem->data4);
99 ink_atomiclist_push(&alists[ali], plistItem);
100 }
101 }
102 }
103
104 void
cycle_data(void * d)105 cycle_data(void *d)
106 {
107 InkAtomicList *l;
108 struct listItem *pli;
109 struct listItem *pli_next;
110 int iterations;
111 int me;
112
113 me = (int)d;
114 iterations = 0;
115
116 while (1) {
117 l = &alists[(me + rand()) % MAX_ATOMIC_LISTS];
118
119 pli = (struct listItem *)ink_atomiclist_popall(l);
120 if (!pli)
121 continue;
122
123 // Place listItems into random queues
124 while (pli) {
125 ink_assert((pli->data1 ^ pli->data2 ^ pli->data3 ^ pli->data4) == pli->check);
126 pli_next = (struct listItem *)pli->link;
127 pli->link = 0;
128 ink_atomiclist_push(&alists[(me + rand()) % MAX_ATOMIC_LISTS], (void *)pli);
129 pli = pli_next;
130 }
131 iterations++;
132 poll(0, 0, 10); // 10 msec delay
133 if ((iterations % 100) == 0)
134 printf("%d ", me);
135 }
136 }
137
138 /************************************************************************/
139 #endif // LONG_ATOMICLIST_TEST
140
141 int
main(int,const char * [])142 main(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */[])
143 {
144 #ifndef LONG_ATOMICLIST_TEST
145 int32_t m = 1, n = 100;
146 // int64 lm = 1LL, ln = 100LL;
147 const char *m2 = "hello";
148 char *n2;
149
150 printf("sizeof(int32_t)==%d sizeof(void *)==%d\n", static_cast<int>(sizeof(int32_t)), static_cast<int>(sizeof(void *)));
151
152 printf("CAS: %d == 1 then 2\n", m);
153 n = ink_atomic_cas(&m, 1, 2);
154 printf("changed to: %d, result=%s\n", m, n ? "true" : "false");
155
156 printf("CAS: %d == 1 then 3\n", m);
157 n = ink_atomic_cas(&m, 1, 3);
158 printf("changed to: %d, result=%s\n", m, n ? "true" : "false");
159
160 printf("CAS pointer: '%s' == 'hello' then 'new'\n", m2);
161 n = ink_atomic_cas(&m2, "hello", "new");
162 printf("changed to: %s, result=%s\n", m2, n ? (char *)"true" : (char *)"false");
163
164 printf("CAS pointer: '%s' == 'hello' then 'new2'\n", m2);
165 n = ink_atomic_cas(&m2, m2, "new2");
166 printf("changed to: %s, result=%s\n", m2, n ? "true" : "false");
167
168 n = 100;
169 printf("Atomic Inc of %d\n", n);
170 m = ink_atomic_increment(static_cast<int *>(&n), 1);
171 printf("changed to: %d, result=%d\n", n, m);
172
173 printf("Atomic Fetch-and-Add 2 to pointer to '%s'\n", m2);
174 n2 = static_cast<char *>(ink_atomic_increment((void **)&m2, (void *)2));
175 printf("changed to: %s, result=%s\n", m2, n2);
176
177 printf("Testing atomic lists\n");
178 {
179 int ali;
180 srand(time(nullptr));
181 printf("sizeof(al_test) = %d\n", static_cast<int>(sizeof(al_test)));
182 memset(&al_test[0][0], 0, sizeof(al_test));
183 for (ali = 0; ali < MAX_ALIST_TEST; ali++) {
184 ink_atomiclist_init(&al[ali], "foo", 0);
185 }
186 for (ali = 0; ali < MAX_ALIST_TEST; ali++) {
187 ink_thread tid;
188 pthread_attr_t attr;
189
190 pthread_attr_init(&attr);
191 #if !defined(freebsd)
192 pthread_attr_setstacksize(&attr, 1024 * 1024);
193 #endif
194 ink_assert(pthread_create(&tid, &attr, testalist, (void *)((intptr_t)ali)) == 0);
195 }
196 while (al_done != MAX_ALIST_TEST) {
197 sleep(1);
198 }
199 }
200 #endif // !LONG_ATOMICLIST_TEST
201
202 #ifdef LONG_ATOMICLIST_TEST
203 printf("Testing atomic lists (long version)\n");
204 {
205 int id;
206
207 init_data();
208 for (id = 0; id < MAX_TEST_THREADS; id++) {
209 ink_assert(thr_create(NULL, 0, cycle_data, (void *)id, THR_NEW_LWP, NULL) == 0);
210 }
211 }
212 while (1) {
213 poll(0, 0, 10); // 10 msec delay
214 }
215 #endif // LONG_ATOMICLIST_TEST
216
217 return 0;
218 }
219