~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-10-20 20:26:18 UTC
  • mfrom: (1859.2.13 refactor)
  • Revision ID: brian@tangent.org-20101020202618-9222n39lm329urv5
Merge for Brian 

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, 2009, 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
 
393
391
                UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, dpage);
394
392
        }
395
393
 
396
 
        UNIV_MEM_INVALID(bpage, sizeof *bpage);
397
 
 
398
 
        mutex_exit(&buf_pool->zip_mutex);
 
394
        mutex_exit(&buf_pool_zip_mutex);
399
395
        return(TRUE);
400
396
}
401
397
 
406
402
ibool
407
403
buf_buddy_relocate(
408
404
/*===============*/
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[] */
 
405
        void*   src,    /*!< in: block to relocate */
 
406
        void*   dst,    /*!< in: free block to relocate to */
 
407
        ulint   i)      /*!< in: index of buf_pool->zip_free[] */
414
408
{
415
409
        buf_page_t*     bpage;
416
 
        ulint           space= 0;
417
 
        ulint           page_no= 0;
418
410
        const ulint     size    = BUF_BUDDY_LOW << i;
419
411
        ullint          usec    = ut_time_us(NULL);
420
412
 
421
 
        ut_ad(buf_pool_mutex_own(buf_pool));
422
 
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
 
413
        ut_ad(buf_pool_mutex_own());
 
414
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
423
415
        ut_ad(!ut_align_offset(src, size));
424
416
        ut_ad(!ut_align_offset(dst, size));
425
417
        UNIV_MEM_ASSERT_W(dst, size);
448
440
                pool), so there is nothing wrong about this.  The
449
441
                mach_read_from_4() calls here will only trigger bogus
450
442
                Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
451
 
                space   = mach_read_from_4(
452
 
                        (const byte*) src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
453
 
                page_no = mach_read_from_4(
454
 
                        (const byte*) src + FIL_PAGE_OFFSET);
455
 
                /* Suppress Valgrind warnings about conditional jump
456
 
                on uninitialized value. */
457
 
                UNIV_MEM_VALID(&space, sizeof space);
458
 
                UNIV_MEM_VALID(&page_no, sizeof page_no);
459
 
                bpage = buf_page_hash_get(buf_pool, space, page_no);
 
443
                bpage = buf_page_hash_get(
 
444
                        mach_read_from_4((const byte*) src
 
445
                                         + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID),
 
446
                        mach_read_from_4((const byte*) src
 
447
                                         + FIL_PAGE_OFFSET));
460
448
 
461
449
                if (!bpage || bpage->zip.data != src) {
462
450
                        /* The block has probably been freshly
467
455
                        return(FALSE);
468
456
                }
469
457
 
470
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
471
 
 
472
458
                if (page_zip_get_size(&bpage->zip) != size) {
473
459
                        /* The block is of different size.  We would
474
460
                        have to relocate all blocks covered by src.
490
476
                        /* Relocate the compressed page. */
491
477
                        ut_a(bpage->zip.data == src);
492
478
                        memcpy(dst, src, size);
493
 
                        bpage->zip.data = (page_zip_t *)dst;
 
479
                        bpage->zip.data = dst;
494
480
                        mutex_exit(mutex);
495
481
success:
496
482
                        UNIV_MEM_INVALID(src, size);
497
483
                        {
498
484
                                buf_buddy_stat_t*       buddy_stat
499
 
                                        = &buf_pool->buddy_stat[i];
 
485
                                        = &buf_buddy_stat[i];
500
486
                                buddy_stat->relocated++;
501
487
                                buddy_stat->relocated_usec
502
488
                                        += ut_time_us(NULL) - usec;
507
493
                mutex_exit(mutex);
508
494
        } else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) {
509
495
                /* This must be a buf_page_t object. */
510
 
#if UNIV_WORD_SIZE == 4
511
 
                /* On 32-bit systems, there is no padding in
512
 
                buf_page_t.  On other systems, Valgrind could complain
513
 
                about uninitialized pad bytes. */
514
496
                UNIV_MEM_ASSERT_RW(src, size);
515
 
#endif
516
 
                if (buf_buddy_relocate_block((buf_page_t *)src, (buf_page_t *)dst)) {
 
497
                if (buf_buddy_relocate_block(src, dst)) {
517
498
 
518
499
                        goto success;
519
500
                }
528
509
void
529
510
buf_buddy_free_low(
530
511
/*===============*/
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 */
 
512
        void*   buf,    /*!< in: block to be freed, must not be
 
513
                        pointed to by the buffer pool */
 
514
        ulint   i)      /*!< in: index of buf_pool->zip_free[],
 
515
                        or BUF_BUDDY_SIZES */
536
516
{
537
517
        buf_page_t*     bpage;
538
518
        buf_page_t*     buddy;
539
519
 
540
 
        ut_ad(buf_pool_mutex_own(buf_pool));
541
 
        ut_ad(!mutex_own(&buf_pool->zip_mutex));
 
520
        ut_ad(buf_pool_mutex_own());
 
521
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
542
522
        ut_ad(i <= BUF_BUDDY_SIZES);
543
 
        ut_ad(buf_pool->buddy_stat[i].used > 0);
 
523
        ut_ad(buf_buddy_stat[i].used > 0);
544
524
 
545
 
        buf_pool->buddy_stat[i].used--;
 
525
        buf_buddy_stat[i].used--;
546
526
recombine:
547
527
        UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i);
548
528
        ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE);
549
529
 
550
530
        if (i == BUF_BUDDY_SIZES) {
551
 
                buf_buddy_block_free(buf_pool, buf);
 
531
                buf_buddy_block_free(buf);
552
532
                return;
553
533
        }
554
534
 
555
535
        ut_ad(i < BUF_BUDDY_SIZES);
556
536
        ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i));
