~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2009-04-14 19:16:51 UTC
  • mto: (997.2.5 mordred)
  • mto: This revision was merged to the branch mainline in revision 994.
  • Revision ID: mordred@inaugust.com-20090414191651-ltbww6hpqks8k7qk
Clarified instructions in README.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
*****************************************************************************/
18
18
 
19
 
/**************************************************//**
20
 
@file buf/buf0buddy.c
 
19
/******************************************************
21
20
Binary buddy allocator for compressed pages
22
21
 
23
22
Created December 2006 by Marko Makela
45
44
Protected by buf_pool_mutex. */
46
45
UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1];
47
46
 
48
 
/**********************************************************************//**
49
 
Get the offset of the buddy of a compressed page frame.
50
 
@return the buddy relative of page */
 
47
/**************************************************************************
 
48
Get the offset of the buddy of a compressed page frame. */
51
49
UNIV_INLINE
52
50
byte*
53
51
buf_buddy_get(
54
52
/*==========*/
55
 
        byte*   page,   /*!< in: compressed page */
56
 
        ulint   size)   /*!< in: page size in bytes */
 
53
                        /* out: the buddy relative of page */
 
54
        byte*   page,   /* in: compressed page */
 
55
        ulint   size)   /* in: page size in bytes */
57
56
{
58
57
        ut_ad(ut_is_2pow(size));
59
58
        ut_ad(size >= BUF_BUDDY_LOW);
67
66
        }
68
67
}
69
68
 
70
 
/**********************************************************************//**
 
69
/**************************************************************************
71
70
Add a block to the head of the appropriate buddy free list. */
72
71
UNIV_INLINE
73
72
void
74
73
buf_buddy_add_to_free(
75
74
/*==================*/
76
 
        buf_page_t*     bpage,  /*!< in,own: block to be freed */
77
 
        ulint           i)      /*!< in: index of buf_pool->zip_free[] */
 
75
        buf_page_t*     bpage,  /* in,own: block to be freed */
 
76
        ulint           i)      /* in: index of buf_pool->zip_free[] */
78
77
{
79
78
#ifdef UNIV_DEBUG_VALGRIND
80
79
        buf_page_t*     b  = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
82
81
        if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i);
83
82
#endif /* UNIV_DEBUG_VALGRIND */
84
83
 
85
 
        ut_ad(buf_pool_mutex_own());
86
 
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
87
84
        ut_ad(buf_pool->zip_free[i].start != bpage);
88
85
        UT_LIST_ADD_FIRST(list, buf_pool->zip_free[i], bpage);
89
86
 
93
90
#endif /* UNIV_DEBUG_VALGRIND */
94
91
}
95
92
 
96
 
/**********************************************************************//**
 
93
/**************************************************************************
97
94
Remove a block from the appropriate buddy free list. */
98
95
UNIV_INLINE
99
96
void
100
97
buf_buddy_remove_from_free(
101
98
/*=======================*/
102
 
        buf_page_t*     bpage,  /*!< in: block to be removed */
103
 
        ulint           i)      /*!< in: index of buf_pool->zip_free[] */
 
99
        buf_page_t*     bpage,  /* in: block to be removed */
 
100
        ulint           i)      /* in: index of buf_pool->zip_free[] */
104
101
{
105
102
#ifdef UNIV_DEBUG_VALGRIND
106
103
        buf_page_t*     prev = UT_LIST_GET_PREV(list, bpage);
113
110
        ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
114
111
#endif /* UNIV_DEBUG_VALGRIND */
115
112
 
116
 
        ut_ad(buf_pool_mutex_own());
117
113
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
118
114
        UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage);
119
115
 
123
119
#endif /* UNIV_DEBUG_VALGRIND */
124
120
}
125
121
 
126
 
/**********************************************************************//**
127
 
Try to allocate a block from buf_pool->zip_free[].
128
 
@return allocated block, or NULL if buf_pool->zip_free[] was empty */
 
122
/**************************************************************************
 
123
Try to allocate a block from buf_pool->zip_free[]. */
129
124
static
130
125
void*
131
126
buf_buddy_alloc_zip(
132
127
/*================*/
133
 
        ulint   i)      /*!< in: index of buf_pool->zip_free[] */
 
128
                        /* out: allocated block, or NULL
 
129
                        if buf_pool->zip_free[] was empty */
 
130
        ulint   i)      /* in: index of buf_pool->zip_free[] */
