From e7bfa6cb1bb043d6ea66e03b32981e26965d2da3 Mon Sep 17 00:00:00 2001 From: Glauber Costa <glommer@cloudius-systems.com> Date: Thu, 24 Apr 2014 11:32:28 +0400 Subject: [PATCH] linux: provide a /proc/$$/stat compatibility file MongoDB wants it. In general, I am providing the information that is easy to get, and ignoring the ones which are not - with the exception of process count, that seemed easy enough to implement. This is the kind of thing Mongo does with it: 2014-04-15T09:54:12.322+0000 [clientcursormon] mem (MB) res:670160 virt:25212 2014-04-15T09:54:12.323+0000 [clientcursormon] mapped (incl journal view):160 2014-04-15T09:54:12.324+0000 [clientcursormon] connections:0 Signed-off-by: Glauber Costa <glommer@cloudius-systems.com> Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com> --- core/sched.cc | 6 ++++ fs/procfs/procfs_vnops.cc | 73 +++++++++++++++++++++++++++++++++++++++ include/osv/sched.hh | 2 ++ 3 files changed, 81 insertions(+) diff --git a/core/sched.cc b/core/sched.cc index 7bf9e0555..a8b7aa034 100644 --- a/core/sched.cc +++ b/core/sched.cc @@ -568,6 +568,12 @@ std::chrono::nanoseconds osv_run_stats() return std::chrono::duration_cast<std::chrono::nanoseconds>(total_app_time); } +int thread::numthreads() +{ + SCOPE_LOCK(thread_map_mutex); + return thread_map.size(); +} + // We reserve a space in the end of the PID space, so we can reuse those // special purpose ids for other things. 4096 positions is arbitrary, but // <<should be enough for anybody>> (tm) diff --git a/fs/procfs/procfs_vnops.cc b/fs/procfs/procfs_vnops.cc index 77839072d..7fed5d09c 100644 --- a/fs/procfs/procfs_vnops.cc +++ b/fs/procfs/procfs_vnops.cc @@ -17,6 +17,12 @@ #include <map> #include "fs/vfs/vfs.h" +#include <libgen.h> +#include <osv/mempool.hh> +#include <osv/printf.hh> + +#include <sys/resource.h> + namespace procfs { using namespace std; @@ -255,6 +261,71 @@ procfs_readdir(vnode *vp, file *fp, dirent *dir) return 0; } +static std::string procfs_stats() +{ + int pid = 0, ppid = 0, pgrp = 0, session = 0, tty = 0, tpgid = -1, + flags = 0; + // Postpone this one. We need to hook into ZFS statistics to properly figure + // out which faults are maj, which are min. + int min_flt = 0, cmin_flt = 0, maj_flt = 0, cmaj_flt = 0; + unsigned long stime = 0, cutime = 0, cstime = 0; + + using namespace std::chrono; + unsigned long utime = duration_cast<microseconds>(sched::osv_run_stats()).count(); + char state = 'R'; + int priority = getpriority(PRIO_PROCESS, 0); + int nice = priority; + int nlwp = sched::thread::numthreads(); + int start_time = 0; // boot is reference, so it is 0. + unsigned long rss = memory::stats::total() - memory::stats::free(); + unsigned long vsize = mmu::all_vmas_size(); + unsigned long rss_rlim = memory::stats::total(); + void *start_code = nullptr; + void *end_code = nullptr; + void *start_stack = nullptr; + void *kstk_esp = nullptr; + void *kstk_eip = nullptr; + + // All the signal stuff is marked in the manpage as obsolete. + unsigned long pending = 0; + unsigned long blocked = 0; + unsigned long sigign = 0; + unsigned long sigcatch = 0; + unsigned long nextalarm = 0; + // Except for this. This is maintained, but we also don't deliver any signal + unsigned long exit_signal = 0; + int cpu = sched::cpu::current()->id; + int wchan = 0, rt_priority = 0, policy = 0; // SCHED_OTHER = 0 + int zero = 0; + + std::ostringstream os; + osv::fprintf(os, "%d (%s) %c " + "%d %d %d %d %d " + "%lu %lu %lu %lu %lu " + "%lu %lu %ld %ld " + "%ld %ld %ld %ld " + "%lu %lu " + "%lu %lu " + "%p %p %p %p %p " + "%lu %lx %lu %lu " + "%d %d %d " + "%lu %d %d %d", + pid, program_invocation_short_name, state, + ppid, pgrp, session, tty, tpgid, + flags, min_flt, cmin_flt, maj_flt, cmaj_flt, + utime, stime, cutime, cstime, + priority, nice, nlwp, nextalarm, + start_time, vsize, + rss, rss_rlim, + start_code, end_code, start_stack, kstk_esp, kstk_eip, + pending, blocked, sigign, sigcatch, + wchan, zero, zero, + exit_signal, cpu, rt_priority, policy + ); + return os.str(); + +} + static int procfs_mount(mount* mp, char *dev, int flags, void* data) { @@ -262,9 +333,11 @@ procfs_mount(mount* mp, char *dev, int flags, void* data) auto self = make_shared<proc_dir_node>(inode_count++); self->add("maps", inode_count++, mmu::procfs_maps); + self->add("stat", inode_count++, procfs_stats); auto* root = new proc_dir_node(vp->v_ino); root->add("self", self); + root->add("0", self); // our standard pid vp->v_data = static_cast<void*>(root); diff --git a/include/osv/sched.hh b/include/osv/sched.hh index becd9639d..befa5d0e1 100644 --- a/include/osv/sched.hh +++ b/include/osv/sched.hh @@ -572,6 +572,8 @@ public: lockless_queue_link<thread> _wakeup_link; static unsigned long _s_idgen; static thread *find_by_id(unsigned int id); + + static int numthreads(); private: class reaper; friend class reaper; -- GitLab