From 122224d32894a8465a09561fc0a5220f5bb9c2c7 Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Thu, 22 May 2014 20:25:22 +0200 Subject: Implement /proc/slabinfo Add a node 'slabinfo' to the root directory that contains information about the slab allocator used in GNU Mach. The formatting code has been taken from Richard Braun's standalone client available here: git://darnassus.sceen.net/rbraun/slabinfo.git * rootdir.c (rootdir_gc_slabinfo): New function. (rootdir_entries): Add node 'slabinfo'. * Makefile (OBJS): Add mach_debugUser.o. (rootdir.o): Add an explicit dependency on mach_debug_U.h. Furthermore, add rules to create both functions. --- Makefile | 22 ++++++++++++++++++- rootdir.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5c51c1d..2820596 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ TARGET = procfs OBJS = procfs.o netfs.o procfs_dir.o \ - process.o proclist.o rootdir.o dircat.o main.o + process.o proclist.o rootdir.o dircat.o main.o mach_debugUser.o LIBS = -lnetfs -lps -lfshelp -lpthread CC = gcc @@ -19,8 +19,28 @@ CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 all: $(TARGET) +rootdir.o: rootdir.c mach_debug_U.h + $(TARGET): $(OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) clean: $(RM) $(TARGET) $(OBJS) + +# This is the gist of the MIG user stub handling from Hurd's build +# system: + +# Where to find .defs files. +vpath %.defs /usr/include/mach_debug + +MIG = mig +MIGCOM = $(MIG) -cc cat - /dev/null +MIGCOMFLAGS := -subrprefix __ + +%.udefsi: %.defs + $(CPP) -x c $(CPPFLAGS) $(MIGUFLAGS) $($*-MIGUFLAGS) \ + $< -o $*.udefsi + +%_U.h %User.c: %.udefsi + $(MIGCOM) $(MIGCOMFLAGS) $(MIGCOMUFLAGS) $($*-MIGCOMUFLAGS) < $< \ + -user $*User.c -server /dev/null -header $*_U.h diff --git a/rootdir.c b/rootdir.c index 94b0ddb..076885c 100644 --- a/rootdir.c +++ b/rootdir.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,8 @@ #include "procfs_dir.h" #include "main.h" +#include "mach_debug_U.h" + /* This implements a directory node with the static files in /proc. NB: the libps functions for host information return static storage; using them would require locking and as a consequence it would be @@ -470,6 +473,69 @@ rootdir_mounts_exists (void *dir_hook, const void *entry_hook) translator_exists = access (MTAB_TRANSLATOR, F_OK|X_OK) == 0; return translator_exists; } + +static error_t +rootdir_gc_slabinfo (void *hook, char **contents, ssize_t *contents_len) +{ + error_t err; + FILE *m; + const char header[] = + "cache obj slab bufs objs bufs" + " total reclaimable\n" + "name flags size size /slab usage count" + " memory memory\n"; + cache_info_array_t cache_info; + size_t mem_usage, mem_reclaimable, mem_total, mem_total_reclaimable; + mach_msg_type_number_t cache_info_count; + int i; + + cache_info = NULL; + cache_info_count = 0; + + err = host_slab_info (mach_host_self(), &cache_info, &cache_info_count); + if (err) + return err; + + m = open_memstream (contents, contents_len); + if (m == NULL) + { + err = ENOMEM; + goto out; + } + + fprintf (m, "%s", header); + + mem_total = 0; + mem_total_reclaimable = 0; + + for (i = 0; i < cache_info_count; i++) + { + mem_usage = (cache_info[i].nr_slabs * cache_info[i].slab_size) + >> 10; + mem_total += mem_usage; + mem_reclaimable = (cache_info[i].flags & CACHE_FLAGS_NO_RECLAIM) + ? 0 : (cache_info[i].nr_free_slabs + * cache_info[i].slab_size) >> 10; + mem_total_reclaimable += mem_reclaimable; + fprintf (m, + "%-21s %04x %7zu %3zuk %4lu %6lu %6lu %7zuk %10zuk\n", + cache_info[i].name, cache_info[i].flags, + cache_info[i].obj_size, cache_info[i].slab_size >> 10, + cache_info[i].bufs_per_slab, cache_info[i].nr_objs, + cache_info[i].nr_bufs, mem_usage, mem_reclaimable); + } + + fprintf (m, "total: %zuk, reclaimable: %zuk\n", + mem_total, mem_total_reclaimable); + + fclose (m); + *contents_len += 1; /* For the terminating 0. */ + + out: + vm_deallocate (mach_task_self (), + cache_info, cache_info_count * sizeof *cache_info); + return err; +} /* Glue logic and entries table */ @@ -563,6 +629,13 @@ static const struct procfs_dir_entry rootdir_entries[] = { .exists = rootdir_mounts_exists, } }, + { + .name = "slabinfo", + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_slabinfo, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, #ifdef PROFILE /* In order to get a usable gmon.out file, we must apparently use exit(). */ { -- cgit v1.2.3