Factored out the time table keeping code from the profiling code and placed it in a separate 'timetable' module, that may be uesd on its own.
This commit is contained in:
parent
f2599b38e7
commit
7b71f23abe
|
@ -50,7 +50,7 @@ ifdef CHAMELEON
|
||||||
include $(CONTIKI)/core/net/chameleon/Makefile.chameleon
|
include $(CONTIKI)/core/net/chameleon/Makefile.chameleon
|
||||||
endif
|
endif
|
||||||
include $(CONTIKI)/core/net/mac/Makefile.mac
|
include $(CONTIKI)/core/net/mac/Makefile.mac
|
||||||
SYSTEM = process.c procinit.c autostart.c elfloader.c profile.c profile-aggregates.c
|
SYSTEM = process.c procinit.c autostart.c elfloader.c profile.c timetable.c timetable-aggregate.c
|
||||||
THREADS = mt.c
|
THREADS = mt.c
|
||||||
LIBS = memb.c timer.c list.c etimer.c energest.c rtimer.c print-stats.c
|
LIBS = memb.c timer.c list.c etimer.c energest.c rtimer.c print-stats.c
|
||||||
UIP = uip.c uiplib.c resolv.c tcpip.c psock.c hc.c uip-split.c uip-fw.c \
|
UIP = uip.c uiplib.c resolv.c tcpip.c psock.c hc.c uip-split.c uip-fw.c \
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
*
|
*
|
||||||
* This file is part of the Contiki operating system.
|
* This file is part of the Contiki operating system.
|
||||||
*
|
*
|
||||||
* $Id: profile.c,v 1.3 2007/11/18 19:16:49 oliverschmidt Exp $
|
* $Id: profile.c,v 1.4 2008/01/17 12:19:26 adamdunkels Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,144 +39,159 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sys/profile.h"
|
#include "sys/profile.h"
|
||||||
|
#include "sys/clock.h"
|
||||||
|
|
||||||
#include <stddef.h> /* For NULL */
|
#include <stdio.h>
|
||||||
|
|
||||||
unsigned int profile_timestamp_ptr;
|
/* XXX: the profiling code is under development and may not work at
|
||||||
struct profile_timestamp profile_timestamps[PROFILE_LIST_LENGTH];
|
present. */
|
||||||
rtimer_clock_t profile_timestamp_time;
|
|
||||||
|
|
||||||
int profile_invalid_episode_overflow, profile_invalid_episode_toolong;
|
|
||||||
|
|
||||||
int profile_max_queuelen = 0;
|
TIMETABLE_NONSTATIC(profile_timetable);
|
||||||
|
|
||||||
|
TIMETABLE_NONSTATIC(profile_begin_timetable);
|
||||||
|
TIMETABLE_NONSTATIC(profile_end_timetable);
|
||||||
|
TIMETABLE_AGGREGATE(profile_aggregate, PROFILE_AGGREGATE_SIZE);
|
||||||
|
|
||||||
static rtimer_clock_t episode_start_time;
|
static rtimer_clock_t episode_start_time;
|
||||||
|
static unsigned int invalid_episode_overflow, invalid_episode_toolong,
|
||||||
|
max_queuelen;
|
||||||
|
|
||||||
/* The number of fine grained ticks per coarse grained ticks. We
|
/* The number of fine grained ticks per coarse grained ticks. We
|
||||||
currently (MSP430) have 2457600 ticks per second for the fine
|
currently (MSP430) have 2457600 ticks per second for the fine
|
||||||
grained timer, and 32678 / 8 ticks per second for the coarse. */
|
grained timer, and 32678 / 8 ticks per second for the coarse. */
|
||||||
#define FINE_TICKS_PER_COARSE_TICK (2457600/(32678/8))
|
#define XXX_HACK_FINE_TICKS_PER_COARSE_TICK (2457600/(32678/8))
|
||||||
|
|
||||||
/* XXX hack: we use a function called clock_counter() that is not part
|
|
||||||
of the clock API and currently is only implemented for the
|
|
||||||
MSP430. We therefore declare this function here instead of in
|
|
||||||
dev/clock.h. */
|
|
||||||
rtimer_clock_t clock_counter(void);
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
rtimer_clock_t
|
|
||||||
profile_timediff(const char *ptr1, const char *ptr2)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int t1, t2;
|
|
||||||
int timestamp_ptr = PROFILE_TIMESTAMP_PTR;
|
|
||||||
|
|
||||||
/* printf("profile_timestamp_ptr %d max %d\n", profile_timestamp_ptr, profile_max_queuelen);*/
|
|
||||||
|
|
||||||
t1 = t2 = PROFILE_LIST_LENGTH;
|
|
||||||
|
|
||||||
for(i = timestamp_ptr - 1; i >= 0; --i) {
|
|
||||||
/* printf("Checking 1 %s %u == %s i %d\n",
|
|
||||||
profile_timestamps[i].ptr,
|
|
||||||
profile_timestamps[i].time,
|
|
||||||
ptr1, i);*/
|
|
||||||
if(profile_timestamps[i].ptr == ptr1) {
|
|
||||||
t1 = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = i - 1; i >= 0; --i) {
|
|
||||||
/* printf("Checking 2 %s %u == %s i %d\n",
|
|
||||||
profile_timestamps[i].ptr,
|
|
||||||
profile_timestamps[i].time,
|
|
||||||
ptr1, i);*/
|
|
||||||
if(profile_timestamps[i].ptr == ptr2) {
|
|
||||||
t2 = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* printf("t1 %d t2 %d\n", t1, t2);*/
|
|
||||||
if(t1 != PROFILE_LIST_LENGTH && t2 != PROFILE_LIST_LENGTH) {
|
|
||||||
return profile_timestamps[t1].time - profile_timestamps[t2].time;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
void
|
|
||||||
profile_clear_timestamps(void)
|
|
||||||
{
|
|
||||||
/* int i;
|
|
||||||
for(i = 0; i < PROFILE_LIST_LENGTH; ++i) {
|
|
||||||
profile_timestamps[i].str = "NULL";
|
|
||||||
profile_timestamps[i].time = 0;
|
|
||||||
}*/
|
|
||||||
profile_timestamp_ptr = 0;
|
|
||||||
}
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
profile_init(void)
|
profile_init(void)
|
||||||
{
|
{
|
||||||
profile_clear_timestamps();
|
timetable_init();
|
||||||
|
timetable_clear(&profile_begin_timetable);
|
||||||
/* Measure the time for taking a timestamp. */
|
timetable_clear(&profile_end_timetable);
|
||||||
PROFILE_TIMESTAMP(NULL);
|
|
||||||
PROFILE_TIMESTAMP(NULL);
|
|
||||||
profile_timestamp_time = profile_timestamps[1].time - profile_timestamps[0].time;
|
|
||||||
|
|
||||||
profile_clear_timestamps();
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
profile_episode_start(void)
|
profile_episode_start(void)
|
||||||
{
|
{
|
||||||
profile_timestamp_ptr = 0;
|
struct timetable_timestamp *e;
|
||||||
|
timetable_clear(&profile_begin_timetable);
|
||||||
|
timetable_clear(&profile_end_timetable);
|
||||||
|
episode_start_time = clock_time();
|
||||||
|
|
||||||
episode_start_time = clock_counter();
|
e = timetable_entry(&profile_begin_timetable,
|
||||||
|
PROFILE_TIMETABLE_SIZE - 1);
|
||||||
profile_timestamps[PROFILE_LIST_LENGTH - 1].ptr = NULL;
|
if(e != NULL) {
|
||||||
|
e->id = NULL;
|
||||||
|
}
|
||||||
|
e = timetable_entry(&profile_end_timetable,
|
||||||
|
PROFILE_TIMETABLE_SIZE - 1);
|
||||||
|
if(e != NULL) {
|
||||||
|
e->id = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
profile_episode_end(void)
|
profile_episode_end(void)
|
||||||
{
|
{
|
||||||
rtimer_clock_t episode_end_time = clock_counter();
|
struct timetable_timestamp *e;
|
||||||
|
rtimer_clock_t episode_end_time = clock_time();
|
||||||
|
|
||||||
PROFILE_TIMESTAMP("profile_episode_end");
|
/* printf("timetable_episode_end start %u, end %u, max time %u\n", episode_start_time, episode_end_time, 65536/FINE_TICKS_PER_COARSE_TICK); */
|
||||||
|
e = timetable_entry(&profile_begin_timetable,
|
||||||
/* printf("profile_episode_end start %u, end %u, max time %u\n", episode_start_time, episode_end_time, 65536/FINE_TICKS_PER_COARSE_TICK); */
|
PROFILE_TIMETABLE_SIZE - 1);
|
||||||
if(profile_timestamps[PROFILE_LIST_LENGTH - 1].ptr != NULL) {
|
if(e != NULL && e->id != NULL) {
|
||||||
/* Invalid episode because of list overflow. */
|
/* Invalid episode because of list overflow. */
|
||||||
profile_invalid_episode_overflow++;
|
invalid_episode_overflow++;
|
||||||
profile_max_queuelen = PROFILE_LIST_LENGTH;
|
max_queuelen = PROFILE_TIMETABLE_SIZE;
|
||||||
} else if(episode_end_time - episode_start_time > 65536/FINE_TICKS_PER_COARSE_TICK) {
|
} else if(episode_end_time - episode_start_time >
|
||||||
|
65536/XXX_HACK_FINE_TICKS_PER_COARSE_TICK) {
|
||||||
/* Invalid episode because of timer overflow. */
|
/* Invalid episode because of timer overflow. */
|
||||||
profile_invalid_episode_toolong++;
|
invalid_episode_toolong++;
|
||||||
} else {
|
} else {
|
||||||
/* Compute aggregates. */
|
/* Compute aggregates. */
|
||||||
if(PROFILE_TIMESTAMP_PTR > profile_max_queuelen) {
|
if(timetable_ptr(&profile_begin_timetable) > max_queuelen) {
|
||||||
profile_max_queuelen = PROFILE_TIMESTAMP_PTR;
|
max_queuelen = timetable_ptr(&profile_begin_timetable);
|
||||||
}
|
}
|
||||||
profile_aggregates_compute();
|
/* timetable_aggregates_compute();*/
|
||||||
/* printf("Episode length %d\n", profile_timestamp_ptr);*/
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Find a specific aggregate ID in the list of aggregates.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static struct timetable_aggregate_entry *
|
||||||
|
find_aggregate(struct timetable_aggregate *a,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < a->ptr; ++i) {
|
||||||
|
if(a->entries[i].id == id) {
|
||||||
|
return &a->entries[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i == a->size) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
a->entries[a->ptr].id = NULL;
|
||||||
|
return &a->entries[a->ptr++];
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
profile_aggregate_print_detailed(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct timetable_aggregate *a = &profile_aggregate;
|
||||||
|
|
||||||
|
/* printf("timetable_aggregate_print_detailed: a ptr %d\n", a->ptr);*/
|
||||||
|
for(i = 0; i < a->ptr; ++i) {
|
||||||
|
printf("-- %s: %lu / %u = %lu\n", a->entries[i].id,
|
||||||
|
a->entries[i].time,
|
||||||
|
a->entries[i].episodes,
|
||||||
|
a->entries[i].time / a->entries[i].episodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* profile_aggregates_print(); */
|
printf("Memory for entries: %d * %d = %d\n",
|
||||||
/* profile_print_stats(); */
|
(int)sizeof(struct timetable_aggregate), a->ptr,
|
||||||
|
(int)sizeof(struct timetable_aggregate) * a->ptr);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#if 0
|
|
||||||
#include <stdio.h>
|
|
||||||
void
|
void
|
||||||
profile_print_stats(void)
|
profile_aggregate_compute_detailed(void)
|
||||||
{
|
{
|
||||||
printf("Memory for profiling: %d * %d = %d\n",
|
int i;
|
||||||
sizeof(struct profile_timestamp), profile_max_queuelen,
|
int last;
|
||||||
sizeof(struct profile_timestamp) * profile_max_queuelen);
|
rtimer_clock_t t;
|
||||||
printf("Invalid episodes overflow %d time %d\n",
|
struct timetable_aggregate *a = &profile_aggregate;
|
||||||
profile_invalid_episode_overflow,
|
struct timetable *timetable = &profile_timetable;
|
||||||
profile_invalid_episode_toolong);
|
struct timetable_aggregate_entry *entry;
|
||||||
|
|
||||||
|
last = timetable_ptr(&profile_begin_timetable);
|
||||||
|
t = profile_begin_timetable.timestamps[0].time;
|
||||||
|
for(i = 0; i < last; ++i) {
|
||||||
|
|
||||||
|
entry = find_aggregate(a, profile_begin_timetable.timestamps[i].id);
|
||||||
|
if(entry == NULL) {
|
||||||
|
/* The list is full, skip this entry */
|
||||||
|
/* printf("detailed_timetable_aggregate_compute: list full\n");*/
|
||||||
|
} else if(entry->id == NULL) {
|
||||||
|
/* The id was found in the list, so we add it. */
|
||||||
|
entry->id = timetable->timestamps[i - 1].id;
|
||||||
|
entry->time = (unsigned long)(timetable->timestamps[i].time - t -
|
||||||
|
timetable_timestamp_time);
|
||||||
|
entry->episodes = 1;
|
||||||
|
/* printf("New entry %s %lu\n", entry->id, entry->time);*/
|
||||||
|
} else {
|
||||||
|
entry->time += (unsigned long)(timetable->timestamps[i].time - t -
|
||||||
|
timetable_timestamp_time);
|
||||||
|
entry->episodes++;
|
||||||
|
}
|
||||||
|
t = timetable->timestamps[i].time;
|
||||||
|
/* printf("a ptr %d\n", a->ptr);*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* 0 */
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
*
|
*
|
||||||
* This file is part of the Contiki operating system.
|
* This file is part of the Contiki operating system.
|
||||||
*
|
*
|
||||||
* $Id: profile.h,v 1.2 2007/11/17 10:14:19 adamdunkels Exp $
|
* $Id: profile.h,v 1.3 2008/01/17 12:19:26 adamdunkels Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,116 +41,48 @@
|
||||||
#ifndef __PROFILE_H__
|
#ifndef __PROFILE_H__
|
||||||
#define __PROFILE_H__
|
#define __PROFILE_H__
|
||||||
|
|
||||||
#include "sys/rtimer.h"
|
/* XXX: the profiling code is under development and may not work at
|
||||||
|
present. */
|
||||||
|
|
||||||
#ifdef EXPERIMENT_SETUP
|
#define TIMETABLE_WITH_TYPE 1
|
||||||
#include "experiment-setup.h"
|
#include "sys/timetable.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "contiki-conf.h"
|
#ifdef PROFILE_CONF_TIMETABLE_SIZE
|
||||||
|
#define PROFILE_TIMETABLE_SIZE PROFILE_CONF_TIMETABLE_SIZE
|
||||||
#ifdef PROFILE_CONF_LIST_LENGTH
|
|
||||||
#define PROFILE_LIST_LENGTH PROFILE_CONF_LIST_LENGTH
|
|
||||||
#else
|
#else
|
||||||
#define PROFILE_LIST_LENGTH 128
|
#define PROFILE_TIMETABLE_SIZE 128
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct profile_timestamp {
|
#ifdef PROFILE_CONF_AGGREGATE_SIZE
|
||||||
const char *ptr;
|
#define PROFILE_AGGREGATE_SIZE PROFILE_CONF_AGGREGATE_SIZE
|
||||||
rtimer_clock_t time;
|
#else
|
||||||
};
|
#define PROFILE_AGGREGATE_SIZE 128
|
||||||
|
#endif
|
||||||
|
|
||||||
extern struct profile_timestamp profile_timestamps[PROFILE_LIST_LENGTH];
|
#define PROFILE_BEGIN(id) TIMETABLE_TIMESTAMP_TYPE(profile_timetable, id, 1)
|
||||||
extern unsigned int profile_timestamp_ptr;
|
#define PROFILE_END(id) TIMETABLE_TIMESTAMP_TYPE(profile_timetable, id, 2)
|
||||||
extern rtimer_clock_t profile_timestamp_time;
|
|
||||||
|
|
||||||
#define PROFILE_TIMESTAMP_PTR (profile_timestamp_ptr / sizeof(struct profile_timestamp))
|
/*#define PROFILE_COND_BEGIN(cond, id) TIMETABLE_COND_TIMESTAMP(profile_begin_timetable, \
|
||||||
|
cond, id)
|
||||||
|
#define PROFILE_COND_END(cond, id) TIMETABLE_COND_TIMESTAMP(profile_end_timetable, \
|
||||||
|
cond, id)
|
||||||
|
*/
|
||||||
|
|
||||||
#if PROFILE_CONF_ON
|
#define profile_begin_timetable_size PROFILE_TIMETABLE_SIZE
|
||||||
#define PROFILE_TIMESTAMP(str) \
|
TIMETABLE_DECLARE(profile_begin_timetable);
|
||||||
do { \
|
#define profile_end_timetable_size PROFILE_TIMETABLE_SIZE
|
||||||
profile_timestamps[profile_timestamp_ptr / sizeof(struct profile_timestamp)].ptr = str; \
|
TIMETABLE_DECLARE(profile_end_timetable);
|
||||||
profile_timestamps[profile_timestamp_ptr / sizeof(struct profile_timestamp)].time = RTIMER_NOW(); \
|
|
||||||
profile_timestamp_ptr = (profile_timestamp_ptr + sizeof(struct profile_timestamp)) % (PROFILE_LIST_LENGTH * sizeof(struct profile_timestamp)); \
|
|
||||||
} while(0)
|
|
||||||
#define PROFILE_RESUME(num) PROFILE_TIMESTAMP(profile_timestamps[num].ptr)
|
|
||||||
|
|
||||||
#define PROFILE_COND_TIMESTAMP(cond, ptr) do { if(cond) {PROFILE_TIMESTAMP(ptr);} } while(0)
|
#define profile_timetable_size PROFILE_TIMETABLE_SIZE
|
||||||
#define PROFILE_COND_RESUME(cond, num) PROFILE_COND_TIMESTAMP(cond, profile_timestamps[num].ptr)
|
TIMETABLE_DECLARE(profile_timetable);
|
||||||
#else /* PROFILE_CONF_ON */
|
|
||||||
#define PROFILE_TIMESTAMP(id)
|
|
||||||
#define PROFILE_RESUME(num)
|
|
||||||
#define PROFILE_COND_TIMESTAMP(cond, id)
|
|
||||||
#define PROFILE_COND_RESUME(cond, num)
|
|
||||||
#endif /* PROFILE_CONF_ON */
|
|
||||||
|
|
||||||
rtimer_clock_t profile_timediff(const char *ptr1, const char *ptr2);
|
|
||||||
|
|
||||||
#define PROFILE_GETPTR() (PROFILE_TIMESTAMP_PTR)
|
|
||||||
|
|
||||||
void profile_clear_timestamps(void);
|
|
||||||
void profile_init(void);
|
void profile_init(void);
|
||||||
|
|
||||||
void profile_episode_start(void);
|
void profile_episode_start(void);
|
||||||
void profile_episode_end(void);
|
void profile_episode_end(void);
|
||||||
|
|
||||||
void profile_aggregates_print(void);
|
void profile_aggregate_print_detailed(void);
|
||||||
void profile_aggregates_compute(void);
|
void profile_aggregate_compute_detailed(void);
|
||||||
|
|
||||||
void profile_print_stats(void);
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PROFILE_TYPE_STACK,
|
|
||||||
PROFILE_TYPE_HW,
|
|
||||||
PROFILE_TYPE_RADIO,
|
|
||||||
PROFILE_TYPE_SYSTEM,
|
|
||||||
PROFILE_TYPE_APP,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __PROFILE_H__ */
|
#endif /* __PROFILE_H__ */
|
||||||
|
|
||||||
/* profile_timestamp_ptr code:
|
|
||||||
|
|
||||||
2e: 1f 42 00 00 mov &0x0000,r15 ;0x0000
|
|
||||||
32: 0e 4f mov r15, r14 ;
|
|
||||||
34: 0e 5e rla r14 ;
|
|
||||||
36: 0e 5e rla r14 ;
|
|
||||||
38: 3e 50 00 00 add #0, r14 ;#0x0000
|
|
||||||
3c: be 40 00 00 mov #0, 0(r14) ;#0x0000
|
|
||||||
40: 00 00
|
|
||||||
42: 9e 42 90 01 mov &0x0190,2(r14) ;0x0190
|
|
||||||
46: 02 00
|
|
||||||
48: 1f 53 inc r15 ;
|
|
||||||
4a: 3f f0 3f 00 and #63, r15 ;#0x003f
|
|
||||||
4e: 82 4f 00 00 mov r15, &0x0000 ;
|
|
||||||
|
|
||||||
msp430-specific profile_timetstamp_2ptr code:
|
|
||||||
|
|
||||||
2e: 1f 42 00 00 mov &0x0000,r15 ;0x0000
|
|
||||||
32: 0e 4f mov r15, r14 ;
|
|
||||||
34: 3e 50 00 00 add #0, r14 ;#0x0000
|
|
||||||
38: be 40 00 00 mov #0, 0(r14) ;#0x0000
|
|
||||||
3c: 00 00
|
|
||||||
3e: 9e 42 90 01 mov &0x0190,2(r14) ;0x0190
|
|
||||||
42: 02 00
|
|
||||||
44: 2f 53 incd r15 ;
|
|
||||||
46: 3f f0 7f 00 and #127, r15 ;#0x007f
|
|
||||||
4a: 82 4f 00 00 mov r15, &0x0000 ;
|
|
||||||
|
|
||||||
generic timestamp_2ptr code:
|
|
||||||
|
|
||||||
2e: 1f 42 00 00 mov &0x0000,r15 ;0x0000
|
|
||||||
32: 0e 4f mov r15, r14 ;
|
|
||||||
34: 1e c3 bic #1, r14 ;r3 As==01
|
|
||||||
36: 0e 5e rla r14 ;
|
|
||||||
38: 3e 50 00 00 add #0, r14 ;#0x0000
|
|
||||||
3c: be 40 00 00 mov #0, 0(r14) ;#0x0000
|
|
||||||
40: 00 00
|
|
||||||
42: 9e 42 90 01 mov &0x0190,2(r14) ;0x0190
|
|
||||||
46: 02 00
|
|
||||||
48: 2f 53 incd r15 ;
|
|
||||||
4a: 3f f0 7f 00 and #127, r15 ;#0x007f
|
|
||||||
4e: 82 4f 00 00 mov r15, &0x0000 ;
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
229
core/sys/timetable-aggregate.c
Normal file
229
core/sys/timetable-aggregate.c
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008, Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
* $Id: timetable-aggregate.c,v 1.1 2008/01/17 12:19:26 adamdunkels Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* A brief description of what this file is.
|
||||||
|
* \author
|
||||||
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sys/timetable-aggregate.h"
|
||||||
|
|
||||||
|
#define XXX_HACK_MAX_CATEGORIES 32
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Find an aggregation category in the list of aggregates. If the
|
||||||
|
* category could not be found, the function returns a pointer to an
|
||||||
|
* empty entry. If the list is full, the function returns NULL.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static struct timetable_aggregate_entry *
|
||||||
|
find_aggregate_category(struct timetable_aggregate *a,
|
||||||
|
const uint16_t cat)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint16_t acat;
|
||||||
|
|
||||||
|
for(i = 0; i < a->ptr; ++i) {
|
||||||
|
acat = (a->entries[i].id[0] << 8) + a->entries[i].id[1];
|
||||||
|
if(acat == cat) {
|
||||||
|
|
||||||
|
return &a->entries[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i == a->size) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->entries[a->ptr].id = NULL;
|
||||||
|
return &a->entries[a->ptr++];
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Find a specific aggregate ID in the list of aggregates.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static struct timetable_aggregate_entry *
|
||||||
|
find_aggregate(struct timetable_aggregate *a,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < a->ptr; ++i) {
|
||||||
|
if(a->entries[i].id == id) {
|
||||||
|
return &a->entries[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i == a->size) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
a->entries[a->ptr].id = NULL;
|
||||||
|
return &a->entries[a->ptr++];
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
timetable_aggregate_print_detailed(struct timetable_aggregate *a)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
/* printf("timetable_aggregate_print_detailed: a ptr %d\n", a->ptr);*/
|
||||||
|
for(i = 0; i < a->ptr; ++i) {
|
||||||
|
printf("-- %s: %lu / %u = %lu\n", a->entries[i].id,
|
||||||
|
a->entries[i].time,
|
||||||
|
a->entries[i].episodes,
|
||||||
|
a->entries[i].time / a->entries[i].episodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Memory for entries: %d * %d = %d\n",
|
||||||
|
(int)sizeof(struct timetable_aggregate), a->ptr,
|
||||||
|
(int)sizeof(struct timetable_aggregate) * a->ptr);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
timetable_aggregate_print_categories(struct timetable_aggregate *a)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* printf("timetable_aggregate_print_categories: a ptr %d\n", a->ptr);*/
|
||||||
|
for(i = 0; i < a->ptr; ++i) {
|
||||||
|
printf("-- %c%c: %lu / %u = %lu\n",
|
||||||
|
a->entries[i].id[0], a->entries[i].id[1],
|
||||||
|
a->entries[i].time,
|
||||||
|
a->entries[i].episodes,
|
||||||
|
a->entries[i].time / a->entries[i].episodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Memory for entries: %d * %d = %d\n",
|
||||||
|
(int)sizeof(struct timetable_aggregate), a->ptr,
|
||||||
|
(int)sizeof(struct timetable_aggregate) * a->ptr);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
timetable_aggregate_compute_detailed(struct timetable_aggregate *a,
|
||||||
|
struct timetable *timetable)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
rtimer_clock_t t;
|
||||||
|
|
||||||
|
t = timetable->timestamps[0].time;
|
||||||
|
|
||||||
|
for(i = 1; i < *timetable->ptr; ++i) {
|
||||||
|
struct timetable_aggregate_entry *entry;
|
||||||
|
entry = find_aggregate(a, timetable->timestamps[i - 1].id);
|
||||||
|
if(entry == NULL) {
|
||||||
|
/* The list is full, skip this entry */
|
||||||
|
/* printf("detailed_timetable_aggregate_compute: list full\n");*/
|
||||||
|
} else if(entry->id == NULL) {
|
||||||
|
/* The id was found in the list, so we add it. */
|
||||||
|
entry->id = timetable->timestamps[i - 1].id;
|
||||||
|
entry->time = (unsigned long)(timetable->timestamps[i].time - t -
|
||||||
|
timetable_timestamp_time);
|
||||||
|
entry->episodes = 1;
|
||||||
|
/* printf("New entry %s %lu\n", entry->id, entry->time);*/
|
||||||
|
} else {
|
||||||
|
entry->time += (unsigned long)(timetable->timestamps[i].time - t -
|
||||||
|
timetable_timestamp_time);
|
||||||
|
entry->episodes++;
|
||||||
|
}
|
||||||
|
t = timetable->timestamps[i].time;
|
||||||
|
/* printf("a ptr %d\n", a->ptr);*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
timetable_aggregate_compute_categories(struct timetable_aggregate *a,
|
||||||
|
struct timetable *timetable)
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
rtimer_clock_t t;
|
||||||
|
uint16_t categories[XXX_HACK_MAX_CATEGORIES];
|
||||||
|
int categories_ptr = 0;
|
||||||
|
|
||||||
|
t = timetable->timestamps[0].time;
|
||||||
|
|
||||||
|
for(i = 1; i < *timetable->ptr; ++i) {
|
||||||
|
struct timetable_aggregate_entry *entry;
|
||||||
|
uint16_t cat;
|
||||||
|
|
||||||
|
/* printf("category_timetable_aggregate_compute %s %d\n",
|
||||||
|
timetable->timestamps[i - 1].id, i);*/
|
||||||
|
cat = (timetable->timestamps[i - 1].id[0] << 8) +
|
||||||
|
(timetable->timestamps[i - 1].id[1] & 0xff);
|
||||||
|
entry = find_aggregate_category(a, cat);
|
||||||
|
if(entry == NULL) {
|
||||||
|
/* The list is full, skip this entry */
|
||||||
|
/* printf("category_timetable_aggregate_compute: list full\n");*/
|
||||||
|
} else if(entry->id == NULL) {
|
||||||
|
/* The category was not found in the list, so we add it. */
|
||||||
|
entry->id = timetable->timestamps[i - 1].id;
|
||||||
|
entry->time = (unsigned long)(timetable->timestamps[i].time - t -
|
||||||
|
timetable_timestamp_time);
|
||||||
|
entry->episodes = 1;
|
||||||
|
/* printf("New category %c%c time %lu\n",
|
||||||
|
timetable->timestamps[i - 1].id[0],
|
||||||
|
timetable->timestamps[i - 1].id[1], entry->time);*/
|
||||||
|
} else {
|
||||||
|
|
||||||
|
entry->time += (unsigned long)(timetable->timestamps[i].time - t -
|
||||||
|
timetable_timestamp_time);
|
||||||
|
/* printf("Adding time to %c%c time %lu\n",
|
||||||
|
timetable->timestamps[i - 1].id[0],
|
||||||
|
timetable->timestamps[i - 1].id[1], entry->time);*/
|
||||||
|
|
||||||
|
/* Make sure that we only update the episodes of each category
|
||||||
|
once per run. We keep track of all updated categories in the
|
||||||
|
"categories" array. If the category is already present in the
|
||||||
|
array, we do not update it. Otherwise, we insert the category
|
||||||
|
in the array and update the episodes counter of the
|
||||||
|
category. */
|
||||||
|
|
||||||
|
for(j = 0; j < categories_ptr; ++j) {
|
||||||
|
if(categories[j] == cat) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(j == categories_ptr) {
|
||||||
|
categories[j] = cat;
|
||||||
|
categories_ptr++;
|
||||||
|
entry->episodes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t = timetable->timestamps[i].time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
91
core/sys/timetable-aggregate.h
Normal file
91
core/sys/timetable-aggregate.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008, Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
* $Id: timetable-aggregate.h,v 1.1 2008/01/17 12:19:26 adamdunkels Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* A brief description of what this file is.
|
||||||
|
* \author
|
||||||
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TIMETABLE_AGGREGATE_H__
|
||||||
|
#define __TIMETABLE_AGGREGATE_H__
|
||||||
|
|
||||||
|
#include "sys/timetable.h"
|
||||||
|
#include "sys/cc.h"
|
||||||
|
|
||||||
|
struct timetable_aggregate_entry {
|
||||||
|
const char *id;
|
||||||
|
unsigned short episodes;
|
||||||
|
unsigned long time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct timetable_aggregate {
|
||||||
|
struct timetable_aggregate_entry *entries;
|
||||||
|
int ptr;
|
||||||
|
const int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define TIMETABLE_AGGREGATE_DECLARE(name) \
|
||||||
|
struct timetable_aggregate name
|
||||||
|
|
||||||
|
|
||||||
|
#define TIMETABLE_AGGREGATE(name, size) \
|
||||||
|
static struct timetable_aggregate_entry CC_CONCAT(name,_entries)[size]; \
|
||||||
|
static struct timetable_aggregate name = { \
|
||||||
|
CC_CONCAT(name,_entries), \
|
||||||
|
0, \
|
||||||
|
size \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TIMETABLE_AGGREGATE_NONSTATIC(name, size) \
|
||||||
|
static struct timetable_aggregate_entry CC_CONCAT(name,_entries)[size]; \
|
||||||
|
struct timetable_aggregate name = { \
|
||||||
|
CC_CONCAT(name,_entries), \
|
||||||
|
0, \
|
||||||
|
size \
|
||||||
|
}
|
||||||
|
|
||||||
|
void timetable_aggregate_print_detailed(struct timetable_aggregate *a);
|
||||||
|
|
||||||
|
void timetable_aggregate_print_categories(struct timetable_aggregate *a);
|
||||||
|
|
||||||
|
void timetable_aggregate_compute_detailed(struct timetable_aggregate *a,
|
||||||
|
struct timetable *timetable);
|
||||||
|
void timetable_aggregate_compute_categories(struct timetable_aggregate *a,
|
||||||
|
struct timetable *timetable);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __TIMETABLE_AGGREGATE_H__ */
|
128
core/sys/timetable.c
Normal file
128
core/sys/timetable.c
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008, Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
* $Id: timetable.c,v 1.1 2008/01/17 12:19:26 adamdunkels Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* A brief description of what this file is.
|
||||||
|
* \author
|
||||||
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sys/timetable.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
rtimer_clock_t timetable_timestamp_time;
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
struct timetable_timestamp *
|
||||||
|
timetable_entry(struct timetable *t, int num)
|
||||||
|
{
|
||||||
|
if(t == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &(t->timestamps[num]);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int
|
||||||
|
timetable_ptr(struct timetable *t)
|
||||||
|
{
|
||||||
|
return *t->ptr;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
timetable_clear(struct timetable *t)
|
||||||
|
{
|
||||||
|
*t->ptr = 0;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
rtimer_clock_t
|
||||||
|
timetable_timediff(struct timetable *t,
|
||||||
|
const char *id1, const char *id2)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int t1, t2;
|
||||||
|
|
||||||
|
t1 = t2 = t->size;
|
||||||
|
|
||||||
|
for(i = *t->ptr - 1; i >= 0; --i) {
|
||||||
|
if(t->timestamps[i].id == id1) {
|
||||||
|
t1 = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = i - 1; i >= 0; --i) {
|
||||||
|
if(t->timestamps[i].id == id2) {
|
||||||
|
t2 = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(t1 != t->size && t2 != t->size) {
|
||||||
|
return t->timestamps[t1].time - t->timestamps[t2].time;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
timetable_init(void)
|
||||||
|
{
|
||||||
|
char dummy1, dummy2;
|
||||||
|
#define temp_size 4
|
||||||
|
TIMETABLE_NONSTATIC(temp);
|
||||||
|
|
||||||
|
timetable_clear(&temp);
|
||||||
|
|
||||||
|
/* Measure the time for taking a timestamp. */
|
||||||
|
TIMETABLE_TIMESTAMP(temp, &dummy1);
|
||||||
|
TIMETABLE_TIMESTAMP(temp, &dummy2);
|
||||||
|
timetable_timestamp_time = timetable_timediff(&temp, &dummy1, &dummy2);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
timetable_print(struct timetable *t)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int time;
|
||||||
|
|
||||||
|
time = t->timestamps[0].time;
|
||||||
|
|
||||||
|
printf("---\n");
|
||||||
|
for(i = 1; i < *t->ptr; ++i) {
|
||||||
|
printf("%s: %u\n", t->timestamps[i - 1].id, t->timestamps[i].time - time);
|
||||||
|
time = t->timestamps[i].time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
140
core/sys/timetable.h
Normal file
140
core/sys/timetable.h
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008, Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
* $Id: timetable.h,v 1.1 2008/01/17 12:19:26 adamdunkels Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* A brief description of what this file is.
|
||||||
|
* \author
|
||||||
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TIMETABLE_H__
|
||||||
|
#define __TIMETABLE_H__
|
||||||
|
|
||||||
|
#include "sys/cc.h"
|
||||||
|
#include "sys/rtimer.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct timetable_timestamp {
|
||||||
|
const char *id;
|
||||||
|
rtimer_clock_t time;
|
||||||
|
#if TIMETABLE_WITH_TYPE
|
||||||
|
uint8_t type;
|
||||||
|
#endif /* TIMETABLE_WITH_TYPE */
|
||||||
|
};
|
||||||
|
struct timetable {
|
||||||
|
struct timetable_timestamp *timestamps;
|
||||||
|
const int size;
|
||||||
|
unsigned int * const ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TIMETABLE_NONSTATIC(name) \
|
||||||
|
struct timetable_timestamp CC_CONCAT(name,_timestamps)[CC_CONCAT(name,_size)]; \
|
||||||
|
unsigned int CC_CONCAT(name,_ptr); \
|
||||||
|
struct timetable name = { \
|
||||||
|
CC_CONCAT(name,_timestamps), \
|
||||||
|
CC_CONCAT(name,_size), \
|
||||||
|
&CC_CONCAT(name,_ptr)}
|
||||||
|
|
||||||
|
#define TIMETABLE_STATIC(name) \
|
||||||
|
static struct timetable_timestamp CC_CONCAT(name,_timestamps)[CC_CONCAT(name,_size)]; \
|
||||||
|
static unsigned int CC_CONCAT(name,_ptr); \
|
||||||
|
static struct timetable name = { \
|
||||||
|
CC_CONCAT(name,_timestamps), \
|
||||||
|
CC_CONCAT(name,_size), \
|
||||||
|
&CC_CONCAT(name,_ptr)}
|
||||||
|
|
||||||
|
#define TIMETABLE_DECLARE(name) \
|
||||||
|
extern unsigned int CC_CONCAT(name,_ptr); \
|
||||||
|
extern struct timetable_timestamp CC_CONCAT(name, _timestamps)[CC_CONCAT(name,_size)]; \
|
||||||
|
extern struct timetable name
|
||||||
|
|
||||||
|
#define TIMETABLE(name) TIMETABLE_STATIC(name)
|
||||||
|
|
||||||
|
#define TIMETABLE_TIMESTAMP(name, str) \
|
||||||
|
do { \
|
||||||
|
CC_CONCAT(name,_timestamps)[CC_CONCAT(name,_ptr)].id = str; \
|
||||||
|
CC_CONCAT(name,_timestamps)[CC_CONCAT(name,_ptr)].time = RTIMER_NOW(); \
|
||||||
|
CC_CONCAT(name,_ptr) = (CC_CONCAT(name,_ptr) + 1) % \
|
||||||
|
CC_CONCAT(name,_size); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#if TIMETABLE_WITH_TYPE
|
||||||
|
#define TIMETABLE_TIMESTAMP_TYPE(name, str, t) \
|
||||||
|
do { \
|
||||||
|
CC_CONCAT(name,_timestamps)[CC_CONCAT(name,_ptr)].id = str; \
|
||||||
|
CC_CONCAT(name,_timestamps)[CC_CONCAT(name,_ptr)].type = t; \
|
||||||
|
CC_CONCAT(name,_timestamps)[CC_CONCAT(name,_ptr)].time = RTIMER_NOW(); \
|
||||||
|
CC_CONCAT(name,_ptr) = (CC_CONCAT(name,_ptr) + 1) % \
|
||||||
|
CC_CONCAT(name,_size); \
|
||||||
|
} while(0)
|
||||||
|
#else /* TIMETABLE_WITH_TYPE */
|
||||||
|
#define TIMETABLE_TIMESTAMP_TYPE(name, str, t) TIMETABLE_TIMESTAMP(name, str)
|
||||||
|
#endif /* TIMETABLE_WITH_TYPE */
|
||||||
|
|
||||||
|
|
||||||
|
#define TIMETABLE_RESUME(name,num) \
|
||||||
|
TIMETABLE_TIMESTAMP(CC_CONCAT(name,_timestamps[num].id))
|
||||||
|
|
||||||
|
#define TIMETABLE_COND_TIMESTAMP(cond,name,id) \
|
||||||
|
do { if(cond) { \
|
||||||
|
TIMETABLE_TIMESTAMP(id); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define TIMETABLE_COND_RESUME(cond,name,num) \
|
||||||
|
TIMETABLE_COND_TIMESTAMP(cond,name, \
|
||||||
|
CC_CONCAT(name,_timestamps[num].id))
|
||||||
|
|
||||||
|
#define TIMETABLE_ENTRY(name, num) CC_CONCAT(name,_timestamps)[num]
|
||||||
|
#define TIMETABLE_PTR(name) CC_CONCAT(name,_ptr)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time for taking a timestamp.
|
||||||
|
*/
|
||||||
|
extern rtimer_clock_t timetable_timestamp_time;
|
||||||
|
|
||||||
|
|
||||||
|
struct timetable_timestamp *timetable_entry(struct timetable *t,
|
||||||
|
int num);
|
||||||
|
int timetable_ptr(struct timetable *t);
|
||||||
|
|
||||||
|
void timetable_clear(struct timetable *t);
|
||||||
|
rtimer_clock_t timetable_timediff(struct timetable *t,
|
||||||
|
const char *id1, const char *id2);
|
||||||
|
void timetable_init(void);
|
||||||
|
|
||||||
|
void timetable_print(struct timetable *t);
|
||||||
|
|
||||||
|
#include "sys/timetable-aggregate.h"
|
||||||
|
|
||||||
|
#endif /* __TIMETABLE_H__ */
|
Loading…
Reference in a new issue