Contiki 2.6

profile.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2007, Swedish Institute of Computer Science.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  *
00031  * $Id: profile.c,v 1.4 2008/01/17 12:19:26 adamdunkels Exp $
00032  */
00033 
00034 /**
00035  * \file
00036  *         Implementation of the Contiki profiling system
00037  * \author
00038  *         Adam Dunkels <adam@sics.se>
00039  */
00040 
00041 #include "sys/profile.h"
00042 #include "sys/clock.h"
00043 
00044 #include <stdio.h>
00045 
00046 /* XXX: the profiling code is under development and may not work at
00047    present. */
00048 
00049 
00050 TIMETABLE_NONSTATIC(profile_timetable);
00051 
00052 TIMETABLE_NONSTATIC(profile_begin_timetable);
00053 TIMETABLE_NONSTATIC(profile_end_timetable);
00054 TIMETABLE_AGGREGATE(profile_aggregate, PROFILE_AGGREGATE_SIZE);
00055 
00056 static rtimer_clock_t episode_start_time;
00057 static unsigned int invalid_episode_overflow, invalid_episode_toolong,
00058   max_queuelen;
00059 
00060 /* The number of fine grained ticks per coarse grained ticks. We
00061    currently (MSP430) have 2457600 ticks per second for the fine
00062    grained timer, and 32678 / 8 ticks per second for the coarse. */
00063 #define XXX_HACK_FINE_TICKS_PER_COARSE_TICK (2457600/(32678/8))
00064 
00065 /*---------------------------------------------------------------------------*/
00066 void
00067 profile_init(void)
00068 {
00069   timetable_init();
00070   timetable_clear(&profile_begin_timetable);
00071   timetable_clear(&profile_end_timetable);
00072 }
00073 /*---------------------------------------------------------------------------*/
00074 void
00075 profile_episode_start(void)
00076 {
00077   struct timetable_timestamp *e;
00078   timetable_clear(&profile_begin_timetable);
00079   timetable_clear(&profile_end_timetable);
00080   episode_start_time = clock_time();
00081   
00082   e = timetable_entry(&profile_begin_timetable,
00083                       PROFILE_TIMETABLE_SIZE - 1);
00084   if(e != NULL) {
00085     e->id = NULL;
00086   }
00087   e = timetable_entry(&profile_end_timetable,
00088                       PROFILE_TIMETABLE_SIZE - 1);
00089   if(e != NULL) {
00090     e->id = NULL;
00091   }
00092 }
00093 /*---------------------------------------------------------------------------*/
00094 void
00095 profile_episode_end(void)
00096 {
00097   struct timetable_timestamp *e;
00098   rtimer_clock_t episode_end_time = clock_time();
00099 
00100 /*   printf("timetable_episode_end start %u, end %u, max time %u\n", episode_start_time, episode_end_time, 65536/FINE_TICKS_PER_COARSE_TICK); */
00101   e = timetable_entry(&profile_begin_timetable,
00102                       PROFILE_TIMETABLE_SIZE - 1);
00103   if(e != NULL && e->id != NULL) {
00104     /* Invalid episode because of list overflow. */
00105     invalid_episode_overflow++;
00106     max_queuelen = PROFILE_TIMETABLE_SIZE;
00107   } else if(episode_end_time - episode_start_time >
00108             65536/XXX_HACK_FINE_TICKS_PER_COARSE_TICK) {
00109     /* Invalid episode because of timer overflow. */
00110     invalid_episode_toolong++;
00111   } else {
00112     /* Compute aggregates. */
00113     if(timetable_ptr(&profile_begin_timetable) > max_queuelen) {
00114       max_queuelen = timetable_ptr(&profile_begin_timetable);
00115     }
00116     /*    timetable_aggregates_compute();*/
00117   }
00118 }
00119 /*---------------------------------------------------------------------------*/
00120 /*
00121  *
00122  * Find a specific aggregate ID in the list of aggregates.
00123  *
00124  */
00125 static struct timetable_aggregate_entry *
00126 find_aggregate(struct timetable_aggregate *a,
00127                const char *id)
00128 {
00129   int i;
00130   for(i = 0; i < a->ptr; ++i) {
00131     if(a->entries[i].id == id) {
00132       return &a->entries[i];
00133     }
00134   }
00135   if(i == a->size) {
00136     return NULL;
00137   }
00138   a->entries[a->ptr].id = NULL;
00139   return &a->entries[a->ptr++];
00140 }
00141 /*---------------------------------------------------------------------------*/
00142 void
00143 profile_aggregate_print_detailed(void)
00144 {
00145   int i;
00146   struct timetable_aggregate *a = &profile_aggregate;
00147   
00148   /*  printf("timetable_aggregate_print_detailed: a ptr %d\n", a->ptr);*/
00149   for(i = 0; i < a->ptr; ++i) {
00150     printf("-- %s: %lu / %u = %lu\n", a->entries[i].id,
00151            a->entries[i].time,
00152            a->entries[i].episodes,
00153            a->entries[i].time / a->entries[i].episodes);
00154   }
00155   
00156   printf("Memory for entries: %d * %d = %d\n",
00157          (int)sizeof(struct timetable_aggregate), a->ptr,
00158          (int)sizeof(struct timetable_aggregate) * a->ptr);
00159 }
00160 /*---------------------------------------------------------------------------*/
00161 void
00162 profile_aggregate_compute_detailed(void)
00163 {
00164   int i;
00165   int last;
00166   rtimer_clock_t t;
00167   struct timetable_aggregate *a = &profile_aggregate;
00168   struct timetable *timetable = &profile_timetable;
00169   struct timetable_aggregate_entry *entry;
00170 
00171   last = timetable_ptr(&profile_begin_timetable);
00172   t = profile_begin_timetable.timestamps[0].time;
00173   for(i = 0; i < last; ++i) {
00174 
00175     entry = find_aggregate(a, profile_begin_timetable.timestamps[i].id);
00176     if(entry == NULL) {
00177       /* The list is full, skip this entry */
00178       /*      printf("detailed_timetable_aggregate_compute: list full\n");*/
00179     } else if(entry->id == NULL) {
00180       /* The id was found in the list, so we add it. */
00181       entry->id = timetable->timestamps[i - 1].id;
00182       entry->time = (unsigned long)(timetable->timestamps[i].time - t -
00183                                     timetable_timestamp_time);
00184       entry->episodes = 1;
00185       /*      printf("New entry %s %lu\n", entry->id, entry->time);*/
00186     } else {
00187       entry->time += (unsigned long)(timetable->timestamps[i].time - t -
00188                                      timetable_timestamp_time);
00189                                      entry->episodes++;
00190     }
00191     t = timetable->timestamps[i].time;
00192     /*    printf("a ptr %d\n", a->ptr);*/
00193 
00194   }
00195 
00196 }
00197 /*---------------------------------------------------------------------------*/