~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/include/mem0mem.ic

  • Committer: Brian Aker
  • Date: 2009-07-11 19:23:04 UTC
  • mfrom: (1089.1.14 merge)
  • Revision ID: brian@gaz-20090711192304-ootijyl5yf9jq9kd
Merge Brian

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/************************************************************************
2
 
The memory management
3
 
 
4
 
(c) 1994, 1995 Innobase Oy
5
 
 
6
 
Created 6/8/1994 Heikki Tuuri
7
 
*************************************************************************/
8
 
 
9
 
#include "mem0dbg.ic"
10
 
 
11
 
#include "mem0pool.h"
12
 
 
13
 
/*******************************************************************
14
 
Creates a memory heap block where data can be allocated. */
15
 
 
16
 
mem_block_t*
17
 
mem_heap_create_block(
18
 
/*==================*/
19
 
                                /* out, own: memory heap block, NULL if
20
 
                                did not succeed (only possible for
21
 
                                MEM_HEAP_BTR_SEARCH type heaps) */
22
 
        mem_heap_t*     heap,   /* in: memory heap or NULL if first block
23
 
                                should be created */
24
 
        ulint           n,      /* in: number of bytes needed for user data, or
25
 
                                if init_block is not NULL, its size in bytes */
26
 
        void*           init_block, /* in: init block in fast create,
27
 
                                type must be MEM_HEAP_DYNAMIC */
28
 
        ulint           type,   /* in: type of heap: MEM_HEAP_DYNAMIC or
29
 
                                MEM_HEAP_BUFFER */
30
 
        const char*     file_name,/* in: file name where created */
31
 
        ulint           line);  /* in: line where created */
32
 
/**********************************************************************
33
 
Frees a block from a memory heap. */
34
 
 
35
 
void
36
 
mem_heap_block_free(
37
 
/*================*/
38
 
        mem_heap_t*     heap,   /* in: heap */
39
 
        mem_block_t*    block); /* in: block to free */
40
 
/**********************************************************************
41
 
Frees the free_block field from a memory heap. */
42
 
 
43
 
void
44
 
mem_heap_free_block_free(
45
 
/*=====================*/
46
 
        mem_heap_t*     heap);  /* in: heap */
47
 
/*******************************************************************
48
 
Adds a new block to a memory heap. */
49
 
 
50
 
mem_block_t*
51
 
mem_heap_add_block(
52
 
/*===============*/
53
 
                                /* out: created block, NULL if did not
54
 
                                succeed (only possible for
55
 
                                MEM_HEAP_BTR_SEARCH type heaps)*/
56
 
        mem_heap_t*     heap,   /* in: memory heap */
57
 
        ulint           n);     /* in: number of bytes user needs */
58
 
 
59
 
UNIV_INLINE
60
 
void
61
 
mem_block_set_len(mem_block_t* block, ulint len)
62
 
{
63
 
        ut_ad(len > 0);
64
 
 
65
 
        block->len = len;
66
 
}
67
 
 
68
 
UNIV_INLINE
69
 
ulint
70
 
mem_block_get_len(mem_block_t* block)
71
 
{
72
 
        return(block->len);
73
 
}
74
 
 
75
 
UNIV_INLINE
76
 
void
77
 
mem_block_set_type(mem_block_t* block, ulint type)
78
 
{
79
 
        ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
80
 
              || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
81
 
 
82
 
        block->type = type;
83
 
}
84
 
 
85
 
UNIV_INLINE
86
 
ulint
87
 
mem_block_get_type(mem_block_t* block)
88
 
{
89
 
        return(block->type);
90
 
}
91
 
 
92
 
UNIV_INLINE
93
 
void
94
 
mem_block_set_free(mem_block_t* block, ulint free)
95
 
{
96
 
        ut_ad(free > 0);
97
 
        ut_ad(free <= mem_block_get_len(block));
98
 
 
99
 
        block->free = free;
100
 
}
101
 
 
102
 
