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 / m68k / gmon / profil.c < prev   
Encoding:
C/C++ Source or Header  |  1994-11-19  |  2.8 KB  |  116 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.  * Modified for m68k by Andreas Schwab <schwab@issan.uni-dortmund.de>
  5.  *
  6.  * This file is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Library General Public License as
  8.  * published by the Free Software Foundation; either version 2 of the
  9.  * License, or (at your option) any later version.
  10.  */
  11.  
  12. /*
  13.  *     IMPORTANT:
  14.  *
  15.  *   This file should never be compiled with -p or -pg!
  16.  *   It will need special consideration in the Makefile for libc_p.a
  17.  *   to ensure that it is not compiled with any profiling flags.
  18.  *
  19.  *     Limitations:
  20.  *
  21.  * - Any program that tries to use SIGPROF itimers and profil at the
  22.  *   same time won't work.
  23.  *
  24.  * - The user's program is free to trash our handler with a call to
  25.  *   signal or sigaction.
  26.  *
  27.  * - Calling profil with an invalid buffer will cause a core dump instead
  28.  *   of just disabling profiling.
  29.  *
  30.  * - The precision of the histogram is worse than with true kernel
  31.  *   profiling.
  32.  *
  33.  */
  34.  
  35. #include <stdio.h>
  36. #include <signal.h>
  37. #include <sys/time.h>
  38. #include <sys/types.h>
  39. #include <unistd.h>
  40.  
  41. static struct sigaction old_sa;
  42. static struct itimerval old_it;
  43.  
  44. static unsigned long prof_buf;
  45. static int prof_bufsiz;
  46. static int prof_offset;
  47. static int prof_scale = 0;
  48.  
  49. struct sigcontext 
  50. {
  51.   unsigned long  sc_mask;
  52.   unsigned long  sc_usp;
  53.   unsigned long  sc_d0;
  54.   unsigned long  sc_d1;
  55.   unsigned long  sc_a0;
  56.   unsigned long  sc_a1;
  57.   unsigned short sc_sr;
  58.   unsigned long  sc_pc;
  59.   unsigned short sc_formatvec;
  60. };
  61.   
  62. static void
  63. _profil_handler(int signr, int code, struct sigcontext *scp)
  64. {
  65.     unsigned long pc, spot;
  66.  
  67. #ifdef PROFIL_DEBUG
  68.     printf("pc = %#x\n", scp->sc_pc);
  69. #endif
  70.     pc = scp->sc_pc - prof_offset;
  71.     spot = (prof_scale*(pc >> 16)
  72.         + ((prof_scale*(pc & (0x10000 - 1))) >> 16)) & ~1;
  73.     if (spot < prof_bufsiz)
  74.         ++*((unsigned short *) (spot + prof_buf));
  75. }
  76.  
  77. int
  78. profil(char *buf, int bufsiz, int offset, int scale)
  79. {
  80.     struct sigaction new_sa;
  81.     struct itimerval new_it;
  82.     int old_scale = prof_scale;
  83.  
  84.     if (!buf || bufsiz == 0 || scale < 2) {
  85.         if (prof_scale) {
  86.             setitimer(ITIMER_PROF, &old_it, &new_it);
  87.             sigaction(SIGPROF, &old_sa, &new_sa);
  88.         }
  89.         prof_scale = 0;
  90.     }
  91.     else {
  92.         prof_buf = (unsigned long) buf;
  93.         prof_bufsiz = bufsiz;
  94.         prof_offset = offset;
  95.         prof_scale = scale;
  96.         if (!old_scale) {
  97.             prof_scale = scale;
  98.             new_sa.sa_handler =
  99.                 (void (*)(int)) _profil_handler;
  100.             new_sa.sa_mask = 0;
  101. #ifdef SA_RESTART
  102.             new_sa.sa_flags = SA_RESTART;
  103. #else
  104.             new_sa.sa_flags = 0;
  105. #endif
  106.             new_it.it_interval.tv_sec = 0;
  107.             new_it.it_interval.tv_usec = 1;
  108.             new_it.it_value.tv_sec = 0;
  109.             new_it.it_value.tv_usec = 1;
  110.             sigaction(SIGPROF, &new_sa, &old_sa);
  111.             setitimer(ITIMER_PROF, &new_it, &old_it);
  112.         }
  113.     }
  114.     return 0;
  115. }
  116.