~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

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
}