Annotation of Gnu-Mach/kern/pc_sample.c, revision 1.1.1.4

1.1       root        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  [email protected]
                     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: 
1.1.1.2   root       27: #include <kern/printf.h>
                     28: #include <string.h>
1.1       root       29: 
                     30: #include <mach/mach_types.h>   /* vm_address_t */
                     31: #include <mach/std_types.h>    /* pointer_t */
                     32: #include <mach/pc_sample.h>
1.1.1.2   root       33: #include <machine/trap.h>
                     34: #include <kern/kalloc.h>
1.1       root       35: #include <kern/host.h>
                     36: #include <kern/thread.h>
                     37: #include <kern/pc_sample.h>
1.1.1.2   root       38: #include <kern/mach_clock.h>
1.1       root       39: 
                     40: #if    MACH_PCSAMPLE
                     41: 
                     42: #define MAX_PC_SAMPLES 512
                     43: 
                     44: typedef sampled_pc_t sampled_pcs[MAX_PC_SAMPLES];
                     45: 
                     46: void take_pc_sample(
1.1.1.3   root       47:     const thread_t t,
                     48:     sample_control_t *cp,
1.1.1.4 ! root       49:     sampled_pc_flavor_t flavor,
        !            50:     boolean_t usermode,
        !            51:     vm_offset_t kern_pc)