UNIV_INLINE
103
 
ulint
104
 
mem_block_get_free(mem_block_t* block)
105
 
{
106
 
        return(block->free);
107
 
}
108
 
 
109
 
UNIV_INLINE
110
 
void
111
 
mem_block_set_start(mem_block_t* block, ulint start)
112
 
{
113
 
        ut_ad(start > 0);
114
 
 
115
 
        block->start = start;
116
 
}
117
 
 
118
 
UNIV_INLINE
119
 
ulint
120
 
mem_block_get_start(mem_block_t* block)
121
 
{
122
 
        return(block->start);
123
 
}
124
 
 
125
 
/*******************************************************************
126
 
Allocates n bytes of memory from a memory heap. */
127
 
UNIV_INLINE
128
 
void*
129
 
mem_heap_alloc(
130
 
/*===========*/
131
 
                                /* out: allocated storage, NULL if did not
132
 
                                succeed (only possible for
133
 
                                MEM_HEAP_BTR_SEARCH type heaps) */
134
 
        mem_heap_t*     heap,   /* in: memory heap */
135
 
        ulint           n)      /* in: number of bytes; if the heap is allowed
136
 
                                to grow into the buffer pool, this must be
137
 
                                <= MEM_MAX_ALLOC_IN_BUF */
138
 
{
139
 
        mem_block_t*    block;
140
 
        void*           buf;
141
 
        ulint           free;
142
 
 
143
 
        ut_ad(mem_heap_check(heap));
144
 
 
145
 
        block = UT_LIST_GET_LAST(heap->base);
146
 
 
147
 
        ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF));
148
 
 
149
 
        /* Check if there is enough space in block. If not, create a new
150
 
        block to the heap */
151
 
 
152
 
        if (mem_block_get_len(block)
153
 
            < mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) {
154
 
 
155
 
                block = mem_heap_add_block(heap, n);
156
 
 
157
 
                if (block == NULL) {
158
 
 
159
 
                        return(NULL);
160
 
                }
161
 
        }
162
 
 
163
 
        free = mem_block_get_free(block);
164
 
 
165
 
        buf = (byte*)block + free;
166
 
 
167
 
        mem_block_set_free(block, free + MEM_SPACE_NEEDED(n));
168
 
 
169
 
#ifdef UNIV_MEM_DEBUG
170
 
        UNIV_MEM_ALLOC(buf,
171
 
                       n + MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE);
172
 
 
173
 
        /* In the debug version write debugging info to the field */
174
 
        mem_field_init((byte*)buf, n);
175
 
 
176
 
        /* Advance buf to point at the storage which will be given to the
177
 
        caller */
178
 
        buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
179
 
 
180
 
#endif
181
 
#ifdef UNIV_SET_MEM_TO_ZERO
182
 
        UNIV_MEM_ALLOC(buf, n);
183
 
        memset(buf, '\0', n);
184
 
#endif
185
 
        UNIV_MEM_ALLOC(buf, n);
186
 
        return(buf);
187
 
}
188
 
 
189
 
/*********************************************************************
190
 
Returns a pointer to the heap top. */
191
 
UNIV_INLINE
192
 
byte*
193
 
mem_heap_get_heap_top(
194
 
/*==================*/
195
 
                                /* out: pointer to the heap top */
196
 
        mem_heap_t*     heap)   /* in: memory heap */
197
 
{
198
 
        mem_block_t*    block;
199
 
        byte*           buf;
200
 
 
201
 
        ut_ad(mem_heap_check(heap));
202
 
 
203
 
        block = UT_LIST_GET_LAST(heap->base);
204
 
 
205
 
        buf = (byte*)block + mem_block_get_free(block);
206
 
 
207
 
        return(buf);
208
 
}
209
 
 
210
 
