~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/mem/mem0pool.c

  • Committer: Monty Taylor
  • Date: 2008-10-30 19:42:06 UTC
  • mto: (520.4.38 devel)
  • mto: This revision was merged to the branch mainline in revision 572.
  • Revision ID: monty@inaugust.com-20081030194206-fzus6yqlw1ekru65
Removed handler from common_includes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************
 
2
The lowest-level memory management
 
3
 
 
4
(c) 1997 Innobase Oy
 
5
 
 
6
Created 5/12/1997 Heikki Tuuri
 
7
*************************************************************************/
 
8
 
 
9
#include "mem0pool.h"
 
10
#ifdef UNIV_NONINL
 
11
#include "mem0pool.ic"
 
12
#endif
 
13
 
 
14
#include "sync0sync.h"
 
15
#include "ut0mem.h"
 
16
#include "ut0lst.h"
 
17
#include "ut0byte.h"
 
18
#include "mem0mem.h"
 
19
 
 
20
/* We would like to use also the buffer frames to allocate memory. This
 
21
would be desirable, because then the memory consumption of the database
 
22
would be fixed, and we might even lock the buffer pool to the main memory.
 
23
The problem here is that the buffer management routines can themselves call
 
24
memory allocation, while the buffer pool mutex is reserved.
 
25
 
 
26
The main components of the memory consumption are:
 
27
 
 
28
1. buffer pool,
 
29
2. parsed and optimized SQL statements,
 
30
3. data dictionary cache,
 
31
4. log buffer,
 
32
5. locks for each transaction,
 
33
6. hash table for the adaptive index,
 
34
7. state and buffers for each SQL query currently being executed,
 
35
8. session for each user, and
 
36
9. stack for each OS thread.
 
37
 
 
38
Items 1 and 2 are managed by an LRU algorithm. Items 5 and 6 can potentially
 
39
consume very much memory. Items 7 and 8 should consume quite little memory,
 
40
and the OS should take care of item 9, which too should consume little memory.
 
41
 
 
42
A solution to the memory management:
 
43
 
 
44
1. the buffer pool size is set separately;
 
45
2. log buffer size is set separately;
 
46
3. the common pool size for all the other entries, except 8, is set separately.
 
47
 
 
48
Problems: we may waste memory if the common pool is set too big. Another
 
49
problem is the locks, which may take very much space in big transactions.
 
50
Then the shared pool size should be set very big. We can allow locks to take
 
51
space from the buffer pool, but the SQL optimizer is then unaware of the
 
52
usable size of the buffer pool. We could also combine the objects in the
 
53
common pool and the buffers in the buffer pool into a single LRU list and
 
54
manage it uniformly, but this approach does not take into account the parsing
 
55
and other costs unique to SQL statements.
 
56
 
 
57
The locks for a transaction can be seen as a part of the state of the
 
58
transaction. Hence, they should be stored in the common pool. We still
 
59
have the problem of a very big update transaction, for example, which
 
60
will set very many x-locks on rows, and the locks will consume a lot
 
61
of memory, say, half of the buffer pool size.
 
62
 
 
63
Another problem is what to do if we are not able to malloc a requested
 
64
block of memory from the common pool. Then we can request memory from
 
65
the operating system. If it does not help, a system error results.
 
66
 
 
67
Because 5 and 6 may potentially consume very much memory, we let them grow
 
68
into the buffer pool. We may let the locks of a transaction take frames
 
69
from the buffer pool, when the corresponding memory heap block has grown to
 
70
the size of a buffer frame. Similarly for the hash node cells of the locks,
 
71
and for the adaptive index. Thus, for each individual transaction, its locks
 
72
can occupy at most about the size of the buffer frame of memory in the common
 
73
pool, and after that its locks will grow into the buffer pool. */
 
74
 
 
75
/* Mask used to extract the free bit from area->size */
 
76
#define MEM_AREA_FREE   1
 
