blob: 2859560796973d03fba425de6ee6f13582303425 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 <stdio.h>
#if defined(__linux__)
#include <syscall.h>
#else
#include <sys/syscall.h>
#endif
#include <unistd.h>
#include <array>
#include <fstream> // IWYU pragma: keep
#include <iostream>
#include <memory>
#include <string>
#include "utils/preloadable.h"
#include "utils/process_utils.h"
#include "utils/time_utils.h"
using std::ios_base;
using std::ifstream;
using std::string;
namespace dsn {
namespace utils {
__thread tls_tid s_tid;
int get_current_tid_internal() { return static_cast<int>(syscall(SYS_gettid)); }
int pipe_execute(const char *command, std::ostream &output)
{
std::array<char, 256> buffer;
int retcode = 0;
{
std::shared_ptr<FILE> command_pipe(popen(command, "r"),
[&retcode](FILE *p) { retcode = pclose(p); });
while (!feof(command_pipe.get())) {
if (fgets(buffer.data(), 256, command_pipe.get()) != NULL)
output << buffer.data();
}
}
return retcode;
}
void process_mem_usage(double &vm_usage, double &resident_set)
{
vm_usage = 0.0;
resident_set = 0.0;
// 'file' stat seems to give the most reliable results
//
ifstream stat_stream("/proc/self/stat", ios_base::in);
// dummy vars for leading entries in stat that we don't care about
//
string pid, comm, state, ppid, pgrp, session, tty_nr;
string tpgid, flags, minflt, cminflt, majflt, cmajflt;
string utime, stime, cutime, cstime, priority, nice;
string O, itrealvalue, starttime;
// the two fields we want
//
unsigned long vsize;
long rss;
stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr >> tpgid >> flags >>
minflt >> cminflt >> majflt >> cmajflt >> utime >> stime >> cutime >> cstime >> priority >>
nice >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest
stat_stream.close();
static long page_size_kb =
sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
vm_usage = vsize / 1024.0;
resident_set = rss * page_size_kb;
}
class record_process_start_time : public preloadable<record_process_start_time>
{
public:
record_process_start_time()
{
mills = get_current_physical_time_ns() / 1000000;
time_ms_to_string(mills, date_time_mills);
}
uint64_t mills = 0;
char date_time_mills[64] = {0};
};
//
// if you call these functions before "main" function,
// the memory space for these variables have been allocated,
// but the values aren't initialized as the constructor
// of "static_module" may not been called yet.
//
uint64_t process_start_millis() { return record_process_start_time::s_instance.mills; }
const char *process_start_date_time_mills()
{
return record_process_start_time::s_instance.date_time_mills;
}
}
}