There should only be one way to get the system memory size.
[WebKit-https.git] / Source / WTF / wtf / RAMSize.cpp
1 /*
2  * Copyright (C) 2012 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 "RAMSize.h"
28
29 #include "StdLibExtras.h"
30 #include <mutex>
31
32 #if OS(DARWIN)
33 #import <dispatch/dispatch.h>
34 #import <mach/host_info.h>
35 #import <mach/mach.h>
36 #import <mach/mach_error.h>
37 #import <math.h>
38 #elif OS(UNIX)
39 #include <unistd.h>
40 #elif OS(WINDOWS)
41 #include <windows.h>
42 #endif
43
44 namespace WTF {
45
46 static const size_t ramSizeGuess = 512 * MB;
47
48 static size_t computeRAMSize()
49 {
50 #if PLATFORM(IOS_SIMULATOR)
51     // Pretend we have 512MB of memory to make cache sizes behave like on device.
52     return ramSizeGuess;
53 #elif OS(DARWIN)
54     host_basic_info_data_t hostInfo;
55
56     mach_port_t host = mach_host_self();
57     mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
58     kern_return_t r = host_info(host, HOST_BASIC_INFO, (host_info_t)&hostInfo, &count);
59     mach_port_deallocate(mach_task_self(), host);
60     if (r != KERN_SUCCESS) {
61         LOG_ERROR("%s : host_info(%d) : %s.\n", __FUNCTION__, r, mach_error_string(r));
62         return ramSizeGuess;
63     }
64
65     if (hostInfo.max_mem > std::numeric_limits<size_t>::max())
66         return std::numeric_limits<size_t>::max();
67
68     size_t sizeAccordingToKernel = static_cast<size_t>(hostInfo.max_mem);
69     size_t multiple = 128 * MB;
70
71     // Round up the memory size to a multiple of 128MB because max_mem may not be exactly 512MB
72     // (for example) and we have code that depends on those boundaries.
73     return ((sizeAccordingToKernel + multiple - 1) / multiple) * multiple;
74 #elif OS(UNIX)
75     long pages = sysconf(_SC_PHYS_PAGES);
76     long pageSize = sysconf(_SC_PAGE_SIZE);
77     if (pages == -1 || pageSize == -1)
78         return ramSizeGuess;
79     return pages * pageSize;
80 #elif OS(WINDOWS)
81     MEMORYSTATUSEX status;
82     status.dwLength = sizeof(status);
83     bool result = GlobalMemoryStatusEx(&status);
84     if (!result)
85         return ramSizeGuess;
86     return status.ullTotalPhys;
87 #endif
88 }
89
90 size_t ramSize()
91 {
92     static size_t ramSize;
93     static std::once_flag onceFlag;
94     std::call_once(onceFlag, [] {
95         ramSize = computeRAMSize();
96     });
97     return ramSize;
98 }
99
100 } // namespace WTF