diff --git a/common/utils/T/tracer/enb.c b/common/utils/T/tracer/enb.c index 5cd59a811ce74aa3c839842fc85673aa48c30550..19cac762af4613ad7879708417dbae0cedfa0e46 100644 --- a/common/utils/T/tracer/enb.c +++ b/common/utils/T/tracer/enb.c @@ -157,24 +157,24 @@ static void enb_main_gui(gui *g, event_handler *h, void *database) timeview = new_view_time(3600, 10, g, timeline_plot); /* tick logging */ timelog = new_timelog(h, database, "ENB_DL_TICK"); - subview = new_subview_time(timeview, 0, FOREGROUND_COLOR); + subview = new_subview_time(timeview, 0, FOREGROUND_COLOR, 3600*1000); logger_add_view(timelog, subview); /* DCI logging */ timelog = new_timelog(h, database, "ENB_DLSCH_UE_DCI"); - subview = new_subview_time(timeview, 1, new_color(g, "#228")); + subview = new_subview_time(timeview, 1, new_color(g, "#228"), 3600*1000); logger_add_view(timelog, subview); /* ACK */ timelog = new_timelog(h, database, "ENB_DLSCH_UE_ACK"); - subview = new_subview_time(timeview, 2, new_color(g, "#282")); + subview = new_subview_time(timeview, 2, new_color(g, "#282"), 3600*1000); logger_add_view(timelog, subview); /* NACK */ timelog = new_timelog(h, database, "ENB_DLSCH_UE_NACK"); - subview = new_subview_time(timeview, 3, new_color(g, "#f22")); + subview = new_subview_time(timeview, 3, new_color(g, "#f22"), 3600*1000); logger_add_view(timelog, subview); /* uplink UE DCIs */ timelog = new_timelog(h, database, "ENB_UL_TICK"); - subview = new_subview_time(timeview, 4, FOREGROUND_COLOR); + subview = new_subview_time(timeview, 4, FOREGROUND_COLOR, 3600*1000); logger_add_view(timelog, subview); } diff --git a/common/utils/T/tracer/view/time.c b/common/utils/T/tracer/view/time.c index efa0f61c5262f95d911580eaf3b80e147937bc75..43f30cc4031cc71d7f0420c6de8287d501093396 100644 --- a/common/utils/T/tracer/view/time.c +++ b/common/utils/T/tracer/view/time.c @@ -10,35 +10,24 @@ /****************************************************************************/ struct plot { - long *nano; - int nanosize; - int nanomaxsize; + struct timespec *tick; + int ticksize; + int tickmaxsize; + int tickstart; int line; int color; }; -struct tick { - struct plot *p; /* one plot per subview, - * so size is 'subcount' - * (see in struct time below) - */ -}; - struct time { view common; gui *g; widget *w; float refresh_rate; pthread_mutex_t lock; - struct tick *t; /* t is a circular list - * a tick lasts one second - */ - int tsize; /* size of t */ - int tstart; /* starting index in t */ - time_t tstart_time; /* timestamp (in seconds) of starting in t */ - int subcount; /* number of subviews */ - struct timespec latest_time; /* time of latest received tick */ + struct plot *p; + int psize; double pixel_length; /* unit: nanosecond (maximum 1 hour/pixel) */ + struct timespec latest_time; }; /* TODO: put that function somewhere else (utils.c) */ @@ -87,13 +76,33 @@ static int time_cmp(struct timespec a, struct timespec b) return 0; } +static int interval_empty(struct time *this, int sub, + struct timespec start, struct timespec end) +{ + int a, b, mid; + int i; + + if (this->p[sub].ticksize == 0) return 1; + + /* look for a tick larger than start and smaller than end */ + a = 0; + b = this->p[sub].ticksize - 1; + while (b >= a) { + mid = (a+b) / 2; + i = (this->p[sub].tickstart + mid) % this->p[sub].ticksize; + if (time_cmp(this->p[sub].tick[i], start) < 0) a = mid + 1; + else if (time_cmp(this->p[sub].tick[i], end) > 0) b = mid - 1; + else return 0; + } + return 1; +} + static void *time_thread(void *_this) { struct time *this = _this; int width; int l; int i; - int t; struct timespec tstart; struct timespec tnext; struct plot *p; @@ -105,7 +114,7 @@ static void *time_thread(void *_this) timeline_get_width(this->g, this->w, &width); timeline_clear_silent(this->g, this->w); - /* TODO: optimize/cleanup */ + /* TODO: optimize? */ /* use rounded pixel_length */ pixel_length = this->pixel_length; @@ -113,34 +122,14 @@ static void *time_thread(void *_this) tnext = time_add(this->latest_time,(struct timespec){tv_sec:0,tv_nsec:1}); tstart = time_sub(tnext, nano_to_time(pixel_length * width)); - for (l = 0; l < this->subcount; l++) { + for (l = 0; l < this->psize; l++) { for (i = 0; i < width; i++) { struct timespec tick_start, tick_end; tick_start = time_add(tstart, nano_to_time(pixel_length * i)); tick_end = time_add(tick_start, nano_to_time(pixel_length-1)); - /* look for a nano between tick_start and tick_end */ - /* TODO: optimize */ - for (t = 0; t < this->tsize; t++) { - int n; - time_t current_second = this->tstart_time + t; - time_t next_second = current_second + 1; - struct timespec current_time = - (struct timespec){tv_sec:current_second,tv_nsec:0}; - struct timespec next_time = - (struct timespec){tv_sec:next_second,tv_nsec:0}; - if (time_cmp(tick_end, current_time) < 0) continue; - if (time_cmp(tick_start, next_time) >= 0) continue; - p = &this->t[(this->tstart + t) % this->tsize].p[l]; - for (n = 0; n < p->nanosize; n++) { - struct timespec nano = - (struct timespec){tv_sec:current_second,tv_nsec:p->nano[n]}; - if (time_cmp(tick_start, nano) <= 0 && - time_cmp(nano, tick_end) <= 0) - goto gotit; - } - } - continue; -gotit: + if (interval_empty(this, l, tick_start, tick_end)) + continue; + p = &this->p[l]; /* TODO: only one call */ timeline_add_points_silent(this->g, this->w, p->line, p->color, &i, 1); } @@ -200,13 +189,11 @@ view *new_view_time(int number_of_seconds, float refresh_rate, ret->g = g; ret->w = w; - ret->t = calloc(number_of_seconds, sizeof(struct tick)); - if (ret->t == NULL) abort(); - ret->tsize = number_of_seconds; - ret->tstart = 0; - ret->tstart_time = 0; - ret->subcount = 0; - ret->pixel_length = 10 * 1000000; /* 10ms */ + ret->p = NULL; + ret->psize = 0; + + /* default pixel length: 10ms */ + ret->pixel_length = 10 * 1000000; register_notifier(g, "scrollup", w, scroll, ret); register_notifier(g, "scrolldown", w, scroll, ret); @@ -234,74 +221,26 @@ static void append(view *_this, struct timespec t) { struct subtime *this = (struct subtime *)_this; struct time *time = this->parent; - time_t start_time, end_time; - int i, l; - int tpos; - struct plot *p; + struct plot *p = &time->p[this->subview]; if (pthread_mutex_lock(&time->lock)) abort(); - start_time = time->tstart_time; - end_time = time->tstart_time + time->tsize - 1; - - /* useless test? */ - if (t.tv_sec < start_time) abort(); - - /* tick out of current window? if yes, move window */ - /* if too far, free all */ - if (t.tv_sec > end_time && t.tv_sec - end_time > time->tsize) { - for (l = 0; l < time->tsize; l++) - for (i = 0; i < time->subcount; i++) { - free(time->t[l].p[i].nano); - time->t[l].p[i].nano = NULL; - time->t[l].p[i].nanosize = 0; - time->t[l].p[i].nanomaxsize = 0; - } - time->tstart = 0; - time->tstart_time = t.tv_sec - (time->tsize-1); - start_time = time->tstart_time; - end_time = time->tstart_time + time->tsize - 1; - } - while (t.tv_sec > end_time) { - for (i = 0; i < time->subcount; i++) { - free(time->t[time->tstart].p[i].nano); - time->t[time->tstart].p[i].nano = NULL; - time->t[time->tstart].p[i].nanosize = 0; - time->t[time->tstart].p[i].nanomaxsize = 0; - } - time->tstart = (time->tstart+1) % time->tsize; - time->tstart_time++; - start_time++; - end_time++; - } - - tpos = (time->tstart + (t.tv_sec - time->tstart_time)) % time->tsize; - p = &time->t[tpos].p[this->subview]; - - /* can we get a new event with <= time than last in list? */ - if (p->nanosize != 0 && t.tv_nsec <= p->nano[p->nanosize-1]) - { printf("%s:%d: possible?\n", __FILE__, __LINE__); abort(); } - - if (p->nanosize == p->nanomaxsize) { - p->nanomaxsize += 4096; - p->nano = realloc(p->nano, p->nanomaxsize * sizeof(long)); - if (p->nano == NULL) abort(); + if (p->ticksize < p->tickmaxsize) { + p->tick[p->ticksize] = t; + p->ticksize++; + } else { + p->tick[p->tickstart] = t; + p->tickstart = (p->tickstart + 1) % p->ticksize; } - p->nano[p->nanosize] = t.tv_nsec; - p->nanosize++; - - if (time->latest_time.tv_sec < t.tv_sec || - (time->latest_time.tv_sec == t.tv_sec && - time->latest_time.tv_nsec < t.tv_nsec)) + if (time_cmp(time->latest_time, t) < 0) time->latest_time = t; if (pthread_mutex_unlock(&time->lock)) abort(); } -view *new_subview_time(view *_time, int line, int color) +view *new_subview_time(view *_time, int line, int color, int size) { - int i; struct time *time = (struct time *)_time; struct subtime *ret = calloc(1, sizeof(struct subtime)); if (ret == NULL) abort(); @@ -313,20 +252,20 @@ view *new_subview_time(view *_time, int line, int color) ret->parent = time; ret->line = line; ret->color = color; - ret->subview = time->subcount; - - for (i = 0; i < time->tsize; i++) { - time->t[i].p = realloc(time->t[i].p, - (time->subcount + 1) * sizeof(struct plot)); - if (time->t[i].p == NULL) abort(); - time->t[i].p[time->subcount].nano = NULL; - time->t[i].p[time->subcount].nanosize = 0; - time->t[i].p[time->subcount].nanomaxsize = 0; - time->t[i].p[time->subcount].line = line; - time->t[i].p[time->subcount].color = color; - } - - time->subcount++; + ret->subview = time->psize; + + time->p = realloc(time->p, + (time->psize + 1) * sizeof(struct plot)); + if (time->p == NULL) abort(); + time->p[time->psize].tick = calloc(size, sizeof(struct timespec)); + if (time->p[time->psize].tick == NULL) abort(); + time->p[time->psize].ticksize = 0; + time->p[time->psize].tickmaxsize = size; + time->p[time->psize].tickstart = 0; + time->p[time->psize].line = line; + time->p[time->psize].color = color; + + time->psize++; if (pthread_mutex_unlock(&time->lock)) abort(); diff --git a/common/utils/T/tracer/view/view.h b/common/utils/T/tracer/view/view.h index 8d8036721c46652b0c7dbf34ae460680b7dc8b09..4b91291b1c3ffa6e2d7621d54f0e0727fe1801eb 100644 --- a/common/utils/T/tracer/view/view.h +++ b/common/utils/T/tracer/view/view.h @@ -19,6 +19,6 @@ view *new_view_tti(float refresh_rate, gui *g, widget *w, int color); view *new_view_time(int number_of_seconds, float refresh_rate, gui *g, widget *w); -view *new_subview_time(view *time, int line, int color); +view *new_subview_time(view *time, int line, int color, int size); #endif /* _VIEW_H_ */