~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/buf/buf0buddy.c

  • Committer: Lee Bieber
  • Date: 2010-11-14 23:15:42 UTC
  • mfrom: (1929.1.42 warning-stack-frame)
  • Revision ID: kalebral@gmail.com-20101114231542-fnnu6ydd2p17n582
Merge Monty - fix bug 672372: some functions use > 32k stack

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 2006, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 2006, 2010, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
34
34
#include "buf0flu.h"
35
35
#include "page0zip.h"
36
36
 
 
37
/* Statistic counters */
 
38
 
 
39
#ifdef UNIV_DEBUG
 
40
/** Number of frames allocated from the buffer pool to the buddy system.
 
41
Protected by buf_pool_mutex. */
 
42
static ulint buf_buddy_n_frames;
 
43
#endif /* UNIV_DEBUG */
 
44
/** Statistics of the buddy system, indexed by block size.
 
45
Protected by buf_pool_mutex. */
 
46
UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1];
 
47
 
37
48
/**********************************************************************//**
38
49
Get the offset of the buddy of a compressed page frame.
39
50
@return the buddy relative of page */
62
73
void
63
74
buf_buddy_add_to_free(
64
75
/*==================*/
65
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
66
 
        buf_page_t*     bpage,          /*!< in,own: block to be freed */
67
 
        ulint           i)              /*!< in: index of
68
 
                                        buf_pool->zip_free[] */
 
76
        buf_page_t*     bpage,  /*!< in,own: block to be freed */
 
77
        ulint           i)      /*!< in: index of buf_pool->zip_free[] */
69
78
{
70
79
#ifdef UNIV_DEBUG_VALGRIND
71
80
        buf_page_t*     b  = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
73
82
        if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i);
74
83
#endif /* UNIV_DEBUG_VALGRIND */
75
84
 
76
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
85
        ut_ad(buf_pool_mutex_own());
77
86
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
78
87
        ut_ad(buf_pool->zip_free[i].start != bpage);
79
88
        UT_LIST_ADD_FIRST(list, buf_pool->zip_free[i], bpage);
90
99
void
91
100
buf_buddy_remove_from_free(
92
101
/*=======================*/
93
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
94
 
        buf_page_t*     bpage,          /*!< in: block to be removed */
95
 
        ulint           i)              /*!< in: index of
96
 
                                        buf_pool->zip_free[] */
 
102
        buf_page_t*     bpage,  /*!< in: block to be removed */
 
103
        ulint           i)      /*!< in: index of buf_pool->zip_free[] */
97
104
{
98
105
#ifdef UNIV_DEBUG_VALGRIND
99
106
        buf_page_t*     prev = UT_LIST_GET_PREV(list, bpage);
106
113
        ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
107
114
#endif /* UNIV_DEBUG_VALGRIND */
108
115
 
109
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
116
        ut_ad(buf_pool_mutex_own());
110
117
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
111
118
        UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage);
112
119
 
123
130
void*
124
131
buf_buddy_alloc_zip(
125
132
/*================*/
126
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
127
 
        ulint           i)              /*!< in: index of buf_pool->zip_free[] */
 
133
        ulint   i)      /*!< in: index of buf_pool->zip_free[] */
128
134
{
129
135
        buf_page_t*     bpage;
130
136
 
131
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
137
        ut_ad(buf_pool_mutex_own());
132
138
        ut_a(i < BUF_BUDDY_SIZES);
133
139
 
134
140
#ifndef UNIV_DEBUG_VALGRIND
143
149
                UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
144
150
                ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
145
151
 
146
 
                buf_buddy_remove_from_free(buf_pool, bpage, i);
 
152
                buf_buddy_remove_from_free(bpage, i);
147
153
        } else if (i + 1 < BUF_BUDDY_SIZES) {
148
154
                /* Attempt to split. */
149
 
                bpage = (buf_page_t *)buf_buddy_alloc_zip(buf_pool, i + 1);
 
155
                bpage = buf_buddy_alloc_zip(i + 1);
150
156
 
151
157
                if (bpage) {
152
158
                        buf_page_t*     buddy = (buf_page_t*)
153
159
                                (((char*) bpage) + (BUF_BUDDY_LOW << i));
154
160
 
155
 
                        ut_ad(!buf_pool_contains_zip(buf_pool, buddy));
 
161
                        ut_ad(!buf_pool_contains_zip(buddy));
156
162
                        ut_d(memset(buddy, i, BUF_BUDDY_LOW << i));
157
163
                        buddy->state = BUF_BLOCK_ZIP_FREE;
158
 
                        buf_buddy_add_to_free(buf_pool, buddy, i);
 
164
                        buf_buddy_add_to_free(buddy, i);
159
165
                }
160
166
        }
