Add optional RS232 debugging
[contiki-2.x.git] / core / sys / profile.c
blob9f16c0b31f7dab62c7e8c09605d26f27e0c1c7d5
1 /*
2 * Copyright (c) 2007, Swedish Institute of Computer Science.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * This file is part of the Contiki operating system.
31 * $Id: profile.c,v 1.4 2008/01/17 12:19:26 adamdunkels Exp $
34 /**
35 * \file
36 * Implementation of the Contiki profiling system
37 * \author
38 * Adam Dunkels <adam@sics.se>
41 #include "sys/profile.h"
42 #include "sys/clock.h"
44 #include <stdio.h>
46 /* XXX: the profiling code is under development and may not work at
47 present. */
50 TIMETABLE_NONSTATIC(profile_timetable);
52 TIMETABLE_NONSTATIC(profile_begin_timetable);
53 TIMETABLE_NONSTATIC(profile_end_timetable);
54 TIMETABLE_AGGREGATE(profile_aggregate, PROFILE_AGGREGATE_SIZE);
56 static rtimer_clock_t episode_start_time;
57 static unsigned int invalid_episode_overflow, invalid_episode_toolong,
58 max_queuelen;
60 /* The number of fine grained ticks per coarse grained ticks. We
61 currently (MSP430) have 2457600 ticks per second for the fine
62 grained timer, and 32678 / 8 ticks per second for the coarse. */
63 #define XXX_HACK_FINE_TICKS_PER_COARSE_TICK (2457600/(32678/8))
65 /*---------------------------------------------------------------------------*/
66 void
67 profile_init(void)
69 timetable_init();
70 timetable_clear(&profile_begin_timetable);
71 timetable_clear(&profile_end_timetable);
73 /*---------------------------------------------------------------------------*/
74 void
75 profile_episode_start(void)
77 struct timetable_timestamp *e;
78 timetable_clear(&profile_begin_timetable);
79 timetable_clear(&profile_end_timetable);
80 episode_start_time = clock_time();
82 e = timetable_entry(&profile_begin_timetable,
83 PROFILE_TIMETABLE_SIZE - 1);
84 if(e != NULL) {
85 e->id = NULL;
87 e = timetable_entry(&profile_end_timetable,
88 PROFILE_TIMETABLE_SIZE - 1);
89 if(e != NULL) {
90 e->id = NULL;
93 /*---------------------------------------------------------------------------*/
94 void
95 profile_episode_end(void)
97 struct timetable_timestamp *e;
98 rtimer_clock_t episode_end_time = clock_time();
100 /* printf("timetable_episode_end start %u, end %u, max time %u\n", episode_start_time, episode_end_time, 65536/FINE_TICKS_PER_COARSE_TICK); */
101 e = timetable_entry(&profile_begin_timetable,
102 PROFILE_TIMETABLE_SIZE - 1);
103 if(e != NULL && e->id != NULL) {
104 /* Invalid episode because of list overflow. */
105 invalid_episode_overflow++;
106 max_queuelen = PROFILE_TIMETABLE_SIZE;
107 } else if(episode_end_time - episode_start_time >
108 65536/XXX_HACK_FINE_TICKS_PER_COARSE_TICK) {
109 /* Invalid episode because of timer overflow. */
110 invalid_episode_toolong++;
111 } else {
112 /* Compute aggregates. */
113 if(timetable_ptr(&profile_begin_timetable) > max_queuelen) {
114 max_queuelen = timetable_ptr(&profile_begin_timetable);
116 /* timetable_aggregates_compute();*/
119 /*---------------------------------------------------------------------------*/
122 * Find a specific aggregate ID in the list of aggregates.
125 static struct timetable_aggregate_entry *
126 find_aggregate(struct timetable_aggregate *a,
127 const char *id)
129 int i;
130 for(i = 0; i < a->ptr; ++i) {
131 if(a->entries[i].id == id) {
132 return &a->entries[i];
135 if(i == a->size) {
136 return NULL;
138 a->entries[a->ptr].id = NULL;
139 return &a->entries[a->ptr++];
141 /*---------------------------------------------------------------------------*/
142 void
143 profile_aggregate_print_detailed(void)
145 int i;
146 struct timetable_aggregate *a = &profile_aggregate;
148 /* printf("timetable_aggregate_print_detailed: a ptr %d\n", a->ptr);*/
149 for(i = 0; i < a->ptr; ++i) {
150 printf("-- %s: %lu / %u = %lu\n", a->entries[i].id,
151 a->entries[i].time,
152 a->entries[i].episodes,
153 a->entries[i].time / a->entries[i].episodes);
156 printf("Memory for entries: %d * %d = %d\n",
157 (int)sizeof(struct timetable_aggregate), a->ptr,
158 (int)sizeof(struct timetable_aggregate) * a->ptr);
160 /*---------------------------------------------------------------------------*/
161 void
162 profile_aggregate_compute_detailed(void)
164 int i;
165 int last;
166 rtimer_clock_t t;
167 struct timetable_aggregate *a = &profile_aggregate;
168 struct timetable *timetable = &profile_timetable;
169 struct timetable_aggregate_entry *entry;
171 last = timetable_ptr(&profile_begin_timetable);
172 t = profile_begin_timetable.timestamps[0].time;
173 for(i = 0; i < last; ++i) {
175 entry = find_aggregate(a, profile_begin_timetable.timestamps[i].id);
176 if(entry == NULL) {
177 /* The list is full, skip this entry */
178 /* printf("detailed_timetable_aggregate_compute: list full\n");*/
179 } else if(entry->id == NULL) {
180 /* The id was found in the list, so we add it. */
181 entry->id = timetable->timestamps[i - 1].id;
182 entry->time = (unsigned long)(timetable->timestamps[i].time - t -
183 timetable_timestamp_time);
184 entry->episodes = 1;
185 /* printf("New entry %s %lu\n", entry->id, entry->time);*/
186 } else {
187 entry->time += (unsigned long)(timetable->timestamps[i].time - t -
188 timetable_timestamp_time);
189 entry->episodes++;
191 t = timetable->timestamps[i].time;
192 /* printf("a ptr %d\n", a->ptr);*/
197 /*---------------------------------------------------------------------------*/