/*********************************************************************
211
 
Frees the space in a memory heap exceeding the pointer given. The
212
 
pointer must have been acquired from mem_heap_get_heap_top. The first
213
 
memory block of the heap is not freed. */
214
 
UNIV_INLINE
215
 
void
216
 
mem_heap_free_heap_top(
217
 
/*===================*/
218
 
        mem_heap_t*     heap,   /* in: heap from which to free */
219
 
        byte*           old_top)/* in: pointer to old top of heap */
220
 
{
221
 
        mem_block_t*    block;
222
 
        mem_block_t*    prev_block;
223
 
#ifdef UNIV_MEM_DEBUG
224
 
        ibool           error;
225
 
        ulint           total_size;
226
 
        ulint           size;
227
 
#endif
228
 
 
229
 
        ut_ad(mem_heap_check(heap));
230
 
 
231
 
#ifdef UNIV_MEM_DEBUG
232
 
 
233
 
        /* Validate the heap and get its total allocated size */
234
 
        mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
235
 
                                   NULL, NULL);
236
 
        ut_a(!error);
237
 
 
238
 
        /* Get the size below top pointer */
239
 
        mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL,
240
 
                                   NULL);
241
 
        ut_a(!error);
242
 
 
243
 
#endif
244
 
 
245
 
        block = UT_LIST_GET_LAST(heap->base);
246
 
 
247
 
        while (block != NULL) {
248
 
                if (((byte*)block + mem_block_get_free(block) >= old_top)
249
 
                    && ((byte*)block <= old_top)) {
250
 
                        /* Found the right block */
251
 
 
252
 
                        break;
253
 
                }
254
 
 
255
 
                /* Store prev_block value before freeing the current block
256
 
                (the current block will be erased in freeing) */
257
 
 
258
 
                prev_block = UT_LIST_GET_PREV(list, block);
259
 
 
260
 
                mem_heap_block_free(heap, block);
261
 
 
262
 
                block = prev_block;
263
 
        }
264
 
 
265
 
        ut_ad(block);
266
 
 
267
 
        /* Set the free field of block */
268
 
        mem_block_set_free(block, old_top - (byte*)block);
269
 
 
270
 
#ifdef UNIV_MEM_DEBUG
271
 
        ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
272
 
 
273
 
        /* In the debug version erase block from top up */
274
 
        mem_erase_buf(old_top, (byte*)block + block->len - old_top);
275
 
 
276
 
        /* Update allocated memory count */
277
 
        mutex_enter(&mem_hash_mutex);
278
 
        mem_current_allocated_memory -= (total_size - size);
279
 
        mutex_exit(&mem_hash_mutex);
280
 
#else /* UNIV_MEM_DEBUG */
281
 
        UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top);
282
 
#endif /* UNIV_MEM_DEBUG */
283
 
        UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top);
284
 
 
285
 
        /* If free == start, we may free the block if it is not the first
286
 
        one */
287
 
 
288
 
        if ((heap != block) && (mem_block_get_free(block)
289
 
                                == mem_block_get_start(block))) {
290
 
                mem_heap_block_free(heap, block);
291
 
        }
292
 
}
293
 
 
294
 
/*********************************************************************
295
 
Empties a memory heap. The first memory block of the heap is not freed. */
296
 
UNIV_INLINE
297
 
void
298
 
mem_heap_empty(
299
 
/*===========*/
300
 
        mem_heap_t*     heap)   /* in: heap to empty */
301
 
{
302
 
        mem_heap_free_heap_top(heap, (byte*)heap + mem_block_get_start(heap));
303
 
 
304
 
        if (heap->free_block) {
305
 
                mem_heap_free_block_free(heap);
306
 
        }
307
 
}
308
 
 
309
 
/*********************************************************************
310
 
Returns a pointer to the topmost element in a memory heap. The size of the
311
 
element must be given. */
312
 
UNIV_INLINE
313
 
void*
314
 
