~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WTF/wtf/OSAllocatorPosix.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010 Apple Inc. All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions
 
6
 * are met:
 
7
 * 1. Redistributions of source code must retain the above copyright
 
8
 *    notice, this list of conditions and the following disclaimer.
 
9
 * 2. Redistributions in binary form must reproduce the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer in the
 
11
 *    documentation and/or other materials provided with the distribution.
 
12
 *
 
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 
14
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
15
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
16
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 
17
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
19
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
20
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
21
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
22
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 
23
 * THE POSSIBILITY OF SUCH DAMAGE.
 
24
 */
 
25
 
 
26
#include "config.h"
 
27
#include "OSAllocator.h"
 
28
 
 
29
#include "PageAllocation.h"
 
30
#include <errno.h>
 
31
#include <sys/mman.h>
 
32
#include <wtf/Assertions.h>
 
33
#include <wtf/UnusedParam.h>
 
34
 
 
35
namespace WTF {
 
36
 
 
37
void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
 
38
{
 
39
#if OS(QNX)
 
40
    // Reserve memory with PROT_NONE and MAP_LAZY so it isn't committed now.
 
41
    void* result = mmap(0, bytes, PROT_NONE, MAP_LAZY | MAP_PRIVATE | MAP_ANON, -1, 0);
 
42
    if (result == MAP_FAILED)
 
43
        CRASH();
 
44
#else // OS(QNX)
 
45
 
 
46
    void* result = reserveAndCommit(bytes, usage, writable, executable, includesGuardPages);
 
47
#if OS(LINUX)
 
48
    madvise(result, bytes, MADV_DONTNEED);
 
49
#elif HAVE(MADV_FREE_REUSE)
 
50
    // To support the "reserve then commit" model, we have to initially decommit.
 
51
    while (madvise(result, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
 
52
#endif
 
53
 
 
54
#endif // OS(QNX)
 
55
 
 
56
    return result;
 
57
}
 
58
 
 
59
void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
 
60
{
 
61
    // All POSIX reservations start out logically committed.
 
62
    int protection = PROT_READ;
 
63
    if (writable)
 
64
        protection |= PROT_WRITE;
 
65
    if (executable)
 
66
        protection |= PROT_EXEC;
 
67
 
 
68
    int flags = MAP_PRIVATE | MAP_ANON;
 
69
#if PLATFORM(IOS)
 
70
    if (executable)
 
71
        flags |= MAP_JIT;
 
72
#endif
 
73
 
 
74
#if (OS(LINUX) && CPU(X86_64))
 
75
    // Linux distros usually do not allow overcommit by default, so
 
76
    // JSC's strategy of mmaping a large amount of memory upfront
 
77
    // won't work very well on some systems. Fortunately there's a
 
78
    // flag we can pass to mmap to disable the overcommit check for
 
79
    // this particular call, so we can get away with it as long as the
 
80
    // overcommit flag value in /proc/sys/vm/overcommit_memory is 0
 
81
    // ('heuristic') and not 2 (always check). 0 is the usual default
 
82
    // value, so this should work well in general.
 
83
    flags |= MAP_NORESERVE;
 
84
#endif
 
85
 
 
86
#if OS(DARWIN)
 
87
    int fd = usage;
 
88
#else
 
89
    UNUSED_PARAM(usage);
 
90
    int fd = -1;
 
91
#endif
 
92
 
 
93
    void* result = 0;
 
94
#if (OS(DARWIN) && CPU(X86_64))
 
95
    if (executable) {
 
96
        ASSERT(includesGuardPages);
 
97
        // Cook up an address to allocate at, using the following recipe:
 
98
        //   17 bits of zero, stay in userspace kids.
 
99
        //   26 bits of randomness for ASLR.
 
100
        //   21 bits of zero, at least stay aligned within one level of the pagetables.
 
101
        //
 
102
        // But! - as a temporary workaround for some plugin problems (rdar://problem/6812854),
 
103
        // for now instead of 2^26 bits of ASLR lets stick with 25 bits of randomization plus
 
104
        // 2^24, which should put up somewhere in the middle of userspace (in the address range
 
105
        // 0x200000000000 .. 0x5fffffffffff).
 
106
        intptr_t randomLocation = 0;
 
107
        randomLocation = arc4random() & ((1 << 25) - 1);
 
108
        randomLocation += (1 << 24);
 
109
        randomLocation <<= 21;
 
110
        result = reinterpret_cast<void*>(randomLocation);
 
111
    }
 
112
#endif
 
113
 
 
114
    result = mmap(result, bytes, protection, flags, fd, 0);
 
115
    if (result == MAP_FAILED) {
 
116
#if ENABLE(LLINT)
 
117
        if (executable)
 
118
            result = 0;
 
119
        else
 
120
#endif
 
121
            CRASH();
 
122
    }
 
123
    if (result && includesGuardPages) {
 
124
        // We use mmap to remap the guardpages rather than using mprotect as
 
125
        // mprotect results in multiple references to the code region.  This
 
126
        // breaks the madvise based mechanism we use to return physical memory
 
127
        // to the OS.
 
128
        mmap(result, pageSize(), PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, fd, 0);
 
129
        mmap(static_cast<char*>(result) + bytes - pageSize(), pageSize(), PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, fd, 0);
 
130
    }
 
131
    return result;
 
132
}
 
133
 
 
134
void OSAllocator::commit(void* address, size_t bytes, bool writable, bool executable)
 
135
{
 
136
#if OS(QNX)
 
137
    int protection = PROT_READ;
 
138
    if (writable)
 
139
        protection |= PROT_WRITE;
 
140
    if (executable)
 
141
        protection |= PROT_EXEC;
 
142
    if (MAP_FAILED == mmap(address, bytes, protection, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0))
 
143
        CRASH();
 
144
#elif OS(LINUX)
 
145
    UNUSED_PARAM(writable);
 
146
    UNUSED_PARAM(executable);
 
147
    madvise(address, bytes, MADV_WILLNEED);
 
148
#elif HAVE(MADV_FREE_REUSE)
 
149
    UNUSED_PARAM(writable);
 
150
    UNUSED_PARAM(executable);
 
151
    while (madvise(address, bytes, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
 
152
#else
 
153
    // Non-MADV_FREE_REUSE reservations automatically commit on demand.
 
154
    UNUSED_PARAM(address);
 
155
    UNUSED_PARAM(bytes);
 
156
    UNUSED_PARAM(writable);
 
157
    UNUSED_PARAM(executable);
 
158
#endif
 
159
}
 
160
 
 
161
void OSAllocator::decommit(void* address, size_t bytes)
 
162
{
 
163
#if OS(QNX)
 
164
    // Use PROT_NONE and MAP_LAZY to decommit the pages.
 
165
    mmap(address, bytes, PROT_NONE, MAP_FIXED | MAP_LAZY | MAP_PRIVATE | MAP_ANON, -1, 0);
 
166
#elif OS(LINUX)
 
167
    madvise(address, bytes, MADV_DONTNEED);
 
168
#elif HAVE(MADV_FREE_REUSE)
 
169
    while (madvise(address, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
 
170
#elif HAVE(MADV_FREE)
 
171
    while (madvise(address, bytes, MADV_FREE) == -1 && errno == EAGAIN) { }
 
172
#elif HAVE(MADV_DONTNEED)
 
173
    while (madvise(address, bytes, MADV_DONTNEED) == -1 && errno == EAGAIN) { }
 
174
#else
 
175
    UNUSED_PARAM(address);
 
176
    UNUSED_PARAM(bytes);
 
177
#endif
 
178
}
 
179
 
 
180
void OSAllocator::releaseDecommitted(void* address, size_t bytes)
 
181
{
 
182
    int result = munmap(address, bytes);
 
183
    if (result == -1)
 
184
        CRASH();
 
185
}
 
186
 
 
187
} // namespace WTF