161
167
 
176
182
void
177
183
buf_buddy_block_free(
178
184
/*=================*/
179
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
180
 
        void*           buf)            /*!< in: buffer frame to deallocate */
 
185
        void*   buf)    /*!< in: buffer frame to deallocate */
181
186
{
182
187
        const ulint     fold    = BUF_POOL_ZIP_FOLD_PTR(buf);
183
188
        buf_page_t*     bpage;
184
189
        buf_block_t*    block;
185
190
 
186
 
        ut_ad(buf_pool_mutex_own(buf_pool));
187
 
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
 
191
        ut_ad(buf_pool_mutex_own());
 
192
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
188
193
        ut_a(!ut_align_offset(buf, UNIV_PAGE_SIZE));
189
194
 
190
195
        HASH_SEARCH(hash, buf_pool->zip_hash, fold, buf_page_t*, bpage,
206
211
        buf_LRU_block_free_non_file_page(block);
207
212
        mutex_exit(&block->mutex);
208
213
 
209
 
        ut_ad(buf_pool->buddy_n_frames > 0);
210
 
        ut_d(buf_pool->buddy_n_frames--);
 
214
        ut_ad(buf_buddy_n_frames > 0);
 
215
        ut_d(buf_buddy_n_frames--);
211
216
}
212
217
 
213
218
/**********************************************************************//**
218
223
/*=====================*/
219
224
        buf_block_t*    block)  /*!< in: buffer frame to allocate */
220
225
{
221
 
        buf_pool_t*     buf_pool = buf_pool_from_block(block);
222
226
        const ulint     fold = BUF_POOL_ZIP_FOLD(block);
223
 
        ut_ad(buf_pool_mutex_own(buf_pool));
224
 
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
 
227
        ut_ad(buf_pool_mutex_own());
 
228
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
225
229
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE);
226
230
 
227
231
        buf_block_set_state(block, BUF_BLOCK_MEMORY);
234
238
        ut_d(block->page.in_zip_hash = TRUE);
235
239
        HASH_INSERT(buf_page_t, hash, buf_pool->zip_hash, fold, &block->page);
236
240
 
237
 
        ut_d(buf_pool->buddy_n_frames++);
 
241
        ut_d(buf_buddy_n_frames++);
238
242
}
239
243
 
240
244
/**********************************************************************//**
244
248
void*
245
249
buf_buddy_alloc_from(
246
250
/*=================*/
247
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
248
 
        void*           buf,            /*!< in: a block that is free to use */
249
 
        ulint           i,              /*!< in: index of
250
 
                                        buf_pool->zip_free[] */
251
 
        ulint           j)              /*!< in: size of buf as an index
252
 
                                        of buf_pool->zip_free[] */
 
251
        void*           buf,    /*!< in: a block that is free to use */
 
252
        ulint           i,      /*!< in: index of buf_pool->zip_free[] */
 
253
        ulint           j)      /*!< in: size of buf as an index
 
254
                                of buf_pool->zip_free[] */
253
255
{
254
256
        ulint   offs    = BUF_BUDDY_LOW << j;
255
257
        ut_ad(j <= BUF_BUDDY_SIZES);
273
275
                                                    ut_list_node_313)
274
276
                                            == BUF_BLOCK_ZIP_FREE)));
275
277
#endif /* !UNIV_DEBUG_VALGRIND */
276
 
                buf_buddy_add_to_free(buf_pool, bpage, j);
 
278
                buf_buddy_add_to_free(bpage, j);