mem_heap_get_top(
315
 
/*=============*/
316
 
                                /* out: pointer to the topmost element */
317
 
        mem_heap_t*     heap,   /* in: memory heap */
318
 
        ulint           n)      /* in: size of the topmost element */
319
 
{
320
 
        mem_block_t*    block;
321
 
        void*           buf;
322
 
 
323
 
        ut_ad(mem_heap_check(heap));
324
 
 
325
 
        block = UT_LIST_GET_LAST(heap->base);
326
 
 
327
 
        buf = (byte*)block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
328
 
 
329
 
#ifdef UNIV_MEM_DEBUG
330
 
        ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
331
 
 
332
 
        /* In the debug version, advance buf to point at the storage which
333
 
        was given to the caller in the allocation*/
334
 
 
335
 
        buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
336
 
 
337
 
        /* Check that the field lengths agree */
338
 
        ut_ad(n == (ulint)mem_field_header_get_len(buf));
339
 
#endif
340
 
 
341
 
        return(buf);
342
 
}
343
 
 
344
 
/*********************************************************************
345
 
Frees the topmost element in a memory heap. The size of the element must be
346
 
given. */
347
 
UNIV_INLINE
348
 
void
349
 
mem_heap_free_top(
350
 
/*==============*/
351
 
        mem_heap_t*     heap,   /* in: memory heap */
352
 
        ulint           n)      /* in: size of the topmost element */
353
 
{
354
 
        mem_block_t*    block;
355
 
 
356
 
        ut_ad(mem_heap_check(heap));
357
 
 
358
 
        block = UT_LIST_GET_LAST(heap->base);
359
 
 
360
 
        /* Subtract the free field of block */
361
 
        mem_block_set_free(block, mem_block_get_free(block)
362
 
                           - MEM_SPACE_NEEDED(n));
363
 
        UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
364
 
#ifdef UNIV_MEM_DEBUG
365
 
 
366
 
        ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
367
 
 
368
 
        /* In the debug version check the consistency, and erase field */
369
 
        mem_field_erase((byte*)block + mem_block_get_free(block), n);
370
 
#endif
371
 
 
372
 
        /* If free == start, we may free the block if it is not the first
373
 
        one */
374
 
 
375
 
        if ((heap != block) && (mem_block_get_free(block)
376
 
                                == mem_block_get_start(block))) {
377
 
                mem_heap_block_free(heap, block);
378
 
        } else {
379
 
                /* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
380
 
                subsequent invocation of mem_heap_free_top().
381
 
                Originally, this was UNIV_MEM_FREE(), to catch writes
382
 
                to freed memory. */
383
 
                UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
384
 
        }
385
 
}
386
 
 
387
 
/*********************************************************************
388
 
NOTE: Use the corresponding macros instead of this function. Creates a
389
 
memory heap. For debugging purposes, takes also the file name and line as
390
 
argument. */
391
 
UNIV_INLINE
392
 
mem_heap_t*
393
 
mem_heap_create_func(
394
 
/*=================*/
395
 
                                        /* out, own: memory heap, NULL if
396
 
                                        did not succeed (only possible for
397
 
                                        MEM_HEAP_BTR_SEARCH type heaps)*/
398
 
        ulint           n,              /* in: desired start block size,
399
 
                                        this means that a single user buffer
400
 
                                        of size n will fit in the block,
401
 
                                        0 creates a default size block;
402
 
                                        if init_block is not NULL, n tells
403
 
                                        its size in bytes */
404
 
        void*           init_block,     /* in: if very fast creation is
405
 
                                        wanted, the caller can reserve some
406
 
                                        memory from its stack, for example,
407
 
                                        and pass it as the the initial block
408
 
                                        to the heap: then no OS call of malloc
409
 
                                        is needed at the creation. CAUTION:
410
 
                                        the caller must make sure the initial
411
 
                                        block is not unintentionally erased
412
 
                                        (if allocated in the stack), before
413
 
                                        the memory heap is explicitly freed. */
414
 
        ulint           type,           /* in: heap type */
415
 
        const char*     file_name,      /* in: file name where created */
416
 
        ulint           line)           /* in: line where created */
