blob: 210c3906279a210013316b16fd2896f4ad29a269 [file] [log] [blame]
// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "starboard/system.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include "starboard/common/file.h"
#include "starboard/common/log.h"
#include "starboard/common/string.h"
// We find the current amount of used memory on Linux by opening
// '/proc/self/status' and scan the file for its "VmRSS" and "VmSwap" entries.
// Essentially, we need to parse a buffer that has the following format:
//
// xxxxxx: 45327 kB
// yyyyyy: 23 kB
// VmRSS: 87432 kB
// zzzzzz: 3213 kB
// VmSwap: 15 kB
// ...
//
// And here, we would want to return the value 87432 * 1024 + 15 * 1024 (i.e.
// (VmRSS + VmSwap) * 1024).
// See http://man7.org/linux/man-pages/man5/proc.5.html for more details.
// Searches for a specific value we're interested in and return it. Will
// modify |buffer| in order to do so quickly and easily. Returns the memory
// value in bytes (not kilobytes as it is presented in /proc/self/status).
int64_t SearchForMemoryValue(
const char* search_key, const char* buffer) {
const char* found = strstr(buffer, search_key);
if (!found) {
SB_LOG(ERROR) << "Could not find '" << search_key << "' in "
<< "/proc/self/status.";
return 0;
}
while (*found != '\0' && (*found < '0' || *found > '9')) {
++found;
}
if (*found == '\0') {
SB_LOG(ERROR) << "Unexpected end of string when searching for '"
<< search_key << "' in /proc/self/status.";
return 0;
}
// Convert the number string into an integer.
int64_t memory_value_in_kilobytes = 0;
while (*found >= '0' && *found <= '9') {
memory_value_in_kilobytes = memory_value_in_kilobytes * 10 + (*found - '0');
++found;
}
return memory_value_in_kilobytes * 1024;
}
int64_t SbSystemGetUsedCPUMemory() {
// Read our process' current physical memory usage from /proc/self/status.
starboard::ScopedFile status_file("/proc/self/status",
kSbFileOpenOnly | kSbFileRead);
if (!status_file.IsValid()) {
SB_LOG(ERROR)
<< "Error opening /proc/self/status in order to query self memory "
"usage.";
return 0;
}
// Read the entire file into memory.
const int kBufferSize = 2048;
char buffer[kBufferSize];
int bytes_read = status_file.ReadAll(buffer, kBufferSize);
// Ensure that this is a null-terminated string.
if (bytes_read == kBufferSize) {
bytes_read = kBufferSize - 1;
}
buffer[bytes_read] = '\0';
// Return the result, multiplied by 1024 because it is given in kilobytes.
return SearchForMemoryValue("VmRSS", buffer) +
SearchForMemoryValue("VmSwap", buffer);
}