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