77
 
 
78
/* The smallest memory area total size */
 
79
#define MEM_AREA_MIN_SIZE       (2 * MEM_AREA_EXTRA_SIZE)
 
80
 
 
81
 
 
82
/* Data structure for a memory pool. The space is allocated using the buddy
 
83
algorithm, where free list i contains areas of size 2 to power i. */
 
84
struct mem_pool_struct{
 
85
        byte*           buf;            /* memory pool */
 
86
        ulint           size;           /* memory common pool size */
 
87
        ulint           reserved;       /* amount of currently allocated
 
88
                                        memory */
 
89
        mutex_t         mutex;          /* mutex protecting this struct */
 
90
        UT_LIST_BASE_NODE_T(mem_area_t)
 
91
                        free_list[64];  /* lists of free memory areas: an
 
92
                                        area is put to the list whose number
 
93
                                        is the 2-logarithm of the area size */
 
94
};
 
95
 
 
96
/* The common memory pool */
 
97
UNIV_INTERN mem_pool_t* mem_comm_pool   = NULL;
 
98
 
 
99
/* We use this counter to check that the mem pool mutex does not leak;
 
100
this is to track a strange assertion failure reported at
 
101
mysql@lists.mysql.com */
 
102
 
 
103
UNIV_INTERN ulint       mem_n_threads_inside            = 0;
 
104
 
 
105
/************************************************************************
 
106
Reserves the mem pool mutex. */
 
107
UNIV_INTERN
 
108
void
 
109
mem_pool_mutex_enter(void)
 
110
/*======================*/
 
111
{
 
112
        mutex_enter(&(mem_comm_pool->mutex));
 
113
}
 
114
 
 
115
/************************************************************************
 
116
Releases the mem pool mutex. */
 
117
UNIV_INTERN
 
118
void
 
119
mem_pool_mutex_exit(void)
 
120
/*=====================*/
 
121
{
 
122
        mutex_exit(&(mem_comm_pool->mutex));
 
123
}
 
124
 
 
125
/************************************************************************
 
126
Returns memory area size. */
 
127
UNIV_INLINE
 
128
ulint
 
129
mem_area_get_size(
 
130
/*==============*/
 
131
                                /* out: size */
 
132
        mem_area_t*     area)   /* in: area */
 
133
{
 
134
        return(area->size_and_free & ~MEM_AREA_FREE);
 
135
}
 
136
 
 
137
/************************************************************************
 
138
Sets memory area size. */
 
139
UNIV_INLINE
 
140
void
 
141
mem_area_set_size(
 
142
/*==============*/
 
143
        mem_area_t*     area,   /* in: area */
 
144
        ulint           size)   /* in: size */
 
145
{
 
146
        area->size_and_free = (area->size_and_free & MEM_AREA_FREE)
 
147
                | size;
 
148
}
 
149
 
 
150
/************************************************************************
 
151
Returns memory area free bit. */
 
152
UNIV_INLINE
 
153
ibool
 
154
mem_area_get_free(
 
155
/*==============*/
 
156
                                /* out: TRUE if free */
 
157
        mem_area_t*     area)   /* in: area */
 
158
{
 
159
#if TRUE != MEM_AREA_FREE
 
160
# error "TRUE != MEM_AREA_FREE"
 
161
#endif
 
162
        return(area->size_and_free & MEM_AREA_FREE);
 
163
}
 
164
 
 
165
/************************************************************************
 
166
Sets memory area free bit. */
 
167
UNIV_INLINE
 
168
void
 
169
mem_area_set_free(
 
170
/*==============*/
 
171
        mem_area_t*     area,   /* in: area */
 
172
        ibool           free)   /* in: free bit value */
 
173
{
 
174
#if TRUE != MEM_AREA_FREE
 
175
# error "TRUE != MEM_AREA_FREE"
 
176
#endif
 
177
        area->size_and_free = (area->size_and_free & ~MEM_AREA_FREE)
 
178
                | free;
 
179
}
 
