1
/* Copyright (C) 2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include "DynArr256.hpp"
38
struct DA256CL m_lines[17];
43
struct DA256CL m_header[2];
44
struct DA256Node m_nodes[30];
47
#define require(x) require_impl(x, __LINE__)
48
//#define DA256_USE_PX
49
//#define DA256_USE_PREFETCH
50
#define DA256_EXTRA_SAFE
55
#include <valgrind/callgrind.h>
57
#define CALLGRIND_TOGGLE_COLLECT()
59
Uint32 allocatedpages = 0;
60
Uint32 allocatednodes = 0;
61
Uint32 releasednodes = 0;
66
require_impl(bool x, int line)
70
ndbout_c("LINE: %d", line);
75
DynArr256Pool::DynArr256Pool()
83
DynArr256Pool::init(Uint32 type_id, const Pool_context & pc)
87
m_memroot = (DA256Page*)m_ctx.get_memroot();
90
static const Uint32 g_max_sizes[5] = { 0, 256, 65536, 16777216, ~0 };
93
* sz = 0 = 1 - 0 level
94
* sz = 1 = 256^1 - 1 level
95
* sz = 2 = 256^2 - 2 level
96
* sz = 3 = 256^3 - 3 level
97
* sz = 4 = 256^4 - 4 level
100
DynArr256::get(Uint32 pos) const
102
Uint32 sz = m_head.m_sz;
103
Uint32 ptrI = m_head.m_ptr_i;
104
DA256Page * memroot = m_pool.m_memroot;
105
Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
107
if (unlikely(pos >= g_max_sizes[sz]))
113
Uint32 px[4] = { (pos >> 24) & 255,
119
Uint32* retVal = &m_head.m_ptr_i;
122
if (unlikely(ptrI == RNIL))
129
Uint32 shr = sz << 3;
130
Uint32 p0 = (pos >> shr) & 255;
132
Uint32 page_no = ptrI >> DA256_BITS;
133
Uint32 page_idx = ptrI & DA256_MASK;
134
DA256Page * page = memroot + page_no;
136
Uint32 *magic_ptr, p;
139
Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
140
Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
143
retVal = (ptr + 1 + p0 + line);
144
magic_ptr =(ptr + (p0 & ~15));
148
Uint32 b = (page_idx + 1) >> 4;
149
Uint32 * ptr = (Uint32*)(page->m_header+b);
151
p = page_idx - (b << 4) + b;
152
retVal = (ptr + 1 + p);
157
Uint32 magic = *magic_ptr;
159
if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
170
DynArr256::set(Uint32 pos)
172
Uint32 sz = m_head.m_sz;
173
Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
174
DA256Page * memroot = m_pool.m_memroot;
176
if (unlikely(pos >= g_max_sizes[sz]))
178
if (unlikely(!expand(pos)))
186
Uint32 px[4] = { (pos >> 24) & 255,
192
Uint32 ptrI = m_head.m_ptr_i;
193
Uint32 *retVal = &m_head.m_ptr_i;
199
Uint32 shr = sz << 3;
200
Uint32 p0 = (pos >> shr) & 255;
204
if (unlikely((ptrI = m_pool.seize()) == RNIL))
211
Uint32 page_no = ptrI >> DA256_BITS;
212
Uint32 page_idx = ptrI & DA256_MASK;
213
DA256Page * page = memroot + page_no;
215
Uint32 *magic_ptr, p;
218
Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
219
Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
222
magic_ptr = (ptr + (p0 & ~15));
223
retVal = (ptr + 1 + p0 + line);
227
Uint32 b = (page_idx + 1) >> 4;
228
Uint32 * ptr = (Uint32*)(page->m_header+b);
230
p = page_idx - (b << 4) + b;
232
retVal = (ptr + 1 + p);
236
Uint32 magic = *magic_ptr;
238
if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
252
initpage(DA256Page* p, Uint32 page_no, Uint32 type_id)
255
#ifdef DA256_USE_PREFETCH
256
#if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
257
#ifdef DA256_EXTRA_SAFE
258
for (i = 0; i<(30 * 17 + 2); i++)
260
__builtin_prefetch (p->m_header + i, 1);
264
__builtin_prefetch (p->m_header + 0, 1);
265
__builtin_prefetch (p->m_header + 1, 1);
266
for (i = 0; i<30; i++)
268
__builtin_prefetch (p->m_nodes + i, 1);
275
for (i = 0; i<2; i++)
277
cl = p->m_header + i;
278
cl->m_magic = (~type_id << 16);
283
for (i = 0; i<30; i++)
285
free = (DA256Free*)(p->m_nodes+i);
286
free->m_magic = type_id;
287
free->m_next_free = (page_no << DA256_BITS) + (i + 1);
288
#ifdef DA256_EXTRA_SAFE
289
DA256Node* node = p->m_nodes+i;
290
for (j = 0; j<17; j++)
291
node->m_lines[j].m_magic = type_id;
295
free = (DA256Free*)(p->m_nodes+29);
296
free->m_next_free = RNIL;
300
DynArr256::expand(Uint32 pos)
305
Uint32 sz = m_head.m_sz;
307
for (; pos >= g_max_sizes[sz]; sz++);
309
if (m_head.m_sz == 0)
316
for (; pos >= g_max_sizes[sz]; sz++)
318
Uint32 ptrI = m_pool.seize();
319
if (unlikely(ptrI == RNIL))
324
alloc[idx] = m_head.m_ptr_i;
326
for (Uint32 i = 0; i<idx; i++)
328
m_head.m_ptr_i = alloc[i];
329
Uint32 * ptr = get(0);
330
* ptr = alloc[i + 1];
334
m_head.m_ptr_i = alloc[0];
339
for (i = 0; i<idx; i++)
340
m_pool.release(alloc[i]);
345
DynArr256::init(ReleaseIterator &iter)
349
iter.m_ptr_i[0] = RNIL;
350
iter.m_ptr_i[1] = m_head.m_ptr_i;
351
iter.m_ptr_i[2] = RNIL;
352
iter.m_ptr_i[3] = RNIL;
353
iter.m_ptr_i[4] = RNIL;
357
* Iter is in next pos
364
DynArr256::release(ReleaseIterator &iter, Uint32 * retptr)
366
Uint32 sz = iter.m_sz;
367
Uint32 ptrI = iter.m_ptr_i[sz];
368
Uint32 page_no = ptrI >> DA256_BITS;
369
Uint32 page_idx = ptrI & DA256_MASK;
370
Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
371
DA256Page * memroot = m_pool.m_memroot;
372
DA256Page * page = memroot + page_no;
376
Uint32 p0 = iter.m_pos & 255;
379
Uint32 *retVal, *magic_ptr, p;
382
Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
383
Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
386
retVal = (ptr + 1 + p0 + line);
387
magic_ptr =(ptr + (p0 & ~15));
391
Uint32 b = (page_idx + 1) >> 4;
392
Uint32 * ptr = (Uint32*)(page->m_header+b);
394
p = page_idx - (b << 4) + b;
395
retVal = (ptr + 1 + p);
399
Uint32 magic = *magic_ptr;
400
Uint32 val = *retVal;
401
if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
404
if (sz == m_head.m_sz)
413
iter.m_pos &= ~(Uint32)255;
421
m_pool.release(ptrI);
427
else if (val != RNIL)
430
iter.m_ptr_i[iter.m_sz] = val;
431
iter.m_pos = (p0 << 8);
438
m_pool.release(ptrI);
444
new (&m_head) Head();
455
seizenode(DA256Page* page, Uint32 idx, Uint32 type_id)
458
Uint32 b = (idx + 1) >> 4;
459
Uint32 p = idx - (b << 4) + b;
461
DA256Node * ptr = (DA256Node*)(page->m_nodes + idx);
463
#ifdef DA256_USE_PREFETCH
464
#if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
465
__builtin_prefetch (page->m_header + b, 1);
466
for (i = 0; i<17; i++)
468
__builtin_prefetch (ptr->m_lines+i, 1);
473
#ifdef DA256_EXTRA_SAFE
474
Uint32 check = type_id;
476
type_id = ((~type_id) << 16) | 0xFFFF;
478
#ifdef DA256_EXTRA_SAFE
479
if (unlikely(((page->m_header + b)->m_magic & (1 << p)) != 0))
485
(page->m_header + b)->m_magic |= (1 << p);
486
(page->m_header + b)->m_data[p] = RNIL;
487
for (i = 0; i<17; i++)
489
DA256CL * line = ptr->m_lines + i;
490
#ifdef DA256_EXTRA_SAFE
491
if (unlikely(line->m_magic != check))
496
line->m_magic = type_id;
497
for (Uint32 j = 0; j<15; j++)
498
line->m_data[j] = RNIL;
509
releasenode(DA256Page* page, Uint32 idx, Uint32 type_id)
512
Uint32 b = (idx + 1) >> 4;
513
Uint32 p = idx - (b << 4) + b;
515
DA256Node * ptr = (DA256Node*)(page->m_nodes + idx);
517
#ifdef DA256_USE_PREFETCH
518
#if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
519
__builtin_prefetch (page->m_header + b, 1);
520
for (i = 0; i<17; i++)
522
__builtin_prefetch (ptr->m_lines+i, 1);
527
#ifdef DA256_EXTRA_SAFE
528
Uint32 check = ((~type_id) << 16) | 0xFFFF;
531
#ifdef DA256_EXTRA_SAFE
532
if (unlikely((((page->m_header + b)->m_magic & (1 << p)) == 0)))
538
(page->m_header + b)->m_magic ^= (1 << p);
539
for (i = 0; i<17; i++)
541
DA256CL * line = ptr->m_lines + i;
542
#ifdef DA256_EXTRA_SAFE
543
if (unlikely(line->m_magic != check))
548
line->m_magic = type_id;
559
DynArr256Pool::seize()
561
Uint32 ff = m_first_free;
562
Uint32 type_id = m_type_id;
565
DA256Page * memroot = m_memroot;
569
if (likely((page = (DA256Page*)m_ctx.alloc_page(type_id, &page_no)) != 0))
571
initpage(page, page_no, type_id);
580
ff = (page_no << DA256_BITS);
584
page = memroot + (ff >> DA256_BITS);
587
Uint32 idx = ff & DA256_MASK;
588
DA256Free * ptr = (DA256Free*)(page->m_nodes + idx);
589
if (likely(ptr->m_magic == type_id))
591
Uint32 next = ptr->m_next_free;
592
if (likely(seizenode(page, idx, type_id)))
605
DynArr256Pool::release(Uint32 ptrI)
607
Uint32 ff = m_first_free;
608
Uint32 type_id = m_type_id;
610
Uint32 page_no = ptrI >> DA256_BITS;
611
Uint32 page_idx = ptrI & DA256_MASK;
612
DA256Page * memroot = m_memroot;
613
DA256Page * page = memroot + page_no;
615
DA256Free * ptr = (DA256Free*)(page->m_nodes + page_idx);
616
if (likely(releasenode(page, page_idx, type_id)))
618
ptr->m_next_free = ff;
619
ptr->m_magic = type_id;
629
#include "ndbd_malloc_impl.hpp"
630
#include "SimulatedBlock.hpp"
634
Block_context ctx(cfg, mm);
635
struct BB : public SimulatedBlock
637
BB(int no, Block_context& ctx) : SimulatedBlock(no, ctx) {}
640
BB block(DBACC, ctx);
644
simple(DynArr256 & arr, int argc, char* argv[])
646
ndbout_c("argc: %d", argc);
647
for (Uint32 i = 1; i<(Uint32)argc; i++)
649
Uint32 * s = arr.set(atoi(argv[i]));
652
for (Uint32 j = 1; j<i; j++)
654
if (atoi(argv[i]) == atoi(argv[j]))
664
Uint32 * g = arr.get(atoi(argv[i]));
665
Uint32 v = g ? *g : ~0;
666
ndbout_c("p: %p %p %d", s, g, v);
672
basic(DynArr256& arr, int argc, char* argv[])
677
Uint32 save[2*MAXLEN];
678
for (Uint32 i = 0; i<MAXLEN; i++)
680
int op = (rand() % 100) > 50;
687
Uint32 item = (rand() % len) << 1;
688
Uint32 idx = save[item];
689
Uint32 val = save[item+1];
690
//ndbout_c("get(%d)", idx);
691
Uint32 *p = arr.get(idx);
697
Uint32 item = len << 1;
698
Uint32 idx = i; //rand() & 0xFFFFF; // & 0xFFFFF; //rand(); //(65536*i) / 10000;
701
for(Uint32 j = 0; j < item; j += 2)
710
//ndbout_c("set(%d, %x)", idx, val);
711
Uint32 *p = arr.set(idx);
713
if (item == (len << 1))
720
assert(* p == save[item+1]);
734
gettimeofday(&tv, 0);
735
unsigned long long ret = tv.tv_sec;
743
read(DynArr256& arr, int argc, char ** argv)
746
Uint64 mbytes = 16*1024;
747
Uint32 seed = time(0);
748
Uint32 seq = 0, seqmask = 0;
750
for (Uint32 i = 2; i<argc; i++)
752
if (strncmp(argv[i], "--mbytes=", sizeof("--mbytes=")-1) == 0)
754
mbytes = atoi(argv[i]+sizeof("--mbytes=")-1);
755
if (argv[i][strlen(argv[i])-1] == 'g' ||
756
argv[i][strlen(argv[i])-1] == 'G')
759
else if (strncmp(argv[i], "--cnt=", sizeof("--cnt=")-1) == 0)
761
cnt = atoi(argv[i]+sizeof("--cnt=")-1);
763
else if (strncmp(argv[i], "--seq", sizeof("--seq")-1) == 0)
772
Uint32 maxidx = (1024*mbytes+31) / 32;
773
Uint32 nodes = (maxidx+255) / 256;
774
Uint32 pages = (nodes + 29)/ 30;
775
ndbout_c("%lldmb data -> %d entries (%dkb)",
776
mbytes, maxidx, 32*pages);
778
for (Uint32 i = 0; i<maxidx; i++)
780
Uint32 *ptr = arr.set(i);
790
seqmask = ~(Uint32)0;
793
ndbout_c("Timing %d %s reads (seed: %u)", cnt,
794
seq ? "sequential" : "random", seed);
796
for (Uint32 i = 0; i<10; i++)
798
Uint32 sum0 = 0, sum1 = 0;
799
Uint64 start = micro();
800
for (Uint32 i = 0; i<cnt; i++)
802
Uint32 idx = ((rand() & (~seqmask)) + ((i + seq) & seqmask)) % maxidx;
803
Uint32 *ptr = arr.get(idx);
807
start = micro() - start;
808
float uspg = start; uspg /= cnt;
809
ndbout_c("Elapsed %lldus diff: %d -> %f us/get", start, sum0 - sum1, uspg);
815
write(DynArr256& arr, int argc, char ** argv)
817
Uint32 seq = 0, seqmask = 0;
819
Uint64 mbytes = 16*1024;
820
Uint32 seed = time(0);
822
for (Uint32 i = 2; i<argc; i++)
824
if (strncmp(argv[i], "--mbytes=", sizeof("--mbytes=")-1) == 0)
826
mbytes = atoi(argv[i]+sizeof("--mbytes=")-1);
827
if (argv[i][strlen(argv[i])-1] == 'g' ||
828
argv[i][strlen(argv[i])-1] == 'G')
831
else if (strncmp(argv[i], "--cnt=", sizeof("--cnt=")-1) == 0)
833
cnt = atoi(argv[i]+sizeof("--cnt=")-1);
835
else if (strncmp(argv[i], "--seq", sizeof("--seq")-1) == 0)
844
Uint32 maxidx = (1024*mbytes+31) / 32;
845
Uint32 nodes = (maxidx+255) / 256;
846
Uint32 pages = (nodes + 29)/ 30;
847
ndbout_c("%lldmb data -> %d entries (%dkb)",
848
mbytes, maxidx, 32*pages);
855
seqmask = ~(Uint32)0;
858
ndbout_c("Timing %d %s writes (seed: %u)", cnt,
859
seq ? "sequential" : "random", seed);
860
for (Uint32 i = 0; i<10; i++)
862
Uint64 start = micro();
863
for (Uint32 i = 0; i<cnt; i++)
865
Uint32 idx = ((rand() & (~seqmask)) + ((i + seq) & seqmask)) % maxidx;
866
Uint32 *ptr = arr.set(idx);
869
start = micro() - start;
870
float uspg = start; uspg /= cnt;
871
ndbout_c("Elapsed %lldus -> %f us/set", start, uspg);
872
DynArr256::ReleaseIterator iter;
875
while(arr.release(iter, &val));
880
main(int argc, char** argv)
884
for (Uint32 i = 0; i<30; i++)
886
Uint32 b = (i + 1) >> 4;
887
Uint32 p = i - (b << 4) + b;
888
printf("[ %d %d %d ]\n", i, b, p);
899
rl.m_resource_id = 0;
900
mm.set_resource_limit(rl);
907
pool.init(0x2001, pc);
909
DynArr256::Head head;
910
DynArr256 arr(pool, head);
912
if (strcmp(argv[1], "--simple") == 0)
913
simple(arr, argc, argv);
914
else if (strcmp(argv[1], "--basic") == 0)
915
basic(arr, argc, argv);
916
else if (strcmp(argv[1], "--read") == 0)
917
read(arr, argc, argv);
918
else if (strcmp(argv[1], "--write") == 0)
919
write(arr, argc, argv);
921
DynArr256::ReleaseIterator iter;
924
while (arr.release(iter, &val)) cnt++;
926
ndbout_c("allocatedpages: %d allocatednodes: %d releasednodes: %d"
935
printf("sizeof(DA256Page): %d\n", sizeof(DA256Page));
939
for (Uint32 i = 0; i<10000; i++)
941
Uint32 arg = rand() & 255;
943
Uint32 idx = arg & 256;
950
Uint32 b = (base + 1) >> 4;
951
Uint32 p = base - (b << 4) + b;
952
Uint32 magic = page.m_header[b].m_magic;
953
Uint32 retVal = page.m_header[b].m_data[p];
955
require(magic & (1 << p));
960
// 4 bit extra offset per idx
961
Uint32 line = idx / 15;
962
Uint32 off = idx % 15;
965
Uint32 pos = 1 + idx + line;
966
Uint32 magic = pos & ~15;
968
Uint32 * ptr = (Uint32*)&page.m_nodes[base];
969
assert((ptr + pos) == &page.m_nodes[base].m_lines[line].m_data[off]);
970
assert((ptr + magic) == &page.m_nodes[base].m_lines[line].m_magic);
977
Uint32 g_currentStartPhase;
979
NdbNodeBitmask g_nowait_nodes;
981
void childExit(int code, Uint32 currentStartPhase)
986
void childAbort(int code, Uint32 currentStartPhase)
991
void childReportError(int error)
997
UpgradeStartup::sendCmAppChg(Ndbcntr& cntr, Signal* signal, Uint32 startLevel){
1001
UpgradeStartup::execCM_APPCHG(SimulatedBlock & block, Signal* signal){
1005
UpgradeStartup::sendCntrMasterReq(Ndbcntr& cntr, Signal* signal, Uint32 n){
1009
UpgradeStartup::execCNTR_MASTER_REPLY(SimulatedBlock & block, Signal* signal){
1012
#include <SimBlockList.hpp>
1015
SimBlockList::unload()