1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2013-2016. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21
22 #ifndef __WIN32__
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #endif
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include "testcase_driver.h"
31 #include "allocator_test.h"
32
33 #define FATAL_ASSERT(A) \
34 ((void) ((A) \
35 ? 1 \
36 : (fatal_assert_failed(#A, \
37 (char *) __FILE__, \
38 __LINE__), \
39 0)))
40
41 static void
fatal_assert_failed(char * expr,char * file,int line)42 fatal_assert_failed(char* expr, char* file, int line)
43 {
44 fflush(stdout);
45 fprintf(stderr, "%s:%d: Assertion failed: %s\n",
46 file, line, expr);
47 fflush(stderr);
48 abort();
49 }
50
51 #define TEST_NO_THREADS 10
52 #define TEST_NO_CARRIERS_PER_THREAD 100000
53 #define TEST_CARRIERS_OFFSET 5
54
55 static Allctr_t *alloc = NULL;
56
stop_allocator(void)57 static void stop_allocator(void)
58 {
59 if (alloc) {
60 STOP_ALC(alloc);
61 alloc = NULL;
62 }
63 }
64
65
66 void *thread_func(void *arg);
67
68 char *
testcase_name(void)69 testcase_name(void)
70 {
71 return "cpool";
72 }
73
74 void
testcase_cleanup(TestCaseState_t * tcs)75 testcase_cleanup(TestCaseState_t *tcs)
76 {
77 stop_allocator();
78 }
79
80 void *
thread_func(void * arg)81 thread_func(void *arg)
82 {
83 Carrier_t *crr = (Carrier_t *) arg;
84 int i;
85
86 for (i = 0; i < (TEST_NO_CARRIERS_PER_THREAD+TEST_CARRIERS_OFFSET); i++) {
87 int d;
88 if (i < TEST_NO_CARRIERS_PER_THREAD) {
89 (void) CPOOL_INSERT(alloc, crr[i]);
90 if ((i & 0x7) == 0)
91 FATAL_ASSERT(CPOOL_IS_IN_POOL(alloc, crr[i]));
92 }
93 d = i-TEST_CARRIERS_OFFSET;
94 if (d >= 0) {
95 (void) CPOOL_DELETE(alloc, crr[d]);
96 if ((d & 0x7) == 0)
97 FATAL_ASSERT(!CPOOL_IS_IN_POOL(alloc, crr[d]));
98 }
99 }
100 for (i = 0; i < TEST_NO_CARRIERS_PER_THREAD; i++)
101 FATAL_ASSERT(!CPOOL_IS_IN_POOL(alloc, crr[i]));
102 return NULL;
103 }
104
105 static struct {
106 erts_thread tid;
107 Carrier_t *crr[TEST_NO_CARRIERS_PER_THREAD];
108 } threads[TEST_NO_THREADS] = {{0}};
109
110 void
testcase_run(TestCaseState_t * tcs)111 testcase_run(TestCaseState_t *tcs)
112 {
113 int no_threads, t, c;
114 char *block, *p;
115 Ulong zcrr_sz;
116
117 if (!IS_SMP_ENABLED)
118 testcase_skipped(tcs, "No SMP support");
119
120 alloc = START_ALC("Zero carrier allocator", 1, NULL);
121
122 zcrr_sz = ZERO_CRR_SIZE;
123
124 block = p = ALLOC(alloc, zcrr_sz*TEST_NO_THREADS*TEST_NO_CARRIERS_PER_THREAD);
125
126 ASSERT(tcs, block != NULL);
127
128 for (t = 0; t < TEST_NO_THREADS; t++) {
129 for (c = 0; c < TEST_NO_CARRIERS_PER_THREAD; c++) {
130 Carrier_t *crr = (Carrier_t *) p;
131 p += zcrr_sz;
132 (void) ZERO_CRR_INIT(alloc, crr);
133 threads[t].crr[c] = crr;
134 }
135 }
136
137 no_threads = 0;
138 for (t = 0; t < TEST_NO_THREADS; t++) {
139 threads[t].tid = THR_CREATE(thread_func, (void *) threads[t].crr);
140 if (threads[t].tid) {
141 testcase_printf(tcs, "Successfully created thread %d\n", t);
142 no_threads++;
143 }
144 else {
145 testcase_printf(tcs, "Failed to create thread %d\n", t);
146 break;
147 }
148 }
149
150 for (t = 0; t < no_threads; t++)
151 THR_JOIN(threads[t].tid);
152
153 FATAL_ASSERT(CPOOL_IS_EMPTY(alloc));
154
155 FREE(alloc, block);
156
157 ASSERT(tcs, no_threads == TEST_NO_THREADS);
158 }
159
160 ERL_NIF_INIT(cpool, testcase_nif_funcs, testcase_nif_init,
161 NULL, NULL, NULL);
162