180
 
 
181
/************************************************************************
 
182
Creates a memory pool. */
 
183
UNIV_INTERN
 
184
mem_pool_t*
 
185
mem_pool_create(
 
186
/*============*/
 
187
                        /* out: memory pool */
 
188
        ulint   size)   /* in: pool size in bytes */
 
189
{
 
190
        mem_pool_t*     pool;
 
191
        mem_area_t*     area;
 
192
        ulint           i;
 
193
        ulint           used;
 
194
 
 
195
        ut_a(size > 10000);
 
196
 
 
197
        pool = ut_malloc(sizeof(mem_pool_t));
 
198
 
 
199
        /* We do not set the memory to zero (FALSE) in the pool,
 
200
        but only when allocated at a higher level in mem0mem.c.
 
201
        This is to avoid masking useful Purify warnings. */
 
202
 
 
203
        pool->buf = ut_malloc_low(size, FALSE, TRUE);
 
204
        pool->size = size;
 
205
 
 
206
        mutex_create(&pool->mutex, SYNC_MEM_POOL);
 
207
 
 
208
        /* Initialize the free lists */
 
209
 
 
210
        for (i = 0; i < 64; i++) {
 
211
 
 
212
                UT_LIST_INIT(pool->free_list[i]);
 
213
        }
 
214
 
 
215
        used = 0;
 
216
 
 
217
        while (size - used >= MEM_AREA_MIN_SIZE) {
 
218
 
 
219
                i = ut_2_log(size - used);
 
220
 
 
221
                if (ut_2_exp(i) > size - used) {
 
222
 
 
223
                        /* ut_2_log rounds upward */
 
224
 
 
225
                        i--;
 
226
                }
 
227
 
 
228
                area = (mem_area_t*)(pool->buf + used);
 
229
 
 
230
                mem_area_set_size(area, ut_2_exp(i));
 
231
                mem_area_set_free(area, TRUE);
 
232
                UNIV_MEM_FREE(MEM_AREA_EXTRA_SIZE + (byte*) area,
 
233
                              ut_2_exp(i) - MEM_AREA_EXTRA_SIZE);
 
234
 
 
235
                UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area);
 
236
 
 
237
                used = used + ut_2_exp(i);
 
238
        }
 
239
 
 
240
        ut_ad(size >= used);
 
241
 
 
242
        pool->reserved = 0;
 
243
 
 
244
        return(pool);
 
245
}
 
246
 
 
247
/************************************************************************
 
248
Fills the specified free list. */
 
249
static
 
250
ibool
 
251
mem_pool_fill_free_list(
 
252
/*====================*/
 
253
                                /* out: TRUE if we were able to insert a
 
254
                                block to the free list */
 
255
        ulint           i,      /* in: free list index */
 
256
        mem_pool_t*     pool)   /* in: memory pool */
 