277
279
        }
278
280
 
279
281
        return(buf);
281
283
 
282
284
/**********************************************************************//**
283
285
Allocate a block.  The thread calling this function must hold
284
 
buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex.
285
 
The buf_pool->mutex may only be released and reacquired if lru != NULL.
 
286
buf_pool_mutex and must not hold buf_pool_zip_mutex or any block->mutex.
 
287
The buf_pool_mutex may only be released and reacquired if lru != NULL.
286
288
@return allocated block, possibly NULL if lru==NULL */
287
289
UNIV_INTERN
288
290
void*
289
291
buf_buddy_alloc_low(
290
292
/*================*/
291
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
292
 
        ulint           i,              /*!< in: index of buf_pool->zip_free[],
293
 
                                        or BUF_BUDDY_SIZES */
294
 
        ibool*          lru)            /*!< in: pointer to a variable that
295
 
                                        will be assigned TRUE if storage was
296
 
                                        allocated from the LRU list and
297
 
                                        buf_pool->mutex was temporarily
298
 
                                        released, or NULL if the LRU list
299
 
                                        should not be used */
 
293
        ulint   i,      /*!< in: index of buf_pool->zip_free[],
 
294
                        or BUF_BUDDY_SIZES */
 
295
        ibool*  lru)    /*!< in: pointer to a variable that will be assigned
 
296
                        TRUE if storage was allocated from the LRU list
 
297
                        and buf_pool_mutex was temporarily released,
 
298
                        or NULL if the LRU list should not be used */
300
299
{
301
300
        buf_block_t*    block;
302
301
 
303
 
        ut_ad(buf_pool_mutex_own(buf_pool));
304
 
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
 
302
        ut_ad(buf_pool_mutex_own());
 
303
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
305
304
 
306
305
        if (i < BUF_BUDDY_SIZES) {
307
306
                /* Try to allocate from the buddy system. */
308
 
                block = (buf_block_t *)buf_buddy_alloc_zip(buf_pool, i);
 
307
                block = buf_buddy_alloc_zip(i);
309
308
 
310
309
                if (block) {
 
310
 
311
311
                        goto func_exit;
312
312
                }
313
313
        }
314
314
 
315
315
        /* Try allocating from the buf_pool->free list. */
316
 
        block = buf_LRU_get_free_only(buf_pool);
 
316
        block = buf_LRU_get_free_only();
317
317
 
318
318
        if (block) {
319
319
 
326
326
        }
327
327
 
328
328
        /* Try replacing an uncompressed page in the buffer pool. */
329
 
        buf_pool_mutex_exit(buf_pool);
330
 
        block = buf_LRU_get_free_block(buf_pool, 0);
 
329
        buf_pool_mutex_exit();
 
330
        block = buf_LRU_get_free_block(0);
331
331
        *lru = TRUE;
332
 
        buf_pool_mutex_enter(buf_pool);
 
332
        buf_pool_mutex_enter();
333
333
 
334
334
alloc_big:
335
335
        buf_buddy_block_register(block);
336
336
 
337
 
        block = (buf_block_t *)buf_buddy_alloc_from(buf_pool, block->frame,
338
 
                                                    i, BUF_BUDDY_SIZES);
 
337
        block = buf_buddy_alloc_from(block->frame, i, BUF_BUDDY_SIZES);
339
338
 
340
339
func_exit:
341
 
        buf_pool->buddy_stat[i].used++;
 
340
        buf_buddy_stat[i].used++;
342
341
        return(block);
343
342
}
344
343
 
353
352
        buf_page_t*     dpage)  /*!< in: free block to relocate to */
