Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/jit/jit-debugger.c  view on Meta::CPAN

 * Get the thread identifier associated with the current thread.
 * The return values are normally values like 1, 2, 3, etc, allowing
 * the user interface to report messages like "thread 3 has stopped
 * at a breakpoint".
 * @end deftypefun
@*/
jit_debugger_thread_id_t jit_debugger_get_self(jit_debugger_t dbg)
{
	jit_thread_id_t id = jit_thread_self();
	jit_debugger_thread_id_t thread;
	thread = jit_debugger_get_thread(dbg, &id);
	jit_thread_release_self(id);
	return thread;
}

/*@
 * @deftypefun jit_debugger_thread_id_t jit_debugger_get_thread (jit_debugger_t @var{dbg}, const void *@var{native_thread})
 * Get the thread identifier for a specific native thread.  The
 * @var{native_thread} pointer is assumed to point at a block
 * of memory containing a native thread handle.  This would be a
 * @code{pthread_t} on Pthreads platforms or a @code{HANDLE}
 * on Win32 platforms.  If the native thread has not been seen
 * previously, then a new thread identifier is allocated.
 * @end deftypefun
@*/
jit_debugger_thread_id_t jit_debugger_get_thread
		(jit_debugger_t dbg, const void *native_thread)
{
	/* TODO */
	return 0;
}

/*@
 * @deftypefun int jit_debugger_get_native_thread (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread}, void *@var{native_thread})
 * Get the native thread handle associated with a debugger thread identifier.
 * Returns non-zero if OK, or zero if the debugger thread identifier is not
 * yet associated with a native thread handle.
 * @end deftypefun
@*/
int jit_debugger_get_native_thread
		(jit_debugger_t dbg, jit_debugger_thread_id_t thread,
		 void *native_thread)
{
	jit_debugger_thread_t th;
	lock_debugger(dbg);
	th = get_specific_thread(dbg, thread);
	if(th)
	{
		jit_memcpy(native_thread, &(th->native_id), sizeof(th->native_id));
		unlock_debugger(dbg);
		return 1;
	}
	else
	{
		unlock_debugger(dbg);
		return 0;
	}
}

/*@
 * @deftypefun void jit_debugger_set_breakable (jit_debugger_t @var{dbg}, const void *@var{native_thread}, int @var{flag})
 * Set a flag that indicates if a native thread can stop at breakpoints.
 * If set to 1 (the default), breakpoints will be active on the thread.
 * If set to 0, breakpoints will be ignored on the thread.  Typically
 * this is used to mark threads associated with the debugger's user
 * interface, or the virtual machine's finalization thread, so that they
 * aren't accidentally suspended by the debugger (which might cause a
 * deadlock).
 * @end deftypefun
@*/
void jit_debugger_set_breakable
		(jit_debugger_t dbg, const void *native_thread, int flag)
{
	jit_debugger_thread_t th;
	jit_debugger_thread_id_t id;
	id = jit_debugger_get_thread(dbg, native_thread);
	lock_debugger(dbg);
	th = get_specific_thread(dbg, id);
	if(th)
	{
		th->breakable = flag;
	}
	unlock_debugger(dbg);
}

/*@
 * @deftypefun void jit_debugger_attach_self (jit_debugger_t @var{dbg}, int @var{stop_immediately})
 * Attach the current thread to a debugger.  If @var{stop_immediately}
 * is non-zero, then the current thread immediately suspends, waiting for
 * the user to start it with @code{jit_debugger_run}.  This function is
 * typically called in a thread's startup code just before any "real work"
 * is performed.
 * @end deftypefun
@*/
void jit_debugger_attach_self(jit_debugger_t dbg, int stop_immediately)
{
	jit_debugger_event_t *event;
	jit_debugger_thread_t th;
	lock_debugger(dbg);
	th = get_current_thread(dbg);
	if(th)
	{
		event = alloc_event();
		if(event)
		{
			event->type = JIT_DEBUGGER_TYPE_ATTACH_THREAD;
			event->thread = th->id;
			event->data1 = (jit_nint)stop_immediately;
			add_event(dbg, event);
			th->find_func = 0;
			th->last_data1 = 0;
			th->last_func_data1 = 0;
			if(stop_immediately)
			{
				th->run_type = JIT_RUN_TYPE_STOPPED;
				suspend_thread(dbg, th);
			}
			else
			{
				th->run_type = JIT_RUN_TYPE_CONTINUE;
			}
		}
	}
	unlock_debugger(dbg);
}

