block_alloc.cpp

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 

Generated on Mon Jan 2 15:13:56 2012 for Shore Storage Manager by  doxygen 1.4.7