1/*
2 Copyright (c) 2005-2019 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17// Declarations for simple estimate of the memory being used by a program.
18// Not yet implemented for macOS*.
19// This header is an optional part of the test harness.
20// It assumes that "harness_assert.h" has already been included.
21
22#if __linux__ || __sun
23#include <sys/resource.h>
24#include <unistd.h>
25
26#elif __APPLE__ && !__ARM_ARCH
27#include <unistd.h>
28#include <mach/mach.h>
29#include <AvailabilityMacros.h>
30#if MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6 || __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0
31#include <mach/shared_region.h>
32#else
33#include <mach/shared_memory_server.h>
34#endif
35#if SHARED_TEXT_REGION_SIZE || SHARED_DATA_REGION_SIZE
36const size_t shared_size = SHARED_TEXT_REGION_SIZE+SHARED_DATA_REGION_SIZE;
37#else
38const size_t shared_size = 0;
39#endif
40
41#elif _WIN32 && !__TBB_WIN8UI_SUPPORT
42#include <windows.h>
43#include <psapi.h>
44#if _MSC_VER
45#pragma comment(lib, "psapi")
46#endif
47
48#endif /* OS selection */
49
50enum MemoryStatType {
51 currentUsage,
52 peakUsage
53};
54
55//! Return estimate of number of bytes of memory that this program is currently using.
56/* Returns 0 if not implemented on platform. */
57size_t GetMemoryUsage(MemoryStatType stat = currentUsage) {
58 ASSERT(stat==currentUsage || stat==peakUsage, NULL);
59#if __TBB_WIN8UI_SUPPORT
60 return 0;
61#elif _WIN32
62 PROCESS_MEMORY_COUNTERS mem;
63 bool status = GetProcessMemoryInfo(GetCurrentProcess(), &mem, sizeof(mem))!=0;
64 ASSERT(status, NULL);
65 return stat==currentUsage? mem.PagefileUsage : mem.PeakPagefileUsage;
66#elif __linux__
67 long unsigned size = 0;
68 FILE *fst = fopen("/proc/self/status", "r");
69 ASSERT(fst, NULL);
70 const int BUF_SZ = 200;
71 char buf_stat[BUF_SZ];
72 const char *pattern = stat==peakUsage ? "VmPeak: %lu" : "VmSize: %lu";
73 while (NULL != fgets(buf_stat, BUF_SZ, fst)) {
74 if (1==sscanf(buf_stat, pattern, &size)) {
75 ASSERT(size, "Invalid value of memory consumption.");
76 break;
77 }
78 }
79 // VmPeak is available in kernels staring 2.6.15
80 if (stat!=peakUsage || LinuxKernelVersion() >= 2006015)
81 ASSERT(size, "Invalid /proc/self/status format, pattern not found.");
82 fclose(fst);
83 return size*1024;
84#elif __APPLE__ && !__ARM_ARCH
85 // TODO: find how detect peak virtual memory size under macOS
86 if (stat == peakUsage)
87 return 0;
88 kern_return_t status;
89 task_basic_info info;
90 mach_msg_type_number_t msg_type = TASK_BASIC_INFO_COUNT;
91 status = task_info(mach_task_self(), TASK_BASIC_INFO, reinterpret_cast<task_info_t>(&info), &msg_type);
92 ASSERT(status==KERN_SUCCESS, NULL);
93 return info.virtual_size - shared_size;
94#else
95 return 0;
96#endif
97}
98
99//! Use approximately a specified amount of stack space.
100/** Recursion is used here instead of alloca because some implementations of alloca do not use the stack. */
101void UseStackSpace( size_t amount, char* top=0 ) {
102 char x[1000];
103 memset( x, -1, sizeof(x) );
104 if( !top )
105 top = x;
106 ASSERT( x<=top, "test assumes that stacks grow downwards" );
107 if( size_t(top-x)<amount )
108 UseStackSpace( amount, top );
109}
110
111#if __linux__
112// Parse file utility
113#include "../tbbmalloc/shared_utils.h"
114
115inline bool isTHPEnabledOnMachine() {
116 unsigned long long thpPresent = 'n';
117 parseFileItem thpItem[] = { { "[alwa%cs] madvise never\n", thpPresent } };
118 parseFile</*BUFF_SIZE=*/100>("/sys/kernel/mm/transparent_hugepage/enabled", thpItem);
119
120 if (thpPresent == 'y') {
121 return true;
122 } else {
123 return false;
124 }
125}
126inline unsigned long long getSystemTHPAllocatedSize() {
127 unsigned long long anonHugePagesSize = 0;
128 parseFileItem meminfoItems[] = {
129 { "AnonHugePages: %llu kB", anonHugePagesSize } };
130 parseFile</*BUFF_SIZE=*/100>("/proc/meminfo", meminfoItems);
131 return anonHugePagesSize;
132}
133inline unsigned long long getSystemTHPCount() {
134 unsigned long long anonHugePages = 0;
135 parseFileItem vmstatItems[] = {
136 { "nr_anon_transparent_hugepages %llu", anonHugePages } };
137 parseFile</*BUFF_SIZE=*/100>("/proc/vmstat", vmstatItems);
138 return anonHugePages;
139}
140#endif // __linux__
141
142