/*@
 * @deftypefun void jit_debugger_detach_self (jit_debugger_t @var{dbg})
 * Detach the current thread from the debugger.  This is typically
 * called just before the thread exits.
 * @end deftypefun
@*/
void jit_debugger_detach_self(jit_debugger_t dbg)
{
	jit_debugger_event_t *event;
	jit_debugger_thread_t th;
	lock_debugger(dbg);
	th = get_current_thread(dbg);
	if(th)
	{
		event = alloc_event();
		if(event)
		{
			event->type = JIT_DEBUGGER_TYPE_DETACH_THREAD;
			event->thread = th->id;
			add_event(dbg, event);
			th->run_type = JIT_RUN_TYPE_DETACHED;
		}
	}
	unlock_debugger(dbg);
}

/*@
 * @deftypefun int jit_debugger_wait_event (jit_debugger_t @var{dbg}, jit_debugger_event_t *@var{event}, jit_nint @var{timeout})
 * Wait for the next debugger event to arrive.  Debugger events typically
 * indicate breakpoints that have occurred.  The @var{timeout} is in
 * milliseconds, or -1 for an infinite timeout period.  Returns non-zero
 * if an event has arrived, or zero on timeout.
 * @end deftypefun
@*/
int jit_debugger_wait_event
		(jit_debugger_t dbg, jit_debugger_event_t *event, jit_int timeout)
{
	jit_debugger_linked_event_t *levent;
	jit_monitor_lock(&(dbg->queue_lock));
	if((levent = dbg->events) == 0)
	{
		if(!jit_monitor_wait(&(dbg->queue_lock), timeout))
		{
			jit_monitor_unlock(&(dbg->queue_lock));
			return 0;
		}
		levent = dbg->events;
	}
	*event = levent->event;
	dbg->events = levent->next;
	if(!(levent->next))
	{
		dbg->last_event = 0;
	}
	jit_free(levent);
	jit_monitor_unlock(&(dbg->queue_lock));
	return 1;
}

/*@
 * @deftypefun jit_debugger_breakpoint_id_t jit_debugger_add_breakpoint (jit_debugger_t @var{dbg}, jit_debugger_breakpoint_info_t @var{info})
 * Add a hard breakpoint to a debugger instance.  The @var{info} structure
 * defines the conditions under which the breakpoint should fire.
 * The fields of @var{info} are as follows:
 *
 * @table @code
 * @item flags
 * Flags that indicate which of the following fields should be matched.
 * If a flag is not present, then all possible values of the field will match.
 * Valid flags are @code{JIT_DEBUGGER_FLAG_THREAD},
 * @code{JIT_DEBUGGER_FLAG_FUNCTION}, @code{JIT_DEBUGGER_FLAG_DATA1},
 * and @code{JIT_DEBUGGER_FLAG_DATA2}.
 *
 * @item thread
 * The thread to match against, if @code{JIT_DEBUGGER_FLAG_THREAD} is set.
 *
 * @item function
 * The function to match against, if @code{JIT_DEBUGGER_FLAG_FUNCTION} is set.
 *
 * @item data1
 * The @code{data1} value to match against, if @code{JIT_DEBUGGER_FLAG_DATA1}
 * is set.
 *
 * @item data2
 * The @code{data2} value to match against, if @code{JIT_DEBUGGER_FLAG_DATA2}
 * is set.
 * @end table
 *
 * The following special values for @code{data1} are recommended for marking
 * breakpoint locations with @code{jit_insn_mark_breakpoint}:
 *
 * @table @code
 * @item JIT_DEBUGGER_DATA1_LINE
 * Breakpoint location that corresponds to a source line.  This is used
 * to determine where to continue to upon a "step".
 *
 * @item JIT_DEBUGGER_DATA1_ENTER
 * Breakpoint location that corresponds to the start of a function.
 *
 * @item JIT_DEBUGGER_DATA1_LEAVE
 * Breakpoint location that corresponds to the end of a function, just
 * prior to a @code{return} statement.  This is used to determine where
 * to continue to upon a "finish".
 *
 * @item JIT_DEBUGGER_DATA1_THROW
 * Breakpoint location that corresponds to an exception throw.
 * @end table
 * @end deftypefun
@*/
jit_debugger_breakpoint_id_t jit_debugger_add_breakpoint
		(jit_debugger_t dbg, jit_debugger_breakpoint_info_t info)
{
	/* TODO */
	return 0;
}

/*@
 * @deftypefun void jit_debugger_remove_breakpoint (jit_debugger_t @var{dbg}, jit_debugger_breakpoint_id_t @var{id})
 * Remove a previously defined breakpoint from a debugger instance.
 * @end deftypefun
@*/
void jit_debugger_remove_breakpoint
		(jit_debugger_t dbg, jit_debugger_breakpoint_id_t id)
{
	/* TODO */
}

/*@
 * @deftypefun void jit_debugger_remove_all_breakpoints (jit_debugger_t @var{dbg})
 * Remove all breakpoints from a debugger instance.
 * @end deftypefun
@*/
void jit_debugger_remove_all_breakpoints(jit_debugger_t dbg)
{
	/* TODO */
}

/*@
 * @deftypefun int jit_debugger_is_alive (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
 * Determine if a particular thread is still alive.
 * @end deftypefun
@*/
int jit_debugger_is_alive(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
	/* TODO */
	return 1;
}

/*@
 * @deftypefun int jit_debugger_is_running (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
 * Determine if a particular thread is currently running (non-zero) or
 * stopped (zero).
 * @end deftypefun
@*/
int jit_debugger_is_running(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
	jit_debugger_thread_t th;
	int flag = 0;
	lock_debugger(dbg);
	th = get_specific_thread(dbg, thread);
	if(th)
	{
		flag = (th->run_type != JIT_RUN_TYPE_STOPPED);
	}
	unlock_debugger(dbg);
	return flag;
}

/*@
 * @deftypefun void jit_debugger_run (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
 * Start the specified thread running, or continue from the last breakpoint.
 *
 * This function, and the others that follow, sends a request to the specified
 * thread and then returns to the caller immediately.
 * @end deftypefun
@*/
void jit_debugger_run(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
	jit_debugger_thread_t th;
	lock_debugger(dbg);
	th = get_specific_thread(dbg, thread);
	if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
	{
		th->run_type = JIT_RUN_TYPE_CONTINUE;
		wakeup_all(dbg);
	}
	unlock_debugger(dbg);
}

/*@
 * @deftypefun void jit_debugger_step (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
 * Step over a single line of code.  If the line performs a method call,
 * then this will step into the call.  The request will be ignored if
 * the thread is currently running.
 * @end deftypefun
@*/
void jit_debugger_step(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
	jit_debugger_thread_t th;
	lock_debugger(dbg);
	th = get_specific_thread(dbg, thread);
	if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
	{
		th->run_type = JIT_RUN_TYPE_STEP;
		wakeup_all(dbg);
	}
	unlock_debugger(dbg);
}

/*@
 * @deftypefun void jit_debugger_next (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
 * Step over a single line of code but do not step into method calls.
 * The request will be ignored if the thread is currently running.
 * @end deftypefun
@*/
void jit_debugger_next(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
{
	jit_debugger_thread_t th;
	lock_debugger(dbg);
	th = get_specific_thread(dbg, thread);
	if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
	{
		th->run_type = JIT_RUN_TYPE_NEXT;
		wakeup_all(dbg);
	}
	unlock_debugger(dbg);



( run in 1.701 second using v1.01-cache-2.11-cpan-796a6f069b2 )