00001 /* -*- mode:C++; c-basic-offset:4 -*- 00002 Shore-MT -- Multi-threaded port of the SHORE storage manager 00003 00004 Copyright (c) 2007-2009 00005 Data Intensive Applications and Systems Labaratory (DIAS) 00006 Ecole Polytechnique Federale de Lausanne 00007 00008 All Rights Reserved. 00009 00010 Permission to use, copy, modify and distribute this software and 00011 its documentation is hereby granted, provided that both the 00012 copyright notice and this permission notice appear in all copies of 00013 the software, derivative works or modified versions, and any 00014 portions thereof, and that both notices appear in supporting 00015 documentation. 00016 00017 This code is distributed in the hope that it will be useful, but 00018 WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS 00020 DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER 00021 RESULTING FROM THE USE OF THIS SOFTWARE. 00022 */ 00023 /*<std-header orig-src='shore' incl-file-exclusion='BLOCK_ALLOC_CPP'> 00024 00025 $Id: block_alloc.cpp,v 1.7 2012/01/02 21:52:21 nhall Exp $ 00026 00027 SHORE -- Scalable Heterogeneous Object REpository 00028 00029 Copyright (c) 1994-99 Computer Sciences Department, University of 00030 Wisconsin -- Madison 00031 All Rights Reserved. 00032 00033 Permission to use, copy, modify and distribute this software and its 00034 documentation is hereby granted, provided that both the copyright 00035 notice and this permission notice appear in all copies of the 00036 software, derivative works or modified versions, and any portions 00037 thereof, and that both notices appear in supporting documentation. 00038 00039 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY 00040 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS 00041 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND 00042 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 00043 00044 This software was developed with support by the Advanced Research 00045 Project Agency, ARPA order number 018 (formerly 8230), monitored by 00046 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518. 00047 Further funding for this work was provided by DARPA through 00048 Rome Research Laboratory Contract No. F30602-97-2-0247. 00049 00050 */ 00051 00052 #include "block_alloc.h" 00053 #include <cassert> 00054 00055 /**\cond skip */ 00056 00057 /* 00058 * dynpool is a thread-safe list into which 00059 * blocks are released and from which blocks are allocated. 00060 * Blocks are never handed back to the underlying array; they 00061 * are put on a free list and can be there while chips in the 00062 * blocks are still allocated. 00063 */ 00064 00065 dynpool::dynpool(size_t chip_size, size_t chip_count, size_t log2_block_size, size_t max_bytes) 00066 : _chip_size(chip_size) 00067 , _chip_count(chip_count) 00068 , _log2_block_size(log2_block_size) 00069 , _arr_end(0) 00070 { 00071 pthread_mutex_init(&_lock, 0); 00072 int err = _arr.init(max_bytes, size_t(1) << _log2_block_size); 00073 if(err) throw std::bad_alloc(); 00074 } 00075 00076 dynpool::~dynpool() { 00077 pthread_mutex_destroy(&_lock); 00078 _arr.fini(); 00079 } 00080 00081 // Not thread-safe; for debugging only 00082 void 00083 dynpool::dump() const { 00084 int s = _free_list.size(); 00085 int total = s*_chip_count; 00086 size_t curr = _arr.size(); 00087 fprintf(stderr, 00088 "DUMP-----> dynpool %p free %d blks; chip_count %d ttl free chp %d chpsz %d curr %lu capacity %lu acqblk %lu relblk %lu\n", 00089 (void *)this, 00090 s, 00091 int(_chip_count), 00092 total, 00093 int(_chip_size), 00094 curr, 00095 _arr.capacity(), 00096 0x0ul , 0x0ul 00097 ); 00098 } 00099 00100 /**\brief Allocate a block. 00101 * Mutex-protected. 00102 * Look on free list first. If nothing there, extend the 00103 * underlying array. 00104 */ 00105 dynpool::mblock* dynpool::_acquire_block() { 00106 mblock* rval; 00107 pthread_mutex_lock(&_lock); 00108 /* 00109 * NOTE: we construct the block of chips only when we 00110 * acquired one from the underlying array; blocks pushed 00111 * onto the free list and popped off might still contain 00112 * allocated chips so we do not construct these. 00113 * Thus one thread can allocate a chip and then go away while 00114 * the chip is still in use. 00115 */ 00116 if(_free_list.empty()) { 00117 size_t block_size = size_t(1) << _log2_block_size; 00118 size_t new_end = _arr_end+block_size; 00119 int err = _arr.ensure_capacity(new_end); 00120 if(err) { 00121 dump(); 00122 throw std::bad_alloc(); 00123 } 00124 rval = new (_arr+_arr_end) mblock(_chip_size, _chip_count, block_size); 00125 _arr_end = new_end; 00126 } 00127 else { 00128 rval = _free_list.front(); 00129 _free_list.pop_front(); 00130 } 00131 pthread_mutex_unlock(&_lock); 00132 00133 return rval; 00134 } 00135 00136 void dynpool::_release_block(mblock* b) { 00137 pthread_mutex_lock(&_lock); 00138 _free_list.push_back(b); 00139 pthread_mutex_unlock(&_lock); 00140 } 00141 00142 bool dynpool::validate_pointer(void* ptr) { 00143 // no need for the mutex... dynarray only grows 00144 union { void* v; char* c; } u={ptr}; 00145 size_t offset = u.c - _arr; 00146 // An assertion here has been seen when the 00147 // user did this: 00148 // w_rc_t func() {} 00149 // and compiled w/o any warning (-Wall) to 00150 // tell him about the lack of a return value. Then 00151 // called the function. That gets us here. 00152 if((u.c < _arr) || (offset >= _arr_end)) { 00153 fprintf(stderr, 00154 "Assertion failure in dynpool: invalid pointer. %s\n", 00155 "(Did you fail to provide a return value for a w_rc_t-valued function?)"); 00156 } 00157 assert (u.c >= _arr); 00158 return offset < _arr_end; 00159 } 00160 /**\endcond skip */ 00161