The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/pc_sample.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1993,1992 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        pc_sample.c,v $
   29  * Revision 2.5  93/11/17  17:17:09  dbg
   30  *      Made file still build when MACH_PCSAMPLE == 0.  Added
   31  *      ANSI function prototypes.  Return current system clock
   32  *      period (in microseconds!) instead of 'tick'.
   33  *      [93/03/02            dbg]
   34  * 
   35  * Revision 2.4  93/08/03  12:31:18  mrt
   36  *      [93/08/02  16:50:13  bershad]
   37  * 
   38  *      Flavor support for PC sampling.
   39  *      [93/07/30  10:23:02  bershad]
   40  * 
   41  * Revision 2.3  93/01/27  09:39:48  danner
   42  *      take_pc_sample() is void, get_sampled_pcs is static return_t
   43  *      [93/01/25            jfriedl]
   44  * 
   45  * Revision 2.2  93/01/24  13:19:46  danner
   46  *      Lots of changes.
   47  *      [93/01/12            rvb]
   48  *      Created.
   49  *      [92/05/10            cmaeda]
   50  * 
   51  */
   52 
   53 
   54 
   55 #include <mach_pcsample.h>
   56 
   57 #include <mach/mach_types.h>    /* vm_address_t */
   58 #include <mach/std_types.h>     /* pointer_t */
   59 #include <mach/pc_sample.h>
   60 
   61 #include <kern/clock.h>
   62 #include <kern/host.h>
   63 #include <kern/kern_io.h>
   64 #include <kern/memory.h>
   65 #include <kern/thread.h>
   66 #include <kern/pc_sample.h>
   67 
   68 #if     MACH_PCSAMPLE
   69 
   70 #define MAX_PC_SAMPLES 512
   71 
   72 typedef sampled_pc_t sampled_pcs[MAX_PC_SAMPLES];
   73 
   74 int pc_sampling_enabled = 0;
   75 decl_simple_lock_data(, pc_sampling_lock)       /* lock for enabling */
   76 
   77 void take_pc_sample(
   78     register thread_t t,
   79     register sample_control_t *cp,
   80     sampled_pc_flavor_t flavor)
   81 {
   82     vm_offset_t pc;
   83     struct sampled_pc *sample;
   84     
   85     pc = INTERRUPTED_PC(t);
   86     cp->seqno++;
   87     sample = &((sampled_pc_t *)cp->buffer)[cp->seqno % MAX_PC_SAMPLES];
   88     sample->id = (natural_t)t;
   89     sample->pc = pc;
   90     sample->sampletype = flavor;
   91 }
   92 
   93 kern_return_t
   94 thread_enable_pc_sampling(
   95     thread_t thread,
   96     int *tickp,
   97     sampled_pc_flavor_t flavors)
   98 {
   99     vm_offset_t buf;
  100 
  101     if (thread == THREAD_NULL)  {
  102         return KERN_INVALID_ARGUMENT;
  103     }
  104     if (thread->pc_sample.buffer == 0)  {
  105         buf = (vm_offset_t) kalloc(sizeof (sampled_pcs));
  106         if (buf == 0) {
  107             printf("thread_enable_pc_sampling: kalloc failed\n");
  108             return KERN_INVALID_ARGUMENT;
  109         }
  110         thread->pc_sample.buffer = buf;
  111         thread->pc_sample.seqno = 0;
  112     }
  113     *tickp = sys_clock->resolution / 1000;      /* nanosec -> microsec */
  114     thread->pc_sample.sampletypes = flavors;
  115     return KERN_SUCCESS;
  116 }
  117 
  118 kern_return_t
  119 task_enable_pc_sampling(
  120     task_t task,
  121     int *tickp,
  122     sampled_pc_flavor_t flavors)
  123 {
  124     vm_offset_t buf;
  125 
  126     if (task == TASK_NULL)  {
  127         return KERN_INVALID_ARGUMENT;
  128     }
  129     if (task->pc_sample.buffer == 0)  {
  130         buf = (vm_offset_t) kalloc(sizeof (sampled_pcs));
  131         if (buf == 0) {
  132             printf("task_enable_pc_sampling: kalloc failed\n");
  133             return KERN_INVALID_ARGUMENT;
  134         }
  135         task->pc_sample.buffer = buf;
  136         task->pc_sample.seqno = 0;
  137     }
  138     *tickp = sys_clock->resolution / 1000;      /* nanosec -> microsec */
  139     task->pc_sample.sampletypes = flavors;
  140     return KERN_SUCCESS;
  141 }
  142 
  143 kern_return_t
  144 thread_disable_pc_sampling(
  145     thread_t thread,
  146     int *samplecntp)
  147 {
  148     vm_offset_t buf;
  149 
  150     if (thread == THREAD_NULL)  {
  151         return KERN_INVALID_ARGUMENT;
  152     }
  153     if ((buf = thread->pc_sample.buffer) != 0)
  154         kfree(buf, sizeof (sampled_pcs));
  155     thread->pc_sample.buffer = (vm_offset_t) 0;
  156     thread->pc_sample.seqno = 0;
  157     thread->pc_sample.sampletypes = 0;  /* shut off sampling */
  158     
  159     return KERN_SUCCESS;
  160 }
  161 
  162 kern_return_t
  163 task_disable_pc_sampling(
  164     task_t task,
  165     int *samplecntp)
  166 {
  167     vm_offset_t buf;
  168 
  169     if (task == TASK_NULL)  {
  170         return KERN_INVALID_ARGUMENT;
  171     }
  172     if ((buf = task->pc_sample.buffer) != 0)
  173         kfree(buf, sizeof (sampled_pcs));
  174     task->pc_sample.buffer = (vm_offset_t) 0;
  175     task->pc_sample.seqno = 0;
  176     task->pc_sample.sampletypes = 0;    /* shut off sampling */
  177 
  178     return KERN_SUCCESS;
  179 }
  180 
  181 static kern_return_t
  182 get_sampled_pcs(
  183         sample_control_t *cp,
  184         sampled_pc_seqno_t *seqnop,
  185         sampled_pc_array_t sampled_pcs_out,
  186         int *sampled_pcs_cntp)
  187 {
  188     int nsamples;
  189     sampled_pc_seqno_t seqidx1, seqidx2;
  190 
  191     nsamples    = cp->seqno - *seqnop;
  192     seqidx1     = *seqnop % MAX_PC_SAMPLES;        /* index of *seqnop */
  193     seqidx2     = cp->seqno % MAX_PC_SAMPLES;  /* index of cp->seqno */
  194 
  195     if  (nsamples > MAX_PC_SAMPLES) {
  196         nsamples = MAX_PC_SAMPLES;
  197         seqidx1  = (seqidx2 + 1) % MAX_PC_SAMPLES;
  198     }
  199 
  200     if (nsamples > 0)  {
  201         /*
  202          * Carefully copy sampled_pcs into sampled_pcs_msgbuf IN ORDER.
  203          */
  204         if (seqidx1 < seqidx2) {
  205             /*
  206              * Simple case: no wraparound.
  207              * Copy from seqidx1 to seqidx2.
  208              */
  209             bcopy((sampled_pc_array_t)cp->buffer + seqidx1 + 1,
  210                   sampled_pcs_out,
  211                   nsamples * sizeof(sampled_pc_t));
  212         } else {
  213             /* seqidx1 > seqidx2 -- Handle wraparound. */
  214 
  215             bcopy((sampled_pc_array_t)cp->buffer + seqidx1 + 1,
  216                   sampled_pcs_out,
  217                   (MAX_PC_SAMPLES - seqidx1 - 1) * sizeof(sampled_pc_t));
  218 
  219             bcopy((sampled_pc_array_t)cp->buffer,
  220                   sampled_pcs_out + (MAX_PC_SAMPLES - seqidx1 - 1),
  221                   (seqidx2 + 1) * sizeof(sampled_pc_t));
  222         }
  223     } else {
  224         /*  could either be zero because of overflow, or because
  225          *  we are being lied to.  In either case, return nothing.
  226          *  If overflow, only once in a blue moon. If being lied to,
  227          *  then we have no obligation to return anything useful anyway.
  228          */
  229         ;
  230     }
  231         
  232     *sampled_pcs_cntp = nsamples;
  233     *seqnop = cp->seqno;
  234     return KERN_SUCCESS;
  235 }
  236 
  237 kern_return_t
  238 thread_get_sampled_pcs(
  239         thread_t thread,
  240         sampled_pc_seqno_t *seqnop,
  241         sampled_pc_array_t sampled_pcs_out,
  242         int *sampled_pcs_cntp)
  243 {
  244     if (thread == THREAD_NULL)
  245         return KERN_INVALID_ARGUMENT;
  246 
  247     if (thread->pc_sample.buffer == 0)
  248         return KERN_FAILURE;
  249 
  250     return get_sampled_pcs(&thread->pc_sample, seqnop, sampled_pcs_out,
  251                            sampled_pcs_cntp);
  252 }
  253 
  254 kern_return_t
  255 task_get_sampled_pcs(
  256         task_t task,
  257         sampled_pc_seqno_t *seqnop,
  258         sampled_pc_array_t sampled_pcs_out,
  259         int *sampled_pcs_cntp)
  260 {
  261     if (task == TASK_NULL)
  262         return KERN_INVALID_ARGUMENT;
  263 
  264     if (task->pc_sample.buffer == 0)
  265         return KERN_FAILURE;
  266 
  267     return get_sampled_pcs(&task->pc_sample, seqnop, sampled_pcs_out,
  268                            sampled_pcs_cntp);
  269 }
  270 
  271 #else   /* MACH_PCSAMPLE */
  272 
  273 kern_return_t
  274 thread_enable_pc_sampling(
  275     thread_t thread,
  276     int *tickp,
  277     sampled_pc_flavor_t flavors)
  278 {
  279     return KERN_FAILURE;        /* not implemented */
  280 }
  281 
  282 kern_return_t
  283 task_enable_pc_sampling(
  284     task_t task;
  285     int *tickp,
  286     sampled_pc_flavor_t flavors)
  287 {
  288     return KERN_FAILURE;        /* not implemented */
  289 }
  290 
  291 kern_return_t
  292 thread_disable_pc_sampling(
  293     thread_t thread,
  294     int *samplecntp)
  295 {
  296     return KERN_FAILURE;        /* not implemented */
  297 }
  298 
  299 kern_return_t
  300 task_disable_pc_sampling(
  301     task_t task,
  302     int *samplecntp)
  303 {
  304     return KERN_FAILURE;        /* not implemented */
  305 }
  306 
  307 kern_return_t
  308 thread_get_sampled_pcs(
  309         thread_t thread,
  310         sampled_pc_seqno_t *seqnop,
  311         sampled_pc_array_t sampled_pcs_out,
  312         int *sampled_pcs_cntp)
  313 {
  314     return KERN_FAILURE;        /* not implemented */
  315 }
  316 
  317 kern_return_t
  318 task_get_sampled_pcs(
  319         task_t task,
  320         sampled_pc_seqno_t *seqnop,
  321         sampled_pc_array_t sampled_pcs_out,
  322         int *sampled_pcs_cntp)
  323 {
  324     return KERN_FAILURE;        /* not implemented */
  325 }
  326 
  327 #endif  /* MACH_PCSAMPLE */

Cache object: bec19ddf295cd76f45b0072bf8e65f5b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.