1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=99 ft=cpp:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Copyright (C) 2010 Apple Inc. All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
17 : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 : * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
20 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 : * THE POSSIBILITY OF SUCH DAMAGE.
27 : *
28 : * ***** END LICENSE BLOCK ***** */
29 :
30 : #include "assembler/wtf/Platform.h"
31 :
32 : #if WTF_OS_UNIX && !WTF_OS_SYMBIAN
33 :
34 : #include "OSAllocator.h"
35 :
36 : #include <errno.h>
37 : #include <sys/mman.h>
38 : #include "wtf/Assertions.h"
39 :
40 : namespace WTF {
41 :
42 0 : void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable)
43 : {
44 0 : void* result = reserveAndCommit(bytes, usage, writable, executable);
45 : #if HAVE_MADV_FREE_REUSE
46 : // To support the "reserve then commit" model, we have to initially decommit.
47 : while (madvise(result, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
48 : #endif
49 0 : return result;
50 : }
51 :
52 31359 : void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable)
53 : {
54 : // All POSIX reservations start out logically committed.
55 31359 : int protection = PROT_READ;
56 31359 : if (writable)
57 31359 : protection |= PROT_WRITE;
58 31359 : if (executable)
59 0 : protection |= PROT_EXEC;
60 :
61 31359 : int flags = MAP_PRIVATE | MAP_ANON;
62 :
63 : #if WTF_OS_DARWIN && !defined(BUILDING_ON_TIGER)
64 : int fd = usage;
65 : #else
66 31359 : int fd = -1;
67 : #endif
68 :
69 31359 : void* result = 0;
70 : #if (WTF_OS_DARWIN && WTF_CPU_X86_64)
71 : if (executable) {
72 : // Cook up an address to allocate at, using the following recipe:
73 : // 17 bits of zero, stay in userspace kids.
74 : // 26 bits of randomness for ASLR.
75 : // 21 bits of zero, at least stay aligned within one level of the pagetables.
76 : //
77 : // But! - as a temporary workaround for some plugin problems (rdar://problem/6812854),
78 : // for now instead of 2^26 bits of ASLR lets stick with 25 bits of randomization plus
79 : // 2^24, which should put up somewhere in the middle of userspace (in the address range
80 : // 0x200000000000 .. 0x5fffffffffff).
81 : intptr_t randomLocation = 0;
82 : randomLocation = arc4random() & ((1 << 25) - 1);
83 : randomLocation += (1 << 24);
84 : randomLocation <<= 21;
85 : result = reinterpret_cast<void*>(randomLocation);
86 : }
87 : #endif
88 :
89 31359 : result = mmap(result, bytes, protection, flags, fd, 0);
90 31359 : if (result == MAP_FAILED)
91 0 : CRASH();
92 31359 : return result;
93 : }
94 :
95 0 : void OSAllocator::commit(void* address, size_t bytes, bool, bool)
96 : {
97 : #if HAVE_MADV_FREE_REUSE
98 : while (madvise(address, bytes, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
99 : #else
100 : // Non-MADV_FREE_REUSE reservations automatically commit on demand.
101 : UNUSED_PARAM(address);
102 : UNUSED_PARAM(bytes);
103 : #endif
104 0 : }
105 :
106 0 : void OSAllocator::decommit(void* address, size_t bytes)
107 : {
108 : #if HAVE_MADV_FREE_REUSE
109 : while (madvise(address, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
110 : #elif HAVE_MADV_FREE
111 : while (madvise(address, bytes, MADV_FREE) == -1 && errno == EAGAIN) { }
112 : #elif HAVE_MADV_DONTNEED
113 : while (madvise(address, bytes, MADV_DONTNEED) == -1 && errno == EAGAIN) { }
114 : #else
115 : UNUSED_PARAM(address);
116 : UNUSED_PARAM(bytes);
117 : #endif
118 0 : }
119 :
120 31359 : void OSAllocator::releaseDecommitted(void* address, size_t bytes)
121 : {
122 31359 : int result = munmap(address, bytes);
123 31359 : if (result == -1)
124 0 : CRASH();
125 31359 : }
126 :
127 : } // namespace WTF
128 :
129 : #endif
|