417
 
{
418
 
        mem_block_t*   block;
419
 
 
420
 
        if (n > 0) {
421
 
                block = mem_heap_create_block(NULL, n, init_block, type,
422
 
                                              file_name, line);
423
 
        } else {
424
 
                block = mem_heap_create_block(NULL, MEM_BLOCK_START_SIZE,
425
 
                                              init_block, type,
426
 
                                              file_name, line);
427
 
        }
428
 
 
429
 
        if (block == NULL) {
430
 
 
431
 
                return(NULL);
432
 
        }
433
 
 
434
 
        UT_LIST_INIT(block->base);
435
 
 
436
 
        /* Add the created block itself as the first block in the list */
437
 
        UT_LIST_ADD_FIRST(list, block->base, block);
438
 
 
439
 
#ifdef UNIV_MEM_DEBUG
440
 
 
441
 
        mem_hash_insert(block, file_name, line);
442
 
 
443
 
#endif
444
 
 
445
 
        return(block);
446
 
}
447
 
 
448
 
/*********************************************************************
449
 
NOTE: Use the corresponding macro instead of this function. Frees the space
450
 
occupied by a memory heap. In the debug version erases the heap memory
451
 
blocks. */
452
 
UNIV_INLINE
453
 
void
454
 
mem_heap_free_func(
455
 
/*===============*/
456
 
        mem_heap_t*     heap,           /* in, own: heap to be freed */
457
 
        const char*     file_name __attribute__((unused)),
458
 
                                        /* in: file name where freed */
459
 
        ulint           line  __attribute__((unused)))
460
 
{
461
 
        mem_block_t*    block;
462
 
        mem_block_t*    prev_block;
463
 
 
464
 
        ut_ad(mem_heap_check(heap));
465
 
 
466
 
        block = UT_LIST_GET_LAST(heap->base);
467
 
 
468
 
#ifdef UNIV_MEM_DEBUG
469
 
 
470
 
        /* In the debug version remove the heap from the hash table of heaps
471
 
        and check its consistency */
472
 
 
473
 
        mem_hash_remove(heap, file_name, line);
474
 
 
475
 
#endif
476
 
 
477
 
        if (heap->free_block) {
478
 
                mem_heap_free_block_free(heap);
479
 
        }
480
 
 
481
 
        while (block != NULL) {
482
 
                /* Store the contents of info before freeing current block
483
 
                (it is erased in freeing) */
484
 
 
485
 
                prev_block = UT_LIST_GET_PREV(list, block);
486
 
 
487
 
                mem_heap_block_free(heap, block);
488
 
 
489
 
                block = prev_block;
490
 
        }
491
 
}
492
 
 
493
 
/*******************************************************************
494
 
NOTE: Use the corresponding macro instead of this function.
495
 
Allocates a single buffer of memory from the dynamic memory of
496
 
the C compiler. Is like malloc of C. The buffer must be freed
497
 
with mem_free. */
498
 
UNIV_INLINE
499
 
void*
500
 
mem_alloc_func(
501
 
/*===========*/
502
 
                                        /* out, own: free storage */
503
 
        ulint           n,              /* in: desired number of bytes */
504
 
        const char*     file_name,      /* in: file name where created */
505
 
        ulint           line            /* in: line where created */
506
 
        )
507
 
{
508
 
        mem_heap_t*     heap;
509
 
        void*           buf;
510
 
 
511
 
        heap = mem_heap_create_func(n, NULL, MEM_HEAP_DYNAMIC, file_name,
512
 
                                    line);
513
 
 
514
 
        /* Note that as we created the first block in the heap big enough
515
 
        for the buffer requested by the caller, the buffer will be in the
516
 
        first block and thus we can calculate the pointer to the heap from
517
 
        the pointer to the buffer when we free the memory buffer. */
518
 
 
519
 
        buf = mem_heap_alloc(heap, n);
520
 
 
521
 
        ut_a((byte*)heap == (byte*)buf - MEM_BLOCK_HEADER_SIZE
522
 
             - MEM_FIELD_HEADER_SIZE);
523
 
        return(buf);
524
 
}
525
 
 
526
 