1.1       root       52: {
                     53:     vm_offset_t pc;
                     54:     struct sampled_pc *sample;
                     55:     
1.1.1.4 ! root       56:     if (usermode)
        !            57:        pc = interrupted_pc(t);
        !            58:     else
        !            59:        pc = kern_pc;
        !            60: 
1.1       root       61:     cp->seqno++;
                     62:     sample = &((sampled_pc_t *)cp->buffer)[cp->seqno % MAX_PC_SAMPLES];
1.1.1.2   root       63:     sample->id = (vm_offset_t)t;
1.1       root       64:     sample->pc = pc;
                     65:     sample->sampletype = flavor;
                     66: }
                     67: 
                     68: kern_return_t
                     69: thread_enable_pc_sampling(
                     70:     thread_t thread,
                     71:     int *tickp,
                     72:     sampled_pc_flavor_t flavors)
                     73: {
                     74:     vm_offset_t buf;
                     75: 
                     76:     if (thread == THREAD_NULL)  {
                     77:        return KERN_INVALID_ARGUMENT;
                     78:     }
                     79:     if (thread->pc_sample.buffer == 0)  {
                     80:        buf = (vm_offset_t) kalloc(sizeof (sampled_pcs));
                     81:        if (buf == 0) {
                     82:            printf("thread_enable_pc_sampling: kalloc failed\n");
                     83:            return KERN_INVALID_ARGUMENT;
                     84:        }
                     85:        thread->pc_sample.buffer = buf;
                     86:        thread->pc_sample.seqno = 0;
                     87:     }
                     88:     *tickp = tick;
                     89:     thread->pc_sample.sampletypes = flavors;
                     90:     return KERN_SUCCESS;
                     91: }
                     92: 
                     93: kern_return_t
                     94: task_enable_pc_sampling(
                     95:     task_t task,
                     96:     int *tickp,
                     97:     sampled_pc_flavor_t flavors)
                     98: {
                     99:     vm_offset_t buf;
                    100: 
                    101:     if (task == TASK_NULL)  {
                    102:        return KERN_INVALID_ARGUMENT;
                    103:     }
                    104:     if (task->pc_sample.buffer == 0)  {
                    105:        buf = (vm_offset_t) kalloc(sizeof (sampled_pcs));
                    106:        if (buf == 0) {
                    107:            printf("task_enable_pc_sampling: kalloc failed\n");
                    108:            return KERN_INVALID_ARGUMENT;
                    109:        }
                    110:        task->pc_sample.buffer = buf;
                    111:        task->pc_sample.seqno = 0;
                    112:     }
                    113:     *tickp = tick;
                    114:     task->pc_sample.sampletypes = flavors;
                    115:     return KERN_SUCCESS;
                    116: }
                    117: 
                    118: kern_return_t
                    119: thread_disable_pc_sampling(
                    120:     thread_t thread,
                    121:     int *samplecntp)
                    122: {
                    123:     vm_offset_t buf;
                    124: 
                    125:     if (thread == THREAD_NULL)  {
                    126:        return KERN_INVALID_ARGUMENT;
                    127:     }
                    128:     if ((buf = thread->pc_sample.buffer) != 0)
                    129:        kfree(buf, sizeof (sampled_pcs));
                    130:     thread->pc_sample.buffer = (vm_offset_t) 0;
                    131:     thread->pc_sample.seqno = 0;
                    132:     thread->pc_sample.sampletypes = 0; /* shut off sampling */
                    133:     
                    134:     return KERN_SUCCESS;
                    135: }
                    136: 
                    137: kern_return_t
                    138: task_disable_pc_sampling(
                    139:     task_t task,
                    140:     int *samplecntp)
                    141: {
                    142:     vm_offset_t buf;
                    143: 
                    144:     if (task == TASK_NULL)  {
                    145:        return KERN_INVALID_ARGUMENT;
                    146:     }
                    147:     if ((buf = task->pc_sample.buffer) != 0)
                    148:        kfree(buf, sizeof (sampled_pcs));
                    149:     task->pc_sample.buffer = (vm_offset_t) 0;
                    150:     task->pc_sample.seqno = 0;
                    151:     task->pc_sample.sampletypes = 0;   /* shut off sampling */
                    152: 
                    153:     return KERN_SUCCESS;
                    154: }
                    155: 
                    156: static kern_return_t
                    157: get_sampled_pcs(
                    158:        sample_control_t *cp,
                    159:        sampled_pc_seqno_t *seqnop,
                    160:        sampled_pc_array_t sampled_pcs_out,
                    161:        int *sampled_pcs_cntp)
                    162: {
                    163:     int nsamples;
                    164:     sampled_pc_seqno_t seqidx1, seqidx2;
                    165: 
                    166:     nsamples   = cp->seqno - *seqnop;
                    167:     seqidx1    = *seqnop % MAX_PC_SAMPLES;        /* index of *seqnop */
                    168:     seqidx2    = cp->seqno % MAX_PC_SAMPLES;  /* index of cp->seqno */
                    169: 
                    170:     if  (nsamples > MAX_PC_SAMPLES) {
                    171:        nsamples = MAX_PC_SAMPLES;
                    172:        seqidx1  = (seqidx2 + 1) % MAX_PC_SAMPLES;
                    173:     }
                    174: 
                    175:     if (nsamples > 0)  {
                    176:        /*
                    177:         * Carefully copy sampled_pcs into sampled_pcs_msgbuf IN ORDER.
                    178:         */
                    179:        if (seqidx1 < seqidx2) {
                    180:            /*
                    181:             * Simple case: no wraparound.
                    182:             * Copy from seqidx1 to seqidx2.
                    183:             */
1.1.1.2   root      184:            memcpy(sampled_pcs_out,
                    185:                   (sampled_pc_array_t)cp->buffer + seqidx1 + 1,
                    186:                   nsamples * sizeof(sampled_pc_t));
1.1       root      187:        } else {
                    188:            /* seqidx1 > seqidx2 -- Handle wraparound. */
                    189: 
1.1.1.2   root      190:            memcpy(sampled_pcs_out,
                    191:                   (sampled_pc_array_t)cp->buffer + seqidx1 + 1,
                    192:                   (MAX_PC_SAMPLES - seqidx1 - 1) * sizeof(sampled_pc_t));
                    193: 
                    194:            memcpy(sampled_pcs_out + (MAX_PC_SAMPLES - seqidx1 - 1),
                    195:                   (sampled_pc_array_t)cp->buffer,
                    196:                   (seqidx2 + 1) * sizeof(sampled_pc_t));
1.1       root      197:        }
1.1.1.3   root      198:     } else if (nsamples < 0) {
                    199:        /* Bogus SEQNO supplied.  */
                    200:        nsamples = 0;
1.1       root      201:     } else {
                    202:        /*  could either be zero because of overflow, or because
                    203:         *  we are being lied to.  In either case, return nothing.
                    204:         *  If overflow, only once in a blue moon. If being lied to,
                    205:         *  then we have no obligation to return anything useful anyway.
                    206:         */
                    207:        ;
                    208:     }
                    209:        
                    210:     *sampled_pcs_cntp = nsamples;
                    211:     *seqnop = cp->seqno;
                    212:     return KERN_SUCCESS;
                    213: }
                    214: 
                    215: kern_return_t
                    216: thread_get_sampled_pcs(
                    217:        thread_t thread,
                    218:        sampled_pc_seqno_t *seqnop,
                    219:        sampled_pc_array_t sampled_pcs_out,
                    220:        int *sampled_pcs_cntp)
                    221: {
                    222:     if (thread == THREAD_NULL)
                    223:        return KERN_INVALID_ARGUMENT;
                    224: 
                    225:     if (thread->pc_sample.buffer == 0)
                    226:         return KERN_FAILURE;
                    227: 
                    228:     return get_sampled_pcs(&thread->pc_sample, seqnop, sampled_pcs_out,
                    229:                           sampled_pcs_cntp);
                    230: }
                    231: 
                    232: kern_return_t
                    233: task_get_sampled_pcs(
                    234:        task_t task,
                    235:        sampled_pc_seqno_t *seqnop,
                    236:        sampled_pc_array_t sampled_pcs_out,
                    237:        int *sampled_pcs_cntp)
                    238: {
                    239:     if (task == TASK_NULL)
                    240:        return KERN_INVALID_ARGUMENT;
                    241: 
                    242:     if (task->pc_sample.buffer == 0)
                    243:         return KERN_FAILURE;
                    244: 
                    245:     return get_sampled_pcs(&task->pc_sample, seqnop, sampled_pcs_out,
                    246:                           sampled_pcs_cntp);
                    247: }
                    248: 
                    249: #else  /* MACH_PCSAMPLE */
                    250: 
                    251: kern_return_t
                    252: thread_enable_pc_sampling(
1.1.1.3   root      253:     const thread_t thread,
                    254:     const int *tickp,
1.1       root      255:     sampled_pc_flavor_t flavors)
                    256: {
                    257:     return KERN_FAILURE;       /* not implemented */
                    258: }
                    259: 
                    260: kern_return_t
                    261: task_enable_pc_sampling(
1.1.1.3   root      262:     const task_t task,
                    263:     const int *tickp,
1.1       root      264:     sampled_pc_flavor_t flavors)
                    265: {
                    266:     return KERN_FAILURE;       /* not implemented */
                    267: }
                    268: 
                    269: kern_return_t
                    270: thread_disable_pc_sampling(
1.1.1.3   root      271:     const thread_t thread,
                    272:     const int *samplecntp)
