예제 #1
0
파일: futex.c 프로젝트: zrho/Carbon
void syscall_futex_wait(cpu_int_state_t *state) {
    // Extract arguments
    uintptr_t futex_vaddr = state->state.rsi;
    uint32_t value_cmp = (uint32_t) state->state.rbx;

    // Check
    if (!memory_user_accessible(futex_vaddr & ~0xFFF)) {
        state->state.rax = 0;
        return;
    }

    // Compare values
    uint32_t *futex = (uint32_t *) futex_vaddr;

    if (value_cmp != *futex) {
        state->state.rax = 0;
        return;
    }

    // Enter sleep
    thread_current->sleep_mode = THREAD_SLEEP_FUTEX;
    thread_current->sleep_ctx = (void *) futex_vaddr;
    thread_freeze(thread_current);

    // Ensure that 1 is returned on wakeup
    state->state.rax = 1;

    // Switch threads
    SYSCALL_SWITCH_THREAD;
}
예제 #2
0
파일: machine.c 프로젝트: rohsaini/mkunity
/*
 * thread_stop_freeze
 *	Block the thread in the kernel and freeze the processor set.
 * return value:
 *	TRUE - the thread has blocked interruptibly, is stopped, and
 *		the processor set assignment is frozen
 *	FALSE - the thread is no longer in the processor set, so it
 *		isn't stopped, and the processor set assignment
 *		is released.
 */
int
thread_stop_freeze( thread_t thread, processor_set_t pset )
{
	thread_act_t	thr_act;
	spl_t	s;

	/*
	 * hold it, and wait for it to stop.
	 */
	thr_act = thread_lock_act(thread);
	thread_hold(thr_act);
	act_unlock_thread(thr_act);

	thread_stop(thread);

	s = splsched();
	wake_lock(thread);
        while( thread->state & (TH_RUN|TH_UNINT) ) {
                thread->wake_active = TRUE;
                assert_wait((event_t)&thread->wake_active, FALSE);
                wake_unlock(thread);
                splx(s);
                thread_block( (void (*)(void)) 0 );
                (void) splsched();
                wake_lock(thread);
        }

	/*
	 * Now, the thread has blocked uninterruptibly; freeze the 
	 * assignment and make sure it's still part of the processor set.
	 */
	wake_unlock(thread);
	thread_freeze(thread);
	thread_lock(thread);

	/*
	 * if the processor set has changed, release the freeze and
	 * then unstop it.
	 */
	if( thread->processor_set != pset ) {
		thread_unlock(thread);
		splx(s);
		thread_unfreeze(thread);
		thread_unstop(thread);
		return FALSE;
	}
	thread_unlock(thread);
	splx(s);
	return TRUE;
}
예제 #3
0
파일: ipc.c 프로젝트: zrho/Carbon
void syscall_ipc_send(cpu_int_state_t *state) {
	// Extract arguments
	uint32_t pid = (uint32_t) state->state.rdi;
	uint16_t flags = (uint32_t) state->state.rbx;
	uint32_t length = (uint32_t) state->state.rcx;

	// Check if process exists
	process_t *process_target = (pid == process_current->pid)
			? process_current
			: process_get(pid);

	if (0 == process_target)
		SYSCALL_RETURN_ERROR(1);

	// Check handler
	if (0 == process_target->message_handler)
		SYSCALL_RETURN_ERROR(2);

	// Check buffer size
	if (length > thread_current->ipc_buffer_sz[IPC_BUFFER_SEND])
		SYSCALL_RETURN_ERROR(3);

	// Spawn handler thread
	thread_t *handler = thread_spawn(
			process_target,
			process_target->message_handler);

	// Set thread role
	ipc_role_ctx_t *role_ctx =
			(ipc_role_ctx_t *) heap_alloc(sizeof(ipc_role_ctx_t));

	role_ctx->flags = flags;
	role_ctx->sender_process = process_current->pid;
	role_ctx->sender_thread = thread_current->tid;

	handler->role = THREAD_ROLE_IPC_RECEIVER;
	handler->role_ctx = role_ctx;

	// Move buffer to handler thread
	if (length > 0)
		ipc_buffer_move(
				thread_current,
				IPC_BUFFER_SEND,
				handler,
				IPC_BUFFER_RECV,
				process_target);

	// Write header to registers
	ipc_message_header(
			IPC_BUFFER_RECV,
			length,
			flags,
			process_current->pid,
			handler->tid,
			&handler->state);

	// Freeze the invoking thread, if a response is expected
	if (0 == (flags & IPC_FLAG_IGNORE_RESPONSE))
		thread_freeze(thread_current);

	// Switch to handler thread
	thread_switch(handler, state);
}