354
353
{
355
354
        buf_page_t*     b;
356
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
357
355
 
358
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
356
        ut_ad(buf_pool_mutex_own());
359
357
 
360
358
        switch (buf_page_get_state(bpage)) {
361
359
        case BUF_BLOCK_ZIP_FREE:
373
371
                break;
374
372
        }
375
373
 
376
 
        mutex_enter(&buf_pool->zip_mutex);
 
374
        mutex_enter(&buf_pool_zip_mutex);
377
375
 
378
376
        if (!buf_page_can_relocate(bpage)) {
379
 
                mutex_exit(&buf_pool->zip_mutex);
 
377
                mutex_exit(&buf_pool_zip_mutex);
380
378
                return(FALSE);
381
379
        }
382
380
 
395
393
 
396
394
        UNIV_MEM_INVALID(bpage, sizeof *bpage);
397
395
 
398
 
        mutex_exit(&buf_pool->zip_mutex);
 
396
        mutex_exit(&buf_pool_zip_mutex);
399
397
        return(TRUE);
400
398
}
401
399
 
406
404
ibool
407
405
buf_buddy_relocate(
408
406
/*===============*/
409
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
410
 
        void*           src,            /*!< in: block to relocate */
411
 
        void*           dst,            /*!< in: free block to relocate to */
412
 
        ulint           i)              /*!< in: index of
413
 
                                        buf_pool->zip_free[] */
 
407
        void*   src,    /*!< in: block to relocate */
 
408
        void*   dst,    /*!< in: free block to relocate to */
 
409
        ulint   i)      /*!< in: index of buf_pool->zip_free[] */
414
410
{
415
411
        buf_page_t*     bpage;
416
 
        ulint           space= 0;
417
 
        ulint           page_no= 0;
418
412
        const ulint     size    = BUF_BUDDY_LOW << i;
419
413
        ullint          usec    = ut_time_us(NULL);
 
414
        ulint           space;
 
415
        ulint           page_no;
420
416
 
421
 
        ut_ad(buf_pool_mutex_own(buf_pool));
422
 
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
 
417
        ut_ad(buf_pool_mutex_own());
 
418
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
423
419
        ut_ad(!ut_align_offset(src, size));
424
420
        ut_ad(!ut_align_offset(dst, size));
425
421
        UNIV_MEM_ASSERT_W(dst, size);
456
452
                on uninitialized value. */
457
453
                UNIV_MEM_VALID(&space, sizeof space);
458
454
                UNIV_MEM_VALID(&page_no, sizeof page_no);
459
 
                bpage = buf_page_hash_get(buf_pool, space, page_no);
 
455
                bpage = buf_page_hash_get(space, page_no);
460
456
 
461
457
                if (!bpage || bpage->zip.data != src) {
462
458
                        /* The block has probably been freshly
467
463
                        return(FALSE);
468
464
                }
469
465
 
470
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
471
 
 
472
466
                if (page_zip_get_size(&bpage->zip) != size) {
473
467
                        /* The block is of different size.  We would
474
468
                        have to relocate all blocks covered by src.
490
484
                        /* Relocate the compressed page. */
491
485
                        ut_a(bpage->zip.data == src);
492
486
                        memcpy(dst, src, size);
493
 
                        bpage->zip.data = (page_zip_t *)dst;
 
487
                        bpage->zip.data = dst;
494
488
                        mutex_exit(mutex);
495
489
success:
496
490
                        UNIV_MEM_INVALID(src, size);
497
491
                        {
498
492
                                buf_buddy_stat_t*       buddy_stat
499
 
                                        = &buf_pool->buddy_stat[i];
 
493
                                        = &buf_buddy_stat[i];
500
494
                                buddy_stat->relocated++;
501
495
                                buddy_stat->relocated_usec
502
496
                                        += ut_time_us(NULL) - usec;
513
507
                about uninitialized pad bytes. */
514
508
                UNIV_MEM_ASSERT_RW(src, size);
515
509
#endif
516
 
                if (buf_buddy_relocate_block((buf_page_t *)src, (buf_page_t *)dst)) {
 
510
                if (buf_buddy_relocate_block(src, dst)) {
517
511
 
518
512
                        goto success;
519
513
                }
528
522
void
529
523
buf_buddy_free_low(
530
524
/*===============*/
531
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
532
 
        void*           buf,            /*!< in: block to be freed, must not be
533
 
                                        pointed to by the buffer pool */
534
 
        ulint           i)              /*!< in: index of buf_pool->zip_free[],
535
 
                                        or BUF_BUDDY_SIZES */
 
525
        void*   buf,    /*!< in: block to be freed, must not be
 
526
                        pointed to by the buffer pool */
 
527
        ulint   i)      /*!< in: index of buf_pool->zip_free[],
 
528
                        or BUF_BUDDY_SIZES */
536
529
{
537
530
        buf_page_t*     bpage;
538
531
        buf_page_t*     buddy;
539
532
 
540
 
        ut_ad(buf_pool_mutex_own(buf_pool));
541
 
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
 
533
        ut_ad(buf_pool_mutex_own());
 
534
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
542
535
        ut_ad(i <= BUF_BUDDY_SIZES);
543
 
        ut_ad(buf_pool->buddy_stat[i].used > 0);
 
536
        ut_ad(buf_buddy_stat[i].used > 0);
544
537
 
545
 
        buf_pool->buddy_stat[i].used--;
 
538
        buf_buddy_stat[i].used--;
546
539
recombine:
547
540
        UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i);
548
541
        ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE);
549
542
 
550
543
        if (i == BUF_BUDDY_SIZES) {
551
 
                buf_buddy_block_free(buf_pool, buf);
 
544
                buf_buddy_block_free(buf);
552
545
                return;
553
546
        }
554
547
 
555
548
        ut_ad(i < BUF_BUDDY_SIZES);
556
549
        ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i));