1.1       root      273: {
                    274:     return KERN_FAILURE;       /* not implemented */
                    275: }
                    276: 
                    277: kern_return_t
                    278: task_disable_pc_sampling(
1.1.1.3   root      279:     const task_t task,
                    280:     const int *samplecntp)
1.1       root      281: {
                    282:     return KERN_FAILURE;       /* not implemented */
                    283: }
                    284: 
                    285: kern_return_t
                    286: thread_get_sampled_pcs(
1.1.1.3   root      287:        const thread_t thread,
                    288:        const sampled_pc_seqno_t *seqnop,
                    289:        const sampled_pc_array_t sampled_pcs_out,
                    290:        const int *sampled_pcs_cntp)
1.1       root      291: {
                    292:     return KERN_FAILURE;       /* not implemented */
                    293: }
                    294: 
                    295: kern_return_t
                    296: task_get_sampled_pcs(
1.1.1.3   root      297:        const task_t task,
                    298:        const sampled_pc_seqno_t *seqnop,
                    299:        const sampled_pc_array_t sampled_pcs_out,
                    300:        const int *sampled_pcs_cntp)
1.1       root      301: {
                    302:     return KERN_FAILURE;       /* not implemented */
                    303: }
                    304: 
                    305: #endif /* MACH_PCSAMPLE */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.