log.o log2.o md5.o md5hex.o mmap.o pagecache.o patimatch.o patmatch.o pool.o \
prime.o random.o realloc.o regex.o timer.o url.o wildmatch.o \
wordsplit.o str_ctype.o str_upper.o bucket.o conf.o object.o sorter.o \
- finger.o proctitle.o ipaccess.o
+ finger.o proctitle.o ipaccess.o profile.o
obj/lib/libsh.a: $(addprefix obj/lib/,$(SHLIB_OBJS))
--- /dev/null
+/*
+ * Sherlock Library -- Poor Man's Profiler
+ *
+ * (c) 2001 Martin Mares <mj@ucw.cz>
+ */
+
+#include "lib/lib.h"
+#include "lib/profile.h"
+
+#include <stdio.h>
+
+#ifdef CONFIG_PROFILE_TOD
+#include <sys/time.h>
+
+void
+prof_init(prof_t *c)
+{
+ c->sec = c->usec = 0;
+}
+
+void
+prof_switch(prof_t *o, prof_t *n)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ if (n)
+ {
+ n->start_sec = tv.tv_sec;
+ n->start_usec = tv.tv_usec;
+ }
+ if (o)
+ {
+ o->sec += tv.tv_sec - o->start_sec;
+ o->usec += tv.tv_usec - o->start_usec;
+ if (o->usec < 0)
+ {
+ o->usec += 1000000;
+ o->sec++;
+ }
+ else while (o->usec >= 1000000)
+ {
+ o->usec -= 1000000;
+ o->sec--;
+ }
+ }
+}
+
+int
+prof_format(char *buf, prof_t *c)
+{
+ return sprintf(buf, "%d.%06d", c->sec, c->usec);
+}
+#endif
+
+#ifdef CONFIG_PROFILE_TSC
+void
+prof_init(prof_t *c)
+{
+ c->ticks = 0;
+}
+
+int
+prof_format(char *buf, prof_t *c)
+{
+ return sprintf(buf, "%Ld", c->ticks);
+}
+#endif
+
+#ifdef CONFIG_PROFILE_KTSC
+#include <fcntl.h>
+#include <unistd.h>
+static int self_prof_fd = -1;
+
+void
+prof_init(prof_t *c)
+{
+ if (self_prof_fd < 0)
+ {
+ self_prof_fd = open("/proc/self/profile", O_RDONLY, 0);
+ if (self_prof_fd < 0)
+ die("Unable to open /proc/self/profile: %m");
+ }
+ c->ticks_user = 0;
+ c->ticks_sys = 0;
+}
+
+void
+prof_switch(prof_t *o, prof_t *n)
+{
+ u64 u, s;
+ byte buf[256];
+
+ int l = pread(self_prof_fd, buf, sizeof(buf)-1, 0);
+ ASSERT(l > 0 && l < (int)sizeof(buf)-1);
+ buf[l] = 0;
+ l = sscanf(buf, "%Ld%Ld", &u, &s);
+ ASSERT(l == 2);
+
+ if (n)
+ {
+ n->start_user = u;
+ n->start_sys = s;
+ }
+ if (o)
+ {
+ u -= o->start_user;
+ o->ticks_user += u;
+ s -= o->start_sys;
+ o->ticks_sys += s;
+ }
+}
+
+int
+prof_format(char *buf, prof_t *c)
+{
+ return sprintf(buf, "%Ld+%Ld", c->ticks_user, c->ticks_sys);
+}
+#endif
--- /dev/null
+/*
+ * Sherlock Library -- Poor Man's Profiler
+ *
+ * (c) 2001 Martin Mares <mj@ucw.cz>
+ */
+
+/*
+ * Usage:
+ * prof_t cnt;
+ * prof_init(&cnt);
+ * ...
+ * prof_start(&cnt);
+ * ...
+ * prof_stop(&cnt);
+ * printf("%s\n", PROF_STRING(&cnt));
+ */
+
+/* Profiling method to use */
+#define CONFIG_PROFILE_TOD /* gettimeofday() */
+#undef CONFIG_PROFILE_TSC /* i386 TSC */
+#undef CONFIG_PROFILE_KTSC /* kernel TSC profiler */
+
+#ifdef CONFIG_PROFILE_TOD
+#define CONFIG_PROFILE
+#define PROF_STR_SIZE 21
+
+typedef struct {
+ u32 start_sec, start_usec;
+ s32 sec, usec;
+} prof_t;
+
+#endif
+
+#ifdef CONFIG_PROFILE_TSC
+#define CONFIG_PROFILE
+#define CONFIG_PROFILE_INLINE
+#define PROF_STR_SIZE 24
+
+typedef struct {
+ u64 start_tsc;
+ u64 ticks;
+} prof_t;
+
+#define rdtscll(val) __asm__ __volatile__("rdtsc" : "=A" (val))
+
+static inline void prof_start(prof_t *c)
+{
+ rdtscll(c->start_tsc);
+}
+
+static inline void prof_stop(prof_t *c)
+{
+ u64 tsc;
+ rdtscll(tsc);
+ tsc -= c->start_tsc;
+ c->ticks += tsc;
+}
+
+static inline void prof_switch(prof_t *o, prof_t *n)
+{
+ u64 tsc;
+ rdtscll(tsc);
+ n->start_tsc = tsc;
+ tsc -= o->start_tsc;
+ o->ticks += tsc;
+}
+#endif
+
+#ifdef CONFIG_PROFILE_KTSC
+#define CONFIG_PROFILE
+#define PROF_STR_SIZE 50
+
+typedef struct {
+ u64 start_user, start_sys;
+ u64 ticks_user, ticks_sys;
+} prof_t;
+#endif
+
+#ifdef CONFIG_PROFILE
+
+/* Stuff common for all profilers */
+#ifndef CONFIG_PROFILE_INLINE
+void prof_switch(prof_t *, prof_t *);
+static inline void prof_start(prof_t *c) { prof_switch(NULL, c); }
+static inline void prof_stop(prof_t *c) { prof_switch(c, NULL); }
+#endif
+int prof_format(char *, prof_t *);
+void prof_init(prof_t *);
+
+#else
+
+/* Dummy profiler with no output */
+typedef struct { } prof_t;
+static inline void prof_init(prof_t *c UNUSED) { }
+static inline void prof_start(prof_t *c UNUSED) { }
+static inline void prof_stop(prof_t *c UNUSED) { }
+static inline void prof_switch(prof_t *c UNUSED, prof_t *d UNUSED) { }
+static inline void prof_format(char *b, prof_t *c UNUSED) { strcpy(b, "?"); }
+#define PROF_STR_SIZE 2
+
+#endif