1 /* ``Licensed under the Apache License, Version 2.0 (the "License");
2  * you may not use this file except in compliance with the License.
3  * You may obtain a copy of the License at
4  *
5  *     http://www.apache.org/licenses/LICENSE-2.0
6  *
7  * Unless required by applicable law or agreed to in writing, software
8  * distributed under the License is distributed on an "AS IS" BASIS,
9  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10  * See the License for the specific language governing permissions and
11  * limitations under the License.
12  *
13  * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
14  * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
15  * AB. All Rights Reserved.''
16  *
17  *     $Id$
18  */
19 
20 #include "erl_int_sizes_config.h"
21 
22 #include "testcase_driver.h"
23 #include "allocator_test.h"
24 #include <stdio.h>
25 
26 #if defined(__WIN32__) && SIZEOF_VOID_P == 8
27 /* Use larger threashold for win64 as block alignment
28    is 16 bytes and not 8 */
29 #define SBCT ((1024*1024))
30 #else
31 #define SBCT ((512*1024))
32 #endif
33 
34 char *
testcase_name(void)35 testcase_name(void)
36 {
37     return "bucket_mask";
38 }
39 
40 void
testcase_cleanup(TestCaseState_t * tcs)41 testcase_cleanup(TestCaseState_t *tcs)
42 {
43     if (tcs->extra) {
44 	STOP_ALC(tcs->extra);
45 	tcs->extra = NULL;
46     }
47 }
48 
49 void
testcase_run(TestCaseState_t * tcs)50 testcase_run(TestCaseState_t *tcs)
51 {
52     typedef struct linked_block {
53 	struct linked_block* next;
54     }Linked;
55     Linked* link = NULL;
56     Linked* fence_list;
57     Linked* pad_list;
58     void* tmp;
59     void **blk;
60     Ulong sz;
61     Ulong residue;
62     Ulong smbcs;
63     int i;
64     int bi;
65     int bi_tests;
66     Ulong sbct = (SBCT/1024)*1024;
67     Ulong min_blk_sz;
68     Ulong ablk_hdr_sz = ABLK_HDR_SZ;
69     char smbcs_buf[30];
70     char sbct_buf[30];
71     int no_bkts = (int) NO_OF_BKTS;
72     char *argv1[] = {"-tasgf", "-tmmbcs0", sbct_buf, NULL};
73     char *argv2[] = {"-tasgf", "-tmmbcs0", sbct_buf, NULL, NULL};
74     Allctr_t *a;
75 
76     sprintf(sbct_buf, "-tsbct%lu", sbct/1024);
77 
78     a = START_ALC("bkt_mask_1_", 0, argv1);
79     tcs->extra = (void *) a;
80     ASSERT(tcs, a);
81 
82     min_blk_sz = MIN_BLK_SZ(a);
83     smbcs = (no_bkts*sizeof(void *) + min_blk_sz) + min_blk_sz;
84     for (i = 0; i < no_bkts; i++) {
85 	sz = BKT_MIN_SZ(a, i);
86 	if (sz >= sbct)
87 	    break;
88 	smbcs += sz + min_blk_sz;
89     }
90 
91     bi_tests = i;
92     testcase_printf(tcs, "Will test %d buckets\n", bi_tests);
93 
94     STOP_ALC(a);
95     tcs->extra = NULL;
96 
97     smbcs /= 1024;
98     smbcs++;
99 
100     testcase_printf(tcs, "smbcs = %lu\n", smbcs);
101     sprintf(smbcs_buf, "-tsmbcs%lu", smbcs);
102     argv2[3] = smbcs_buf;
103 
104     a = START_ALC("bkt_mask_2_", 0, argv2);
105     tcs->extra = (void *) a;
106     ASSERT(tcs, a);
107 
108 
109     blk = (void **) ALLOC(a, no_bkts*sizeof(void *));
110 
111     ASSERT(tcs, blk);
112     fence_list = NULL;
113 
114     testcase_printf(tcs, "Allocating blocks and fences\n");
115     for (i = 0; i < bi_tests; i++) {
116 	sz = BKT_MIN_SZ(a, i);
117 	blk[i] = ALLOC(a, sz - ablk_hdr_sz);
118 	link = (Linked*) ALLOC(a, sizeof(Linked));
119 	ASSERT(tcs, blk[i] && link);
120 	link->next = fence_list;
121 	fence_list = link;
122     }
123 
124     pad_list = 0;
125     do {
126 	tmp = (void *) UMEM2BLK(link); /* last allocated */
127 	tmp = (void *) NXT_BLK((Block_t *) tmp);
128 	ASSERT(tcs, IS_LAST_BLK(tmp));
129 	sz = BLK_SZ((Block_t *) tmp);
130 	if (sz >= sbct) {
131 	    residue = sz;
132 	    sz = sbct - min_blk_sz;
133 	    residue -= sz;
134 	}
135 	else {
136 	    residue = 0;
137 	}
138 	testcase_printf(tcs, "Allocating leftover size = %lu, residue = %lu\n", sz, residue);
139 	link = (Linked*) ALLOC(a, sz - ablk_hdr_sz);
140 	ASSERT(tcs, link);
141 	link->next = pad_list;
142 	pad_list = link;
143     } while (residue);
144 
145     bi = FIND_BKT(a, 0);
146     ASSERT(tcs, bi < 0);
147 
148     for (i = 0; i < bi_tests; i++) {
149 	sz = BKT_MIN_SZ(a, i);
150 	testcase_printf(tcs, "Testing bucket %d\n", i);
151 	FREE(a, blk[i]);
152 	bi = FIND_BKT(a, i);
153 	ASSERT(tcs, bi == i);
154 	blk[i] = ALLOC(a, sz - ablk_hdr_sz);
155 	bi = FIND_BKT(a, i);
156 	ASSERT(tcs, bi != i);
157     }
158 
159     for (i = 0; i < bi_tests; i++) {
160 	FREE(a, blk[i]);
161     }
162     while (fence_list) {
163 	link = fence_list;
164 	fence_list = link->next;
165 	FREE(a, link);
166     }
167 
168     FREE(a, (void *) blk);
169 
170     bi = FIND_BKT(a, 0);
171     ASSERT(tcs, bi == no_bkts - 1);
172 
173     while (pad_list) {
174 	link = pad_list;
175 	pad_list = link->next;
176 	FREE(a, link);
177     }
178 
179     bi = FIND_BKT(a, 0);
180     ASSERT(tcs, bi < 0);
181 
182     STOP_ALC(a);
183     tcs->extra = NULL;
184 }
185 
186 ERL_NIF_INIT(bucket_mask, testcase_nif_funcs, testcase_nif_init,
187 	     NULL, NULL, NULL);
188