/*******************************************************************
527
 
NOTE: Use the corresponding macro instead of this function. Frees a single
528
 
buffer of storage from the dynamic memory of the C compiler. Similar to the
529
 
free of C. */
530
 
UNIV_INLINE
531
 
void
532
 
mem_free_func(
533
 
/*==========*/
534
 
        void*           ptr,            /* in, own: buffer to be freed */
535
 
        const char*     file_name,      /* in: file name where created */
536
 
        ulint           line            /* in: line where created */
537
 
        )
538
 
{
539
 
        mem_heap_t*   heap;
540
 
 
541
 
        heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE
542
 
                             - MEM_FIELD_HEADER_SIZE);
543
 
        mem_heap_free_func(heap, file_name, line);
544
 
}
545
 
 
546
 
/*********************************************************************
547
 
Returns the space in bytes occupied by a memory heap. */
548
 
UNIV_INLINE
549
 
ulint
550
 
mem_heap_get_size(
551
 
/*==============*/
552
 
        mem_heap_t*     heap)   /* in: heap */
553
 
{
554
 
        mem_block_t*    block;
555
 
        ulint           size    = 0;
556
 
 
557
 
        ut_ad(mem_heap_check(heap));
558
 
 
559
 
        block = heap;
560
 
 
561
 
        while (block != NULL) {
562
 
 
563
 
                size += mem_block_get_len(block);
564
 
                block = UT_LIST_GET_NEXT(list, block);
565
 
        }
566
 
 
567
 
        if (heap->free_block) {
568
 
                size += UNIV_PAGE_SIZE;
569
 
        }
570
 
 
571
 
        return(size);
572
 
}
573
 
 
574
 
/**************************************************************************
575
 
Duplicates a NUL-terminated string. */
576
 
UNIV_INLINE
577
 
char*
578
 
mem_strdup(
579
 
/*=======*/
580
 
                                /* out, own: a copy of the string,
581
 
                                must be deallocated with mem_free */
582
 
        const char*     str)    /* in: string to be copied */
583
 
{
584
 
        ulint   len = strlen(str) + 1;
585
 
        return(memcpy(mem_alloc(len), str, len));
586
 
}
587
 
 
588
 
/**************************************************************************
589
 
Makes a NUL-terminated copy of a nonterminated string. */
590
 
UNIV_INLINE
591
 
char*
592
 
mem_strdupl(
593
 
/*========*/
594
 
                                /* out, own: a copy of the string,
595
 
                                must be deallocated with mem_free */
596
 
        const char*     str,    /* in: string to be copied */
597
 
        ulint           len)    /* in: length of str, in bytes */
598
 
{
599
 
        char*   s = mem_alloc(len + 1);
600
 
        s[len] = 0;
601
 
        return(memcpy(s, str, len));
602
 
}
603
 
 
604
 
/**************************************************************************
605
 
Makes a NUL-terminated copy of a nonterminated string,
606
 
allocated from a memory heap. */
607
 
UNIV_INLINE
608
 
char*
609
 
mem_heap_strdupl(
610
 
/*=============*/
611
 
                                /* out, own: a copy of the string */
612
 
        mem_heap_t*     heap,   /* in: memory heap where string is allocated */
613
 
        const char*     str,    /* in: string to be copied */
614
 
        ulint           len)    /* in: length of str, in bytes */
615
 
{
616
 
        char*   s = mem_heap_alloc(heap, len + 1);
617
 
        s[len] = 0;
618
 
        return(memcpy(s, str, len));
619
 
}