Utils.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  3. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #ifndef Utils_h
  5. #define Utils_h
  6. #include <pthread.h>
  7. #include <stdint.h>
  8. #include <stddef.h>
  9. #include <sys/mman.h>
  10. #include <unistd.h>
  11. #include "mozilla/Assertions.h"
  12. #include "mozilla/Scoped.h"
  13. /**
  14. * On architectures that are little endian and that support unaligned reads,
  15. * we can use direct type, but on others, we want to have a special class
  16. * to handle conversion and alignment issues.
  17. */
  18. #if !defined(DEBUG) && (defined(__i386__) || defined(__x86_64__))
  19. typedef uint16_t le_uint16;
  20. typedef uint32_t le_uint32;
  21. #else
  22. /**
  23. * Template that allows to find an unsigned int type from a (computed) bit size
  24. */
  25. template <int s> struct UInt { };
  26. template <> struct UInt<16> { typedef uint16_t Type; };
  27. template <> struct UInt<32> { typedef uint32_t Type; };
  28. /**
  29. * Template to access 2 n-bit sized words as a 2*n-bit sized word, doing
  30. * conversion from little endian and avoiding alignment issues.
  31. */
  32. template <typename T>
  33. class le_to_cpu
  34. {
  35. public:
  36. typedef typename UInt<16 * sizeof(T)>::Type Type;
  37. operator Type() const
  38. {
  39. return (b << (sizeof(T) * 8)) | a;
  40. }
  41. const le_to_cpu& operator =(const Type &v)
  42. {
  43. a = v & ((1 << (sizeof(T) * 8)) - 1);
  44. b = v >> (sizeof(T) * 8);
  45. return *this;
  46. }
  47. le_to_cpu() { }
  48. le_to_cpu(const Type &v)
  49. {
  50. operator =(v);
  51. }
  52. const le_to_cpu& operator +=(const Type &v)
  53. {
  54. return operator =(operator Type() + v);
  55. }
  56. const le_to_cpu& operator ++(int)
  57. {
  58. return operator =(operator Type() + 1);
  59. }
  60. private:
  61. T a, b;
  62. };
  63. /**
  64. * Type definitions
  65. */
  66. typedef le_to_cpu<unsigned char> le_uint16;
  67. typedef le_to_cpu<le_uint16> le_uint32;
  68. #endif
  69. /**
  70. * AutoCloseFD is a RAII wrapper for POSIX file descriptors
  71. */
  72. struct AutoCloseFDTraits
  73. {
  74. typedef int type;
  75. static int empty() { return -1; }
  76. static void release(int fd) { if (fd != -1) close(fd); }
  77. };
  78. typedef mozilla::Scoped<AutoCloseFDTraits> AutoCloseFD;
  79. /**
  80. * AutoCloseFILE is a RAII wrapper for POSIX streams
  81. */
  82. struct AutoCloseFILETraits
  83. {
  84. typedef FILE *type;
  85. static FILE *empty() { return nullptr; }
  86. static void release(FILE *f) { if (f) fclose(f); }
  87. };
  88. typedef mozilla::Scoped<AutoCloseFILETraits> AutoCloseFILE;
  89. /**
  90. * Page alignment helpers
  91. */
  92. static inline size_t PageSize()
  93. {
  94. return 4096;
  95. }
  96. static inline uintptr_t AlignedPtr(uintptr_t ptr, size_t alignment)
  97. {
  98. return ptr & ~(alignment - 1);
  99. }
  100. template <typename T>
  101. static inline T *AlignedPtr(T *ptr, size_t alignment)
  102. {
  103. return reinterpret_cast<T *>(
  104. AlignedPtr(reinterpret_cast<uintptr_t>(ptr), alignment));
  105. }
  106. template <typename T>
  107. static inline T PageAlignedPtr(T ptr)
  108. {
  109. return AlignedPtr(ptr, PageSize());
  110. }
  111. static inline uintptr_t AlignedEndPtr(uintptr_t ptr, size_t alignment)
  112. {
  113. return AlignedPtr(ptr + alignment - 1, alignment);
  114. }
  115. template <typename T>
  116. static inline T *AlignedEndPtr(T *ptr, size_t alignment)
  117. {
  118. return reinterpret_cast<T *>(
  119. AlignedEndPtr(reinterpret_cast<uintptr_t>(ptr), alignment));
  120. }
  121. template <typename T>
  122. static inline T PageAlignedEndPtr(T ptr)
  123. {
  124. return AlignedEndPtr(ptr, PageSize());
  125. }
  126. static inline size_t AlignedSize(size_t size, size_t alignment)
  127. {
  128. return (size + alignment - 1) & ~(alignment - 1);
  129. }
  130. static inline size_t PageAlignedSize(size_t size)
  131. {
  132. return AlignedSize(size, PageSize());
  133. }
  134. static inline bool IsAlignedPtr(uintptr_t ptr, size_t alignment)
  135. {
  136. return ptr % alignment == 0;
  137. }
  138. template <typename T>
  139. static inline bool IsAlignedPtr(T *ptr, size_t alignment)
  140. {
  141. return IsAlignedPtr(reinterpret_cast<uintptr_t>(ptr), alignment);
  142. }
  143. template <typename T>
  144. static inline bool IsPageAlignedPtr(T ptr)
  145. {
  146. return IsAlignedPtr(ptr, PageSize());
  147. }
  148. static inline bool IsAlignedSize(size_t size, size_t alignment)
  149. {
  150. return size % alignment == 0;
  151. }
  152. static inline bool IsPageAlignedSize(size_t size)
  153. {
  154. return IsAlignedSize(size, PageSize());
  155. }
  156. static inline size_t PageNumber(size_t size)
  157. {
  158. return (size + PageSize() - 1) / PageSize();
  159. }
  160. /**
  161. * MemoryRange stores a pointer, size pair.
  162. */
  163. class MemoryRange
  164. {
  165. public:
  166. MemoryRange(void *buf, size_t length): buf(buf), length(length) { }
  167. void Assign(void *b, size_t len) {
  168. buf = b;
  169. length = len;
  170. }
  171. void Assign(const MemoryRange& other) {
  172. buf = other.buf;
  173. length = other.length;
  174. }
  175. void *get() const
  176. {
  177. return buf;
  178. }
  179. operator void *() const
  180. {
  181. return buf;
  182. }
  183. operator unsigned char *() const
  184. {
  185. return reinterpret_cast<unsigned char *>(buf);
  186. }
  187. bool operator ==(void *ptr) const {
  188. return buf == ptr;
  189. }
  190. bool operator ==(unsigned char *ptr) const {
  191. return buf == ptr;
  192. }
  193. void *operator +(off_t offset) const
  194. {
  195. return reinterpret_cast<char *>(buf) + offset;
  196. }
  197. /**
  198. * Returns whether the given address is within the mapped range
  199. */
  200. bool Contains(void *ptr) const
  201. {
  202. return (ptr >= buf) && (ptr < reinterpret_cast<char *>(buf) + length);
  203. }
  204. /**
  205. * Returns the length of the mapped range
  206. */
  207. size_t GetLength() const
  208. {
  209. return length;
  210. }
  211. static MemoryRange mmap(void *addr, size_t length, int prot, int flags,
  212. int fd, off_t offset) {
  213. return MemoryRange(::mmap(addr, length, prot, flags, fd, offset), length);
  214. }
  215. private:
  216. void *buf;
  217. size_t length;
  218. };
  219. /**
  220. * MappedPtr is a RAII wrapper for mmap()ed memory. It can be used as
  221. * a simple void * or unsigned char *.
  222. *
  223. * It is defined as a derivative of a template that allows to use a
  224. * different unmapping strategy.
  225. */
  226. template <typename T>
  227. class GenericMappedPtr: public MemoryRange
  228. {
  229. public:
  230. GenericMappedPtr(void *buf, size_t length): MemoryRange(buf, length) { }
  231. GenericMappedPtr(const MemoryRange& other): MemoryRange(other) { }
  232. GenericMappedPtr(): MemoryRange(MAP_FAILED, 0) { }
  233. void Assign(void *b, size_t len) {
  234. if (get() != MAP_FAILED)
  235. static_cast<T *>(this)->munmap(get(), GetLength());
  236. MemoryRange::Assign(b, len);
  237. }
  238. void Assign(const MemoryRange& other) {
  239. Assign(other.get(), other.GetLength());
  240. }
  241. ~GenericMappedPtr()
  242. {
  243. if (get() != MAP_FAILED)
  244. static_cast<T *>(this)->munmap(get(), GetLength());
  245. }
  246. void release()
  247. {
  248. MemoryRange::Assign(MAP_FAILED, 0);
  249. }
  250. };
  251. struct MappedPtr: public GenericMappedPtr<MappedPtr>
  252. {
  253. MappedPtr(void *buf, size_t length)
  254. : GenericMappedPtr<MappedPtr>(buf, length) { }
  255. MappedPtr(const MemoryRange& other)
  256. : GenericMappedPtr<MappedPtr>(other) { }
  257. MappedPtr(): GenericMappedPtr<MappedPtr>() { }
  258. private:
  259. friend class GenericMappedPtr<MappedPtr>;
  260. void munmap(void *buf, size_t length)
  261. {
  262. ::munmap(buf, length);
  263. }
  264. };
  265. /**
  266. * UnsizedArray is a way to access raw arrays of data in memory.
  267. *
  268. * struct S { ... };
  269. * UnsizedArray<S> a(buf);
  270. * UnsizedArray<S> b; b.Init(buf);
  271. *
  272. * This is roughly equivalent to
  273. * const S *a = reinterpret_cast<const S *>(buf);
  274. * const S *b = nullptr; b = reinterpret_cast<const S *>(buf);
  275. *
  276. * An UnsizedArray has no known length, and it's up to the caller to make
  277. * sure the accessed memory is mapped and makes sense.
  278. */
  279. template <typename T>
  280. class UnsizedArray
  281. {
  282. public:
  283. typedef size_t idx_t;
  284. /**
  285. * Constructors and Initializers
  286. */
  287. UnsizedArray(): contents(nullptr) { }
  288. UnsizedArray(const void *buf): contents(reinterpret_cast<const T *>(buf)) { }
  289. void Init(const void *buf)
  290. {
  291. MOZ_ASSERT(contents == nullptr);
  292. contents = reinterpret_cast<const T *>(buf);
  293. }
  294. /**
  295. * Returns the nth element of the array
  296. */
  297. const T &operator[](const idx_t index) const
  298. {
  299. MOZ_ASSERT(contents);
  300. return contents[index];
  301. }
  302. operator const T *() const
  303. {
  304. return contents;
  305. }
  306. /**
  307. * Returns whether the array points somewhere
  308. */
  309. operator bool() const
  310. {
  311. return contents != nullptr;
  312. }
  313. private:
  314. const T *contents;
  315. };
  316. /**
  317. * Array, like UnsizedArray, is a way to access raw arrays of data in memory.
  318. * Unlike UnsizedArray, it has a known length, and is enumerable with an
  319. * iterator.
  320. *
  321. * struct S { ... };
  322. * Array<S> a(buf, len);
  323. * UnsizedArray<S> b; b.Init(buf, len);
  324. *
  325. * In the above examples, len is the number of elements in the array. It is
  326. * also possible to initialize an Array with the buffer size:
  327. *
  328. * Array<S> c; c.InitSize(buf, size);
  329. *
  330. * It is also possible to initialize an Array in two steps, only providing
  331. * one data at a time:
  332. *
  333. * Array<S> d;
  334. * d.Init(buf);
  335. * d.Init(len); // or d.InitSize(size);
  336. *
  337. */
  338. template <typename T>
  339. class Array: public UnsizedArray<T>
  340. {
  341. public:
  342. typedef typename UnsizedArray<T>::idx_t idx_t;
  343. /**
  344. * Constructors and Initializers
  345. */
  346. Array(): UnsizedArray<T>(), length(0) { }
  347. Array(const void *buf, const idx_t length)
  348. : UnsizedArray<T>(buf), length(length) { }
  349. void Init(const void *buf)
  350. {
  351. UnsizedArray<T>::Init(buf);
  352. }
  353. void Init(const idx_t len)
  354. {
  355. MOZ_ASSERT(length == 0);
  356. length = len;
  357. }
  358. void InitSize(const idx_t size)
  359. {
  360. Init(size / sizeof(T));
  361. }
  362. void Init(const void *buf, const idx_t len)
  363. {
  364. UnsizedArray<T>::Init(buf);
  365. Init(len);
  366. }
  367. void InitSize(const void *buf, const idx_t size)
  368. {
  369. UnsizedArray<T>::Init(buf);
  370. InitSize(size);
  371. }
  372. /**
  373. * Returns the nth element of the array
  374. */
  375. const T &operator[](const idx_t index) const
  376. {
  377. MOZ_ASSERT(index < length);
  378. MOZ_ASSERT(operator bool());
  379. return UnsizedArray<T>::operator[](index);
  380. }
  381. /**
  382. * Returns the number of elements in the array
  383. */
  384. idx_t numElements() const
  385. {
  386. return length;
  387. }
  388. /**
  389. * Returns whether the array points somewhere and has at least one element.
  390. */
  391. operator bool() const
  392. {
  393. return (length > 0) && UnsizedArray<T>::operator bool();
  394. }
  395. /**
  396. * Iterator for an Array. Use is similar to that of STL const_iterators:
  397. *
  398. * struct S { ... };
  399. * Array<S> a(buf, len);
  400. * for (Array<S>::iterator it = a.begin(); it < a.end(); ++it) {
  401. * // Do something with *it.
  402. * }
  403. */
  404. class iterator
  405. {
  406. public:
  407. iterator(): item(nullptr) { }
  408. const T &operator *() const
  409. {
  410. return *item;
  411. }
  412. const T *operator ->() const
  413. {
  414. return item;
  415. }
  416. iterator &operator ++()
  417. {
  418. ++item;
  419. return *this;
  420. }
  421. bool operator<(const iterator &other) const
  422. {
  423. return item < other.item;
  424. }
  425. protected:
  426. friend class Array<T>;
  427. iterator(const T &item): item(&item) { }
  428. private:
  429. const T *item;
  430. };
  431. /**
  432. * Returns an iterator pointing at the beginning of the Array
  433. */
  434. iterator begin() const {
  435. if (length)
  436. return iterator(UnsizedArray<T>::operator[](0));
  437. return iterator();
  438. }
  439. /**
  440. * Returns an iterator pointing past the end of the Array
  441. */
  442. iterator end() const {
  443. if (length)
  444. return iterator(UnsizedArray<T>::operator[](length));
  445. return iterator();
  446. }
  447. /**
  448. * Reverse iterator for an Array. Use is similar to that of STL
  449. * const_reverse_iterators:
  450. *
  451. * struct S { ... };
  452. * Array<S> a(buf, len);
  453. * for (Array<S>::reverse_iterator it = a.rbegin(); it < a.rend(); ++it) {
  454. * // Do something with *it.
  455. * }
  456. */
  457. class reverse_iterator
  458. {
  459. public:
  460. reverse_iterator(): item(nullptr) { }
  461. const T &operator *() const
  462. {
  463. const T *tmp = item;
  464. return *--tmp;
  465. }
  466. const T *operator ->() const
  467. {
  468. return &operator*();
  469. }
  470. reverse_iterator &operator ++()
  471. {
  472. --item;
  473. return *this;
  474. }
  475. bool operator<(const reverse_iterator &other) const
  476. {
  477. return item > other.item;
  478. }
  479. protected:
  480. friend class Array<T>;
  481. reverse_iterator(const T &item): item(&item) { }
  482. private:
  483. const T *item;
  484. };
  485. /**
  486. * Returns a reverse iterator pointing at the end of the Array
  487. */
  488. reverse_iterator rbegin() const {
  489. if (length)
  490. return reverse_iterator(UnsizedArray<T>::operator[](length));
  491. return reverse_iterator();
  492. }
  493. /**
  494. * Returns a reverse iterator pointing past the beginning of the Array
  495. */
  496. reverse_iterator rend() const {
  497. if (length)
  498. return reverse_iterator(UnsizedArray<T>::operator[](0));
  499. return reverse_iterator();
  500. }
  501. private:
  502. idx_t length;
  503. };
  504. /**
  505. * Transforms a pointer-to-function to a pointer-to-object pointing at the
  506. * same address.
  507. */
  508. template <typename T>
  509. void *FunctionPtr(T func)
  510. {
  511. union {
  512. void *ptr;
  513. T func;
  514. } f;
  515. f.func = func;
  516. return f.ptr;
  517. }
  518. class AutoLock {
  519. public:
  520. AutoLock(pthread_mutex_t *mutex): mutex(mutex)
  521. {
  522. if (pthread_mutex_lock(mutex))
  523. MOZ_CRASH("pthread_mutex_lock failed");
  524. }
  525. ~AutoLock()
  526. {
  527. if (pthread_mutex_unlock(mutex))
  528. MOZ_CRASH("pthread_mutex_unlock failed");
  529. }
  530. private:
  531. pthread_mutex_t *mutex;
  532. };
  533. #endif /* Utils_h */