/* ``Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* The Initial Developer of the Original Code is Ericsson Utvecklings AB.
* Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
* AB. All Rights Reserved.''
*
* $Id$
*/
#include "erl_int_sizes_config.h"
#include "testcase_driver.h"
#include "allocator_test.h"
#include <stdio.h>
#if defined(__WIN32__) && SIZEOF_VOID_P == 8
/* Use larger threashold for win64 as block alignment
is 16 bytes and not 8 */
#define SBCT ((1024*1024))
#else
#define SBCT ((512*1024))
#endif
char *
testcase_name(void)
{
return "bucket_mask";
}
void
testcase_cleanup(TestCaseState_t *tcs)
{
if (tcs->extra) {
STOP_ALC(tcs->extra);
tcs->extra = NULL;
}
}
void
testcase_run(TestCaseState_t *tcs)
{
typedef struct linked_block {
struct linked_block* next;
}Linked;
Linked* link = NULL;
Linked* fence_list;
Linked* pad_list;
void* tmp;
void **blk;
Ulong sz;
Ulong residue;
Ulong smbcs;
int i;
int bi;
int bi_tests;
Ulong sbct = (SBCT/1024)*1024;
Ulong min_blk_sz;
Ulong ablk_hdr_sz = ABLK_HDR_SZ;
char smbcs_buf[30];
char sbct_buf[30];
int no_bkts = (int) NO_OF_BKTS;
char *argv1[] = {"-tasgf", "-tmmbcs0", sbct_buf, NULL};
char *argv2[] = {"-tasgf", "-tmmbcs0", sbct_buf, NULL, NULL};
Allctr_t *a;
sprintf(sbct_buf, "-tsbct%lu", sbct/1024);
a = START_ALC("bkt_mask_1_", 0, argv1);
tcs->extra = (void *) a;
ASSERT(tcs, a);
min_blk_sz = MIN_BLK_SZ(a);
smbcs = (no_bkts*sizeof(void *) + min_blk_sz) + min_blk_sz;
for (i = 0; i < no_bkts; i++) {
sz = BKT_MIN_SZ(a, i);
if (sz >= sbct)
break;
smbcs += sz + min_blk_sz;
}
bi_tests = i;
testcase_printf(tcs, "Will test %d buckets\n", bi_tests);
STOP_ALC(a);
tcs->extra = NULL;
smbcs /= 1024;
smbcs++;
testcase_printf(tcs, "smbcs = %lu\n", smbcs);
sprintf(smbcs_buf, "-tsmbcs%lu", smbcs);
argv2[3] = smbcs_buf;
a = START_ALC("bkt_mask_2_", 0, argv2);
tcs->extra = (void *) a;
ASSERT(tcs, a);
blk = (void **) ALLOC(a, no_bkts*sizeof(void *));
ASSERT(tcs, blk);
fence_list = NULL;
testcase_printf(tcs, "Allocating blocks and fences\n");
for (i = 0; i < bi_tests; i++) {
sz = BKT_MIN_SZ(a, i);
blk[i] = ALLOC(a, sz - ablk_hdr_sz);
link = (Linked*) ALLOC(a, sizeof(Linked));
ASSERT(tcs, blk[i] && link);
link->next = fence_list;
fence_list = link;
}
pad_list = 0;
do {
tmp = (void *) UMEM2BLK(link); /* last allocated */
tmp = (void *) NXT_BLK((Block_t *) tmp);
ASSERT(tcs, IS_LAST_BLK(tmp));
sz = BLK_SZ((Block_t *) tmp);
if (sz >= sbct) {
residue = sz;
sz = sbct - min_blk_sz;
residue -= sz;
}
else {
residue = 0;
}
testcase_printf(tcs, "Allocating leftover size = %lu, residue = %lu\n", sz, residue);
link = (Linked*) ALLOC(a, sz - ablk_hdr_sz);
ASSERT(tcs, link);
link->next = pad_list;
pad_list = link;
} while (residue);
bi = FIND_BKT(a, 0);
ASSERT(tcs, bi < 0);
for (i = 0; i < bi_tests; i++) {
sz = BKT_MIN_SZ(a, i);
testcase_printf(tcs, "Testing bucket %d\n", i);
FREE(a, blk[i]);
bi = FIND_BKT(a, i);
ASSERT(tcs, bi == i);
blk[i] = ALLOC(a, sz - ablk_hdr_sz);
bi = FIND_BKT(a, i);
ASSERT(tcs, bi != i);
}
for (i = 0; i < bi_tests; i++) {
FREE(a, blk[i]);
}
while (fence_list) {
link = fence_list;
fence_list = link->next;
FREE(a, link);
}
FREE(a, (void *) blk);
bi = FIND_BKT(a, 0);
ASSERT(tcs, bi == no_bkts - 1);
while (pad_list) {
link = pad_list;
pad_list = link->next;
FREE(a, link);
}
bi = FIND_BKT(a, 0);
ASSERT(tcs, bi < 0);
STOP_ALC(a);
tcs->extra = NULL;
}
ERL_NIF_INIT(bucket_mask, testcase_nif_funcs, testcase_nif_init,
NULL, NULL, NULL);