diff --git a/Makefile.am b/Makefile.am index 74c0f11d5a5..7edfe241644 100644 --- a/Makefile.am +++ b/Makefile.am @@ -40,6 +40,7 @@ SUBDIRS = os ut btr buf data dict dyn eval fil fsp fut \ EXTRA_DIST = include/btr0btr.h include/btr0btr.ic include/btr0cur.h include/btr0cur.ic \ include/btr0pcur.h include/btr0pcur.ic include/btr0sea.h include/btr0sea.ic \ include/btr0types.h \ + include/buf0buddy.h include/buf0buddy.ic \ include/buf0buf.h include/buf0buf.ic include/buf0flu.h include/buf0flu.ic \ include/buf0lru.h include/buf0lru.ic include/buf0rea.h include/buf0types.h \ include/data0data.h include/data0data.ic include/data0type.h include/data0type.ic \ diff --git a/buf/Makefile.am b/buf/Makefile.am index 3f56c8b02d7..21f58506baa 100644 --- a/buf/Makefile.am +++ b/buf/Makefile.am @@ -19,6 +19,6 @@ include ../include/Makefile.i noinst_LIBRARIES = libbuf.a -libbuf_a_SOURCES = buf0buf.c buf0flu.c buf0lru.c buf0rea.c +libbuf_a_SOURCES = buf0buf.c buf0buddy.c buf0flu.c buf0lru.c buf0rea.c EXTRA_PROGRAMS = diff --git a/buf/buf0buddy.c b/buf/buf0buddy.c new file mode 100644 index 00000000000..76fc848639e --- /dev/null +++ b/buf/buf0buddy.c @@ -0,0 +1,43 @@ +/****************************************************** +Binary buddy allocator for compressed pages + +(c) 2006 Innobase Oy + +Created December 2006 by Marko Makela +*******************************************************/ + +#define THIS_MODULE +#include "buf0buddy.h" +#ifdef UNIV_NONINL +# include "buf0buddy.ic" +#endif +#undef THIS_MODULE +#include "buf0buf.h" + +/************************************************************************** +Try to allocate a block from buf_pool->zip_free[]. */ + +void* +buf_buddy_alloc_free_low( +/*=====================*/ + /* out: allocated block, or NULL + if buf_pool->zip_free[] was empty */ + ulint i) /* in: index of buf_pool->zip_free[] */ +{ + buf_page_t* bpage; + +#ifdef UNIV_SYNC_DEBUG + ut_a(mutex_own(&buf_pool->mutex)); +#endif /* UNIV_SYNC_DEBUG */ + ut_a(i < BUF_BUDDY_SIZES); + + bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); + + if (bpage) { + ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE); + + UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage); + } + + return(bpage); +} diff --git a/buf/buf0buf.c b/buf/buf0buf.c index c7b22ed15b1..23b563aa7e8 100644 --- a/buf/buf0buf.c +++ b/buf/buf0buf.c @@ -826,6 +826,8 @@ buf_pool_init(void) mutex_enter(&(buf_pool->mutex)); + mutex_create(&buf_pool->zip_mutex, SYNC_BUF_BLOCK); + buf_pool->n_chunks = 1; buf_pool->chunks = chunk = mem_alloc(sizeof *chunk); @@ -884,6 +886,14 @@ buf_pool_init(void) btr_search_sys_create(buf_pool->curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64); + /* 4. Initialize the buddy allocator fields */ + + UT_LIST_INIT(buf_pool->zip_clean); + + for (i = 0; i < BUF_BUDDY_SIZES; i++) { + UT_LIST_INIT(buf_pool->zip_free[i]); + } + return(buf_pool); } diff --git a/include/buf0buddy.h b/include/buf0buddy.h new file mode 100644 index 00000000000..96fa76de84e --- /dev/null +++ b/include/buf0buddy.h @@ -0,0 +1,57 @@ +/****************************************************** +Binary buddy allocator for compressed pages + +(c) 2006 Innobase Oy + +Created December 2006 by Marko Makela +*******************************************************/ + +#ifndef buf0buddy_h +#define buf0buddy_h + +#ifdef UNIV_MATERIALIZE +# undef UNIV_INLINE +# define UNIV_INLINE +#endif + +#include "univ.i" +#include "buf0types.h" + +/************************************************************************** +Get the offset of the buddy of a compressed page frame. */ +UNIV_INLINE +lint +buf_buddy_get_offset( +/*=================*/ + /* out: offset of the buddy relative to page */ + const void* page, /* in: compressed page */ + ulint size) /* in: page size in bytes */ + __attribute__((nonnull)); + +/************************************************************************** +Get the buddy of a compressed page frame. */ +#define buf_buddy_get(page,size) ((page) + buf_buddy_get_offset((page),(size))) + +/************************************************************************** +Get the index of buf_pool->zip_free[] for a given block size. */ +UNIV_INLINE +ulint +buf_buddy_get_slot( +/*===============*/ + /* out: index of buf_pool->zip_free[] */ + ulint size); /* in: block size */ + +/************************************************************************** +Try to allocate a block from buf_pool->zip_free[]. */ +UNIV_INLINE +void* +buf_buddy_alloc_free( +/*=================*/ + ulint size) /* in: block size, up to UNIV_PAGE_SIZE / 2 */ + __attribute__((malloc)); + +#ifndef UNIV_NONINL +# include "buf0buddy.ic" +#endif + +#endif /* buf0buddy_h */ diff --git a/include/buf0buddy.ic b/include/buf0buddy.ic new file mode 100644 index 00000000000..c34860d4982 --- /dev/null +++ b/include/buf0buddy.ic @@ -0,0 +1,85 @@ +/****************************************************** +Binary buddy allocator for compressed pages + +(c) 2006 Innobase Oy + +Created December 2006 by Marko Makela +*******************************************************/ + +#ifdef UNIV_MATERIALIZE +# undef UNIV_INLINE +# define UNIV_INLINE +#endif + +#include "buf0buddy.h" +#include "ut0ut.h" + +/************************************************************************** +Try to allocate a block from buf_pool->zip_free[]. */ + +void* +buf_buddy_alloc_free_low( +/*=====================*/ + /* out: allocated block, or NULL + if buf_pool->zip_free[] was empty */ + ulint i) /* in: index of buf_pool->zip_free[] */ + __attribute__((malloc)); + +/************************************************************************** +Get the offset of the buddy of a compressed page frame. */ +UNIV_INLINE +lint +buf_buddy_get_offset( +/*=================*/ + /* out: offset of the buddy relative to page */ + const void* page, /* in: compressed page */ + ulint size) /* in: page size in bytes */ +{ + ut_ad(ut_is_2pow(size)); + ut_ad(size >= BUF_BUDDY_LOW); + ut_ad(size < BUF_BUDDY_LOW << BUF_BUDDY_SIZES); + + if (((ulint) page) & size) { + return(-(lint) size); + } else { + return((lint) size); + } +} + +/************************************************************************** +Get the index of buf_pool->zip_free[] for a given block size. */ +UNIV_INLINE +ulint +buf_buddy_get_slot( +/*===============*/ + /* out: index of buf_pool->zip_free[] */ + ulint size) /* in: block size */ +{ + ulint i; + ulint s; + + for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1); + + ut_ad(i < BUF_BUDDY_SIZES); + return(i); +} + +/************************************************************************** +Try to allocate a block from buf_pool->zip_free[]. */ +UNIV_INLINE +void* +buf_buddy_alloc_free( +/*=================*/ + ulint size) /* in: block size, up to UNIV_PAGE_SIZE / 2 */ +{ +#ifdef UNIV_SYNC_DEBUG + ut_a(mutex_own(&buf_pool->mutex)); +#endif /* UNIV_SYNC_DEBUG */ + + return(buf_buddy_alloc_free_low(buf_buddy_get_slot(size))); +} + +#ifdef UNIV_MATERIALIZE +# undef UNIV_INLINE +# define UNIV_INLINE UNIV_INLINE_ORIGINAL +#endif diff --git a/include/buf0buf.h b/include/buf0buf.h index f5cd4a6e971..e676b866228 100644 --- a/include/buf0buf.h +++ b/include/buf0buf.h @@ -1089,6 +1089,9 @@ struct buf_pool_struct{ mutex_t mutex; /* mutex protecting the buffer pool struct and control blocks, except the read-write lock in them */ + mutex_t zip_mutex; /* mutex protecting the control blocks + of compressed-only pages (of type + buf_page_t, not buf_block_t) */ ulint n_chunks; /* number of buffer pool chunks */ buf_chunk_t* chunks; /* buffer pool chunks */ ulint curr_size; /* current pool size in pages */ @@ -1162,6 +1165,18 @@ struct buf_pool_struct{ see buf0lru.c for the restrictions on this value; not defined if LRU_old == NULL */ + + /* 4. Fields for the buddy allocator of compressed pages */ + UT_LIST_BASE_NODE_T(buf_page_t) zip_clean; + /* unmodified compressed pages */ + UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES]; + /* buddy free lists */ +#if BUF_BUDDY_LOW << BUF_BUDDY_SIZES != UNIV_PAGE_SIZE +# error "BUF_BUDDY_LOW << BUF_BUDDY_SIZES != UNIV_PAGE_SIZE" +#endif +#if BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE +# error "BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE" +#endif }; /************************************************************************ diff --git a/include/buf0buf.ic b/include/buf0buf.ic index a91959969c7..964d0d8766b 100644 --- a/include/buf0buf.ic +++ b/include/buf0buf.ic @@ -261,7 +261,7 @@ buf_page_get_mutex( break; case BUF_BLOCK_ZIP_PAGE: case BUF_BLOCK_ZIP_DIRTY: - return(NULL); /* TODO: return common mutex for page_zip */ + return(&buf_pool->zip_mutex); default: return(&((buf_block_t*) bpage)->mutex); } diff --git a/include/buf0types.h b/include/buf0types.h index 38e40d8a1f5..83ed19e4a11 100644 --- a/include/buf0types.h +++ b/include/buf0types.h @@ -32,5 +32,16 @@ enum buf_io_fix { BUF_IO_WRITE /**< write pending */ }; +/* Parameters of binary buddy system for compressed pages (buf0buddy.h) */ +#if UNIV_WORD_SIZE <= 4 /* 32-bit system */ +# define BUF_BUDDY_LOW 64 /* minimum block size in the binary + buddy system; must be at least + sizeof(buf_page_t) */ +# define BUF_BUDDY_SIZES 8 /* number of buddy sizes */ +#else /* 64-bit system */ +# define BUF_BUDDY_LOW 128 /* sizeof(buf_page_t) > 64 */ +# define BUF_BUDDY_SIZES 7 +#endif + #endif