134
131
{
135
132
        buf_page_t*     bpage;
136
133
 
137
134
        ut_ad(buf_pool_mutex_own());
138
135
        ut_a(i < BUF_BUDDY_SIZES);
139
136
 
140
 
#ifndef UNIV_DEBUG_VALGRIND
 
137
#if defined UNIV_DEBUG && !defined UNIV_DEBUG_VALGRIND
141
138
        /* Valgrind would complain about accessing free memory. */
142
 
        ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
143
 
                              ut_ad(buf_page_get_state(ut_list_node_313)
144
 
                                    == BUF_BLOCK_ZIP_FREE)));
145
 
#endif /* !UNIV_DEBUG_VALGRIND */
 
139
        UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i]);
 
140
#endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
146
141
        bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
147
142
 
148
143
        if (bpage) {
176
171
        return(bpage);
177
172
}
178
173
 
179
 
/**********************************************************************//**
 
174
/**************************************************************************
180
175
Deallocate a buffer frame of UNIV_PAGE_SIZE. */
181
176
static
182
177
void
183
178
buf_buddy_block_free(
184
179
/*=================*/
185
 
        void*   buf)    /*!< in: buffer frame to deallocate */
 
180
        void*   buf)    /* in: buffer frame to deallocate */
186
181
{
187
182
        const ulint     fold    = BUF_POOL_ZIP_FOLD_PTR(buf);
188
183
        buf_page_t*     bpage;
215
210
        ut_d(buf_buddy_n_frames--);
216
211
}
217
212
 
218
 
/**********************************************************************//**
 
213
/**************************************************************************
219
214
Allocate a buffer block to the buddy allocator. */
220
215
static
221
216
void
222
217
buf_buddy_block_register(
223
218
/*=====================*/
224
 
        buf_block_t*    block)  /*!< in: buffer frame to allocate */
 
219
        buf_block_t*    block)  /* in: buffer frame to allocate */
225
220
{
226
221
        const ulint     fold = BUF_POOL_ZIP_FOLD(block);
227
222
        ut_ad(buf_pool_mutex_own());
228
223
        ut_ad(!mutex_own(&buf_pool_zip_mutex));
229
 
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE);
230
224
 
231
225
        buf_block_set_state(block, BUF_BLOCK_MEMORY);
232
226
 
241
235
        ut_d(buf_buddy_n_frames++);
242
236
}
243
237
 
244
 
/**********************************************************************//**
245
 
Allocate a block from a bigger object.
246
 
@return allocated block */
 
238
/**************************************************************************
 
239
Allocate a block from a bigger object. */
247
240
static
248
241
void*
249
242
buf_buddy_alloc_from(
250
243
/*=================*/
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
 
244
                                /* out: allocated block */
 
245
        void*           buf,    /* in: a block that is free to use */
 
246
        ulint           i,      /* in: index of buf_pool->zip_free[] */
 
247
        ulint           j)      /* in: size of buf as an index
254
248
                                of buf_pool->zip_free[] */
255
249
{
256
250
        ulint   offs    = BUF_BUDDY_LOW << j;
268
262
                bpage = (buf_page_t*) ((byte*) buf + offs);
269
263
                ut_d(memset(bpage, j, BUF_BUDDY_LOW << j));
270
264
                bpage->state = BUF_BLOCK_ZIP_FREE;
271
 
#ifndef UNIV_DEBUG_VALGRIND
 
265
#if defined UNIV_DEBUG && !defined UNIV_DEBUG_VALGRIND
272
266
                /* Valgrind would complain about accessing free memory. */
273
 
                ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
274
 
                                      ut_ad(buf_page_get_state(
275
 
                                                    ut_list_node_313)
276
 
                                            == BUF_BLOCK_ZIP_FREE)));
277
 
#endif /* !UNIV_DEBUG_VALGRIND */
 
267
                UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[j]);
 
268
#endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
278
269
                buf_buddy_add_to_free(bpage, j);
279
270
        }
280
271
 
281
272
        return(buf);
282
273
}
283
274
 
284
 
/**********************************************************************//**
 
275
/**************************************************************************
285
276
Allocate a block.  The thread calling this function must hold
286
277
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.
288
 
@return allocated block, possibly NULL if lru==NULL */
 
278
The buf_pool_mutex may only be released and reacquired if lru != NULL. */
289
279
UNIV_INTERN
290
280
void*
291
281
buf_buddy_alloc_low(
292
282
/*================*/
293
 
        ulint   i,      /*!< in: index of buf_pool->zip_free[],
 
283
                        /* out: allocated block,
 
284
                        possibly NULL if lru==NULL */
 
285
        ulint   i,      /* in: index of buf_pool->zip_free[],
294
286
                        or BUF_BUDDY_SIZES */
295
 
        ibool*  lru)    /*!< in: pointer to a variable that will be assigned
 
287
        ibool*  lru)    /* in: pointer to a variable that will be assigned
296
288
                        TRUE if storage was allocated from the LRU list
297
289
                        and buf_pool_mutex was temporarily released,
298
290
                        or NULL if the LRU list should not be used */
