home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / LIBC / LIBC-4.6 / LIBC-4 / libc-linux / sysdeps / linux / i386 / gmon / profil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-02  |  2.8 KB  |  111 lines

  1. /*
  2.  * profil.c -- user space version of the profil(2) system call
  3.  * Copyright (C) 1992, 1993 Rick Sladkey <jrs@world.std.com>
  4.  *
  5.  * This file is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Library General Public License as
  7.  * published by the Free Software Foundation; either version 2 of the
  8.  * License, or (at your option) any later version.
  9.  */
  10.  
  11. /*
  12.  *     IMPORTANT:
  13.  *
  14.  *   This file should never be compiled with -p or -pg!
  15.  *   It will need special consideration in the Makefile for libc_p.a
  16.  *   to ensure that it is not compiled with any profiling flags.
  17.  *
  18.  *     Limitations:
  19.  *
  20.  * - Any program that tries to use SIGPROF itimers and profil at the
  21.  *   same time won't work.
  22.  *
  23.  * - The user's program is free to trash our handler with a call to
  24.  *   signal or sigaction.
  25.  *
  26.  * - Calling profil with an invalid buffer will cause a core dump instead
  27.  *   of just disabling profiling.
  28.  *
  29.  * - The precision of the histogram is worse than with true kernel
  30.  *   profiling.
  31.  *
  32.  */
  33.  
  34. #include <stdio.h>
  35. #include <signal.h>
  36. #include <sys/time.h>
  37. #include <sys/types.h>
  38. #include <unistd.h>
  39.  
  40. static struct sigaction old_sa;
  41. static struct itimerval old_it;
  42.  
  43. static unsigned long prof_buf;
  44. static int prof_bufsiz;
  45. static int prof_offset;
  46. static int prof_scale = 0;
  47.  
  48. /*
  49.  * This depends a lot on the stack at the time the signal handler
  50.  * is invoked.  For Linux-0.99.8 and before eip was the seventh
  51.  * argument.  For Linux-0.99.9 and later it is the fourteenth.
  52.  * I think.  For Linux-0.99.13 it is the sixteenth.  It's a
  53.  * continuing mystery.
  54.  */
  55.   
  56. static void
  57. _profil_handler(int signr)
  58. {
  59.     unsigned long pc, spot;
  60.     unsigned long eip = ((unsigned long *) &signr)[15];
  61.  
  62. #ifdef PROFIL_DEBUG
  63.     printf("eip = %#x\n", eip);
  64. #endif
  65.     pc = eip - prof_offset;
  66.     spot = (prof_scale*(pc >> 16)
  67.         + ((prof_scale*(pc & (0x10000 - 1))) >> 16)) & ~1;
  68.     if (spot < prof_bufsiz)
  69.         ++*((unsigned short *) (spot + prof_buf));
  70. }
  71.  
  72. int
  73. profil(char *buf, int bufsiz, int offset, int scale)
  74. {
  75.     struct sigaction new_sa;
  76.     struct itimerval new_it;
  77.     int old_scale = prof_scale;
  78.  
  79.     if (!buf || bufsiz == 0 || scale < 2) {
  80.         if (prof_scale) {
  81.             setitimer(ITIMER_PROF, &old_it, &new_it);
  82.             sigaction(SIGPROF, &old_sa, &new_sa);
  83.         }
  84.         prof_scale = 0;
  85.     }
  86.     else {
  87.         prof_buf = (unsigned long) buf;
  88.         prof_bufsiz = bufsiz;
  89.         prof_offset = offset;
  90.         prof_scale = scale;
  91.         if (!old_scale) {
  92.             prof_scale = scale;
  93.             new_sa.sa_handler =
  94.                 (void (*)(int)) _profil_handler;
  95.             new_sa.sa_mask = 0;
  96. #ifdef SA_RESTART
  97.             new_sa.sa_flags = SA_RESTART;
  98. #else
  99.             new_sa.sa_flags = 0;
  100. #endif
  101.             new_it.it_interval.tv_sec = 0;
  102.             new_it.it_interval.tv_usec = 1;
  103.             new_it.it_value.tv_sec = 0;
  104.             new_it.it_value.tv_usec = 1;
  105.             sigaction(SIGPROF, &new_sa, &old_sa);
  106.             setitimer(ITIMER_PROF, &new_it, &old_it);
  107.         }
  108.     }
  109.     return 0;
  110. }
  111.