17
17
*****************************************************************************/
19
/**************************************************//**
19
/******************************************************
21
20
Binary buddy allocator for compressed pages
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];
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. */
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 */
58
57
ut_ad(ut_is_2pow(size));
59
58
ut_ad(size >= BUF_BUDDY_LOW);
70
/**********************************************************************//**
69
/**************************************************************************
71
70
Add a block to the head of the appropriate buddy free list. */
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[] */
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 */
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);
93
90
#endif /* UNIV_DEBUG_VALGRIND */
96
/**********************************************************************//**
93
/**************************************************************************
97
94
Remove a block from the appropriate buddy free list. */
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[] */
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 */
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);
123
119
#endif /* UNIV_DEBUG_VALGRIND */
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[]. */
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[] */
135
132
buf_page_t* bpage;
137
134
ut_ad(buf_pool_mutex_own());
138
135
ut_a(i < BUF_BUDDY_SIZES);
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]);
179
/**********************************************************************//**
174
/**************************************************************************
180
175
Deallocate a buffer frame of UNIV_PAGE_SIZE. */
183
178
buf_buddy_block_free(
184
179
/*=================*/
185
void* buf) /*!< in: buffer frame to deallocate */
180
void* buf) /* in: buffer frame to deallocate */
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--);
218
/**********************************************************************//**
213
/**************************************************************************
219
214
Allocate a buffer block to the buddy allocator. */
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 */
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);
231
225
buf_block_set_state(block, BUF_BLOCK_MEMORY);
241
235
ut_d(buf_buddy_n_frames++);
244
/**********************************************************************//**
245
Allocate a block from a bigger object.
246
@return allocated block */
238
/**************************************************************************
239
Allocate a block from a bigger object. */
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[] */
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(
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);
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. */
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 */
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. */
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 */
398
/**********************************************************************//**
399
Try to relocate a block.
400
@return TRUE if relocated */
390
/**************************************************************************
391
Try to relocate a block. */
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[] */
409
401
buf_page_t* bpage;
410
402
const ulint size = BUF_BUDDY_LOW << i;
506
/**********************************************************************//**
498
/**************************************************************************
507
499
Deallocate a block. */
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[] */
517
508
buf_page_t* bpage;
518
509
buf_page_t* buddy;
582
573
#ifndef UNIV_DEBUG_VALGRIND
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 */
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);
613
#ifndef UNIV_DEBUG_VALGRIND
614
/* Valgrind would complain about accessing free memory. */
616
/* The buddy must not be (completely) free, because we
617
always recombine adjacent free blocks.
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(
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
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)) {
616
#endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
628
618
if (buf_buddy_relocate(buddy, buf, i)) {