341
333
        return(block);
342
334
}
343
335
 
344
 
/**********************************************************************//**
345
 
Try to relocate the control block of a compressed page.
346
 
@return TRUE if relocated */
 
336
/**************************************************************************
 
337
Try to relocate the control block of a compressed page. */
347
338
static
348
339
ibool
349
340
buf_buddy_relocate_block(
350
341
/*=====================*/
351
 
        buf_page_t*     bpage,  /*!< in: block to relocate */
352
 
        buf_page_t*     dpage)  /*!< in: free block to relocate to */
 
342
                                /* out: TRUE if relocated */
 
343
        buf_page_t*     bpage,  /* in: block to relocate */
 
344
        buf_page_t*     dpage)  /* in: free block to relocate to */
353
345
{
354
346
        buf_page_t*     b;
355
347
 
395
387
        return(TRUE);
396
388
}
397
389
 
398
 
/**********************************************************************//**
399
 
Try to relocate a block.
400
 
@return TRUE if relocated */
 
390
/**************************************************************************
 
391
Try to relocate a block. */
401
392
static
402
393
ibool
403
394
buf_buddy_relocate(
404
395
/*===============*/
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[] */
 
396
                        /* out: TRUE if relocated */
 
397
        void*   src,    /* in: block to relocate */
 
398
        void*   dst,    /* in: free block to relocate to */
 
399
        ulint   i)      /* in: index of buf_pool->zip_free[] */
408
400
{
409
401
        buf_page_t*     bpage;
410
402
        const ulint     size    = BUF_BUDDY_LOW << i;
503
495
        return(FALSE);
504
496
}
505
497
 
506
 
/**********************************************************************//**
 
498
/**************************************************************************
507
499
Deallocate a block. */
508
500
UNIV_INTERN
509
501
void
510
502
buf_buddy_free_low(
511
503
/*===============*/
512
 
        void*   buf,    /*!< in: block to be freed, must not be
 
504
        void*   buf,    /* in: block to be freed, must not be
513
505
                        pointed to by the buffer pool */
514
 
        ulint   i)      /*!< in: index of buf_pool->zip_free[],
515
 
                        or BUF_BUDDY_SIZES */
 
506
        ulint   i)      /* in: index of buf_pool->zip_free[] */
516
507
{
517
508
        buf_page_t*     bpage;
518
509
        buf_page_t*     buddy;
582
573
#ifndef UNIV_DEBUG_VALGRIND
583
574
buddy_nonfree:
584
575
        /* Valgrind would complain about accessing free memory. */
585
 
        ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
586
 
                              ut_ad(buf_page_get_state(ut_list_node_313)
587
 
                                    == BUF_BLOCK_ZIP_FREE)));
 
576
        ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i]));
588
577
#endif /* UNIV_DEBUG_VALGRIND */
589
578
 
590
579
        /* The buddy is not free. Is there a free block of this size? */
610
599
                buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage),
611
600
                                                    BUF_BUDDY_LOW << i);
612
601
 
613
 
#ifndef UNIV_DEBUG_VALGRIND
614
 
                /* Valgrind would complain about accessing free memory. */
615
 
 
616
 
                /* The buddy must not be (completely) free, because we
617
 
                always recombine adjacent free blocks.
618
 
 
619
 
                (Parts of the buddy can be free in
620
 
                buf_pool->zip_free[j] with j < i.) */
621
 
                ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
622
 
                                      ut_ad(buf_page_get_state(
623
 
                                                    ut_list_node_313)
624
 
                                            == BUF_BLOCK_ZIP_FREE
625
 
                                            && ut_list_node_313 != buddy)));
626
 
#endif /* !UNIV_DEBUG_VALGRIND */
 
602
#if defined UNIV_DEBUG && !defined UNIV_DEBUG_VALGRIND
 
603
                {
 
604
                        const buf_page_t* b;
 
605
 
 
606
                        /* The buddy must not be (completely) free, because
 
607
                        we always recombine adjacent free blocks.
 
608
                        (Parts of the buddy can be free in
 
609
                        buf_pool->zip_free[j] with j < i.)*/
 
610
                        for (b = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
 
611
                             b; b = UT_LIST_GET_NEXT(list, b)) {
 
612
 
 
613
                                ut_a(b != buddy);
 
614
                        }
 
615
                }
 
616
#endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
627
617
 
628
618
                if (buf_buddy_relocate(buddy, buf, i)) {
629
619