Contiki 2.6

profile-aggregates.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-aggregates.c,v 1.4 2007/11/18 12:27:45 ksb Exp $
00032  */
00033 
00034 /**
00035  * \file
00036  *         Compuation of aggregates for the Contiki profiling system
00037  * \author
00038  *         Adam Dunkels <adam@sics.se>
00039  */
00040 
00041 #include "sys/profile.h"
00042 
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 
00046 struct aggregate {
00047   const char *ptr;
00048   unsigned short episodes;
00049   unsigned long cycles;
00050 };
00051 
00052 #define DETAILED_AGGREGATES 0
00053 
00054 #define MAX_CATEGORIES 32
00055 #define LIST_LEN 100
00056 
00057 static struct aggregate aggregates[LIST_LEN];
00058 
00059 static int aggregates_list_ptr = 0;
00060 
00061 /*---------------------------------------------------------------------------*/
00062 static struct aggregate *
00063 find_aggregate_category(const uint16_t cat)
00064 {
00065   int i;
00066   uint16_t acat;
00067 
00068 /*   printf("find_aggregate_category 0x%04x %c%c\n", */
00069 /*       cat, cat >> 8, cat & 0xff); */
00070   
00071   for(i = 0; i < aggregates_list_ptr; ++i) {
00072     acat = (aggregates[i].ptr[0] << 8) + aggregates[i].ptr[1];
00073 
00074 /*     printf("acat 0x%04x %c%c\n", */
00075 /*         acat, acat >> 8, acat & 0xff); */
00076       
00077     if(acat == cat) {
00078       return &aggregates[i];
00079     }
00080   }
00081 
00082   if(i == LIST_LEN) {
00083     return NULL;
00084   }
00085 
00086   aggregates[aggregates_list_ptr].ptr = NULL;
00087   return &aggregates[aggregates_list_ptr++];
00088 }
00089 /*---------------------------------------------------------------------------*/
00090 #if DETAILED_AGGREGATES
00091 static struct aggregate *
00092 find_aggregate(const unsigned char *ptr)
00093 {
00094   int i;
00095   for(i = 0; i < aggregates_list_ptr; ++i) {
00096     if(aggregates[i].ptr == ptr) {
00097       return &aggregates[i];
00098     }
00099   }
00100   if(i == LIST_LEN) {
00101     return NULL;
00102   }
00103 
00104   return &aggregates[aggregates_list_ptr++];
00105 }
00106 #endif /* DETAILED_AGGREGATES */
00107 /*---------------------------------------------------------------------------*/
00108 void
00109 profile_aggregates_print(void)
00110 {
00111   int i;
00112 
00113 #if DETAILED_AGGREGATES
00114   for(i = 0; i < aggregates_list_ptr; ++i) {
00115     printf("-- %s: %lu / %u = %lu\n", aggregates[i].ptr,
00116            aggregates[i].cycles,
00117            aggregates[i].episodes,
00118            aggregates[i].cycles / aggregates[i].episodes);
00119   }
00120 #else
00121   for(i = 0; i < aggregates_list_ptr; ++i) {
00122     printf("-- %c%c: %lu / %u = %lu\n",
00123            aggregates[i].ptr[0], aggregates[i].ptr[1],
00124            aggregates[i].cycles,
00125            aggregates[i].episodes,
00126            aggregates[i].cycles / aggregates[i].episodes);
00127   }
00128 #endif
00129 
00130   printf("Memory for aggregates: %d * %d = %d\n",
00131          (int)sizeof(struct aggregate), aggregates_list_ptr,
00132          (int)sizeof(struct aggregate) * aggregates_list_ptr);
00133 }
00134 /*---------------------------------------------------------------------------*/
00135 #if DETAILED_AGGREGATES
00136 static void
00137 detailed_profile_aggregates_compute(void)
00138 {
00139   int i;
00140   rtimer_clock_t t;
00141   /*  const char *str = "profile_aggregates_compute";
00142 
00143   PROFILE_TIMESTAMP(str);*/
00144   
00145   t = profile_timestamps[0].time;
00146   
00147   for(i = 1; i < PROFILE_TIMESTAMP_PTR; ++i) {
00148     struct aggregate *a;
00149     a = find_aggregate(profile_timestamps[i - 1].ptr);
00150     if(a == NULL) {
00151       /* The list is full, skip this entry */
00152       printf("profile_aggregates_compute: list full\n");
00153     } else if(a->ptr == NULL) {
00154       a->ptr = profile_timestamps[i - 1].ptr;
00155       a->cycles = (unsigned long)(profile_timestamps[i].time - t);
00156       a->episodes = 1;
00157     } else {
00158       a->cycles += (unsigned long)(profile_timestamps[i].time - t);
00159       a->episodes++;
00160     }
00161     t = profile_timestamps[i].time;
00162   }
00163 
00164   /*  PROFILE_TIMESTAMP(str);*/
00165 
00166   /*printf("Aggregating time %u, len %d, list len %d, overhead %d\n",
00167          profile_timediff(str, str), PROFILE_TIMESTAMP_PTR,
00168          aggregates_list_ptr, profile_timestamp_time);*/
00169   
00170 
00171   /* print_aggregates();*/
00172 }
00173 #endif /* DETAILED_AGGREGATES */
00174 /*---------------------------------------------------------------------------*/
00175 static void
00176 category_profile_aggregates_compute(void)
00177 {
00178   int i,j;
00179   rtimer_clock_t t;
00180   uint16_t categories[MAX_CATEGORIES];
00181   int categories_ptr = 0;
00182   /*  const char *str = "profile_aggregates_compute";
00183 
00184   PROFILE_TIMESTAMP(str);*/
00185   
00186   t = profile_timestamps[0].time;
00187   
00188   for(i = 1; i < PROFILE_TIMESTAMP_PTR; ++i) {
00189     struct aggregate *a;
00190     uint16_t cat;
00191 
00192 /*     printf("category_profile_aggregates_compute %s\n", */
00193 /*         profile_timestamps[i - 1].ptr); */
00194     cat = (profile_timestamps[i - 1].ptr[0] << 8) +
00195       (profile_timestamps[i - 1].ptr[1] & 0xff);
00196     a = find_aggregate_category(cat);
00197     if(a == NULL) {
00198       /* The list is full, skip this entry */
00199       printf("profile_aggregates_compute: list full\n");
00200     } else if(a->ptr == NULL) {
00201       a->ptr = profile_timestamps[i - 1].ptr;
00202       a->cycles = (unsigned long)(profile_timestamps[i].time - t - profile_timestamp_time);
00203       a->episodes = 1;
00204     } else {
00205       
00206       a->cycles += (unsigned long)(profile_timestamps[i].time - t - profile_timestamp_time);
00207 
00208       /* Make sure that we only update the episodes of each category
00209          once per run. We keep track of all updated categories in the
00210          "categories" array. If the category is already present in the
00211          array, we do not update it. Otherwise, we insert the category
00212          in the array and update the episodes counter of the
00213          category. */
00214       
00215       for(j = 0; j < categories_ptr; ++j) {
00216         if(categories[j] == cat) {
00217           break;
00218         }
00219       }
00220       if(j == categories_ptr) {
00221         categories[j] = cat;
00222         categories_ptr++;
00223         a->episodes++;
00224       }
00225     }
00226     t = profile_timestamps[i].time;
00227   }
00228 
00229   /*  PROFILE_TIMESTAMP(str);*/
00230 
00231   /*printf("Aggregating time %u, len %d, list len %d, overhead %d\n",
00232          profile_timediff(str, str), PROFILE_TIMESTAMP_PTR,
00233          aggregates_list_ptr, profile_timestamp_time);*/
00234   
00235 
00236   /* print_aggregates();*/
00237 }
00238 /*---------------------------------------------------------------------------*/
00239 void
00240 profile_aggregates_compute(void)
00241 {
00242 #if DETAILED_AGGREGATES
00243   detailed_profile_aggregates_compute();
00244 #else
00245   category_profile_aggregates_compute();
00246 #endif
00247 }
00248 /*---------------------------------------------------------------------------*/