557
 
        ut_ad(!buf_pool_contains_zip(buf_pool, buf));
 
550
        ut_ad(!buf_pool_contains_zip(buf));
558
551
 
559
552
        /* Try to combine adjacent blocks. */
560
553
 
580
573
                if (bpage == buddy) {
581
574
buddy_free:
582
575
                        /* The buddy is free: recombine */
583
 
                        buf_buddy_remove_from_free(buf_pool, bpage, i);
 
576
                        buf_buddy_remove_from_free(bpage, i);
584
577
buddy_free2:
585
578
                        ut_ad(buf_page_get_state(buddy) == BUF_BLOCK_ZIP_FREE);
586
 
                        ut_ad(!buf_pool_contains_zip(buf_pool, buddy));
 
579
                        ut_ad(!buf_pool_contains_zip(buddy));
587
580
                        i++;
588
581
                        buf = ut_align_down(buf, BUF_BUDDY_LOW << i);
589
582
 
615
608
                buf_buddy_relocate() will overwrite bpage->list. */
616
609
 
617
610
                UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
618
 
                buf_buddy_remove_from_free(buf_pool, bpage, i);
 
611
                buf_buddy_remove_from_free(bpage, i);
619
612
 
620
613
                /* Try to relocate the buddy of buf to the free block. */
621
 
                if (buf_buddy_relocate(buf_pool, buddy, bpage, i)) {
 
614
                if (buf_buddy_relocate(buddy, bpage, i)) {
622
615
 
623
616
                        ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
624
617
                        goto buddy_free2;
625
618
                }
626
619
 
627
 
                buf_buddy_add_to_free(buf_pool, bpage, i);
 
620
                buf_buddy_add_to_free(bpage, i);
628
621
 
629
622
                /* Try to relocate the buddy of the free block to buf. */
630
623
                buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage),
645
638
                                            && ut_list_node_313 != buddy)));
646
639
#endif /* !UNIV_DEBUG_VALGRIND */
647
640
 
648
 
                if (buf_buddy_relocate(buf_pool, buddy, buf, i)) {
 
641
                if (buf_buddy_relocate(buddy, buf, i)) {
649
642
 
650
643
                        buf = bpage;
651
644
                        UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
655
648
        }
656
649
 
657
650
        /* Free the block to the buddy list. */
658
 
        bpage = (buf_page_t *)buf;
 
651
        bpage = buf;
659
652
#ifdef UNIV_DEBUG
660
653
        if (i < buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)) {
661
654
                /* This area has most likely been allocated for at
708
701
        }
709
702
#endif /* UNIV_DEBUG */
710
703
        bpage->state = BUF_BLOCK_ZIP_FREE;
711
 
        buf_buddy_add_to_free(buf_pool, bpage, i);
 
704
        buf_buddy_add_to_free(bpage, i);
712
705
}