1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mozglue/linker/Mappable.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,275 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#ifndef Mappable_h 1.9 +#define Mappable_h 1.10 + 1.11 +#include <sys/types.h> 1.12 +#include <pthread.h> 1.13 +#include "Zip.h" 1.14 +#include "SeekableZStream.h" 1.15 +#include "mozilla/RefPtr.h" 1.16 +#include "mozilla/Scoped.h" 1.17 +#include "zlib.h" 1.18 + 1.19 +/** 1.20 + * Abstract class to handle mmap()ing from various kind of entities, such as 1.21 + * plain files or Zip entries. The virtual members are meant to act as the 1.22 + * equivalent system functions, except mapped memory is always MAP_PRIVATE, 1.23 + * even though a given implementation may use something different internally. 1.24 + */ 1.25 +class Mappable: public mozilla::RefCounted<Mappable> 1.26 +{ 1.27 +public: 1.28 + MOZ_DECLARE_REFCOUNTED_TYPENAME(Mappable) 1.29 + virtual ~Mappable() { } 1.30 + 1.31 + virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags, 1.32 + off_t offset) = 0; 1.33 + 1.34 + enum Kind { 1.35 + MAPPABLE_FILE, 1.36 + MAPPABLE_EXTRACT_FILE, 1.37 + MAPPABLE_DEFLATE, 1.38 + MAPPABLE_SEEKABLE_ZSTREAM 1.39 + }; 1.40 + 1.41 + virtual Kind GetKind() const = 0; 1.42 + 1.43 +private: 1.44 + virtual void munmap(void *addr, size_t length) { 1.45 + ::munmap(addr, length); 1.46 + } 1.47 + /* Limit use of Mappable::munmap to classes that keep track of the address 1.48 + * and size of the mapping. This allows to ignore ::munmap return value. */ 1.49 + friend class Mappable1stPagePtr; 1.50 + friend class LibHandle; 1.51 + 1.52 +public: 1.53 + /** 1.54 + * Ensures the availability of the memory pages for the page(s) containing 1.55 + * the given address. Returns whether the pages were successfully made 1.56 + * available. 1.57 + */ 1.58 + virtual bool ensure(const void *addr) { return true; } 1.59 + 1.60 + /** 1.61 + * Indicate to a Mappable instance that no further mmap is going to happen. 1.62 + */ 1.63 + virtual void finalize() = 0; 1.64 + 1.65 + /** 1.66 + * Shows some stats about the Mappable instance. 1.67 + * Meant for MappableSeekableZStream only. 1.68 + * As Mappables don't keep track of what they are instanciated for, the name 1.69 + * argument is used to make the stats logging useful to the reader. The when 1.70 + * argument is to be used by the caller to give an identifier of the when 1.71 + * the stats call is made. 1.72 + */ 1.73 + virtual void stats(const char *when, const char *name) const { } 1.74 + 1.75 + /** 1.76 + * Returns the maximum length that can be mapped from this Mappable for 1.77 + * offset = 0. 1.78 + */ 1.79 + virtual size_t GetLength() const = 0; 1.80 +}; 1.81 + 1.82 +/** 1.83 + * Mappable implementation for plain files 1.84 + */ 1.85 +class MappableFile: public Mappable 1.86 +{ 1.87 +public: 1.88 + ~MappableFile() { } 1.89 + 1.90 + /** 1.91 + * Create a MappableFile instance for the given file path. 1.92 + */ 1.93 + static Mappable *Create(const char *path); 1.94 + 1.95 + /* Inherited from Mappable */ 1.96 + virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags, off_t offset); 1.97 + virtual void finalize(); 1.98 + virtual size_t GetLength() const; 1.99 + 1.100 + virtual Kind GetKind() const { return MAPPABLE_FILE; }; 1.101 +protected: 1.102 + MappableFile(int fd): fd(fd) { } 1.103 + 1.104 +private: 1.105 + /* File descriptor */ 1.106 + AutoCloseFD fd; 1.107 +}; 1.108 + 1.109 +/** 1.110 + * Mappable implementation for deflated stream in a Zip archive 1.111 + * Inflates the complete stream into a cache file. 1.112 + */ 1.113 +class MappableExtractFile: public MappableFile 1.114 +{ 1.115 +public: 1.116 + ~MappableExtractFile(); 1.117 + 1.118 + /** 1.119 + * Create a MappableExtractFile instance for the given Zip stream. The name 1.120 + * argument is used to create the cache file in the cache directory. 1.121 + */ 1.122 + static Mappable *Create(const char *name, Zip *zip, Zip::Stream *stream); 1.123 + 1.124 + /* Override finalize from MappableFile */ 1.125 + virtual void finalize() {} 1.126 + 1.127 + virtual Kind GetKind() const { return MAPPABLE_EXTRACT_FILE; }; 1.128 +private: 1.129 + MappableExtractFile(int fd, char *path) 1.130 + : MappableFile(fd), path(path), pid(getpid()) { } 1.131 + 1.132 + /** 1.133 + * AutoUnlinkFile keeps track or a file name and removes (unlinks) the file 1.134 + * when the instance is destroyed. 1.135 + */ 1.136 + struct AutoUnlinkFileTraits: public mozilla::ScopedDeleteArrayTraits<char> 1.137 + { 1.138 + static void release(char *value) 1.139 + { 1.140 + if (!value) 1.141 + return; 1.142 + unlink(value); 1.143 + mozilla::ScopedDeleteArrayTraits<char>::release(value); 1.144 + } 1.145 + }; 1.146 + typedef mozilla::Scoped<AutoUnlinkFileTraits> AutoUnlinkFile; 1.147 + 1.148 + /* Extracted file */ 1.149 + AutoUnlinkFile path; 1.150 + 1.151 + /* Id of the process that initialized the instance */ 1.152 + pid_t pid; 1.153 +}; 1.154 + 1.155 +class _MappableBuffer; 1.156 + 1.157 +/** 1.158 + * Mappable implementation for deflated stream in a Zip archive. 1.159 + * Inflates the mapped bits in a temporary buffer. 1.160 + */ 1.161 +class MappableDeflate: public Mappable 1.162 +{ 1.163 +public: 1.164 + ~MappableDeflate(); 1.165 + 1.166 + /** 1.167 + * Create a MappableDeflate instance for the given Zip stream. The name 1.168 + * argument is used for an appropriately named temporary file, and the Zip 1.169 + * instance is given for the MappableDeflate to keep a reference of it. 1.170 + */ 1.171 + static Mappable *Create(const char *name, Zip *zip, Zip::Stream *stream); 1.172 + 1.173 + /* Inherited from Mappable */ 1.174 + virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags, off_t offset); 1.175 + virtual void finalize(); 1.176 + virtual size_t GetLength() const; 1.177 + 1.178 + virtual Kind GetKind() const { return MAPPABLE_DEFLATE; }; 1.179 +private: 1.180 + MappableDeflate(_MappableBuffer *buf, Zip *zip, Zip::Stream *stream); 1.181 + 1.182 + /* Zip reference */ 1.183 + mozilla::RefPtr<Zip> zip; 1.184 + 1.185 + /* Decompression buffer */ 1.186 + mozilla::ScopedDeletePtr<_MappableBuffer> buffer; 1.187 + 1.188 + /* Zlib data */ 1.189 + z_stream zStream; 1.190 +}; 1.191 + 1.192 +/** 1.193 + * Mappable implementation for seekable zStreams. 1.194 + * Inflates the mapped bits in a temporary buffer, on demand. 1.195 + */ 1.196 +class MappableSeekableZStream: public Mappable 1.197 +{ 1.198 +public: 1.199 + ~MappableSeekableZStream(); 1.200 + 1.201 + /** 1.202 + * Create a MappableSeekableZStream instance for the given Zip stream. The 1.203 + * name argument is used for an appropriately named temporary file, and the 1.204 + * Zip instance is given for the MappableSeekableZStream to keep a reference 1.205 + * of it. 1.206 + */ 1.207 + static Mappable *Create(const char *name, Zip *zip, 1.208 + Zip::Stream *stream); 1.209 + 1.210 + /* Inherited from Mappable */ 1.211 + virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags, off_t offset); 1.212 + virtual void munmap(void *addr, size_t length); 1.213 + virtual void finalize(); 1.214 + virtual bool ensure(const void *addr); 1.215 + virtual void stats(const char *when, const char *name) const; 1.216 + virtual size_t GetLength() const; 1.217 + 1.218 + virtual Kind GetKind() const { return MAPPABLE_SEEKABLE_ZSTREAM; }; 1.219 +private: 1.220 + MappableSeekableZStream(Zip *zip); 1.221 + 1.222 + /* Zip reference */ 1.223 + mozilla::RefPtr<Zip> zip; 1.224 + 1.225 + /* Decompression buffer */ 1.226 + mozilla::ScopedDeletePtr<_MappableBuffer> buffer; 1.227 + 1.228 + /* Seekable ZStream */ 1.229 + SeekableZStream zStream; 1.230 + 1.231 + /* Keep track of mappings performed with MappableSeekableZStream::mmap so 1.232 + * that they can be realized by MappableSeekableZStream::ensure. 1.233 + * Values stored in the struct are those passed to mmap */ 1.234 + struct LazyMap 1.235 + { 1.236 + const void *addr; 1.237 + size_t length; 1.238 + int prot; 1.239 + off_t offset; 1.240 + 1.241 + /* Returns addr + length, as a pointer */ 1.242 + const void *end() const { 1.243 + return reinterpret_cast<const void *> 1.244 + (reinterpret_cast<const unsigned char *>(addr) + length); 1.245 + } 1.246 + 1.247 + /* Returns offset + length */ 1.248 + const off_t endOffset() const { 1.249 + return offset + length; 1.250 + } 1.251 + 1.252 + /* Returns the offset corresponding to the given address */ 1.253 + const off_t offsetOf(const void *ptr) const { 1.254 + return reinterpret_cast<uintptr_t>(ptr) 1.255 + - reinterpret_cast<uintptr_t>(addr) + offset; 1.256 + } 1.257 + 1.258 + /* Returns whether the given address is in the LazyMap range */ 1.259 + const bool Contains(const void *ptr) const { 1.260 + return (ptr >= addr) && (ptr < end()); 1.261 + } 1.262 + }; 1.263 + 1.264 + /* List of all mappings */ 1.265 + std::vector<LazyMap> lazyMaps; 1.266 + 1.267 + /* Array keeping track of which chunks have already been decompressed. 1.268 + * Each value is the number of pages decompressed for the given chunk. */ 1.269 + mozilla::ScopedDeleteArray<unsigned char> chunkAvail; 1.270 + 1.271 + /* Number of chunks that have already been decompressed. */ 1.272 + mozilla::Atomic<size_t> chunkAvailNum; 1.273 + 1.274 + /* Mutex protecting decompression */ 1.275 + pthread_mutex_t mutex; 1.276 +}; 1.277 + 1.278 +#endif /* Mappable_h */