11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc. 41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMMapStream.h" 90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include <unistd.h> 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include <sys/mman.h> 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include <fcntl.h> 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include <errno.h> 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkMMAPStream::SkMMAPStream(const char filename[]) 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fAddr = NULL; // initialize to failure case 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int fildes = open(filename, O_RDONLY); 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fildes < 0) 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGF(("---- failed to open(%s) for mmap stream error=%d\n", filename, errno)); 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project off_t offset = lseek(fildes, 0, SEEK_END); // find the file size 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (offset == -1) 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGF(("---- failed to lseek(%s) for mmap stream error=%d\n", filename, errno)); 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project close(fildes); 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (void)lseek(fildes, 0, SEEK_SET); // restore file offset to beginning 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // to avoid a 64bit->32bit warning, I explicitly create a size_t size 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t size = static_cast<size_t>(offset); 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fildes, 0); 391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // According to the POSIX documentation of mmap it adds an extra reference 411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // to the file associated with the fildes which is not removed by a 421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // subsequent close() on that fildes. This reference is removed when there 431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // are no more mappings to the file. 441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger close(fildes); 451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (MAP_FAILED == addr) 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGF(("---- failed to mmap(%s) for mmap stream error=%d\n", filename, errno)); 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->INHERITED::setMemory(addr, size); 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fAddr = addr; 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSize = size; 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkMMAPStream::~SkMMAPStream() 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->closeMMap(); 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkMMAPStream::setMemory(const void* data, size_t length, bool copyData) 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->closeMMap(); 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->INHERITED::setMemory(data, length, copyData); 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkMMAPStream::closeMMap() 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fAddr) 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project munmap(fAddr, fSize); 741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fAddr = NULL; 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 78