257
{
 
258
        mem_area_t*     area;
 
259
        mem_area_t*     area2;
 
260
        ibool           ret;
 
261
 
 
262
        ut_ad(mutex_own(&(pool->mutex)));
 
263
 
 
264
        if (UNIV_UNLIKELY(i >= 63)) {
 
265
                /* We come here when we have run out of space in the
 
266
                memory pool: */
 
267
 
 
268
                return(FALSE);
 
269
        }
 
270
 
 
271
        area = UT_LIST_GET_FIRST(pool->free_list[i + 1]);
 
272
 
 
273
        if (area == NULL) {
 
274
                if (UT_LIST_GET_LEN(pool->free_list[i + 1]) > 0) {
 
275
                        ut_print_timestamp(stderr);
 
276
 
 
277
                        fprintf(stderr,
 
278
                                "  InnoDB: Error: mem pool free list %lu"
 
279
                                " length is %lu\n"
 
280
                                "InnoDB: though the list is empty!\n",
 
281
                                (ulong) i + 1,
 
282
                                (ulong)
 
283
                                UT_LIST_GET_LEN(pool->free_list[i + 1]));
 
284
                }
 
285
 
 
286
                ret = mem_pool_fill_free_list(i + 1, pool);
 
287
 
 
288
                if (ret == FALSE) {
 
289
 
 
290
                        return(FALSE);
 
291
                }
 
292
 
 
293
                area = UT_LIST_GET_FIRST(pool->free_list[i + 1]);
 
294
        }
 
295
 
 
296
        if (UNIV_UNLIKELY(UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0)) {
 
297
                mem_analyze_corruption(area);
 
298
 
 
299
                ut_error;
 
300
        }
 
301
 
 
302
        UT_LIST_REMOVE(free_list, pool->free_list[i + 1], area);
 
303
 
 
304
        area2 = (mem_area_t*)(((byte*)area) + ut_2_exp(i));
 
305
        UNIV_MEM_ALLOC(area2, MEM_AREA_EXTRA_SIZE);
 
306
 
 
307
        mem_area_set_size(area2, ut_2_exp(i));
 
308
        mem_area_set_free(area2, TRUE);
 
309
 
 
310
        UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area2);
 
311
 
 
312
        mem_area_set_size(area, ut_2_exp(i));
 
313
 
 
314
        UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area);
 
315
 
 
316
        return(TRUE);
 
317
}
 
318
 
 
319
/************************************************************************
 
320
Allocates memory from a pool. NOTE: This low-level function should only be
 
321
used in mem0mem.*! */
 
322
UNIV_INTERN
 
323
void*
 
324
mem_area_alloc(
 
325
/*===========*/
 
326
                                /* out, own: allocated memory buffer */
 
327
        ulint*          psize,  /* in: requested size in bytes; for optimum
 
328
                                space usage, the size should be a power of 2
 
329
                                minus MEM_AREA_EXTRA_SIZE;
 
330
                                out: allocated size in bytes (greater than
 
331
                                or equal to the requested size) */
 
332
        mem_pool_t*     pool)   /* in: memory pool */
 
333
{
 
334
        mem_area_t*     area;
 
335
        ulint           size;
 
336
        ulint           n;
 
337
        ibool           ret;
 
338
 
 
339
        size = *psize;
 
340
        n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE));
 
341
 
 
342
        mutex_enter(&(pool->mutex));
 
343
        mem_n_threads_inside++;
 
344
 
 
345
        ut_a(mem_n_threads_inside == 1);
 
346
 
 
347
        area = UT_LIST_GET_FIRST(pool->free_list[n]);
 
348
 
 
349
        if (area == NULL) {
 
350
                ret = mem_pool_fill_free_list(n, pool);
 
351
 
 
352
                if (ret == FALSE) {
 
353
                        /* Out of memory in memory pool: we try to allocate
 
354
                        from the operating system with the regular malloc: */
 
355
 
 
356
                        mem_n_threads_inside--;
 
357
                        mutex_exit(&(pool->mutex));
 
358
 
 
359
                        return(ut_malloc(size));
 
360
                }
 
361
 
 
362
                area = UT_LIST_GET_FIRST(pool->free_list[n]);
 
363
        }
 
364
 
 
365
        if (!mem_area_get_free(area)) {
 
366
                fprintf(stderr,
 
367
                        "InnoDB: Error: Removing element from mem pool"
 
368
                        " free list %lu though the\n"
 
369
                        "InnoDB: element is not marked free!\n",
 
370
                        (ulong) n);
 
371
 
 
372
                mem_analyze_corruption(area);
 
373
 
 
374
                /* Try to analyze a strange assertion failure reported at
 
375
                mysql@lists.mysql.com where the free bit IS 1 in the
 
376
                hex dump above */
 
377
 
 
378
                if (mem_area_get_free(area)) {
 
379
                        fprintf(stderr,
 
380
                                "InnoDB: Probably a race condition"
 
381
                                " because now the area is marked free!\n");
 
382
                }
 
383
 
 
384
                ut_error;
 
385
        }
 
