• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

kvmallocator.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of the KDE libraries
00003 
00004     Copyright (C) 1999 Waldo Bastian (bastian@kde.org)
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, USA.
00020 */
00021 //----------------------------------------------------------------------------
00022 //
00023 // Virtual Memory Allocator
00024 
00025 // TODO: Add large file support.
00026 // TODO: Error reporting. (e.g. disk-full)
00027 
00028 #include <unistd.h>
00029 #include <sys/mman.h>
00030 
00031 #include <qintdict.h>
00032 #include <qmap.h>
00033 
00034 #include <ktempfile.h>
00035 #include <kdebug.h>
00036 
00037 #include "kvmallocator.h"
00038 
00039 
00040 #define KVM_ALIGN 4095
00041 
00042 struct KVMAllocator::Block
00043 {
00044    off_t start;
00045    size_t length; // Requested length
00046    size_t size; // Actual size
00047    void *mmap;
00048 };
00049 
00050 
00051 class KVMAllocatorPrivate
00052 {
00053 public:
00054    KTempFile *tempfile;
00055    off_t max_length;
00056    QMap<off_t, KVMAllocator::Block> used_blocks;
00057    QMap<off_t, KVMAllocator::Block> free_blocks;
00058 };
00059 
00063 KVMAllocator::KVMAllocator()
00064 {
00065    d = new KVMAllocatorPrivate;
00066    d->tempfile = 0;
00067    d->max_length = 0;
00068 }
00069 
00073 KVMAllocator::~KVMAllocator()
00074 {
00075    delete d->tempfile;
00076    delete d;
00077 }
00078 
00083 KVMAllocator::Block *
00084 KVMAllocator::allocate(size_t _size)
00085 {
00086    if (!d->tempfile)
00087    {
00088       d->tempfile = new KTempFile(QString::null, "vmdata");
00089       d->tempfile->unlink();
00090    }
00091    // Search in free list
00092    QMap<off_t,KVMAllocator::Block>::iterator it;
00093    it = d->free_blocks.begin();
00094    while (it != d->free_blocks.end())
00095    {
00096       if (it.data().size > _size)
00097       {
00098          Block &free_block = it.data();
00099          Block block;
00100          kdDebug(180)<<"VM alloc: using block from free list "<<(long)free_block.start<<" size ="<<(long)free_block.size<<" request = "<<_size<< endl;
00101          block.start = free_block.start;
00102          block.length = _size;
00103          block.size = (_size + KVM_ALIGN) & ~KVM_ALIGN;
00104          block.mmap = 0;
00105          free_block.size -= block.size;
00106          free_block.start += block.size;
00107          if (!free_block.size)
00108             d->free_blocks.remove(it);
00109          it = d->used_blocks.replace(block.start, block);
00110          return &(it.data());
00111       }
00112       ++it;
00113    } 
00114 
00115 
00116    // Create new block
00117    Block block;
00118    block.start = d->max_length;
00119    block.length = _size;
00120    block.size = (_size + KVM_ALIGN) & ~KVM_ALIGN;
00121    block.mmap = 0;
00122    kdDebug(180)<<"VM alloc: using new block "<<(long)block.start<<" size ="<<(long)block.size<<" request = "<<_size<< endl;
00123    it = d->used_blocks.replace(block.start, block);
00124    d->max_length += block.size;
00125    return &(it.data());
00126 }
00127 
00131 void
00132 KVMAllocator::free(Block *block_p)
00133 {
00134    Block block = *block_p;
00135    if (block.mmap)
00136    {
00137       kdDebug(180)<<"VM free: Block "<<(long)block.start<<" is still mmapped!"<<endl;
00138       return;
00139    }
00140    QMap<off_t,KVMAllocator::Block>::iterator it;
00141    it = d->used_blocks.find(block.start);
00142    if (it == d->used_blocks.end())
00143    {
00144       kdDebug(180)<<"VM free: Block "<<(long)block.start<<" is not allocated."<<endl;
00145       return;
00146    }
00147    d->used_blocks.remove(it);
00148    it = d->free_blocks.replace(block.start, block);
00149    QMap<off_t,KVMAllocator::Block>::iterator before = it;
00150    --before;
00151    if (before != d->free_blocks.end())
00152    {
00153       Block &block_before = before.data();
00154       if ((block_before.start + off_t(block_before.size)) == block.start)
00155       {
00156          // Merge blocks.
00157          kdDebug(180) << "VM merging: Block "<< (long)block_before.start<<
00158                            " with "<< (long)block.start<< " (before)" << endl;
00159          block.size += block_before.size;
00160          block.start = block_before.start;
00161          it.data() = block;
00162          d->free_blocks.remove(before);
00163       }
00164    }
00165    
00166    QMap<off_t,KVMAllocator::Block>::iterator after = it;
00167    ++after;
00168    if (after != d->free_blocks.end())
00169    {
00170       Block &block_after = after.data();
00171       if ((block.start + off_t(block.size)) == block_after.start)
00172       {
00173          // Merge blocks.
00174          kdDebug(180) << "VM merging: Block "<< (long)block.start<<
00175                            " with "<< (long)block_after.start<< " (after)" << endl;
00176          block.size += block_after.size;
00177          it.data() = block;
00178          d->free_blocks.remove(after);
00179       }
00180    }
00181 }
00182 
00186 void
00187 KVMAllocator::copy(void *dest, Block *src, int _offset, size_t length)
00188 {
00189    (void) copyBlock(dest, src, _offset, length);
00190 }
00191 
00192 bool
00193 KVMAllocator::copyBlock(void *dest, Block *src, int _offset, size_t length)
00194 {
00195    //kdDebug(180)<<"VM read: seek "<<(long)src->start<<" +"<<_offset<<":"<<length<<endl;
00196    lseek(d->tempfile->handle(), src->start+_offset, SEEK_SET);
00197    if (length == 0)
00198       length = src->length - _offset;
00199    int to_go = length;
00200    int done = 0;
00201    char *buf = (char *) dest;
00202    while(to_go > 0)
00203    {
00204       int n = read(d->tempfile->handle(), buf+done, to_go);
00205       if (n <= 0) 
00206       {
00207          if (n < 0)
00208             return false; // Error
00209          else
00210             return true; // End of data
00211       }
00212       done += n;
00213       to_go -= n;
00214    }
00215    // Done.
00216    return true;
00217 }
00218 
00222 void
00223 KVMAllocator::copy(Block *dest, void *src, int _offset, size_t length)
00224 {
00225    (void) copyBlock(dest, src, _offset, length);
00226 }
00227 
00228 bool
00229 KVMAllocator::copyBlock(Block *dest, void *src, int _offset, size_t length)
00230 {
00231    //kdDebug(180)<<"VM write: seek "<<(long)dest->start<<" +"<<_offset<< ":" << length << endl;
00232    lseek(d->tempfile->handle(), dest->start+_offset, SEEK_SET);
00233    if (length == 0)
00234       length = dest->length - _offset;
00235    int to_go = length;
00236    int done = 0;
00237    char *buf = (char *) src;
00238    while(to_go > 0)
00239    {
00240       int n = write(d->tempfile->handle(), buf+done, to_go);
00241       if (n <= 0) return false; // Error
00242       done += n;
00243       to_go -= n;
00244    }
00245    // Done.
00246    return true;
00247 }
00248 
00252 void *
00253 KVMAllocator::map(Block *block)
00254 {
00255    if (block->mmap)
00256       return block->mmap;
00257 
00258    void *result = mmap(0, block->length, PROT_READ| PROT_WRITE,
00259                        MAP_SHARED, d->tempfile->handle(), block->start);
00260    block->mmap = result;
00261    return block->mmap;
00262 }
00263 
00267 void
00268 KVMAllocator::unmap(Block *block)
00269 {
00270    // The following cast is necassery for Solaris.
00271    // (touch it and die). --Waba
00272    munmap((char *)block->mmap, block->length);
00273    block->mmap = 0;
00274 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal