static Eina_Semaphore _wait_for_bts_sem;
-// _bt_buf[0] is always for mainloop, 1 + is for extra threads
static void ***_bt_buf;
static int *_bt_buf_len;
static struct timespec *_bt_ts;
static int *_bt_cpu;
+static int _bt_threads_nb;
/* Used by trace timer */
static double _trace_t0 = 0.0;
+static Eina_Debug_Timer *_timer = NULL;
static int _prof_get_op = EINA_DEBUG_OPCODE_INVALID;
{
file = NULL;
offset = base = 0;
- // we have little choice but to hgope/assume dladdr() doesn't alloc
+ // we have little choice but to hope/assume dladdr() doesn't alloc
// anything here
if ((dladdr(bt[i], &info)) && (info.dli_fname[0]))
{
return total;
}
-// this signal handler is called inside each and every thread when the
-// thread gets a signal via pthread_kill(). this causes the thread to
-// stop here inside this handler and "do something" then when this returns
-// resume whatever it was doing like any signal handler
-static void
-_eina_debug_signal(int sig EINA_UNUSED,
- siginfo_t *si EINA_UNUSED,
- void *foo EINA_UNUSED)
-{
- int i, slot = 0;
- pthread_t self = pthread_self();
- clockid_t cid;
-
- // find which slot in the array of threads we have so we store info
- // in the correct slot for us
- if (self != _eina_debug_thread_mainloop)
- {
- for (i = 0; i < _eina_debug_thread_active_num; i++)
- {
- if (self == _eina_debug_thread_active[i].thread)
- {
- slot = i + 1;
- goto found;
- }
- }
- // we couldn't find out thread reference! help!
- e_debug("EINA DEBUG ERROR: can't find thread slot!");
- eina_semaphore_release(&_wait_for_bts_sem, 1);
- return;
- }
-found:
- // store thread info like what cpu core we are on now (not reliable
- // but hey - better than nothing), the amount of cpu time total
- // we have consumed (it's cumulative so subtracing deltas can give
- // you an average amount of cpu time consumed between now and the
- // previous time we looked) and also a full backtrace
- _bt_cpu[slot] = sched_getcpu();
- pthread_getcpuclockid(self, &cid);
- clock_gettime(cid, &(_bt_ts[slot]));
- _bt_buf_len[slot] = _eina_debug_unwind_bt(_bt_buf[slot], EINA_MAX_BT);
- // now wake up the monitor to let them know we are done collecting our
- // backtrace info
- eina_semaphore_release(&_wait_for_bts_sem, 1);
-}
-
-
// a quick and dirty local time point getter func - not portable
static inline double
get_time(void)
#endif
}
-static void
-_eina_debug_collect_bt(pthread_t pth EINA_UNUSED)
+static Eina_Debug_Error
+_prof_get_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
{
- // this async signals the thread to switch to the deebug signal handler
- // and collect a backtrace and other info from inside the thread
- //pthread_kill(pth, SIG);
+ clockid_t cid;
+ int slot = eina_debug_thread_id_get();
+ if (slot >= _bt_threads_nb) return EINA_DEBUG_OK;
+ _bt_cpu[slot] = sched_getcpu();
+ pthread_getcpuclockid(pthread_self(), &cid);
+ clock_gettime(cid, &(_bt_ts[slot]));
+ _bt_buf_len[slot] = _eina_debug_unwind_bt(_bt_buf[slot], EINA_MAX_BT);
+ return EINA_DEBUG_OK;
}
static Eina_Bool
_trace_cb(void *data)
{
static Eina_Debug_Packet_Header *hdr = NULL;
+ static int bts = 0;
+ int i;
if (!hdr)
{
hdr->opcode = _prof_get_op;
}
- eina_debug_dispatch(data, (void *)hdr);
- return EINA_TRUE;
-}
-
-static Eina_Debug_Error
-_prof_get_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
-{
- static int bts = 0;
- int i;
if (!_trace_t0) _trace_t0 = get_time();
- // take a lock on grabbing thread debug info like backtraces
- eina_spinlock_take(&_eina_debug_thread_lock);
+
+ _bt_threads_nb = _eina_debug_thread_active_num;
// reset our "stack" of memory se use to dump thread info into
_eina_debug_chunk_tmp_reset();
// get an array of pointers for the backtrace array for main + th
- _bt_buf = _eina_debug_chunk_tmp_push
- ((1 + _eina_debug_thread_active_num) * sizeof(void *));
+ _bt_buf = _eina_debug_chunk_tmp_push(_bt_threads_nb * sizeof(void *));
if (!_bt_buf) goto err;
// get an array of pointers for the timespec array for mainloop + th
- _bt_ts = _eina_debug_chunk_tmp_push
- ((1 + _eina_debug_thread_active_num) * sizeof(struct timespec));
+ _bt_ts = _eina_debug_chunk_tmp_push(_bt_threads_nb * sizeof(struct timespec));
if (!_bt_ts) goto err;
// get an array of pointers for the cpuid array for mainloop + th
- _bt_cpu = _eina_debug_chunk_tmp_push
- ((1 + _eina_debug_thread_active_num) * sizeof(int));
+ _bt_cpu = _eina_debug_chunk_tmp_push(_bt_threads_nb * sizeof(int));
if (!_bt_cpu) goto err;
- // now get an array of void pts for mainloop bt
- _bt_buf[0] = _eina_debug_chunk_tmp_push(EINA_MAX_BT * sizeof(void *));
- if (!_bt_buf[0]) goto err;
// get an array of void ptrs for each thread we know about for bt
- for (i = 0; i < _eina_debug_thread_active_num; i++)
+ for (i = 0; i < _bt_threads_nb; i++)
{
- _bt_buf[i + 1] = _eina_debug_chunk_tmp_push(EINA_MAX_BT * sizeof(void *));
- if (!_bt_buf[i + 1]) goto err;
+ _bt_buf[i] = _eina_debug_chunk_tmp_push(EINA_MAX_BT * sizeof(void *));
+ if (!_bt_buf[i]) goto err;
}
// get an array of ints to stor the bt len for mainloop + threads
- _bt_buf_len = _eina_debug_chunk_tmp_push
- ((1 + _eina_debug_thread_active_num) * sizeof(int));
- // collect bt from the mainloop - always there
- _eina_debug_collect_bt(_eina_debug_thread_mainloop);
+ _bt_buf_len = _eina_debug_chunk_tmp_push(_bt_threads_nb * sizeof(int));
+
// now collect per thread
- for (i = 0; i < _eina_debug_thread_active_num; i++)
- _eina_debug_collect_bt(_eina_debug_thread_active[i].thread);
- // we're done probing. now collec all the "i'm done" msgs on the
- // semaphore for every thread + mainloop
- for (i = 0; i < (_eina_debug_thread_active_num + 1); i++)
- eina_semaphore_lock(&_wait_for_bts_sem);
- // we now have gotten all the data from all threadd + mainloop.
+ eina_debug_dispatch(data, (void *)hdr);
+
+ // we now have gotten all the data from all threads
// we can process it now as we see fit, so release thread lock
- //// XXX: some debug so we can see the bt's we collect - will go
- // for (i = 0; i < (_eina_debug_thread_active_num + 1); i++)
- // {
- // _eina_debug_dump_fhandle_bt(stderr, _bt_buf[i], _bt_buf_len[i]);
- // }
+ for (i = 0; i < _eina_debug_thread_active_num; i++)
+ {
+ _eina_debug_dump_fhandle_bt(stderr, _bt_buf[i], _bt_buf_len[i]);
+ }
err:
- eina_spinlock_release(&_eina_debug_thread_lock);
//// XXX: some debug just to see how well we perform - will go
bts++;
if (bts >= 10000)
_trace_t0 = t;
bts = 0;
}
- return EINA_DEBUG_OK;
+ return EINA_TRUE;
}
// profiling on with poll time gap as uint payload
{
memcpy(&time, buffer, 4);
_trace_t0 = 0.0;
- eina_debug_timer_add(time, _trace_cb, session);
+ _timer = eina_debug_timer_add(time, _trace_cb, session);
}
return EINA_DEBUG_OK;
}
static Eina_Debug_Error
_prof_off_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
{
- eina_debug_timer_add(0, NULL, NULL);
+ eina_debug_timer_del(_timer);
+ _timer = NULL;
return EINA_DEBUG_OK;
}