forked from enlightenment/efl
Remove thread management
The handling to forward requests is let to the callbacks.
This commit is contained in:
parent
67391a6684
commit
253d3ffe44
|
@ -49,7 +49,7 @@ static int _cid = 0;
|
|||
static int my_argc = 0;
|
||||
static char **my_argv = NULL;
|
||||
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_evlog_get_cb(Eina_Debug_Session *session EINA_UNUSED, int src EINA_UNUSED, void *buffer, int size)
|
||||
{
|
||||
static int received_times = 0;
|
||||
|
@ -81,7 +81,7 @@ _evlog_get_cb(Eina_Debug_Session *session EINA_UNUSED, int src EINA_UNUSED, void
|
|||
ecore_main_loop_quit();
|
||||
}
|
||||
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
|
@ -103,7 +103,7 @@ _cb_evlog(void *data EINA_UNUSED)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_cid_get_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
||||
{
|
||||
_cid = *(int *)buffer;
|
||||
|
@ -143,10 +143,10 @@ _cid_get_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *
|
|||
if(quit)
|
||||
ecore_main_loop_quit();
|
||||
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_clients_info_added_cb(Eina_Debug_Session *session EINA_UNUSED, int src EINA_UNUSED, void *buffer, int size)
|
||||
{
|
||||
char *buf = buffer;
|
||||
|
@ -162,10 +162,10 @@ _clients_info_added_cb(Eina_Debug_Session *session EINA_UNUSED, int src EINA_UNU
|
|||
buf += len;
|
||||
size -= (2 * sizeof(int) + len);
|
||||
}
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_clients_info_deleted_cb(Eina_Debug_Session *session EINA_UNUSED, int src EINA_UNUSED, void *buffer, int size)
|
||||
{
|
||||
char *buf = buffer;
|
||||
|
@ -191,7 +191,7 @@ _clients_info_deleted_cb(Eina_Debug_Session *session EINA_UNUSED, int src EINA_U
|
|||
else
|
||||
printf("Deleted: CID: %d\n", cid);
|
||||
}
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -200,11 +200,11 @@ _ecore_thread_dispatcher(void *data)
|
|||
eina_debug_dispatch(_session, data);
|
||||
}
|
||||
|
||||
Eina_Debug_Error
|
||||
Eina_Bool
|
||||
_disp_cb(Eina_Debug_Session *session EINA_UNUSED, void *buffer)
|
||||
{
|
||||
ecore_main_loop_thread_safe_call_async(_ecore_thread_dispatcher, buffer);
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -123,7 +123,6 @@ _send(Client *dest, int opcode, void *payload, int payload_size)
|
|||
Eina_Debug_Packet_Header *hdr = (Eina_Debug_Packet_Header *)buf;
|
||||
hdr->size = size;
|
||||
hdr->cid = 0;
|
||||
hdr->thread_id = 0;
|
||||
hdr->opcode = opcode;
|
||||
memcpy(buf + sizeof(Eina_Debug_Packet_Header), payload, payload_size);
|
||||
printf("Send packet (size = %d, opcode %s) to %s\n", size,
|
||||
|
|
|
@ -56,8 +56,6 @@
|
|||
# define LIBEXT ".so"
|
||||
#endif
|
||||
|
||||
#define SIG SIGPROF
|
||||
|
||||
// yes - a global debug spinlock. i expect contention to be low for now, and
|
||||
// when needed we can split this up into mroe locks to reduce contention when
|
||||
// and if that day comes
|
||||
|
@ -82,13 +80,6 @@ static Eina_Bool _debug_disabled = EINA_FALSE;
|
|||
/* __thread here to allow debuggers to be master and slave by using two different threads */
|
||||
static Eina_Debug_Session *_last_local_session = NULL;
|
||||
|
||||
/* Semaphore used by the debug thread to wait for another thread to do the
|
||||
* requested job.
|
||||
* It is needed when packets are needed to be treated into a specific
|
||||
* thread.
|
||||
*/
|
||||
static Eina_Semaphore _thread_cmd_ready_sem;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const Eina_Debug_Opcode *ops;
|
||||
|
@ -110,7 +101,7 @@ static void _opcodes_register_all(Eina_Debug_Session *session);
|
|||
static void _thread_start(Eina_Debug_Session *session);
|
||||
|
||||
EAPI int
|
||||
eina_debug_session_send_to_thread(Eina_Debug_Session *session, int dest_id, int thread_id, int op, void *data, int size)
|
||||
eina_debug_session_send(Eina_Debug_Session *session, int dest, int op, void *data, int size)
|
||||
{
|
||||
Eina_Debug_Packet_Header hdr;
|
||||
|
||||
|
@ -119,8 +110,7 @@ eina_debug_session_send_to_thread(Eina_Debug_Session *session, int dest_id, int
|
|||
/* Preparation of the packet header */
|
||||
hdr.size = size + sizeof(Eina_Debug_Packet_Header);
|
||||
hdr.opcode = op;
|
||||
hdr.cid = dest_id;
|
||||
hdr.thread_id = thread_id;
|
||||
hdr.cid = dest;
|
||||
e_debug("socket: %d / opcode %X / bytes to send: %d",
|
||||
session->fd, op, hdr.size);
|
||||
#ifndef _WIN32
|
||||
|
@ -134,12 +124,6 @@ eina_debug_session_send_to_thread(Eina_Debug_Session *session, int dest_id, int
|
|||
return hdr.size;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
eina_debug_session_send(Eina_Debug_Session *session, int dest, int op, void *data, int size)
|
||||
{
|
||||
return eina_debug_session_send_to_thread(session, dest, 0, op, data, size);
|
||||
}
|
||||
|
||||
static void
|
||||
_daemon_greet(Eina_Debug_Session *session)
|
||||
{
|
||||
|
@ -274,7 +258,7 @@ _static_opcode_register(Eina_Debug_Session *session,
|
|||
* Response of the daemon containing the ids of the requested opcodes.
|
||||
* PTR64 + (opcode id)*
|
||||
*/
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_callbacks_register_cb(Eina_Debug_Session *session, int src_id EINA_UNUSED, void *buffer, int size)
|
||||
{
|
||||
_opcode_reply_info *info = NULL, *info2;
|
||||
|
@ -286,7 +270,7 @@ _callbacks_register_cb(Eina_Debug_Session *session, int src_id EINA_UNUSED, void
|
|||
memcpy(&info_64, buffer, sizeof(uint64_t));
|
||||
info = (_opcode_reply_info *)info_64;
|
||||
|
||||
if (!info) return EINA_DEBUG_ERROR;
|
||||
if (!info) return EINA_FALSE;
|
||||
EINA_LIST_FOREACH(session->opcode_reply_infos, itr, info2)
|
||||
{
|
||||
if (info2 == info)
|
||||
|
@ -301,11 +285,11 @@ _callbacks_register_cb(Eina_Debug_Session *session, int src_id EINA_UNUSED, void
|
|||
e_debug("Opcode %s -> %d", info->ops[i].opcode_name, os[i]);
|
||||
}
|
||||
if (info->status_cb) info->status_cb(info->status_data, EINA_TRUE);
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return EINA_DEBUG_ERROR;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -520,7 +504,7 @@ _monitor(void *_data)
|
|||
// if not negative - we have a real message
|
||||
if (size > 0)
|
||||
{
|
||||
if (EINA_DEBUG_OK != session->dispatch_cb(session, buffer))
|
||||
if (EINA_TRUE != session->dispatch_cb(session, buffer))
|
||||
{
|
||||
// something we don't understand
|
||||
e_debug("EINA DEBUG ERROR: Unknown command");
|
||||
|
@ -600,8 +584,8 @@ eina_debug_opcodes_register(Eina_Debug_Session *session, const Eina_Debug_Opcode
|
|||
_opcodes_registration_send(session, info);
|
||||
}
|
||||
|
||||
static Eina_Debug_Error
|
||||
_self_dispatch(Eina_Debug_Session *session, void *buffer)
|
||||
EAPI Eina_Bool
|
||||
eina_debug_dispatch(Eina_Debug_Session *session, void *buffer)
|
||||
{
|
||||
Eina_Debug_Packet_Header *hdr = buffer;
|
||||
Eina_List *itr;
|
||||
|
@ -611,83 +595,18 @@ _self_dispatch(Eina_Debug_Session *session, void *buffer)
|
|||
if (opcode >= session->cbs_length)
|
||||
{
|
||||
e_debug("Invalid opcode %d", opcode);
|
||||
return EINA_DEBUG_ERROR;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EINA_LIST_FOREACH(session->cbs[opcode], itr, cb)
|
||||
{
|
||||
if (!cb) continue;
|
||||
Eina_Debug_Error ret = cb(session, hdr->cid,
|
||||
Eina_Bool ret = cb(session, hdr->cid,
|
||||
(unsigned char *)buffer + sizeof(*hdr),
|
||||
hdr->size - sizeof(*hdr));
|
||||
if (ret == EINA_DEBUG_ERROR) return ret;
|
||||
if (ret == EINA_FALSE) return ret;
|
||||
}
|
||||
return EINA_DEBUG_OK;
|
||||
}
|
||||
|
||||
EAPI Eina_Debug_Error
|
||||
eina_debug_dispatch(Eina_Debug_Session *session, void *buffer)
|
||||
{
|
||||
Eina_Debug_Packet_Header *hdr = buffer;
|
||||
Eina_Debug_Error ret = EINA_DEBUG_OK;
|
||||
if (hdr->thread_id == 0) return _self_dispatch(session, buffer);
|
||||
else
|
||||
{
|
||||
int i, nb_calls = 0;
|
||||
eina_spinlock_take(&_eina_debug_thread_lock);
|
||||
for (i = 0; i < _eina_debug_thread_active_num; i++)
|
||||
{
|
||||
_eina_debug_thread_active[i].cmd_buffer = NULL;
|
||||
if (hdr->thread_id == (int)0xFFFFFFFF ||
|
||||
hdr->thread_id == _eina_debug_thread_active[i].thread_id)
|
||||
{
|
||||
_eina_debug_thread_active[i].cmd_session = session;
|
||||
_eina_debug_thread_active[i].cmd_buffer = buffer;
|
||||
_eina_debug_thread_active[i].cmd_result = EINA_DEBUG_OK;
|
||||
if (!pthread_kill(_eina_debug_thread_active[i].thread, SIG))
|
||||
nb_calls++;
|
||||
}
|
||||
}
|
||||
eina_spinlock_release(&_eina_debug_thread_lock);
|
||||
while (nb_calls)
|
||||
{
|
||||
while (nb_calls)
|
||||
{
|
||||
eina_semaphore_lock(&_thread_cmd_ready_sem);
|
||||
nb_calls--;
|
||||
}
|
||||
eina_spinlock_take(&_eina_debug_thread_lock);
|
||||
for (i = 0; i < _eina_debug_thread_active_num; i++)
|
||||
{
|
||||
if (_eina_debug_thread_active[i].cmd_buffer)
|
||||
{
|
||||
switch (_eina_debug_thread_active[i].cmd_result)
|
||||
{
|
||||
case EINA_DEBUG_OK:
|
||||
{
|
||||
_eina_debug_thread_active[i].cmd_buffer = NULL;
|
||||
break;
|
||||
}
|
||||
case EINA_DEBUG_ERROR:
|
||||
{
|
||||
_eina_debug_thread_active[i].cmd_buffer = NULL;
|
||||
ret = EINA_DEBUG_ERROR;
|
||||
break;
|
||||
}
|
||||
case EINA_DEBUG_AGAIN:
|
||||
{
|
||||
if (!pthread_kill(_eina_debug_thread_active[i].thread, SIG))
|
||||
nb_calls++;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
eina_spinlock_release(&_eina_debug_thread_lock);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
@ -703,51 +622,6 @@ eina_debug_session_data_get(Eina_Debug_Session *session)
|
|||
else return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_signal_handler(int sig EINA_UNUSED,
|
||||
siginfo_t *si EINA_UNUSED, void *foo EINA_UNUSED)
|
||||
{
|
||||
int i, slot = -1;
|
||||
pthread_t self = pthread_self();
|
||||
eina_spinlock_take(&_eina_debug_thread_lock);
|
||||
for (i = 0; i < _eina_debug_thread_active_num; i++)
|
||||
{
|
||||
if (self == _eina_debug_thread_active[i].thread)
|
||||
{
|
||||
slot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
eina_spinlock_release(&_eina_debug_thread_lock);
|
||||
if (slot != -1)
|
||||
{
|
||||
_eina_debug_thread_active[slot].cmd_result =
|
||||
_self_dispatch(_eina_debug_thread_active[slot].cmd_session,
|
||||
_eina_debug_thread_active[slot].cmd_buffer);
|
||||
}
|
||||
eina_semaphore_release(&_thread_cmd_ready_sem, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
_signal_init(void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
// set up signal handler for our profiling signal - eevery thread should
|
||||
// obey this (this is the case on linux - other OSs may vary)
|
||||
sa.sa_sigaction = _signal_handler;
|
||||
sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
if (sigaction(SIG, &sa, NULL) != 0)
|
||||
e_debug("EINA DEBUG ERROR: Can't set up sig %i handler!", SIG);
|
||||
|
||||
sa.sa_sigaction = NULL;
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
if (sigaction(SIGPIPE, &sa, 0) == -1) perror(0);
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
eina_debug_init(void)
|
||||
{
|
||||
|
@ -783,8 +657,6 @@ eina_debug_init(void)
|
|||
{
|
||||
eina_debug_local_connect(EINA_FALSE);
|
||||
}
|
||||
eina_semaphore_new(&_thread_cmd_ready_sem, 0);
|
||||
_signal_init();
|
||||
_eina_debug_cpu_init();
|
||||
_eina_debug_bt_init();
|
||||
_eina_debug_timer_init();
|
||||
|
@ -797,7 +669,6 @@ eina_debug_shutdown(void)
|
|||
_eina_debug_timer_shutdown();
|
||||
_eina_debug_bt_shutdown();
|
||||
_eina_debug_cpu_shutdown();
|
||||
eina_semaphore_free(&_thread_cmd_ready_sem);
|
||||
eina_spinlock_take(&_eina_debug_thread_lock);
|
||||
// yes - we never free on shutdown - this is because the monitor thread
|
||||
// never exits. this is not a leak - we intend to never free up any
|
||||
|
|
|
@ -33,14 +33,6 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
/** Used as a return value for callbacks invoked by the dispatcher */
|
||||
typedef enum
|
||||
{
|
||||
EINA_DEBUG_OK, /**< Success */
|
||||
EINA_DEBUG_ERROR, /**< Error in packet - will close the connection */
|
||||
EINA_DEBUG_AGAIN /**< Recall the callback - may due to resources unavailability at the invocation time */
|
||||
} Eina_Debug_Error;
|
||||
|
||||
enum
|
||||
{
|
||||
EINA_DEBUG_OPCODE_INVALID = -1, /**< Invalid opcode value */
|
||||
|
@ -66,8 +58,10 @@ typedef struct _Eina_Debug_Session Eina_Debug_Session;
|
|||
* @param srcid the source id
|
||||
* @param buffer the packet payload data. It doesn't contain any transport information.
|
||||
* @param size the packet payload size
|
||||
*
|
||||
* return true on success, false if the connection seems compromised
|
||||
*/
|
||||
typedef Eina_Debug_Error (*Eina_Debug_Cb)(Eina_Debug_Session *session, int srcid, void *buffer, int size);
|
||||
typedef Eina_Bool (*Eina_Debug_Cb)(Eina_Debug_Session *session, int srcid, void *buffer, int size);
|
||||
|
||||
/**
|
||||
* @typedef Eina_Debug_Opcode_Status_Cb
|
||||
|
@ -94,8 +88,10 @@ typedef void (*Eina_Debug_Opcode_Status_Cb)(void *data, Eina_Bool status);
|
|||
* @param buffer the packet received
|
||||
*
|
||||
* The given packet is the entire data received, including the header.
|
||||
*
|
||||
* return the return result of the invoked callback
|
||||
*/
|
||||
typedef Eina_Debug_Error (*Eina_Debug_Dispatch_Cb)(Eina_Debug_Session *session, void *buffer);
|
||||
typedef Eina_Bool (*Eina_Debug_Dispatch_Cb)(Eina_Debug_Session *session, void *buffer);
|
||||
|
||||
/**
|
||||
* @typedef Eina_Debug_Timer_Cb
|
||||
|
@ -122,7 +118,6 @@ typedef struct
|
|||
* The daemon is in charge of swapping the id before forwarding the packet to the destination.
|
||||
*/
|
||||
int cid;
|
||||
int thread_id;
|
||||
int opcode; /**< Opcode of the packet */
|
||||
} Eina_Debug_Packet_Header;
|
||||
|
||||
|
@ -207,9 +202,9 @@ EAPI Eina_Debug_Dispatch_Cb eina_debug_session_dispatch_get(Eina_Debug_Session *
|
|||
* @param session the session
|
||||
* @param buffer the packet
|
||||
*
|
||||
* @return EINA_DEBUG_OK on success, EINA_DEBUG_ERROR if the packet is not as expected.
|
||||
* return true on success, false if the connection seems compromised
|
||||
*/
|
||||
EAPI Eina_Debug_Error eina_debug_dispatch(Eina_Debug_Session *session, void *buffer);
|
||||
EAPI Eina_Bool eina_debug_dispatch(Eina_Debug_Session *session, void *buffer);
|
||||
|
||||
/**
|
||||
* @brief Set data to a session
|
||||
|
@ -262,24 +257,6 @@ EAPI void eina_debug_opcodes_register(Eina_Debug_Session *session,
|
|||
*/
|
||||
EAPI int eina_debug_session_send(Eina_Debug_Session *session, int dest_id, int op, void *data, int size);
|
||||
|
||||
/**
|
||||
* @brief Send a packet to the given thread of the given destination
|
||||
*
|
||||
* If the thread is 0x0, the packet will be treated by the debug thread itself.
|
||||
* If the thread is 0xFF..FF, the packet will be broadcasted to all the threads.
|
||||
* Otherwise, the packet will be treated by the specific thread.
|
||||
*
|
||||
* @param session the session to use to send the packet
|
||||
* @param dest_id the destination id to send the packet to
|
||||
* @param thread_id the thread to send the packet to.
|
||||
* @param op the opcode for this packet
|
||||
* @param data payload to send
|
||||
* @param size payload size
|
||||
*
|
||||
* @return the number of sent bytes
|
||||
*/
|
||||
EAPI int eina_debug_session_send_to_thread(Eina_Debug_Session *session, int dest_id, int thread_id, int op, void *data, int size);
|
||||
|
||||
/**
|
||||
* @brief Add a timer
|
||||
*
|
||||
|
@ -301,14 +278,6 @@ EAPI Eina_Debug_Timer *eina_debug_timer_add(unsigned int timeout_ms, Eina_Debug_
|
|||
*/
|
||||
EAPI void eina_debug_timer_del(Eina_Debug_Timer *timer);
|
||||
|
||||
/**
|
||||
* @brief Get an id of the current thread
|
||||
*
|
||||
* This id corresponds to the index in the Eina threads table where the thread
|
||||
* information is stored.
|
||||
*/
|
||||
EAPI int eina_debug_thread_id_get(void);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
|
|
|
@ -28,20 +28,20 @@
|
|||
#include "eina_debug.h"
|
||||
#include "eina_debug_private.h"
|
||||
|
||||
#define SIG SIGPROF
|
||||
|
||||
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;
|
||||
|
||||
void
|
||||
_eina_debug_dump_fhandle_bt(FILE *f, void **bt, int btlen)
|
||||
{
|
||||
|
@ -107,60 +107,119 @@ get_time(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
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)
|
||||
static void
|
||||
_signal_handler(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;
|
||||
int slot = eina_debug_thread_id_get();
|
||||
if (slot >= _bt_threads_nb) return EINA_DEBUG_OK;
|
||||
|
||||
// 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(pthread_self(), &cid);
|
||||
pthread_getcpuclockid(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;
|
||||
// now wake up the monitor to let them know we are done collecting our
|
||||
// backtrace info
|
||||
eina_semaphore_release(&_wait_for_bts_sem, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
_signal_init(void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
// set up signal handler for our profiling signal - eevery thread should
|
||||
// obey this (this is the case on linux - other OSs may vary)
|
||||
sa.sa_sigaction = _signal_handler;
|
||||
sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
if (sigaction(SIG, &sa, NULL) != 0)
|
||||
e_debug("EINA DEBUG ERROR: Can't set up sig %i handler!", SIG);
|
||||
|
||||
sa.sa_sigaction = NULL;
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
if (sigaction(SIGPIPE, &sa, 0) == -1) perror(0);
|
||||
}
|
||||
|
||||
static void
|
||||
_collect_bt(pthread_t pth)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_trace_cb(void *data)
|
||||
_trace_cb(void *data EINA_UNUSED)
|
||||
{
|
||||
static Eina_Debug_Packet_Header *hdr = NULL;
|
||||
static int bts = 0;
|
||||
int i;
|
||||
|
||||
if (!hdr)
|
||||
{
|
||||
hdr = calloc(1, sizeof(*hdr));
|
||||
hdr->size = sizeof(Eina_Debug_Packet_Header);
|
||||
hdr->thread_id = 0xFFFFFFFF;
|
||||
hdr->opcode = _prof_get_op;
|
||||
}
|
||||
|
||||
if (!_trace_t0) _trace_t0 = get_time();
|
||||
|
||||
_bt_threads_nb = _eina_debug_thread_active_num;
|
||||
// take a lock on grabbing thread debug info like backtraces
|
||||
eina_spinlock_take(&_eina_debug_thread_lock);
|
||||
// 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(_bt_threads_nb * sizeof(void *));
|
||||
_bt_buf = _eina_debug_chunk_tmp_push
|
||||
((1 + _eina_debug_thread_active_num) * 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(_bt_threads_nb * sizeof(struct timespec));
|
||||
_bt_ts = _eina_debug_chunk_tmp_push
|
||||
((1 + _eina_debug_thread_active_num) * 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(_bt_threads_nb * sizeof(int));
|
||||
_bt_cpu = _eina_debug_chunk_tmp_push
|
||||
((1 + _eina_debug_thread_active_num) * 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 < _bt_threads_nb; i++)
|
||||
for (i = 0; i < _eina_debug_thread_active_num; i++)
|
||||
{
|
||||
_bt_buf[i] = _eina_debug_chunk_tmp_push(EINA_MAX_BT * sizeof(void *));
|
||||
if (!_bt_buf[i]) goto err;
|
||||
_bt_buf[i + 1] = _eina_debug_chunk_tmp_push(EINA_MAX_BT * sizeof(void *));
|
||||
if (!_bt_buf[i + 1]) goto err;
|
||||
}
|
||||
// get an array of ints to stor the bt len for mainloop + threads
|
||||
_bt_buf_len = _eina_debug_chunk_tmp_push(_bt_threads_nb * sizeof(int));
|
||||
|
||||
_bt_buf_len = _eina_debug_chunk_tmp_push
|
||||
((1 + _eina_debug_thread_active_num) * sizeof(int));
|
||||
// collect bt from the mainloop - always there
|
||||
_collect_bt(_eina_debug_thread_mainloop);
|
||||
// now collect per thread
|
||||
eina_debug_dispatch(data, (void *)hdr);
|
||||
|
||||
for (i = 0; i < _eina_debug_thread_active_num; i++)
|
||||
_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 threads
|
||||
// we can process it now as we see fit, so release thread lock
|
||||
for (i = 0; i < _eina_debug_thread_active_num; i++)
|
||||
|
@ -168,6 +227,7 @@ _trace_cb(void *data)
|
|||
_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)
|
||||
|
@ -182,7 +242,7 @@ err:
|
|||
}
|
||||
|
||||
// profiling on with poll time gap as uint payload
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_prof_on_cb(Eina_Debug_Session *session, int cid EINA_UNUSED, void *buffer, int size)
|
||||
{
|
||||
unsigned int time;
|
||||
|
@ -192,27 +252,27 @@ _prof_on_cb(Eina_Debug_Session *session, int cid EINA_UNUSED, void *buffer, int
|
|||
_trace_t0 = 0.0;
|
||||
_timer = eina_debug_timer_add(time, _trace_cb, session);
|
||||
}
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_prof_off_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
|
||||
{
|
||||
eina_debug_timer_del(_timer);
|
||||
_timer = NULL;
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static const Eina_Debug_Opcode _OPS[] = {
|
||||
{"profiler/on", NULL, &_prof_on_cb},
|
||||
{"profiler/off", NULL, &_prof_off_cb},
|
||||
{"profiler/bt_get", &_prof_get_op, &_prof_get_cb},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
Eina_Bool
|
||||
_eina_debug_bt_init(void)
|
||||
{
|
||||
_signal_init();
|
||||
eina_semaphore_new(&_wait_for_bts_sem, 0);
|
||||
eina_debug_opcodes_register(NULL, _OPS, NULL, NULL);
|
||||
return EINA_TRUE;
|
||||
|
|
|
@ -239,7 +239,7 @@ _sysmon(void *_data EINA_UNUSED)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_cpufreq_on_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
|
||||
{
|
||||
if (!_eina_debug_evlog_active)
|
||||
|
@ -253,10 +253,10 @@ _cpufreq_on_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, voi
|
|||
_eina_debug_sysmon_active = 1;
|
||||
eina_lock_release(&_sysmon_lock);
|
||||
}
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_cpufreq_off_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
|
||||
{
|
||||
if (_eina_debug_sysmon_active)
|
||||
|
@ -269,7 +269,7 @@ _cpufreq_off_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, vo
|
|||
eina_evlog_stop();
|
||||
_eina_debug_evlog_active = 0;
|
||||
}
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static const Eina_Debug_Opcode _OPS[] = {
|
||||
|
|
|
@ -103,16 +103,3 @@ _eina_debug_thread_mainloop_set(void *th)
|
|||
_eina_debug_thread_mainloop = *pth;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
eina_debug_thread_id_get(void)
|
||||
{
|
||||
pthread_t self = pthread_self();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _eina_debug_thread_active_num; i++)
|
||||
{
|
||||
if (self == _eina_debug_thread_active[i].thread)
|
||||
return _eina_debug_thread_active[i].thread_id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ eina_evlog_stop(void)
|
|||
}
|
||||
|
||||
// get evlog
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_get_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
|
||||
{
|
||||
Eina_Evlog_Buf *evlog = eina_evlog_steal();
|
||||
|
@ -230,23 +230,23 @@ _get_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *buff
|
|||
printf("send evlog size %d\n", resp_size);
|
||||
eina_debug_session_send(session, cid, _evlog_get_opcode, resp_buf, resp_size);
|
||||
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
// enable evlog
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_start_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
|
||||
{
|
||||
eina_evlog_start();
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
// stop evlog
|
||||
static Eina_Debug_Error
|
||||
static Eina_Bool
|
||||
_stop_cb(Eina_Debug_Session *session EINA_UNUSED, int cid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
|
||||
{
|
||||
eina_evlog_stop();
|
||||
return EINA_DEBUG_OK;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static const Eina_Debug_Opcode _EINA_DEBUG_EVLOG_OPS[] = {
|
||||
|
|
Loading…
Reference in New Issue