1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/MemoryMap.cpp Sun Sep 20 15:14:12 2009 -0700
1.3 @@ -0,0 +1,103 @@
1.4 +/*
1.5 + * MemoryMap.cpp
1.6 + * Ottoman
1.7 + *
1.8 + * Created by Jens Alfke on 9/17/09.
1.9 + * Copyright 2009 Jens Alfke. All rights reserved.
1.10 + * BSD-Licensed: See the file "LICENSE.txt" for details.
1.11 + */
1.12 +
1.13 +#include "MemoryMap.h"
1.14 +
1.15 +#include <errno.h>
1.16 +#include <stdio.h>
1.17 +#include <sys/mman.h>
1.18 +
1.19 +namespace Mooseyard {
1.20 +
1.21 + MemoryMap::~MemoryMap() {
1.22 + for (int i=0; i<_nRegions; i++)
1.23 + delete _regions[i];
1.24 + free(_regions);
1.25 + }
1.26 +
1.27 + void MemoryMap::mapRegion (off_t pos, size_t length) {
1.28 + size_t end = pos+length;
1.29 + for (int i=0; i<_nRegions; i++) {
1.30 + Region *region = _regions[i];
1.31 + if (region->position() <= pos) {
1.32 + if (end <= region->end())
1.33 + return; // found an existing region covering this range
1.34 + else if (region->setLength(end - region->position()))
1.35 + return; // able to grow the existing region
1.36 + }
1.37 + }
1.38 +
1.39 + // No existing region, so add a new one:
1.40 + Region *region = new Region(_file, pos,length);
1.41 + _regions = (Region**) realloc(_regions, (_nRegions+1)*sizeof(*_regions));
1.42 + _regions[_nRegions++] = region;
1.43 + }
1.44 +
1.45 + const void* MemoryMap::_at (off_t pos) const {
1.46 + for (int i=0; i<_nRegions; i++) {
1.47 + const void *ptr = _regions[i]->mappedPosition(pos);
1.48 + if (ptr)
1.49 + return ptr;
1.50 + }
1.51 + return NULL;
1.52 + }
1.53 +
1.54 + const void* MemoryMap::mappedPosition (off_t pos) const {
1.55 + const void *result = _at(pos);
1.56 + if (!result)
1.57 + throw File::Error("No memory mapped at this position");
1.58 + return result;
1.59 + }
1.60 +
1.61 +
1.62 +
1.63 +
1.64 + MemoryMap::Region::Region (File* file, off_t position, size_t length)
1.65 + :_file(file),
1.66 + _position(position),
1.67 + _length (length),
1.68 + _start( (const uint8_t*) ::mmap(NULL, length, PROT_READ, MAP_PRIVATE, file->_fd, position) )
1.69 + {
1.70 + printf("File#%i: Mapped (%6llu -- %6llu) --> %p\n", file->_fd, _position, end(), _start);
1.71 + if (_start==NULL || _start == MAP_FAILED) {
1.72 + _start = NULL;
1.73 + throw File::Error(errno, strerror(errno));
1.74 + }
1.75 + }
1.76 +
1.77 + MemoryMap::Region::~Region() {
1.78 + if (_start) {
1.79 + printf("File#%i: Unmapped (%6llu -- %6llu) from %p\n", _file->_fd, _position, end(), _start);
1.80 + ::munmap((void*)_start,_length);
1.81 + }
1.82 + }
1.83 +
1.84 + bool MemoryMap::Region::setLength (size_t length) {
1.85 + if (length != _length) {
1.86 + printf("File#%i: Resiging (%6llu -- %6llu) from %lu to %lu ...",
1.87 + _file->_fd, _position, end(), _length,length);
1.88 + if (::mmap((void*)_start, length, PROT_READ, MAP_PRIVATE | MAP_FIXED, _file->_fd, _position) == MAP_FAILED) {
1.89 + printf("failed! errno=%i\n", errno);
1.90 + return false;
1.91 + }
1.92 + printf("OK\n");
1.93 + _length = length;
1.94 + }
1.95 + return true;
1.96 + }
1.97 +
1.98 + const void* MemoryMap::Region::mappedPosition (off_t pos) {
1.99 + if (pos >= _position && pos < end())
1.100 + return _start + (pos-_position);
1.101 + else
1.102 + return NULL;
1.103 + }
1.104 +
1.105 +
1.106 +}