386
 
 
387
        if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) {
 
388
                fprintf(stderr,
 
389
                        "InnoDB: Error: Removing element from mem pool"
 
390
                        " free list %lu\n"
 
391
                        "InnoDB: though the list length is 0!\n",
 
392
                        (ulong) n);
 
393
                mem_analyze_corruption(area);
 
394
 
 
395
                ut_error;
 
396
        }
 
397
 
 
398
        ut_ad(mem_area_get_size(area) == ut_2_exp(n));
 
399
 
 
400
        mem_area_set_free(area, FALSE);
 
401
 
 
402
        UT_LIST_REMOVE(free_list, pool->free_list[n], area);
 
403
 
 
404
        pool->reserved += mem_area_get_size(area);
 
405
 
 
406
        mem_n_threads_inside--;
 
407
        mutex_exit(&(pool->mutex));
 
408
 
 
409
        ut_ad(mem_pool_validate(pool));
 
410
 
 
411
        *psize = ut_2_exp(n) - MEM_AREA_EXTRA_SIZE;
 
412
        UNIV_MEM_ALLOC(MEM_AREA_EXTRA_SIZE + (byte*)area, *psize);
 
413
 
 
414
        return((void*)(MEM_AREA_EXTRA_SIZE + ((byte*)area)));
 
415
}
 
416
 
 
417
/************************************************************************
 
418
Gets the buddy of an area, if it exists in pool. */
 
419
UNIV_INLINE
 
420
mem_area_t*
 
421
mem_area_get_buddy(
 
422
/*===============*/
 
423
                                /* out: the buddy, NULL if no buddy in pool */
 
424
        mem_area_t*     area,   /* in: memory area */
 
425
        ulint           size,   /* in: memory area size */
 
426
        mem_pool_t*     pool)   /* in: memory pool */
 
427
{
 
428
        mem_area_t*     buddy;
 
429
 
 
430
        ut_ad(size != 0);
 
431
 
 
432
        if (((((byte*)area) - pool->buf) % (2 * size)) == 0) {
 
433
 
 
434
                /* The buddy is in a higher address */
 
435
 
 
436
                buddy = (mem_area_t*)(((byte*)area) + size);
 
437
 
 
438
                if ((((byte*)buddy) - pool->buf) + size > pool->size) {
 
439
 
 
440
                        /* The buddy is not wholly contained in the pool:
 
441
                        there is no buddy */
 
442
 
 
443
                        buddy = NULL;
 
444
                }
 
445
        } else {
 
446
                /* The buddy is in a lower address; NOTE that area cannot
 
447
                be at the pool lower end, because then we would end up to
 
448
                the upper branch in this if-clause: the remainder would be
 
449
                0 */
 
450
 
 
451
                buddy = (mem_area_t*)(((byte*)area) - size);
 
452
        }
 
453
 
 
454
        return(buddy);
 
455
}
 
456
 
 
457
/************************************************************************
 
458
Frees memory to a pool. */
 
459
UNIV_INTERN
 
460
void
 
461
mem_area_free(
 
462
/*==========*/
 
463
        void*           ptr,    /* in, own: pointer to allocated memory
 
464
                                buffer */
 
465
        mem_pool_t*     pool)   /* in: memory pool */
 
