Beispiel #1
0
void
wait_for_thread_state_change(struct thread *thread, lispobj state)
{
    sigset_t old;
    os_sem_t *wait_sem;
    block_blockable_signals(&old);
  start:
    os_sem_wait(thread->state_sem, "wait_for_thread_state_change");
    if (thread->state == state) {
        switch (state) {
        case STATE_RUNNING:
            wait_sem = thread->state_not_running_sem;
            thread->state_not_running_waitcount++;
            break;
        case STATE_STOPPED:
            wait_sem = thread->state_not_stopped_sem;
            thread->state_not_stopped_waitcount++;
            break;
        default:
            lose("Invalid state in wait_for_thread_state_change: "OBJ_FMTX"\n", state);
        }
    } else {
        wait_sem = NULL;
    }
    os_sem_post(thread->state_sem, "wait_for_thread_state_change");
    if (wait_sem) {
        os_sem_wait(wait_sem, "wait_for_thread_state_change");
        goto start;
    }
    thread_sigmask(SIG_SETMASK, &old, NULL);
}
Beispiel #2
0
void handle_breakpoint(os_context_t *context)
{
    lispobj code;
    DX_ALLOC_SAP(context_sap, context);

    fake_foreign_function_call(context);

#ifndef LISP_FEATURE_SB_SAFEPOINT
    unblock_gc_signals(0, 0);
#endif
    code = find_code(context);

#ifndef LISP_FEATURE_WIN32
    /* Don't disallow recursive breakpoint traps. Otherwise, we can't
     * use debugger breakpoints anywhere in here. */
    thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
#endif

    funcall3(StaticSymbolFunction(HANDLE_BREAKPOINT),
             compute_offset(context, code),
             code,
             context_sap);

    undo_fake_foreign_function_call(context);
}
Beispiel #3
0
void
set_thread_state(struct thread *thread, lispobj state)
{
    int i, waitcount = 0;
    sigset_t old;
    block_blockable_signals(&old);
    os_sem_wait(thread->state_sem, "set_thread_state");
    if (thread->state != state) {
        if ((STATE_STOPPED==state) ||
            (STATE_DEAD==state)) {
            waitcount = thread->state_not_running_waitcount;
            thread->state_not_running_waitcount = 0;
            for (i=0; i<waitcount; i++)
                os_sem_post(thread->state_not_running_sem, "set_thread_state (not running)");
        }
        if ((STATE_RUNNING==state) ||
            (STATE_DEAD==state)) {
            waitcount = thread->state_not_stopped_waitcount;
            thread->state_not_stopped_waitcount = 0;
            for (i=0; i<waitcount; i++)
                os_sem_post(thread->state_not_stopped_sem, "set_thread_state (not stopped)");
        }
        thread->state = state;
    }
    os_sem_post(thread->state_sem, "set_thread_state");
    thread_sigmask(SIG_SETMASK, &old, NULL);
}
Beispiel #4
0
SigMaskInt SigBlock_FL(FL_PAR,SigMaskInt mask){
	SigMaskInt omask,nmask;
	if( Nthreads && !ismainthread() ){
		thread_sigmask("BLOCK",mask,&omask);
		thread_sigmask("GET",0,&nmask);
/*
		if( lTHREADSIG() )
		fprintf(stderr,"-- %X thread_sigblock(%X +> %X)=%X <= %s:%d\n",
			TID,omask,mask,nmask,FL_BAR);
*/
		return omask;
	}
	nmask = sigblock(mask);
	if( lTHREADSIG() )
	fprintf(stderr,"-- %X sigblock(%X)=%X <= %s:%d\n",TID,mask,nmask,FL_BAR);
	return nmask;
}
Beispiel #5
0
void
detach_os_thread(init_thread_data *scribble)
{
    struct thread *th = arch_os_get_current_thread();
    odxprint(misc, "detach_os_thread: detaching");

    undo_init_new_thread(th, scribble);

    odxprint(misc, "deattach_os_thread: detached");
    pthread_setspecific(lisp_thread, (void *)0);
    thread_sigmask(SIG_SETMASK, &scribble->oldset, 0);
}
Beispiel #6
0
/* Only access thread state with blockables blocked. */
lispobj
thread_state(struct thread *thread)
{
    lispobj state;
    sigset_t old;
    block_blockable_signals(&old);
    os_sem_wait(thread->state_sem, "thread_state");
    state = thread->state;
    os_sem_post(thread->state_sem, "thread_state");
    thread_sigmask(SIG_SETMASK, &old, NULL);
    return state;
}
Beispiel #7
0
int thread_start(const char *name,void *ta){
	int ix;
	SigMaskInt umask,omask,nmask;

	ix = getthreadix();
	StartedThreads++;
	if( 0 <= ix ){
		threads[ix].t_what = name;
	}

	if( !lNOSIGPIPE() )
	if( !SuppThreadSignal() ){
		/*
		umask = sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGPIPE);
		only the main-thread should receive SIGINT/SIGTERM
		*/
		umask = sigmask(SIGPIPE);
		thread_sigmask("UNBLOCK",umask,&omask);
		thread_sigmask("UNBLOCK",0,&nmask);
		syslog_DEBUG("thread_started sigmask=%X <- %X\n",nmask,omask);
	}
	return 0;
}
Beispiel #8
0
void
handle_single_step_trap (os_context_t *context, int kind, int register_offset)
{
    fake_foreign_function_call(context);

#ifndef LISP_FEATURE_WIN32
    thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
#endif

    funcall2(StaticSymbolFunction(HANDLE_SINGLE_STEP_TRAP),
             make_fixnum(kind),
             make_fixnum(register_offset));

    undo_fake_foreign_function_call(context); /* blocks signals again */
}
Beispiel #9
0
void *handle_fun_end_breakpoint(os_context_t *context)
{
    lispobj code, lra;
    struct code *codeptr;
    DX_ALLOC_SAP(context_sap, context);

    fake_foreign_function_call(context);

#ifndef LISP_FEATURE_SB_SAFEPOINT
    unblock_gc_signals(0, 0);
#endif

    code = find_code(context);
    codeptr = (struct code *)native_pointer(code);

#ifndef LISP_FEATURE_WIN32
    /* Don't disallow recursive breakpoint traps. Otherwise, we can't
     * use debugger breakpoints anywhere in here. */
    thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
#endif

    funcall3(StaticSymbolFunction(HANDLE_BREAKPOINT),
             compute_offset(context, code),
             code,
             context_sap);

    lra = codeptr->constants[REAL_LRA_SLOT];

#ifdef LISP_FEATURE_PPC
    /* PPC now passes LRA objects in reg_LRA during return.  Other
     * platforms should as well, but haven't been fixed yet. */
    *os_context_register_addr(context, reg_LRA) = lra;
#else
#ifdef reg_CODE
    *os_context_register_addr(context, reg_CODE) = lra;
#endif
#endif

    undo_fake_foreign_function_call(context);

#ifdef reg_LRA
    return (void *)(lra-OTHER_POINTER_LOWTAG+sizeof(lispobj));
#else
    return compute_pc(lra, fixnum_value(codeptr->constants[REAL_LRA_SLOT+1]));
#endif
}
Beispiel #10
0
static void *thread_main_loop(void *_state)
{
	struct thread_state *state = (struct thread_state *)_state;
	struct packet *pkt = NULL;
	sigset_t set;
#ifdef HAKA_MEMCHECK
	int64 pkt_count=0;
	const int mem_rate=10;
#endif

	thread_setid(state->thread_id);

	if (!state->pool->single) {
		/* Block all signal to let the main thread handle them */
		sigfillset(&set);
		sigdelset(&set, SIGSEGV);
		sigdelset(&set, SIGILL);
		sigdelset(&set, SIGFPE);

		if (!thread_sigmask(SIG_BLOCK, &set, NULL)) {
			LOG_FATAL(core, "%s", clear_error());
			barrier_wait(&state->pool->thread_start_sync);
			state->state = STATE_ERROR;
			return NULL;
		}

		if (!timer_init_thread()) {
			LOG_FATAL(core, "%s", clear_error());
			barrier_wait(&state->pool->thread_start_sync);
			state->state = STATE_ERROR;
			return NULL;
		}

		/* To make sure we can still cancel even if some thread are locked in
		 * infinite loops */
		if (!thread_setcanceltype(THREAD_CANCEL_ASYNCHRONOUS)) {
			LOG_FATAL(core, "%s", clear_error());
			barrier_wait(&state->pool->thread_start_sync);
			state->state = STATE_ERROR;
			return NULL;
		}

		if (!init_thread_lua_state(state)) {
			barrier_wait(&state->pool->thread_start_sync);
			state->state = STATE_ERROR;
			return NULL;
		}
	}

	state->engine = engine_thread_init(state->lua->L, state->thread_id);
	engine_thread_update_status(state->engine, THREAD_RUNNING);

	packet_init(state->capture);

	if (!state->pool->single) {
		if (!barrier_wait(&state->pool->thread_start_sync)) {
			LOG_FATAL(core, "%s", clear_error());
			state->state = STATE_ERROR;
			engine_thread_update_status(state->engine, THREAD_DEFUNC);
			return NULL;
		}
	}

	if (!state->pool->single) {
		if (!barrier_wait(&state->pool->thread_sync)) {
			LOG_FATAL(core, "%s", clear_error());
			state->state = STATE_ERROR;
			engine_thread_update_status(state->engine, THREAD_DEFUNC);
			return NULL;
		}
	}

	lua_state_trigger_haka_event(state->lua, "started");

	engine_thread_update_status(state->engine, THREAD_WAITING);

	while (packet_receive(state->engine, &pkt) == 0) {
		engine_thread_update_status(state->engine, THREAD_RUNNING);

		/* The packet can be NULL in case of failure in packet receive */
		if (pkt) {
			filter_wrapper(state, pkt);
			pkt = NULL;
		}

		lua_state_runinterrupt(state->lua);
		engine_thread_check_remote_launch(state->engine);

		if (state->pool->attach_debugger > state->attach_debugger) {
			luadebug_debugger_start(state->lua->L, true);
			state->attach_debugger = state->pool->attach_debugger;
		}

		engine_thread_update_status(state->engine, THREAD_WAITING);

#ifdef HAKA_MEMCHECK
		if (((pkt_count++) % mem_rate) == 0) {
			size_t vmsize, rss;
			if (!get_memory_size(&vmsize, &rss)) {
				LOG_ERROR(core, "cannot get memory report: %s", clear_error());
			}
			else {
				const size_t luasize = lua_gc(state->lua->L, LUA_GCCOUNT, 0);
				LOG_DEBUG(core, "memory report: thread=%d vmsize=%zd rsssize=%zd luasize=%zd",
						engine_thread_id(state->engine), vmsize, rss, luasize);
			}
		}
#endif

		if (state->pool->stop) {
			break;
		}
	}

	state->state = STATE_FINISHED;
	engine_thread_update_status(state->engine, THREAD_STOPPED);

	return NULL;
}
Beispiel #11
0
static void *thread_main_loop(void *_state)
{
	struct thread_state *state = (struct thread_state *)_state;
	struct packet *pkt = NULL;
	sigset_t set;

	thread_setid(state->thread_id);

	if (!state->pool->single) {
		/* Block all signal to let the main thread handle them */
		sigfillset(&set);
		sigdelset(&set, SIGSEGV);
		sigdelset(&set, SIGILL);
		sigdelset(&set, SIGFPE);

		if (!thread_sigmask(SIG_BLOCK, &set, NULL)) {
			message(HAKA_LOG_FATAL, "core", clear_error());
			barrier_wait(&state->pool->thread_start_sync);
			state->state = STATE_ERROR;
			return NULL;
		}

		if (!timer_init_thread()) {
			message(HAKA_LOG_FATAL, "core", clear_error());
			barrier_wait(&state->pool->thread_start_sync);
			state->state = STATE_ERROR;
			return NULL;
		}

		/* To make sure we can still cancel even if some thread are locked in
		 * infinite loops */
		if (!thread_setcanceltype(THREAD_CANCEL_ASYNCHRONOUS)) {
			message(HAKA_LOG_FATAL, "core", clear_error());
			barrier_wait(&state->pool->thread_start_sync);
			state->state = STATE_ERROR;
			return NULL;
		}

		if (!init_thread_lua_state(state)) {
			barrier_wait(&state->pool->thread_start_sync);
			state->state = STATE_ERROR;
			return NULL;
		}
	}

	state->engine = engine_thread_init(state->lua->L, state->thread_id);
	engine_thread_update_status(state->engine, THREAD_RUNNING);

	packet_init(state->capture);

	if (!state->pool->single) {
		if (!barrier_wait(&state->pool->thread_start_sync)) {
			message(HAKA_LOG_FATAL, "core", clear_error());
			state->state = STATE_ERROR;
			engine_thread_update_status(state->engine, THREAD_DEFUNC);
			return NULL;
		}
	}

	if (!state->pool->single) {
		if (!barrier_wait(&state->pool->thread_sync)) {
			message(HAKA_LOG_FATAL, "core", clear_error());
			state->state = STATE_ERROR;
			engine_thread_update_status(state->engine, THREAD_DEFUNC);
			return NULL;
		}
	}

	lua_state_trigger_haka_event(state->lua, "started");

	engine_thread_update_status(state->engine, THREAD_WAITING);

	while (packet_receive(&pkt) == 0) {
		engine_thread_update_status(state->engine, THREAD_RUNNING);

		/* The packet can be NULL in case of failure in packet receive */
		if (pkt) {
			filter_wrapper(state, pkt);
			pkt = NULL;
		}

		lua_state_runinterrupt(state->lua);
		engine_thread_check_remote_launch(state->engine);

		if (state->pool->attach_debugger > state->attach_debugger) {
			luadebug_debugger_start(state->lua->L, true);
			state->attach_debugger = state->pool->attach_debugger;
		}

		engine_thread_update_status(state->engine, THREAD_WAITING);

		if (state->pool->stop) {
			break;
		}
	}

	state->state = STATE_FINISHED;
	engine_thread_update_status(state->engine, THREAD_STOPPED);

	return NULL;
}