557
 
        ut_ad(!buf_pool_contains_zip(buf_pool, buf));
 
537
        ut_ad(!buf_pool_contains_zip(buf));
558
538
 
559
539
        /* Try to combine adjacent blocks. */
560
540
 
580
560
                if (bpage == buddy) {
581
561
buddy_free:
582
562
                        /* The buddy is free: recombine */
583
 
                        buf_buddy_remove_from_free(buf_pool, bpage, i);
 
563
                        buf_buddy_remove_from_free(bpage, i);
584
564
buddy_free2:
585
565
                        ut_ad(buf_page_get_state(buddy) == BUF_BLOCK_ZIP_FREE);
586
 
                        ut_ad(!buf_pool_contains_zip(buf_pool, buddy));
 
566
                        ut_ad(!buf_pool_contains_zip(buddy));
587
567
                        i++;
588
568
                        buf = ut_align_down(buf, BUF_BUDDY_LOW << i);
589
569
 
615
595
                buf_buddy_relocate() will overwrite bpage->list. */
616
596
 
617
597
                UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
618
 
                buf_buddy_remove_from_free(buf_pool, bpage, i);
 
598
                buf_buddy_remove_from_free(bpage, i);
619
599
 
620
600
                /* Try to relocate the buddy of buf to the free block. */
621
 
                if (buf_buddy_relocate(buf_pool, buddy, bpage, i)) {
 
601
                if (buf_buddy_relocate(buddy, bpage, i)) {
622
602
 
623
603
                        ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
624
604
                        goto buddy_free2;
625
605
                }
626
606
 
627
 
                buf_buddy_add_to_free(buf_pool, bpage, i);
 
607
                buf_buddy_add_to_free(bpage, i);
628
608
 
629
609
                /* Try to relocate the buddy of the free block to buf. */
630
610
                buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage),
645
625
                                            && ut_list_node_313 != buddy)));
646
626
#endif /* !UNIV_DEBUG_VALGRIND */
647
627
 
648
 
                if (buf_buddy_relocate(buf_pool, buddy, buf, i)) {
 
628
                if (buf_buddy_relocate(buddy, buf, i)) {
649
629
 
650
630
                        buf = bpage;
651
631
                        UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
655
635
        }
656
636
 
657
637
        /* Free the block to the buddy list. */
658
 
        bpage = (buf_page_t *)buf;
 
638
        bpage = buf;
659
639
#ifdef UNIV_DEBUG
660
640
        if (i < buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)) {
661
641
                /* This area has most likely been allocated for at
708
688
        }
709
689
#endif /* UNIV_DEBUG */
710
690
        bpage->state = BUF_BLOCK_ZIP_FREE;
711
 
        buf_buddy_add_to_free(buf_pool, bpage, i);
 
691
        buf_buddy_add_to_free(bpage, i);
712
692
}