466
{
 
467
        mem_area_t*     area;
 
468
        mem_area_t*     buddy;
 
469
        void*           new_ptr;
 
470
        ulint           size;
 
471
        ulint           n;
 
472
 
 
473
        /* It may be that the area was really allocated from the OS with
 
474
        regular malloc: check if ptr points within our memory pool */
 
475
 
 
476
        if ((byte*)ptr < pool->buf || (byte*)ptr >= pool->buf + pool->size) {
 
477
                ut_free(ptr);
 
478
 
 
479
                return;
 
480
        }
 
481
 
 
482
        area = (mem_area_t*) (((byte*)ptr) - MEM_AREA_EXTRA_SIZE);
 
483
 
 
484
        if (mem_area_get_free(area)) {
 
485
                fprintf(stderr,
 
486
                        "InnoDB: Error: Freeing element to mem pool"
 
487
                        " free list though the\n"
 
488
                        "InnoDB: element is marked free!\n");
 
489
 
 
490
                mem_analyze_corruption(area);
 
491
                ut_error;
 
492
        }
 
493
 
 
494
        size = mem_area_get_size(area);
 
495
        UNIV_MEM_FREE(ptr, size - MEM_AREA_EXTRA_SIZE);
 
496
 
 
497
        if (size == 0) {
 
498
                fprintf(stderr,
 
499
                        "InnoDB: Error: Mem area size is 0. Possibly a"
 
500
                        " memory overrun of the\n"
 
501
                        "InnoDB: previous allocated area!\n");
 
502
 
 
503
                mem_analyze_corruption(area);
 
504
                ut_error;
 
505
        }
 
506
 
 
507
#ifdef UNIV_LIGHT_MEM_DEBUG
 
508
        if (((byte*)area) + size < pool->buf + pool->size) {
 
509
 
 
510
                ulint   next_size;
 
511
 
 
512
                next_size = mem_area_get_size(
 
513
                        (mem_area_t*)(((byte*)area) + size));
 
514
                if (UNIV_UNLIKELY(!next_size || !ut_is_2pow(next_size))) {
 
515
                        fprintf(stderr,
 
516
                                "InnoDB: Error: Memory area size %lu,"
 
517
                                " next area size %lu not a power of 2!\n"
 
518
                                "InnoDB: Possibly a memory overrun of"
 
519
                                " the buffer being freed here.\n",
 
520
                                (ulong) size, (ulong) next_size);
 
521
                        mem_analyze_corruption(area);
 
522
 
 
523
                        ut_error;
 
524
                }
 
525
        }
 
526
#endif
 
527
        buddy = mem_area_get_buddy(area, size, pool);
 
528
 
 
529
        n = ut_2_log(size);
 
530
 
 
531
        mutex_enter(&(pool->mutex));
 
532
        mem_n_threads_inside++;
 
533
 
 
534
        ut_a(mem_n_threads_inside == 1);
 
535
 
 
536
        if (buddy && mem_area_get_free(buddy)
 
537
            && (size == mem_area_get_size(buddy))) {
 
538
 
 
539
                /* The buddy is in a free list */
 
540
 
 
541
                if ((byte*)buddy < (byte*)area) {
 
542
                        new_ptr = ((byte*)buddy) + MEM_AREA_EXTRA_SIZE;
 
543
 
 
544
                        mem_area_set_size(buddy, 2 * size);
 
545
                        mem_area_set_free(buddy, FALSE);
 
546
                } else {
 
547
                        new_ptr = ptr;
 
548
 
 
549
                        mem_area_set_size(area, 2 * size);
 
550
                }
 
551
 
 
552
                /* Remove the buddy from its free list and merge it to area */
 
553
 
 
554
                UT_LIST_REMOVE(free_list, pool->free_list[n], buddy);
 
555
 
 
556
                pool->reserved += ut_2_exp(n);
 
557
 
 
558
                mem_n_threads_inside--;
 
559
                mutex_exit(&(pool->mutex));
 
560
 
 
561
                mem_area_free(new_ptr, pool);
 
562
 
 
563
                return;
 
564
        } else {
 
565
                UT_LIST_ADD_FIRST(free_list, pool->free_list[n], area);
 
566
 
 
567
                mem_area_set_free(area, TRUE);
 
568
 
 
569
                ut_ad(pool->reserved >= size);
 
570
 
 
571
                pool->reserved -= size;
 
572
        }
 
573
 
 
574
        mem_n_threads_inside--;
 
575
        mutex_exit(&(pool->mutex));
 
576
 
 
577
        ut_ad(mem_pool_validate(pool));
 
578
}
 
