OSDN Git Service

Add an implementation of profil(), based on the version from
authorEric Andersen <andersen@codepoet.org>
Sat, 6 Sep 2003 13:00:11 +0000 (13:00 -0000)
committerEric Andersen <andersen@codepoet.org>
Sat, 6 Sep 2003 13:00:11 +0000 (13:00 -0000)
glibc, with several changes for use in uClibc.

libc/sysdeps/linux/common/Makefile
libc/sysdeps/linux/common/profil.c [new file with mode: 0644]

index 3135172..bee640d 100644 (file)
@@ -26,7 +26,7 @@ CSRC= waitpid.c getdnnm.c gethstnm.c getcwd.c ptrace.c \
        truncate64.c getrlimit64.c setrlimit64.c creat64.c \
        llseek.c pread_write.c _exit.c sync.c getdirname.c \
        sendfile64.c xstatconv.c getdents.c getdents64.c vfork.c \
-       ulimit.c
+       ulimit.c profil.c
 ifneq ($(strip $(EXCLUDE_BRK)),y)
 CSRC+=sbrk.c
 endif
diff --git a/libc/sysdeps/linux/common/profil.c b/libc/sysdeps/linux/common/profil.c
new file mode 100644 (file)
index 0000000..3df0836
--- /dev/null
@@ -0,0 +1,113 @@
+/* Low-level statistical profiling support function.  Mostly POSIX.1 version.
+   Copyright (C) 1996,97,98,2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/time.h>
+
+#ifndef SIGPROF
+
+int profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
+{
+    if (scale == 0)
+       /* Disable profiling.  */
+       return 0;
+    __set_errno (ENOSYS);
+    return -1;
+}
+
+#else
+
+static u_short *samples;
+static size_t nsamples;
+static size_t pc_offset;
+static u_int pc_scale;
+
+static inline void
+profil_count (void *pc)
+{
+    size_t i = (pc - pc_offset - (void *) 0) / 2;
+    if (sizeof (unsigned long long int) > sizeof (size_t))
+       i = (unsigned long long int) i * pc_scale / 65536;
+    else
+       i = i / 65536 * pc_scale + i % 65536 * pc_scale / 65536;
+    if (i < nsamples)
+       ++samples[i];
+}
+
+/* Get the machine-dependent definition of `profil_counter', the signal
+   handler for SIGPROF.  It calls `profil_count' (above) with the PC of the
+   interrupted code.  */
+#include <bits/profil-counter.h>
+
+
+/* Enable statistical profiling, writing samples of the PC into at most
+   SIZE bytes of SAMPLE_BUFFER; every processor clock tick while profiling
+   is enabled, the system examines the user PC and increments
+   SAMPLE_BUFFER[((PC - OFFSET) / 2) * SCALE / 65536].  If SCALE is zero,
+   disable profiling.  Returns zero on success, -1 on error.  */
+int profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
+{
+    static struct sigaction oact;
+    static struct itimerval otimer;
+    struct sigaction act;
+    struct itimerval timer;
+
+    if (sample_buffer == NULL)
+    {
+       /* Disable profiling.  */
+       if (samples == NULL)
+           /* Wasn't turned on.  */
+           return 0;
+
+       if (setitimer (ITIMER_PROF, &otimer, NULL) < 0)
+           return -1;
+       samples = NULL;
+       return sigaction (SIGPROF, &oact, NULL);
+    }
+
+    if (samples)
+    {
+       /* Was already turned on.  Restore old timer and signal handler
+          first.  */
+       if (setitimer (ITIMER_PROF, &otimer, NULL) < 0
+               || sigaction (SIGPROF, &oact, NULL) < 0)
+           return -1;
+    }
+
+    samples = sample_buffer;
+    nsamples = size / sizeof *samples;
+    pc_offset = offset;
+    pc_scale = scale;
+
+    act.sa_handler = (__sighandler_t) &profil_counter;
+    act.sa_flags = SA_RESTART;
+    __sigfillset (&act.sa_mask);
+    if (sigaction (SIGPROF, &act, &oact) < 0)
+       return -1;
+
+    timer.it_value.tv_sec = 0;
+    timer.it_value.tv_usec = 1;
+    timer.it_interval = timer.it_value;
+    return setitimer (ITIMER_PROF, &timer, &otimer);
+}
+
+#endif