summaryrefslogtreecommitdiff
path: root/src/lib/eina
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2015-05-10 19:05:54 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2015-05-10 19:05:54 +0900
commit2aeb289063dba3d71773d2e3dc61573da4847093 (patch)
tree358b695a7477b44c08785ec0416f7d9a772c674a /src/lib/eina
parent1ce417eb8b928053cd21b0fe829923745821aff8 (diff)
eina - begin event log infra we can get from the new debug monitor
we can down dump event logs. some ecore mainloop bits are logging at the moment.
Diffstat (limited to 'src/lib/eina')
-rw-r--r--src/lib/eina/Eina.h1
-rw-r--r--src/lib/eina/eina_debug_monitor.c33
-rw-r--r--src/lib/eina/eina_evlog.c220
-rw-r--r--src/lib/eina/eina_evlog.h121
-rw-r--r--src/lib/eina/eina_main.c4
5 files changed, 379 insertions, 0 deletions
diff --git a/src/lib/eina/Eina.h b/src/lib/eina/Eina.h
index b0b24ee09e..c05ab9abee 100644
--- a/src/lib/eina/Eina.h
+++ b/src/lib/eina/Eina.h
@@ -264,6 +264,7 @@ extern "C" {
264#include <eina_thread_queue.h> 264#include <eina_thread_queue.h>
265#include <eina_matrix.h> 265#include <eina_matrix.h>
266#include <eina_crc.h> 266#include <eina_crc.h>
267#include <eina_evlog.h>
267 268
268#undef EAPI 269#undef EAPI
269#define EAPI 270#define EAPI
diff --git a/src/lib/eina/eina_debug_monitor.c b/src/lib/eina/eina_debug_monitor.c
index 324759f2a2..c06d5e9df3 100644
--- a/src/lib/eina/eina_debug_monitor.c
+++ b/src/lib/eina/eina_debug_monitor.c
@@ -1,4 +1,5 @@
1#include "eina_debug.h" 1#include "eina_debug.h"
2#include "eina_evlog.h"
2 3
3#ifdef EINA_HAVE_DEBUG 4#ifdef EINA_HAVE_DEBUG
4 5
@@ -177,6 +178,38 @@ _eina_debug_monitor(void *data EINA_UNUSED)
177 poll_time = 1000; 178 poll_time = 1000;
178 poll_on = EINA_FALSE; 179 poll_on = EINA_FALSE;
179 } 180 }
181 // enable evlog
182 else if (!strcmp(op, "EVON"))
183 {
184 eina_evlog_start();
185 }
186 // stop evlog
187 else if (!strcmp(op, "EVOF"))
188 {
189 eina_evlog_stop();
190 }
191 // fetch the evlog
192 else if (!strcmp(op, "EVLG"))
193 {
194 Eina_Evlog_Buf *evlog = eina_evlog_steal();
195 if ((evlog) && (evlog->buf))
196 {
197 char tmp[16];
198 unsigned int *size = (unsigned int *)(tmp + 0);
199 char *op2 = "EVLG";
200 unsigned int *overflow = (unsigned int *)(tmp + 8);
201 unsigned int *stolen = (unsigned int *)(tmp + 12);
202
203 *size = (sizeof(tmp) - 4) + evlog->top;
204 memcpy(tmp + 4, op2, 4);
205 *overflow = evlog->overflow;
206 *stolen = evlog->stolen;
207 write(_eina_debug_monitor_service_fd,
208 tmp, 16);
209 write(_eina_debug_monitor_service_fd,
210 evlog->buf, evlog->top);
211 }
212 }
180 // something we don't understand 213 // something we don't understand
181 else fprintf(stderr, 214 else fprintf(stderr,
182 "EINA DEBUG ERROR: " 215 "EINA DEBUG ERROR: "
diff --git a/src/lib/eina/eina_evlog.c b/src/lib/eina/eina_evlog.c
new file mode 100644
index 0000000000..4703c962c8
--- /dev/null
+++ b/src/lib/eina/eina_evlog.c
@@ -0,0 +1,220 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include "Eina.h"
6#include "eina_evlog.h"
7#include "eina_debug.h"
8
9#ifdef EINA_HAVE_DEBUG
10
11# ifdef HAVE_MMAP
12# include <sys/mman.h>
13# endif
14
15# define EVLOG_BUF_SIZE (4 * (1024 * 1024))
16
17static Eina_Spinlock _evlog_lock;
18static int _evlog_go = 0;
19
20static Eina_Evlog_Buf *buf; // current event log we are writing events to
21static Eina_Evlog_Buf buffers[2]; // double-buffer our event log buffers
22
23static inline double
24get_time(void)
25{
26 struct timeval timev;
27 gettimeofday(&timev, NULL);
28 return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000.0);
29}
30
31static void
32alloc_buf(Eina_Evlog_Buf *b, unsigned int size)
33{
34 if (b->buf) return;
35 b->size = size;
36 b->top = 0;
37# ifdef HAVE_MMAP
38 b->buf = mmap(NULL, size, PROT_READ | PROT_WRITE,
39 MAP_PRIVATE | MAP_ANON, -1, 0);
40 if (b->buf == MAP_FAILED) b->buf = NULL;
41# else
42 b->buf = malloc(size);
43# endif
44 b->overflow = 0;
45 b->stolen = 0;
46}
47
48static void
49free_buf(Eina_Evlog_Buf *b)
50{
51 if (!b->buf) return;
52 b->size = 0;
53 b->top = 0;
54# ifdef HAVE_MMAP
55 munmap(b->buf, b->size);
56# else
57 free(b->buf);
58# endif
59 b->buf = NULL;
60}
61
62static inline void *
63push_buf(Eina_Evlog_Buf *b, unsigned int size)
64{
65 void *ptr;
66
67 if (b->size < size) abort();
68 if ((b->top + size) > (b->size))
69 {
70 b->overflow++;
71 b->top = 0;
72 }
73 ptr = (b->buf + b->top);
74 b->top += size;
75 return ptr;
76}
77
78EAPI void
79eina_evlog(const char *event, void *obj, double srctime, const char *detail)
80{
81 Eina_Evlog_Item *item;
82 int size;
83 char *strings;
84 double now = get_time();
85 unsigned short detail_offset = 0;
86 unsigned short event_size;
87
88 eina_spinlock_take(&_evlog_lock);
89 if (!_evlog_go)
90 {
91 eina_spinlock_release(&_evlog_lock);
92 return;
93 }
94 size = sizeof(Eina_Evlog_Item);
95 event_size = strlen(event) + 1;
96 size += event_size;
97 if (detail)
98 {
99 detail_offset = size;
100 size += strlen(detail) + 1;
101 }
102 size = sizeof(double) * ((size + sizeof(double) - 1) / sizeof(double));
103
104 strings = push_buf(buf, size);
105 item = (Eina_Evlog_Item *)strings;
106 item->tim = now;
107 item->srctim = srctime;
108 item->thread = (unsigned long long)pthread_self();
109 item->obj = (unsigned long long)obj;
110 item->event_offset = sizeof(Eina_Evlog_Item);
111 item->detail_offset = detail_offset;
112 item->event_next = size;
113
114 strcpy(strings + sizeof(Eina_Evlog_Item), event);
115 if (detail_offset > 0) strcpy(strings + detail_offset, detail);
116
117 eina_spinlock_release(&_evlog_lock);
118}
119
120EAPI Eina_Evlog_Buf *
121eina_evlog_steal(void)
122{
123 Eina_Evlog_Buf *stolen = NULL;
124
125 eina_spinlock_take(&_evlog_lock);
126 if (buf == &(buffers[0]))
127 {
128 buf = &(buffers[1]);
129 buf->top = 0;
130 stolen = &(buffers[0]);
131 stolen->stolen++;
132 }
133 else
134 {
135 buf = &(buffers[0]);
136 buf->top = 0;
137 stolen = &(buffers[1]);
138 stolen->stolen++;
139 }
140 eina_spinlock_release(&_evlog_lock);
141 return stolen;
142}
143
144EAPI void
145eina_evlog_start(void)
146{
147 eina_spinlock_take(&_evlog_lock);
148 _evlog_go++;
149 if (_evlog_go == 1)
150 {
151 // alloc 2 buffers for spinning around in
152 alloc_buf(&(buffers[0]), EVLOG_BUF_SIZE);
153 alloc_buf(&(buffers[1]), EVLOG_BUF_SIZE);
154 }
155 eina_spinlock_release(&_evlog_lock);
156}
157
158EAPI void
159eina_evlog_stop(void)
160{
161 eina_spinlock_take(&_evlog_lock);
162 _evlog_go--;
163 if (_evlog_go == 0)
164 {
165 free_buf(&(buffers[0]));
166 free_buf(&(buffers[1]));
167 }
168 eina_spinlock_release(&_evlog_lock);
169}
170
171Eina_Bool
172eina_evlog_init(void)
173{
174 eina_spinlock_new(&_evlog_lock);
175 buf = &(buffers[0]);
176 eina_evlog("+eina_init", NULL, 0.0, NULL);
177 return EINA_TRUE;
178}
179
180Eina_Bool
181eina_evlog_shutdown(void)
182{
183 // yes - we don't free tyhe evlog buffers. they may be in used by debug th
184 eina_spinlock_free(&_evlog_lock);
185 return EINA_TRUE;
186}
187#else
188EAPI void
189eina_evlog(const char *event EINA_UNUSED, void *obj EINA_UNUSED, double srctime EINA_UNUSED, const char *detail EINA_UNUSED)
190{
191}
192
193EAPI Eina_Evlog_Buf *
194eina_evlog_steal(void)
195{
196 return NULL;
197}
198
199EAPI void
200eina_evlog_start(void)
201{
202}
203
204EAPI void
205eina_evlog_stop(void)
206{
207}
208
209Eina_Bool
210eina_evlog_init(void)
211{
212 return EINA_TRUE;
213}
214
215Eina_Bool
216eina_evlog_shutdown(void)
217{
218 return EINA_TRUE;
219}
220#endif
diff --git a/src/lib/eina/eina_evlog.h b/src/lib/eina/eina_evlog.h
new file mode 100644
index 0000000000..82a8dd6138
--- /dev/null
+++ b/src/lib/eina/eina_evlog.h
@@ -0,0 +1,121 @@
1#ifndef EINA_EVLOG_H_
2#define EINA_EVLOG_H_
3
4/**
5 * @addtogroup Eina_Evlog Event Log Debugging
6 * @ingroup Eina
7 *
8 * @brief These functions are use internally by EFL in general for profiling
9 *
10 * @{
11 *
12 * @since 1.15
13 */
14
15typedef struct _Eina_Evlog_Item Eina_Evlog_Item;
16typedef struct _Eina_Evlog_Buf Eina_Evlog_Buf;
17
18struct _Eina_Evlog_Item
19{
20 double tim; // the time when this event happened
21 double srctim; // if > 0.0, then this is the src event time causing this
22 unsigned long long thread; // a thread handle/id where this log happened
23 unsigned long long obj; // an object associated with this event (anything)
24 unsigned short event_offset; // must be provided - mem pos after item
25 unsigned short detail_offset; // if not provided, 0, otherwise mem pos
26 unsigned short event_next; // mem offset in bytes for next event;
27};
28
29struct _Eina_Evlog_Buf
30{
31 unsigned char *buf; // current buffer we fill with event logs
32 unsigned int size; // the max size of the evlog buffer
33 unsigned int top; // the current top byte for a new evlog item
34 unsigned int overflow; // how many times this biffer has overflown
35 unsigned int stolen; // how many times this buffer has been stolen
36};
37
38/**
39 * @brief Log an event in our event log for profiling data
40 *
41 * Log some interesting event inside of EFL, eg a wakeup (and why etc.).
42 * The @p event string must alwasy be provided and be of the form:
43 *
44 * "+eventname"
45 * "-eventname"
46 * "!eventname"
47 *
48 * etc. The "+" char means an event is beginning (and any subsequent
49 * events logged are really children of this event). The "-" char means an
50 * event is ending and so all child events SHOULD have ended by now. A "!"
51 * character means the event is a one-off with no beginning or end. Any string
52 * following this initial character is the eventy name (and must be provided
53 * in the exact same string at both + and - events). This is what will be
54 * displayed in a debugger (and may be a well known string thus given a nice
55 * UI flourish with icons, labels and colors, so don't change this string
56 * unless you want to impact such visibility of these events). The event
57 * string after the first character as above can be anything, including white
58 * space. It is suggested to keep it human readable and as short as feasible.
59 *
60 * The @p object is optional, and if not used, pass in NULL. If it is used,
61 * it can be a pointer to anything. It is intended simply to be of use to
62 * indicate an event happens on object A vs object B. What this points to
63 * is irrelevant as the pointer is never de-references or used other than
64 * as a label to differentiate an event on 2 different objects.
65 *
66 * The @p srctime parameter is 0.0 if not used, or if used, contains a
67 * timepoint for an event that triggered this one. For example, if a device
68 * or hardware interrupt causes this event, that device may provide a
69 * timestamp/timepoint as part of the device information to indicate the
70 * exact time the hardware interrupt happened. This can be useful to have
71 * more information as to the latency of an actual source of an event such
72 * as the hardware interrupt time, and when the code actually begins seeing
73 * or processing it.
74 *
75 * The @p detail string is optional (and if unused should be NULL). This is
76 * for providing more detailed information to log such as perhaps a the
77 * state at the time of the log events or a series of parameters and input
78 * that caused this event.
79 *
80 * @param event The event string - see above for format
81 * @param obj An optional object "pointer" to associate
82 * @param srctime An optional source event timestamp that caused this event
83 * @param detail An optional event detail string with more info
84 *
85 * @since 1.15
86 */
87EAPI void
88eina_evlog(const char *event, void *obj, double srctime, const char *detail);
89
90/**
91 * @brief Steal an event log buffer from the evlog core
92 *
93 * Only one buffer can be stolen at any time. If you steal a new buffer, the
94 * old stolen buffer is "released" back to the evlog core.
95 *
96 * @return The stolen evlog buffer
97 *
98 * @since 1.15
99 */
100EAPI Eina_Evlog_Buf *
101eina_evlog_steal(void);
102
103/**
104 * @brief Begin logging - until now eina_evlog is a NOOP
105 */
106EAPI void
107eina_evlog_start(void);
108
109/**
110 * @brief Stop logging
111 *
112 * You must not be using any evlog buffers stolen by eina_evlog_steal() by
113 * the time you call this function.
114 */
115EAPI void
116eina_evlog_stop(void);
117
118/**
119 * @}
120 */
121#endif
diff --git a/src/lib/eina/eina_main.c b/src/lib/eina/eina_main.c
index 358c3a4bfb..1daa795e87 100644
--- a/src/lib/eina/eina_main.c
+++ b/src/lib/eina/eina_main.c
@@ -67,6 +67,7 @@
67#include "eina_inlist.h" 67#include "eina_inlist.h"
68#include "eina_inarray.h" 68#include "eina_inarray.h"
69#include "eina_value.h" 69#include "eina_value.h"
70#include "eina_evlog.h"
70/* no model for now 71/* no model for now
71#include "eina_model.h" 72#include "eina_model.h"
72 */ 73 */
@@ -121,6 +122,7 @@ EAPI Eina_Inlist *_eina_tracking = NULL;
121#define S(x) extern Eina_Bool eina_ ## x ## _init(void); \ 122#define S(x) extern Eina_Bool eina_ ## x ## _init(void); \
122 extern Eina_Bool eina_ ## x ## _shutdown(void) 123 extern Eina_Bool eina_ ## x ## _shutdown(void)
123 S(debug); 124 S(debug);
125 S(evlog);
124 S(log); 126 S(log);
125 S(error); 127 S(error);
126 S(safety_checks); 128 S(safety_checks);
@@ -167,6 +169,7 @@ static const struct eina_desc_setup _eina_desc_setup[] = {
167#define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown} 169#define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown}
168 /* log is a special case as it needs printf */ 170 /* log is a special case as it needs printf */
169 S(debug), 171 S(debug),
172 S(evlog),
170 S(stringshare), 173 S(stringshare),
171 S(error), 174 S(error),
172 S(safety_checks), 175 S(safety_checks),
@@ -299,6 +302,7 @@ eina_init(void)
299 eina_log_timing(_eina_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT); 302 eina_log_timing(_eina_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT);
300 303
301 _eina_main_count = 1; 304 _eina_main_count = 1;
305 eina_evlog("-eina_init", NULL, 0.0, NULL);
302 return 1; 306 return 1;
303} 307}
304 308