579
 
 
580
/************************************************************************
 
581
Validates a memory pool. */
 
582
UNIV_INTERN
 
583
ibool
 
584
mem_pool_validate(
 
585
/*==============*/
 
586
                                /* out: TRUE if ok */
 
587
        mem_pool_t*     pool)   /* in: memory pool */
 
588
{
 
589
        mem_area_t*     area;
 
590
        mem_area_t*     buddy;
 
591
        ulint           free;
 
592
        ulint           i;
 
593
 
 
594
        mutex_enter(&(pool->mutex));
 
595
 
 
596
        free = 0;
 
597
 
 
598
        for (i = 0; i < 64; i++) {
 
599
 
 
600
                UT_LIST_VALIDATE(free_list, mem_area_t, pool->free_list[i]);
 
601
 
 
602
                area = UT_LIST_GET_FIRST(pool->free_list[i]);
 
603
 
 
604
                while (area != NULL) {
 
605
                        ut_a(mem_area_get_free(area));
 
606
                        ut_a(mem_area_get_size(area) == ut_2_exp(i));
 
607
 
 
608
                        buddy = mem_area_get_buddy(area, ut_2_exp(i), pool);
 
609
 
 
610
                        ut_a(!buddy || !mem_area_get_free(buddy)
 
611
                             || (ut_2_exp(i) != mem_area_get_size(buddy)));
 
612
 
 
613
                        area = UT_LIST_GET_NEXT(free_list, area);
 
614
 
 
615
                        free += ut_2_exp(i);
 
616
                }
 
617
        }
 
618
 
 
619
        ut_a(free + pool->reserved == pool->size);
 
620
 
 
621
        mutex_exit(&(pool->mutex));
 
622
 
 
623
        return(TRUE);
 
624
}
 
625
 
 
626
/************************************************************************
 
627
Prints info of a memory pool. */
 
628
UNIV_INTERN
 
629
void
 
630
mem_pool_print_info(
 
631
/*================*/
 
632
        FILE*           outfile,/* in: output file to write to */
 
633
        mem_pool_t*     pool)   /* in: memory pool */
 
634
{
 
635
        ulint           i;
 
636
 
 
637
        mem_pool_validate(pool);
 
638
 
 
639
        fprintf(outfile, "INFO OF A MEMORY POOL\n");
 
640
 
 
641
        mutex_enter(&(pool->mutex));
 
642
 
 
643
        for (i = 0; i < 64; i++) {
 
644
                if (UT_LIST_GET_LEN(pool->free_list[i]) > 0) {
 
645
 
 
646
                        fprintf(outfile,
 
647
                                "Free list length %lu for"
 
648
                                " blocks of size %lu\n",
 
649
                                (ulong) UT_LIST_GET_LEN(pool->free_list[i]),
 
650
                                (ulong) ut_2_exp(i));
 
651
                }
 
652
        }
 
653
 
 
654
        fprintf(outfile, "Pool size %lu, reserved %lu.\n", (ulong) pool->size,
 
655
                (ulong) pool->reserved);
 
656
        mutex_exit(&(pool->mutex));
 
657
}
 
658
 
 
659
/************************************************************************
 
660
Returns the amount of reserved memory. */
 
661
UNIV_INTERN
 
662
ulint
 
663
mem_pool_get_reserved(
 
664
/*==================*/
 
665
                                /* out: reserved memory in bytes */
 
666
        mem_pool_t*     pool)   /* in: memory pool */
 
667
{
 
668
        ulint   reserved;
 
669
 
 
670
        mutex_enter(&(pool->mutex));
 
671
 
 
672
        reserved = pool->reserved;
 
673
 
 
674
        mutex_exit(&(pool->mutex));
 
675
 
 
676
        return(reserved);
 
677
}