summaryrefslogtreecommitdiff
path: root/src/shared/util.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-04-06 10:05:59 +0200
committerLennart Poettering <lennart@poettering.net>2013-04-08 15:26:32 +0200
commitab7d9b674e8eb1388dff4d44def1b661892832e6 (patch)
tree240db615184028e12ff1743389625c6151dfb752 /src/shared/util.c
parentb6b7d4337976eeac610b9ed2c3e1fd596a247b14 (diff)
util: Avoid memory allocations for formatting paths
Avoid memory allocations to construct the path for files in the procfs. The procfs paths are way shorter than the PATH_MAX so we can use snprintf on a string located on the stack. This shows up as a win on x86 using the benchmark program below. $ make libsystemd-shared.la; gcc -O2 -Isrc/systemd/ -Isrc/ \ -o simple-perf-test simple-perf-test.c \ .libs/libsystemd-shared.a -lrt #include "shared/util.h" void test_once(void) { pid_t pid = getpid(); char *tmp = NULL; get_process_comm(pid, &tmp); free(tmp); tmp = NULL; get_process_cmdline(pid, 0, 1, &tmp); free(tmp); is_kernel_thread(pid); tmp = NULL; get_process_exe(pid, &tmp); free(tmp); } int main(int argc, char **argv) { int i; for (i = 0; i < 50000; ++i) test_once(); }
Diffstat (limited to 'src/shared/util.c')
-rw-r--r--src/shared/util.c54
1 files changed, 25 insertions, 29 deletions
diff --git a/src/shared/util.c b/src/shared/util.c
index 52867a1779..49d2a0dace 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -80,6 +80,16 @@ char **saved_argv = NULL;
static volatile unsigned cached_columns = 0;
static volatile unsigned cached_lines = 0;
+#define PROCFS_PATH_LEN (sizeof("/proc/")-1 + DECIMAL_STR_MAX(pid_t))
+
+#define FORMAT_PROCFS_PATH(buffer, path, pid) \
+ do { \
+ assert_cc(sizeof(buffer) == (PROCFS_PATH_LEN + 1 + sizeof(path))); \
+ snprintf(buffer, sizeof(buffer) - 1, "/proc/%lu/%s", (unsigned long) pid, path); \
+ char_array_0(buffer); \
+ } while(0)
+
+
size_t page_size(void) {
static __thread size_t pgsz = 0;
long r;
@@ -571,12 +581,9 @@ int get_process_comm(pid_t pid, char **name) {
if (pid == 0)
r = read_one_line_file("/proc/self/comm", name);
else {
- char *p;
- if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- r = read_one_line_file(p, name);
- free(p);
+ char path[PROCFS_PATH_LEN + sizeof("/comm")];
+ FORMAT_PROCFS_PATH(path, "comm", pid);
+ r = read_one_line_file(path, name);
}
return r;
@@ -592,12 +599,9 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
if (pid == 0)
f = fopen("/proc/self/cmdline", "re");
else {
- char *p;
- if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
- free(p);
+ char path[PROCFS_PATH_LEN + sizeof("/cmdline")];
+ FORMAT_PROCFS_PATH(path, "cmdline", pid);
+ f = fopen(path, "re");
}
if (!f)
@@ -684,7 +688,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
}
int is_kernel_thread(pid_t pid) {
- char *p;
+ char path[PROCFS_PATH_LEN + sizeof("/cmdline")];
size_t count;
char c;
bool eof;
@@ -693,11 +697,8 @@ int is_kernel_thread(pid_t pid) {
if (pid == 0)
return 0;
- if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
- free(p);
+ FORMAT_PROCFS_PATH(path, "cmdline", pid);
+ f = fopen(path, "re");
if (!f)
return -errno;
@@ -722,12 +723,9 @@ int get_process_exe(pid_t pid, char **name) {
if (pid == 0)
r = readlink_malloc("/proc/self/exe", name);
else {
- char *p;
- if (asprintf(&p, "/proc/%lu/exe", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- r = readlink_malloc(p, name);
- free(p);
+ char path[PROCFS_PATH_LEN + sizeof("/exe")];
+ FORMAT_PROCFS_PATH(path, "exe", pid);
+ r = readlink_malloc(path, name);
}
return r;
@@ -735,7 +733,7 @@ int get_process_exe(pid_t pid, char **name) {
static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
_cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *p = NULL;
+ char path[PROCFS_PATH_LEN + sizeof("/status")];
char line[LINE_MAX];
assert(field);
@@ -744,10 +742,8 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
if (pid == 0)
return getuid();
- if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
+ FORMAT_PROCFS_PATH(path, "status", pid);
+ f = fopen(path, "re");
if (!f)
return -errno;