Merge remote-tracking branch 'origin/develop' into feature-21-TM7-tmp
Conflicts: targets/RT/USER/lte-enb.c
This commit is contained in:
@@ -16,7 +16,7 @@ ID = ENB_PHY_DL_TICK
|
||||
ID = ENB_PHY_DLSCH_UE_DCI
|
||||
DESC = eNodeB downlink UE specific DCI as sent by the PHY layer
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,dci_format : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS
|
||||
ID = ENB_PHY_DLSCH_UE_ACK
|
||||
DESC = eNodeB downlink UE ACK as seen by the PHY layer in process_HARQ_feedback
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
@@ -28,7 +28,7 @@ ID = ENB_PHY_DLSCH_UE_NACK
|
||||
ID = ENB_PHY_ULSCH_UE_DCI
|
||||
DESC = eNodeB uplink UE specific DCI as sent by the PHY layer
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS
|
||||
ID = ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION
|
||||
DESC = eNodeB uplink UE retransmission due to PHICH NACK (see generate_phich_top)
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
|
||||
@@ -32,6 +32,8 @@ typedef struct {
|
||||
widget *pucch1_energy_ue_xy_plot;
|
||||
widget *pucch_iq_ue_xy_plot;
|
||||
widget *dl_ul_harq_ue_label;
|
||||
widget *dl_mcs_xy_plot;
|
||||
widget *ul_mcs_xy_plot;
|
||||
logger *pusch_iq_ue_logger;
|
||||
logger *ul_estimate_ue_logger;
|
||||
logger *pucch1_energy_ue_threshold_logger;
|
||||
@@ -44,6 +46,8 @@ typedef struct {
|
||||
logger *ul_dci_retransmission_logger[8];
|
||||
logger *ul_ack_logger[8];
|
||||
logger *ul_nack_logger[8];
|
||||
logger *dl_mcs_logger;
|
||||
logger *ul_mcs_logger;
|
||||
} enb_gui;
|
||||
|
||||
typedef struct {
|
||||
@@ -137,6 +141,10 @@ static void set_current_ue(gui *g, enb_data *e, int ue)
|
||||
xy_plot_set_title(g, e->e->pucch_iq_ue_xy_plot, s);
|
||||
sprintf(s, "DL/UL HARQ (x8) [UE %d]", ue);
|
||||
label_set_text(g, e->e->dl_ul_harq_ue_label, s);
|
||||
sprintf(s, "DL MCS [UE %d]", ue);
|
||||
xy_plot_set_title(g, e->e->dl_mcs_xy_plot, s);
|
||||
sprintf(s, "UL MCS [UE %d]", ue);
|
||||
xy_plot_set_title(g, e->e->ul_mcs_xy_plot, s);
|
||||
|
||||
logger_set_filter(e->e->pusch_iq_ue_logger,
|
||||
filter_eq(
|
||||
@@ -175,6 +183,14 @@ static void set_current_ue(gui *g, enb_data *e, int ue)
|
||||
logger_set_filter(e->e->ul_nack_logger[i],
|
||||
ticktime_filter(e->database, "ENB_PHY_ULSCH_UE_NACK", i, ue));
|
||||
}
|
||||
logger_set_filter(e->e->dl_mcs_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "ENB_PHY_DLSCH_UE_DCI", "UE_id"),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->ul_mcs_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "ENB_PHY_ULSCH_UE_DCI", "UE_id"),
|
||||
filter_int(ue)));
|
||||
}
|
||||
|
||||
static void click(void *private, gui *g,
|
||||
@@ -190,8 +206,12 @@ static void click(void *private, gui *g,
|
||||
if (w == e->prev_ue_button) { ue--; if (ue < 0) ue = 0; }
|
||||
if (w == e->next_ue_button) ue++;
|
||||
|
||||
if (ue != ed->ue) set_current_ue(g, ed, ue);
|
||||
ed->ue = ue;
|
||||
if (pthread_mutex_lock(&ed->lock)) abort();
|
||||
if (ue != ed->ue) {
|
||||
set_current_ue(g, ed, ue);
|
||||
ed->ue = ue;
|
||||
}
|
||||
if (pthread_mutex_unlock(&ed->lock)) abort();
|
||||
}
|
||||
|
||||
static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
|
||||
@@ -305,6 +325,30 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
|
||||
logger_add_view(l, v);
|
||||
e->pucch_iq_ue_logger = l;
|
||||
|
||||
/* UE x DL mcs */
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
w = new_xy_plot(g, 128, 55, "", 20);
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -2, 30);
|
||||
e->dl_mcs_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe",
|
||||
"ENB_PHY_DLSCH_UE_DCI", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
logger_add_view(l, v);
|
||||
e->dl_mcs_logger = l;
|
||||
|
||||
/* UE x UL mcs */
|
||||
w = new_xy_plot(g, 128, 55, "", 20);
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -2, 30);
|
||||
e->ul_mcs_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe",
|
||||
"ENB_PHY_ULSCH_UE_DCI", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
logger_add_view(l, v);
|
||||
e->ul_mcs_logger = l;
|
||||
|
||||
/* downlink/uplink UE DCIs */
|
||||
widget_add_child(g, top_container,
|
||||
new_label(g,"DL/UL TICK/DCI/ACK/NACK [all UEs]"), -1);
|
||||
@@ -745,7 +789,9 @@ restart:
|
||||
event e;
|
||||
e = get_event(enb_data.socket, v, database);
|
||||
if (e.type == -1) goto restart;
|
||||
if (pthread_mutex_lock(&enb_data.lock)) abort();
|
||||
handle_event(h, e);
|
||||
if (pthread_mutex_unlock(&enb_data.lock)) abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -2,8 +2,8 @@ CC=gcc
|
||||
CFLAGS=-Wall -g -pthread -I/usr/include/X11/Xft -I/usr/include/freetype2
|
||||
|
||||
OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
|
||||
gui.o label.o event.o xy_plot.o textlist.o notify.o positioner.o \
|
||||
timeline.o space.o image.o
|
||||
gui.o label.o textarea.o event.o xy_plot.o textlist.o notify.o \
|
||||
positioner.o timeline.o space.o image.o
|
||||
|
||||
gui.a: $(OBJS)
|
||||
ar cr gui.a $(OBJS)
|
||||
|
||||
@@ -14,6 +14,10 @@ typedef void widget;
|
||||
|
||||
#define DEFAULT_FONT 0
|
||||
|
||||
/* tic type for XY plot */
|
||||
#define XY_PLOT_DEFAULT_TICK 0
|
||||
#define XY_PLOT_SCROLL_TICK 1
|
||||
|
||||
/* key modifiers */
|
||||
#define KEY_SHIFT (1<<0)
|
||||
#define KEY_CONTROL (1<<1)
|
||||
@@ -30,6 +34,7 @@ widget *new_toplevel_window(gui *gui, int width, int height, char *title);
|
||||
widget *new_container(gui *gui, int vertical);
|
||||
widget *new_positioner(gui *gui);
|
||||
widget *new_label(gui *gui, const char *text);
|
||||
widget *new_textarea(gui *gui, int width, int height, int maxsize);
|
||||
widget *new_xy_plot(gui *gui, int width, int height, char *label,
|
||||
int vruler_width);
|
||||
widget *new_textlist(gui *gui, int width, int nlines, int background_color);
|
||||
@@ -41,6 +46,8 @@ widget *new_image(gui *gui, unsigned char *data, int length);
|
||||
void label_set_clickable(gui *gui, widget *label, int clickable);
|
||||
void label_set_text(gui *gui, widget *label, char *text);
|
||||
|
||||
void textarea_set_text(gui *gui, widget *textarea, char *text);
|
||||
|
||||
void container_set_child_growable(gui *_gui, widget *_this,
|
||||
widget *child, int growable);
|
||||
|
||||
@@ -51,6 +58,7 @@ void xy_plot_set_points(gui *gui, widget *this,
|
||||
int plot, int npoints, float *x, float *y);
|
||||
void xy_plot_get_dimensions(gui *gui, widget *this, int *width, int *height);
|
||||
void xy_plot_set_title(gui *gui, widget *this, char *label);
|
||||
void xy_plot_set_tick_type(gui *gui, widget *this, int type);
|
||||
|
||||
void textlist_add(gui *gui, widget *this, const char *text, int position,
|
||||
int color);
|
||||
|
||||
@@ -31,7 +31,7 @@ extern int volatile gui_logd;
|
||||
|
||||
enum widget_type {
|
||||
TOPLEVEL_WINDOW, CONTAINER, POSITIONER, TEXT_LIST, XY_PLOT, BUTTON, LABEL,
|
||||
TIMELINE, SPACE, IMAGE
|
||||
TEXTAREA, TIMELINE, SPACE, IMAGE
|
||||
};
|
||||
|
||||
struct widget_list;
|
||||
@@ -117,6 +117,7 @@ struct xy_plot_widget {
|
||||
int wanted_height;
|
||||
struct xy_plot_plot *plots;
|
||||
int nplots;
|
||||
int tick_type;
|
||||
};
|
||||
|
||||
struct timeline_subline {
|
||||
@@ -148,6 +149,17 @@ struct label_widget {
|
||||
int baseline; /* as given by the graphic's backend */
|
||||
};
|
||||
|
||||
struct textarea_widget {
|
||||
struct widget common;
|
||||
char *t;
|
||||
int tmaxsize;
|
||||
int color;
|
||||
int wanted_width;
|
||||
int wanted_height;
|
||||
int baseline; /* as given by the graphic's backend */
|
||||
int text_width; /* as given by the graphic's backend */
|
||||
};
|
||||
|
||||
struct space_widget {
|
||||
struct widget common;
|
||||
int wanted_width;
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void paint(gui *_gui, widget *_w)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct textarea_widget *t = _w;
|
||||
LOGD("PAINT textarea '%s'\n", t->t);
|
||||
x_fill_rectangle(g->x, g->xwin, BACKGROUND_COLOR,
|
||||
t->common.x, t->common.y,
|
||||
t->common.width, t->common.height);
|
||||
x_draw_clipped_string(g->x, g->xwin, DEFAULT_FONT, t->color,
|
||||
t->common.x + t->common.width - t->text_width,
|
||||
t->common.y + t->baseline, t->t,
|
||||
t->common.x, t->common.y,
|
||||
t->common.width, t->common.height);
|
||||
}
|
||||
|
||||
static void hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
struct textarea_widget *t = _w;
|
||||
LOGD("HINTS textarea '%s'\n", t->t);
|
||||
*width = t->wanted_width;
|
||||
*height = t->wanted_height;
|
||||
}
|
||||
|
||||
widget *new_textarea(gui *_gui, int width, int height, int maxsize)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct textarea_widget *w;
|
||||
int _;
|
||||
|
||||
glock(g);
|
||||
|
||||
w = new_widget(g, TEXTAREA, sizeof(struct textarea_widget));
|
||||
|
||||
w->t = calloc(maxsize, 1);
|
||||
if (w->t == NULL) OOM;
|
||||
w->tmaxsize = maxsize;
|
||||
w->wanted_width = width;
|
||||
w->wanted_height = height;
|
||||
w->color = FOREGROUND_COLOR;
|
||||
w->text_width = 0;
|
||||
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, "jlM",
|
||||
&_, &_, &w->baseline);
|
||||
|
||||
w->common.paint = paint;
|
||||
w->common.hints = hints;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* public functions */
|
||||
/*************************************************************************/
|
||||
|
||||
void textarea_set_text(gui *_g, widget *_this, char *text)
|
||||
{
|
||||
struct gui *g = _g;
|
||||
struct textarea_widget *this = _this;
|
||||
int _;
|
||||
int len = strlen(text);
|
||||
if (len >= this->tmaxsize) {
|
||||
fprintf(stderr, "ERROR: string '%s' too big for textarea\n", text);
|
||||
return;
|
||||
}
|
||||
|
||||
glock(g);
|
||||
|
||||
strcpy(this->t, text);
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, text,
|
||||
&this->text_width, &_, &this->baseline);
|
||||
send_event(g, DIRTY, this->common.id);
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
@@ -265,7 +265,7 @@ void widget_dirty(gui *_gui, widget *_this)
|
||||
|
||||
static const char *names[] = {
|
||||
"TOPLEVEL_WINDOW", "CONTAINER", "POSITIONER", "TEXT_LIST",
|
||||
"XY_PLOT", "BUTTON", "LABEL", "TIMELINE", "SPACE", "IMAGE"
|
||||
"XY_PLOT", "BUTTON", "LABEL", "TEXTAREA", "TIMELINE", "SPACE", "IMAGE"
|
||||
};
|
||||
const char *widget_name(enum widget_type type)
|
||||
{
|
||||
@@ -277,6 +277,7 @@ const char *widget_name(enum widget_type type)
|
||||
case XY_PLOT:
|
||||
case BUTTON:
|
||||
case LABEL:
|
||||
case TEXTAREA:
|
||||
case TIMELINE:
|
||||
case SPACE:
|
||||
case IMAGE:
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include "../utils.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#if 0
|
||||
/* this version behaves differently when you resize the XY plot. Say
|
||||
* you increase the size. The old (smaller) view is put at the center
|
||||
* of the new view. Everything inside keeps the same size/aspect ratio.
|
||||
* The other version below resizes the old view so that it fully occupies
|
||||
* the new view. It may introduce aspect ratio changes, but usage seems
|
||||
* to suggest it's a better behaviour.
|
||||
*/
|
||||
static void paint(gui *_gui, widget *_this)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
@@ -70,9 +79,9 @@ static void paint(gui *_gui, widget *_this)
|
||||
*/
|
||||
char v[64];
|
||||
int vwidth, dummy;
|
||||
float x = (k * ticstep - allocated_xmin) /
|
||||
(allocated_xmax - allocated_xmin) *
|
||||
(allocated_plot_width - 1);
|
||||
int x = (k * ticstep - allocated_xmin) /
|
||||
(allocated_xmax - allocated_xmin) *
|
||||
(allocated_plot_width - 1);
|
||||
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width + x,
|
||||
this->common.y + this->common.height - this->label_height * 2,
|
||||
@@ -85,7 +94,7 @@ static void paint(gui *_gui, widget *_this)
|
||||
this->common.y + this->common.height - this->label_height * 2 +
|
||||
this->label_baseline,
|
||||
v);
|
||||
LOGD("tic k %d val %g x %g\n", k, k * ticstep, x);
|
||||
LOGD("tic k %d val %g x %d\n", k, k * ticstep, x);
|
||||
}
|
||||
|
||||
/* vertical tics */
|
||||
@@ -112,9 +121,9 @@ static void paint(gui *_gui, widget *_this)
|
||||
for (k = kmin; k <= kmax; k++) {
|
||||
char v[64];
|
||||
int vwidth, dummy;
|
||||
float y = (k * ticstep - allocated_ymin) /
|
||||
(allocated_ymax - allocated_ymin) *
|
||||
(allocated_plot_height - 1);
|
||||
int y = (k * ticstep - allocated_ymin) /
|
||||
(allocated_ymax - allocated_ymin) *
|
||||
(allocated_plot_height - 1);
|
||||
sprintf(v, "%g", k * ticstep);
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
|
||||
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
|
||||
@@ -155,6 +164,184 @@ static void paint(gui *_gui, widget *_this)
|
||||
x_plot_points(g->x, g->xwin, this->plots[n].color);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void paint(gui *_gui, widget *_this)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct xy_plot_widget *this = _this;
|
||||
int allocated_plot_width;
|
||||
int allocated_plot_height;
|
||||
float pxsize;
|
||||
float ticdist;
|
||||
float tic;
|
||||
float ticstep;
|
||||
int k, kmin, kmax;
|
||||
float allocated_xmin, allocated_xmax;
|
||||
float allocated_ymin, allocated_ymax;
|
||||
int i;
|
||||
int n;
|
||||
char v[64];
|
||||
int vwidth, dummy;
|
||||
|
||||
# define FLIP(v) (-(v) + allocated_plot_height-1)
|
||||
|
||||
LOGD("PAINT xy plot xywh %d %d %d %d\n", this->common.x, this->common.y, this->common.width, this->common.height);
|
||||
|
||||
//x_draw_rectangle(g->x, g->xwin, 1, this->common.x, this->common.y, this->common.width, this->common.height);
|
||||
|
||||
allocated_plot_width = this->common.width - this->vrule_width;
|
||||
allocated_plot_height = this->common.height - this->label_height * 2;
|
||||
|
||||
if (allocated_plot_width <= 1 || allocated_plot_height <= 1) {
|
||||
WARN("PAINT xy plot: width (%d) or height (%d) is wrong, not painting\n",
|
||||
this->common.width, this->common.height);
|
||||
return;
|
||||
}
|
||||
|
||||
/* plot zone */
|
||||
/* TODO: refine height - height of hrule text may be != from label */
|
||||
x_draw_rectangle(g->x, g->xwin, 1,
|
||||
this->common.x + this->vrule_width,
|
||||
this->common.y,
|
||||
this->common.width - this->vrule_width -1, /* -1 to see right border */
|
||||
this->common.height - this->label_height * 2);
|
||||
|
||||
/* horizontal tics */
|
||||
pxsize = (this->xmax - this->xmin) / allocated_plot_width;
|
||||
ticdist = 100;
|
||||
tic = floor(log10(ticdist * pxsize));
|
||||
ticstep = powf(10, tic);
|
||||
allocated_xmin = this->xmin;
|
||||
allocated_xmax = this->xmax;
|
||||
/* adjust tic if too tight */
|
||||
LOGD("pre x ticstep %g\n", ticstep);
|
||||
while (1) {
|
||||
if (ticstep / (allocated_xmax - allocated_xmin)
|
||||
* (allocated_plot_width - 1) > 40) break;
|
||||
ticstep *= 2;
|
||||
}
|
||||
LOGD("post x ticstep %g\n", ticstep);
|
||||
LOGD("xmin/max %g %g width allocated %d alloc xmin/max %g %g ticstep %g\n", this->xmin, this->xmax, allocated_plot_width, allocated_xmin, allocated_xmax, ticstep);
|
||||
kmin = ceil(allocated_xmin / ticstep);
|
||||
kmax = floor(allocated_xmax / ticstep);
|
||||
for (k = kmin; k <= kmax; k++) {
|
||||
/*
|
||||
(k * ticstep - allocated_xmin) / (allocated_max - allocated_xmin) =
|
||||
(x - 0) / (allocated_plot_width-1 - 0)
|
||||
*/
|
||||
int x = (k * ticstep - allocated_xmin) /
|
||||
(allocated_xmax - allocated_xmin) *
|
||||
(allocated_plot_width - 1);
|
||||
int px;
|
||||
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width + x,
|
||||
this->common.y + this->common.height - this->label_height * 2,
|
||||
this->common.x + this->vrule_width + x,
|
||||
this->common.y + this->common.height - this->label_height * 2 - 5);
|
||||
sprintf(v, "%g", k * ticstep);
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
|
||||
|
||||
/* do not draw after the widget ('width-1' for if we use 'width'
|
||||
* it is still off by 1 pixel for whatever reason) */
|
||||
px = this->vrule_width + x - vwidth/2;
|
||||
if (px + vwidth > this->common.width-1)
|
||||
px = this->common.width-1 - vwidth;
|
||||
|
||||
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
|
||||
this->common.x + px,
|
||||
this->common.y + this->common.height - this->label_height * 2 +
|
||||
this->label_baseline,
|
||||
v);
|
||||
LOGD("tic k %d val %g x %d\n", k, k * ticstep, x);
|
||||
}
|
||||
|
||||
/* vertical tics */
|
||||
allocated_ymin = this->ymin;
|
||||
allocated_ymax = this->ymax;
|
||||
switch (this->tick_type) {
|
||||
case XY_PLOT_DEFAULT_TICK:
|
||||
pxsize = (this->ymax - this->ymin) / allocated_plot_height;
|
||||
ticdist = 30;
|
||||
tic = floor(log10(ticdist * pxsize));
|
||||
ticstep = powf(10, tic);
|
||||
/* adjust tic if too tight */
|
||||
LOGD("pre y ticstep %g\n", ticstep);
|
||||
while (1) {
|
||||
if (ticstep / (allocated_ymax - allocated_ymin)
|
||||
* (allocated_plot_height - 1) > 20) break;
|
||||
ticstep *= 2;
|
||||
}
|
||||
LOGD("post y ticstep %g\n", ticstep);
|
||||
LOGD("ymin/max %g %g height allocated %d alloc "
|
||||
"ymin/max %g %g ticstep %g\n", this->ymin, this->ymax,
|
||||
allocated_plot_height, allocated_ymin, allocated_ymax, ticstep);
|
||||
kmin = ceil(allocated_ymin / ticstep);
|
||||
kmax = floor(allocated_ymax / ticstep);
|
||||
for (k = kmin; k <= kmax; k++) {
|
||||
int y = (k * ticstep - allocated_ymin) /
|
||||
(allocated_ymax - allocated_ymin) *
|
||||
(allocated_plot_height - 1);
|
||||
sprintf(v, "%g", k * ticstep);
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
|
||||
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width,
|
||||
this->common.y + FLIP(y),
|
||||
this->common.x + this->vrule_width + 5,
|
||||
this->common.y + FLIP(y));
|
||||
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width - vwidth - 2,
|
||||
this->common.y + FLIP(y)-this->label_height/2+this->label_baseline,
|
||||
v);
|
||||
}
|
||||
break;
|
||||
case XY_PLOT_SCROLL_TICK:
|
||||
/* print only max value, formatted using 'bps' for readability */
|
||||
bps(v, this->ymax, "");
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
|
||||
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width - vwidth - 2,
|
||||
this->common.y + +this->label_baseline,
|
||||
v);
|
||||
/* vertically divide into 5 */
|
||||
for (k = 1; k < 5; k++) {
|
||||
int y = round((k * (allocated_plot_height - 1)) / 5.);
|
||||
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width,
|
||||
this->common.y + y,
|
||||
this->common.x + this->vrule_width + 5,
|
||||
this->common.y + y);
|
||||
}
|
||||
break;
|
||||
} /* swich (this->tick_type) */
|
||||
|
||||
/* label at bottom, in the middle */
|
||||
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
|
||||
this->common.x + (this->common.width - this->label_width) / 2,
|
||||
this->common.y + this->common.height - this->label_height
|
||||
+ this->label_baseline,
|
||||
this->label);
|
||||
|
||||
for (n = 0; n < this->nplots; n++) {
|
||||
/* points */
|
||||
float ax, bx, ay, by;
|
||||
ax = (allocated_plot_width-1) / (allocated_xmax - allocated_xmin);
|
||||
bx = -ax * allocated_xmin;
|
||||
ay = (allocated_plot_height-1) / (allocated_ymax - allocated_ymin);
|
||||
by = -ay * allocated_ymin;
|
||||
for (i = 0; i < this->plots[n].npoints; i++) {
|
||||
int x, y;
|
||||
x = ax * this->plots[n].x[i] + bx;
|
||||
y = ay * this->plots[n].y[i] + by;
|
||||
if (x >= 0 && x < allocated_plot_width &&
|
||||
y >= 0 && y < allocated_plot_height)
|
||||
x_add_point(g->x,
|
||||
this->common.x + this->vrule_width + x,
|
||||
this->common.y + FLIP(y));
|
||||
}
|
||||
x_plot_points(g->x, g->xwin, this->plots[n].color);
|
||||
}
|
||||
}
|
||||
|
||||
static void hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
@@ -191,6 +378,7 @@ widget *new_xy_plot(gui *_gui, int width, int height, char *label,
|
||||
w->ymax = 1;
|
||||
w->plots = NULL;
|
||||
w->nplots = 0;
|
||||
w->tick_type = XY_PLOT_DEFAULT_TICK;
|
||||
|
||||
w->common.paint = paint;
|
||||
w->common.hints = hints;
|
||||
@@ -309,3 +497,17 @@ void xy_plot_set_title(gui *_gui, widget *_this, char *label)
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void xy_plot_set_tick_type(gui *_gui, widget *_this, int type)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct xy_plot_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
this->tick_type = type;
|
||||
|
||||
send_event(g, DIRTY, this->common.id);
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ CC=gcc
|
||||
CFLAGS=-Wall -g -pthread -I..
|
||||
|
||||
OBJS=logger.o textlog.o framelog.o ttilog.o timelog.o ticklog.o iqlog.o \
|
||||
iqdotlog.o
|
||||
iqdotlog.o ticked_ttilog.o throughputlog.o
|
||||
|
||||
logger.a: $(OBJS)
|
||||
ar cr logger.a $(OBJS)
|
||||
|
||||
@@ -10,6 +10,13 @@ logger *new_textlog(void *event_handler, void *database,
|
||||
logger *new_ttilog(void *event_handler, void *database,
|
||||
char *event_name, char *frame_varname, char *subframe_varname,
|
||||
char *data_varname, int convert_to_dB);
|
||||
logger *new_ticked_ttilog(void *event_handler, void *database,
|
||||
char *tick_event_name, char *frame_varname, char *subframe_varname,
|
||||
char *event_name, char *data_varname,
|
||||
int convert_to_dB, float empty_value);
|
||||
logger *new_throughputlog(void *event_handler, void *database,
|
||||
char *tick_event_name, char *frame_varname, char *subframe_varname,
|
||||
char *event_name, char *data_varname);
|
||||
logger *new_timelog(void *event_handler, void *database, char *event_name);
|
||||
logger *new_ticklog(void *event_handler, void *database,
|
||||
char *event_name, char *frame_name, char *subframe_name);
|
||||
@@ -28,5 +35,6 @@ void textlog_dump_buffer(logger *_this, int dump_buffer);
|
||||
|
||||
void logger_add_view(logger *l, view *v);
|
||||
void logger_set_filter(logger *l, void *filter);
|
||||
void ticked_ttilog_set_tick_filter(logger *l, void *filter);
|
||||
|
||||
#endif /* _LOGGER_H_ */
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
#include "logger.h"
|
||||
#include "logger_defs.h"
|
||||
#include "event.h"
|
||||
#include "database.h"
|
||||
#include "handler.h"
|
||||
#include "filter/filter.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
struct throughputlog {
|
||||
struct logger common;
|
||||
void *database;
|
||||
int tick_frame_arg;
|
||||
int tick_subframe_arg;
|
||||
int data_frame_arg;
|
||||
int data_subframe_arg;
|
||||
int data_arg;
|
||||
int last_tick_frame;
|
||||
int last_tick_subframe;
|
||||
unsigned long bits[1000];
|
||||
unsigned long total;
|
||||
int insert_point;
|
||||
char *tick_event_name;
|
||||
unsigned long tick_handler_id;
|
||||
/* tick filter - NULL is no filter set */
|
||||
void *tick_filter;
|
||||
};
|
||||
|
||||
static void _event(void *p, event e)
|
||||
{
|
||||
struct throughputlog *l = p;
|
||||
int frame;
|
||||
int subframe;
|
||||
unsigned long value;
|
||||
|
||||
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
|
||||
return;
|
||||
|
||||
frame = e.e[l->data_frame_arg].i;
|
||||
subframe = e.e[l->data_subframe_arg].i;
|
||||
|
||||
if (frame != l->last_tick_frame || subframe != l->last_tick_subframe) {
|
||||
printf("WARNING: %s:%d: data comes without previous tick!\n",
|
||||
__FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.e[l->data_arg].type) {
|
||||
case EVENT_INT: value = e.e[l->data_arg].i; break;
|
||||
case EVENT_ULONG: value = e.e[l->data_arg].ul; break;
|
||||
default: printf("%s:%d: unsupported type\n", __FILE__, __LINE__); abort();
|
||||
}
|
||||
|
||||
l->total += value;
|
||||
l->bits[l->insert_point] += value;
|
||||
}
|
||||
|
||||
static void _tick_event(void *p, event e)
|
||||
{
|
||||
struct throughputlog *l = p;
|
||||
int i;
|
||||
int frame;
|
||||
int subframe;
|
||||
|
||||
if (l->tick_filter != NULL && filter_eval(l->tick_filter, e) == 0)
|
||||
return;
|
||||
|
||||
frame = e.e[l->tick_frame_arg].i;
|
||||
subframe = e.e[l->tick_subframe_arg].i;
|
||||
|
||||
for (i = 0; i < l->common.vsize; i++)
|
||||
l->common.v[i]->append(l->common.v[i], frame, subframe, (double)l->total);
|
||||
|
||||
l->insert_point = (l->insert_point + 1) % 1000;
|
||||
l->total -= l->bits[l->insert_point];
|
||||
l->bits[l->insert_point] = 0;
|
||||
|
||||
l->last_tick_frame = frame;
|
||||
l->last_tick_subframe = subframe;
|
||||
}
|
||||
|
||||
logger *new_throughputlog(event_handler *h, void *database,
|
||||
char *tick_event_name, char *frame_varname, char *subframe_varname,
|
||||
char *event_name, char *data_varname)
|
||||
{
|
||||
struct throughputlog *ret;
|
||||
int event_id;
|
||||
database_event_format f;
|
||||
int i;
|
||||
|
||||
ret = calloc(1, sizeof(struct throughputlog)); if (ret == NULL) abort();
|
||||
|
||||
ret->common.event_name = strdup(event_name);
|
||||
if (ret->common.event_name == NULL) abort();
|
||||
ret->database = database;
|
||||
|
||||
ret->tick_event_name = strdup(tick_event_name);
|
||||
if (ret->tick_event_name == NULL) abort();
|
||||
|
||||
/* tick event */
|
||||
event_id = event_id_from_name(database, tick_event_name);
|
||||
|
||||
ret->tick_handler_id=register_handler_function(h,event_id,_tick_event,ret);
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* look for frame and subframe */
|
||||
ret->tick_frame_arg = -1;
|
||||
ret->tick_subframe_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], frame_varname)) ret->tick_frame_arg = i;
|
||||
if (!strcmp(f.name[i], subframe_varname)) ret->tick_subframe_arg = i;
|
||||
}
|
||||
if (ret->tick_frame_arg == -1) {
|
||||
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, frame_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->tick_subframe_arg == -1) {
|
||||
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, subframe_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->tick_frame_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, frame_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->tick_subframe_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, subframe_varname);
|
||||
abort();
|
||||
}
|
||||
|
||||
/* data event */
|
||||
event_id = event_id_from_name(database, event_name);
|
||||
|
||||
ret->common.handler_id = register_handler_function(h,event_id,_event,ret);
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* look for frame, subframe and data args */
|
||||
ret->data_frame_arg = -1;
|
||||
ret->data_subframe_arg = -1;
|
||||
ret->data_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], frame_varname)) ret->data_frame_arg = i;
|
||||
if (!strcmp(f.name[i], subframe_varname)) ret->data_subframe_arg = i;
|
||||
if (!strcmp(f.name[i], data_varname)) ret->data_arg = i;
|
||||
}
|
||||
if (ret->data_frame_arg == -1) {
|
||||
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, frame_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->data_subframe_arg == -1) {
|
||||
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, subframe_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->data_arg == -1) {
|
||||
printf("%s:%d: data argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, data_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->data_frame_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, frame_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->data_subframe_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, subframe_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->data_arg], "int") != 0 &&
|
||||
strcmp(f.type[ret->data_arg], "float") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type"
|
||||
" (should be 'int' or 'float')\n",
|
||||
__FILE__, __LINE__, data_varname);
|
||||
abort();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void throughputlog_set_tick_filter(logger *_l, void *filter)
|
||||
{
|
||||
struct throughputlog *l = (struct throughputlog *)_l;
|
||||
free(l->tick_filter);
|
||||
l->tick_filter = filter;
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
#include "logger.h"
|
||||
#include "logger_defs.h"
|
||||
#include "event.h"
|
||||
#include "database.h"
|
||||
#include "handler.h"
|
||||
#include "filter/filter.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
struct ticked_ttilog {
|
||||
struct logger common;
|
||||
void *database;
|
||||
int tick_frame_arg;
|
||||
int tick_subframe_arg;
|
||||
int data_frame_arg;
|
||||
int data_subframe_arg;
|
||||
int data_arg;
|
||||
int convert_to_dB;
|
||||
int last_tick_frame;
|
||||
int last_tick_subframe;
|
||||
float last_value;
|
||||
float empty_value;
|
||||
char *tick_event_name;
|
||||
unsigned long tick_handler_id;
|
||||
/* tick filter - NULL is no filter set */
|
||||
void *tick_filter;
|
||||
};
|
||||
|
||||
static void _event(void *p, event e)
|
||||
{
|
||||
struct ticked_ttilog *l = p;
|
||||
int frame;
|
||||
int subframe;
|
||||
float value;
|
||||
|
||||
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
|
||||
return;
|
||||
|
||||
frame = e.e[l->data_frame_arg].i;
|
||||
subframe = e.e[l->data_subframe_arg].i;
|
||||
|
||||
if (frame != l->last_tick_frame || subframe != l->last_tick_subframe) {
|
||||
printf("WARNING: %s:%d: data comes without previous tick!\n",
|
||||
__FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.e[l->data_arg].type) {
|
||||
case EVENT_INT: value = e.e[l->data_arg].i; break;
|
||||
case EVENT_ULONG: value = e.e[l->data_arg].ul; break;
|
||||
default: printf("%s:%d: unsupported type\n", __FILE__, __LINE__); abort();
|
||||
}
|
||||
|
||||
if (l->convert_to_dB) value = 10 * log10(value);
|
||||
|
||||
l->last_value = value;
|
||||
}
|
||||
|
||||
static void _tick_event(void *p, event e)
|
||||
{
|
||||
struct ticked_ttilog *l = p;
|
||||
int i;
|
||||
int frame;
|
||||
int subframe;
|
||||
|
||||
if (l->tick_filter != NULL && filter_eval(l->tick_filter, e) == 0)
|
||||
return;
|
||||
|
||||
frame = e.e[l->tick_frame_arg].i;
|
||||
subframe = e.e[l->tick_subframe_arg].i;
|
||||
|
||||
for (i = 0; i < l->common.vsize; i++)
|
||||
l->common.v[i]->append(l->common.v[i], frame, subframe, l->last_value);
|
||||
|
||||
l->last_value = l->empty_value;
|
||||
l->last_tick_frame = frame;
|
||||
l->last_tick_subframe = subframe;
|
||||
}
|
||||
|
||||
logger *new_ticked_ttilog(event_handler *h, void *database,
|
||||
char *tick_event_name, char *frame_varname, char *subframe_varname,
|
||||
char *event_name, char *data_varname,
|
||||
int convert_to_dB, float empty_value)
|
||||
{
|
||||
struct ticked_ttilog *ret;
|
||||
int event_id;
|
||||
database_event_format f;
|
||||
int i;
|
||||
|
||||
ret = calloc(1, sizeof(struct ticked_ttilog)); if (ret == NULL) abort();
|
||||
|
||||
ret->common.event_name = strdup(event_name);
|
||||
if (ret->common.event_name == NULL) abort();
|
||||
ret->database = database;
|
||||
ret->convert_to_dB = convert_to_dB;
|
||||
|
||||
ret->tick_event_name = strdup(tick_event_name);
|
||||
if (ret->tick_event_name == NULL) abort();
|
||||
ret->empty_value = empty_value;
|
||||
ret->last_value = empty_value;
|
||||
|
||||
/* tick event */
|
||||
event_id = event_id_from_name(database, tick_event_name);
|
||||
|
||||
ret->tick_handler_id=register_handler_function(h,event_id,_tick_event,ret);
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* look for frame and subframe */
|
||||
ret->tick_frame_arg = -1;
|
||||
ret->tick_subframe_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], frame_varname)) ret->tick_frame_arg = i;
|
||||
if (!strcmp(f.name[i], subframe_varname)) ret->tick_subframe_arg = i;
|
||||
}
|
||||
if (ret->tick_frame_arg == -1) {
|
||||
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, frame_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->tick_subframe_arg == -1) {
|
||||
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, subframe_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->tick_frame_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, frame_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->tick_subframe_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, subframe_varname);
|
||||
abort();
|
||||
}
|
||||
|
||||
/* data event */
|
||||
event_id = event_id_from_name(database, event_name);
|
||||
|
||||
ret->common.handler_id = register_handler_function(h,event_id,_event,ret);
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* look for frame, subframe and data args */
|
||||
ret->data_frame_arg = -1;
|
||||
ret->data_subframe_arg = -1;
|
||||
ret->data_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], frame_varname)) ret->data_frame_arg = i;
|
||||
if (!strcmp(f.name[i], subframe_varname)) ret->data_subframe_arg = i;
|
||||
if (!strcmp(f.name[i], data_varname)) ret->data_arg = i;
|
||||
}
|
||||
if (ret->data_frame_arg == -1) {
|
||||
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, frame_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->data_subframe_arg == -1) {
|
||||
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, subframe_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->data_arg == -1) {
|
||||
printf("%s:%d: data argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, data_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->data_frame_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, frame_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->data_subframe_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, subframe_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->data_arg], "int") != 0 &&
|
||||
strcmp(f.type[ret->data_arg], "float") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type"
|
||||
" (should be 'int' or 'float')\n",
|
||||
__FILE__, __LINE__, data_varname);
|
||||
abort();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ticked_ttilog_set_tick_filter(logger *_l, void *filter)
|
||||
{
|
||||
struct ticked_ttilog *l = (struct ticked_ttilog *)_l;
|
||||
free(l->tick_filter);
|
||||
l->tick_filter = filter;
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <ctype.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <math.h>
|
||||
|
||||
void new_thread(void *(*f)(void *), void *data)
|
||||
{
|
||||
@@ -36,6 +37,16 @@ void sleepms(int ms)
|
||||
if (nanosleep(&t, NULL)) abort();
|
||||
}
|
||||
|
||||
void bps(char *out, float v, char *suffix)
|
||||
{
|
||||
static char *bps_unit[4] = { "", "k", "M", "G" };
|
||||
int flog;
|
||||
if (v < 1000) flog = 0; else flog = floor(floor(log10(v)) / 3);
|
||||
if (flog > 3) flog = 3;
|
||||
v /= pow(10, flog*3);
|
||||
sprintf(out, "%g%s%s", round(v*100)/100, bps_unit[flog], suffix);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* list */
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
void new_thread(void *(*f)(void *), void *data);
|
||||
void sleepms(int ms);
|
||||
void bps(char *out, float v, char *suffix);
|
||||
|
||||
/****************************************************************************/
|
||||
/* list */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -pthread -I.. -I../logger
|
||||
|
||||
OBJS=stdout.o textlist.o xy.o tti.o time.o ticktime.o
|
||||
OBJS=stdout.o textlist.o xy.o tti.o time.o ticktime.o scrolltti.o
|
||||
|
||||
view.a: $(OBJS)
|
||||
ar cr view.a $(OBJS)
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "view.h"
|
||||
#include "../utils.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
struct scrolltti {
|
||||
view common;
|
||||
gui *g;
|
||||
widget *w;
|
||||
widget *throughput_textarea;
|
||||
int plot;
|
||||
float refresh_rate;
|
||||
pthread_mutex_t lock;
|
||||
unsigned long data[1000];
|
||||
unsigned long total; /* sum data[0..999] to have smoother value printed */
|
||||
float xout[1000];
|
||||
float yout[1000];
|
||||
int insert_point;
|
||||
};
|
||||
|
||||
/* this array is used to get Y range 1000, 2000, 5000, 10000, ... */
|
||||
static int tolog[11] = { -1, 1, 2, 5, 5, 5, 10, 10, 10, 10, 10 };
|
||||
|
||||
static void *scrolltti_thread(void *_this)
|
||||
{
|
||||
struct scrolltti *this = _this;
|
||||
int i;
|
||||
int p;
|
||||
float max, mlog;
|
||||
char o[64];
|
||||
|
||||
while (1) {
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
/* TODO: optimize */
|
||||
p = this->insert_point;
|
||||
max = 0;
|
||||
for (i = 0; i < 1000; i++) {
|
||||
this->xout[i] = i;
|
||||
this->yout[i] = this->data[p];
|
||||
if (this->data[p] > max) max = this->data[p];
|
||||
p = (p + 1) % 1000;
|
||||
}
|
||||
bps(o, this->total/1000., "b/s");
|
||||
textarea_set_text(this->g, this->throughput_textarea, o);
|
||||
/* for Y range we want 1000, 2000, 5000, 10000, 20000, 50000, etc. */
|
||||
if (max < 1000) max = 1000;
|
||||
mlog = pow(10, floor(log10(max)));
|
||||
max = tolog[(int)ceil(max/mlog)] * mlog;
|
||||
xy_plot_set_range(this->g, this->w, 0, 1000, 0, max);
|
||||
xy_plot_set_points(this->g, this->w, this->plot,
|
||||
1000, this->xout, this->yout);
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
sleepms(1000/this->refresh_rate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clear(view *this)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void append(view *_this, int frame, int subframe, double value)
|
||||
{
|
||||
struct scrolltti *this = (struct scrolltti *)_this;
|
||||
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
this->total -= this->data[this->insert_point];
|
||||
this->data[this->insert_point] = value;
|
||||
this->total += this->data[this->insert_point];
|
||||
this->insert_point = (this->insert_point + 1) % 1000;
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color,
|
||||
widget *throughput_textarea)
|
||||
{
|
||||
struct scrolltti *ret = calloc(1, sizeof(struct scrolltti));
|
||||
if (ret == NULL) abort();
|
||||
|
||||
ret->common.clear = clear;
|
||||
ret->common.append = (void (*)(view *, ...))append;
|
||||
|
||||
ret->refresh_rate = refresh_rate;
|
||||
ret->g = g;
|
||||
ret->w = w;
|
||||
ret->throughput_textarea = throughput_textarea;
|
||||
ret->plot = xy_plot_new_plot(g, w, color);
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
|
||||
new_thread(scrolltti_thread, ret);
|
||||
|
||||
return (view *)ret;
|
||||
}
|
||||
@@ -19,6 +19,8 @@ view *new_view_xy(int length, float refresh_rate, gui *g, widget *w,
|
||||
int color, enum xy_mode mode);
|
||||
view *new_view_tti(float refresh_rate, gui *g, widget *w,
|
||||
int color);
|
||||
view *new_view_scrolltti(float refresh_rate, gui *g, widget *w,
|
||||
int color, widget *throughput_label);
|
||||
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, int size);
|
||||
|
||||
+177
-54
@@ -1,4 +1,8 @@
|
||||
/*
|
||||
/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
|
||||
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*-
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -26,6 +30,8 @@
|
||||
#ifndef _SYS_TREE_H_
|
||||
#define _SYS_TREE_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* This file defines data structures for different types of trees:
|
||||
* splay trees and red-black trees.
|
||||
@@ -63,7 +69,7 @@ struct name { \
|
||||
|
||||
#define SPLAY_INIT(root) do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
@@ -81,32 +87,32 @@ struct { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
||||
@@ -207,7 +213,7 @@ name##_SPLAY(struct name *head, struct type *elm) \
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root))) { \
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
@@ -286,7 +292,7 @@ void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
(x) != NULL; \
|
||||
(x) = SPLAY_NEXT(name, head, x))
|
||||
|
||||
/* Macros that define a red-back tree */
|
||||
/* Macros that define a red-black tree */
|
||||
#define RB_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *rbh_root; /* root of the tree */ \
|
||||
@@ -297,7 +303,7 @@ struct name { \
|
||||
|
||||
#define RB_INIT(root) do { \
|
||||
(root)->rbh_root = NULL; \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_BLACK 0
|
||||
#define RB_RED 1
|
||||
@@ -320,24 +326,24 @@ struct { \
|
||||
RB_PARENT(elm, field) = parent; \
|
||||
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
|
||||
RB_COLOR(elm, field) = RB_RED; \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_SET_BLACKRED(black, red, field) do { \
|
||||
RB_COLOR(black, field) = RB_BLACK; \
|
||||
RB_COLOR(red, field) = RB_RED; \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#ifndef RB_AUGMENT
|
||||
#define RB_AUGMENT(x)
|
||||
#define RB_AUGMENT(x) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
|
||||
(tmp) = RB_RIGHT(elm, field); \
|
||||
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
|
||||
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
|
||||
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
else \
|
||||
@@ -349,15 +355,15 @@ struct { \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((RB_PARENT(tmp, field))) \
|
||||
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
|
||||
(tmp) = RB_LEFT(elm, field); \
|
||||
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
|
||||
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
|
||||
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
|
||||
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
else \
|
||||
@@ -369,28 +375,66 @@ struct { \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((RB_PARENT(tmp, field))) \
|
||||
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||
} while (0)
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
#define RB_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
|
||||
struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
struct type *name##_RB_NEXT(struct type *); \
|
||||
struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
\
|
||||
#define RB_PROTOTYPE(name, type, field, cmp) \
|
||||
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
|
||||
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
|
||||
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
|
||||
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
|
||||
RB_PROTOTYPE_INSERT_COLOR(name, type, attr); \
|
||||
RB_PROTOTYPE_REMOVE_COLOR(name, type, attr); \
|
||||
RB_PROTOTYPE_INSERT(name, type, attr); \
|
||||
RB_PROTOTYPE_REMOVE(name, type, attr); \
|
||||
RB_PROTOTYPE_FIND(name, type, attr); \
|
||||
RB_PROTOTYPE_NFIND(name, type, attr); \
|
||||
RB_PROTOTYPE_NEXT(name, type, attr); \
|
||||
RB_PROTOTYPE_PREV(name, type, attr); \
|
||||
RB_PROTOTYPE_MINMAX(name, type, attr);
|
||||
#define RB_PROTOTYPE_INSERT_COLOR(name, type, attr) \
|
||||
attr void name##_RB_INSERT_COLOR(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_REMOVE_COLOR(name, type, attr) \
|
||||
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *)
|
||||
#define RB_PROTOTYPE_REMOVE(name, type, attr) \
|
||||
attr struct type *name##_RB_REMOVE(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_INSERT(name, type, attr) \
|
||||
attr struct type *name##_RB_INSERT(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_FIND(name, type, attr) \
|
||||
attr struct type *name##_RB_FIND(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_NFIND(name, type, attr) \
|
||||
attr struct type *name##_RB_NFIND(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_NEXT(name, type, attr) \
|
||||
attr struct type *name##_RB_NEXT(struct type *)
|
||||
#define RB_PROTOTYPE_PREV(name, type, attr) \
|
||||
attr struct type *name##_RB_PREV(struct type *)
|
||||
#define RB_PROTOTYPE_MINMAX(name, type, attr) \
|
||||
attr struct type *name##_RB_MINMAX(struct name *, int)
|
||||
|
||||
/* Main rb operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define RB_GENERATE(name, type, field, cmp) \
|
||||
void \
|
||||
#define RB_GENERATE(name, type, field, cmp) \
|
||||
RB_GENERATE_INTERNAL(name, type, field, cmp,)
|
||||
#define RB_GENERATE_STATIC(name, type, field, cmp) \
|
||||
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
|
||||
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
|
||||
RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
|
||||
RB_GENERATE_INSERT(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_REMOVE(name, type, field, attr) \
|
||||
RB_GENERATE_FIND(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_NFIND(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_NEXT(name, type, field, attr) \
|
||||
RB_GENERATE_PREV(name, type, field, attr) \
|
||||
RB_GENERATE_MINMAX(name, type, field, attr)
|
||||
|
||||
#define RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
|
||||
attr void \
|
||||
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *parent, *gparent, *tmp; \
|
||||
while ((parent = RB_PARENT(elm, field)) && \
|
||||
while ((parent = RB_PARENT(elm, field)) != NULL && \
|
||||
RB_COLOR(parent, field) == RB_RED) { \
|
||||
gparent = RB_PARENT(parent, field); \
|
||||
if (parent == RB_LEFT(gparent, field)) { \
|
||||
@@ -428,9 +472,10 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
} \
|
||||
} \
|
||||
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
}
|
||||
|
||||
#define RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
|
||||
attr void \
|
||||
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
@@ -454,7 +499,8 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
|
||||
if (RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
|
||||
struct type *oleft; \
|
||||
if ((oleft = RB_LEFT(tmp, field)))\
|
||||
if ((oleft = RB_LEFT(tmp, field)) \
|
||||
!= NULL) \
|
||||
RB_COLOR(oleft, field) = RB_BLACK;\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
|
||||
@@ -486,7 +532,8 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
|
||||
if (RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
|
||||
struct type *oright; \
|
||||
if ((oright = RB_RIGHT(tmp, field)))\
|
||||
if ((oright = RB_RIGHT(tmp, field)) \
|
||||
!= NULL) \
|
||||
RB_COLOR(oright, field) = RB_BLACK;\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
RB_ROTATE_LEFT(head, tmp, oright, field);\
|
||||
@@ -504,9 +551,10 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
|
||||
} \
|
||||
if (elm) \
|
||||
RB_COLOR(elm, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
}
|
||||
|
||||
#define RB_GENERATE_REMOVE(name, type, field, attr) \
|
||||
attr struct type * \
|
||||
name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *child, *parent, *old = elm; \
|
||||
@@ -518,7 +566,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
else { \
|
||||
struct type *left; \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while ((left = RB_LEFT(elm, field))) \
|
||||
while ((left = RB_LEFT(elm, field)) != NULL) \
|
||||
elm = left; \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
@@ -551,7 +599,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
left = parent; \
|
||||
do { \
|
||||
RB_AUGMENT(left); \
|
||||
} while ((left = RB_PARENT(left, field))); \
|
||||
} while ((left = RB_PARENT(left, field)) != NULL); \
|
||||
} \
|
||||
goto color; \
|
||||
} \
|
||||
@@ -572,9 +620,10 @@ color: \
|
||||
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||
return (old); \
|
||||
} \
|
||||
\
|
||||
|
||||
#define RB_GENERATE_INSERT(name, type, field, cmp, attr) \
|
||||
/* Inserts a node into the RB tree */ \
|
||||
struct type * \
|
||||
attr struct type * \
|
||||
name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
@@ -599,15 +648,14 @@ name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
RB_RIGHT(parent, field) = elm; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
{ \
|
||||
RB_ROOT(head) = elm; \
|
||||
} \
|
||||
name##_RB_INSERT_COLOR(head, elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
||||
#define RB_GENERATE_FIND(name, type, field, cmp, attr) \
|
||||
/* Finds the node with the same key as elm */ \
|
||||
struct type * \
|
||||
attr struct type * \
|
||||
name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
@@ -622,9 +670,33 @@ name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
}
|
||||
|
||||
#define RB_GENERATE_NFIND(name, type, field, cmp, attr) \
|
||||
/* Finds the first node greater than or equal to the search key */ \
|
||||
attr struct type * \
|
||||
name##_RB_NFIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *res = NULL; \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = cmp(elm, tmp); \
|
||||
if (comp < 0) { \
|
||||
res = tmp; \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
} \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (res); \
|
||||
}
|
||||
|
||||
#define RB_GENERATE_NEXT(name, type, field, attr) \
|
||||
/* ARGSUSED */ \
|
||||
attr struct type * \
|
||||
name##_RB_NEXT(struct type *elm) \
|
||||
{ \
|
||||
if (RB_RIGHT(elm, field)) { \
|
||||
@@ -643,9 +715,33 @@ name##_RB_NEXT(struct type *elm) \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
}
|
||||
|
||||
#define RB_GENERATE_PREV(name, type, field, attr) \
|
||||
/* ARGSUSED */ \
|
||||
attr struct type * \
|
||||
name##_RB_PREV(struct type *elm) \
|
||||
{ \
|
||||
if (RB_LEFT(elm, field)) { \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
while (RB_RIGHT(elm, field)) \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
} else { \
|
||||
if (RB_PARENT(elm, field) && \
|
||||
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
else { \
|
||||
while (RB_PARENT(elm, field) && \
|
||||
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
|
||||
elm = RB_PARENT(elm, field); \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
}
|
||||
|
||||
#define RB_GENERATE_MINMAX(name, type, field, attr) \
|
||||
attr struct type * \
|
||||
name##_RB_MINMAX(struct name *head, int val) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
@@ -666,7 +762,9 @@ name##_RB_MINMAX(struct name *head, int val) \
|
||||
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
|
||||
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
|
||||
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||
#define RB_PREV(name, x, y) name##_RB_PREV(y)
|
||||
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
|
||||
|
||||
@@ -675,4 +773,29 @@ name##_RB_MINMAX(struct name *head, int val) \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_NEXT(x))
|
||||
|
||||
#define RB_FOREACH_FROM(x, name, y) \
|
||||
for ((x) = (y); \
|
||||
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_SAFE(x, name, head, y) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_REVERSE(x, name, head) \
|
||||
for ((x) = RB_MAX(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_PREV(x))
|
||||
|
||||
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
|
||||
for ((x) = (y); \
|
||||
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
|
||||
for ((x) = RB_MAX(name, head); \
|
||||
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
|
||||
(x) = (y))
|
||||
|
||||
#endif /* _SYS_TREE_H_ */
|
||||
|
||||
@@ -86,8 +86,8 @@ int timer_handle_signal(siginfo_t *info)
|
||||
timer_p = (struct timer_elm_s *)info->si_ptr;
|
||||
|
||||
// LG: To many traces for msc timer:
|
||||
// TMR_DEBUG("Timer with id 0x%lx has expired\n", (long)timer_p->timer);
|
||||
|
||||
TMR_DEBUG("Timer with id 0x%lx has expired\n", (long)timer_p->timer);
|
||||
|
||||
task_id = timer_p->task_id;
|
||||
instance = timer_p->instance;
|
||||
message_p = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED);
|
||||
@@ -120,6 +120,10 @@ int timer_handle_signal(siginfo_t *info)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(ENB_AGENT_SB_IF)
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user