예제 #1
0
/* Finish a context. If the context has no parent, its state will be set
 * to 'x86_ctx_finished'. If it has, its state is set to 'x86_ctx_zombie', waiting for
 * a call to 'waitpid'.
 * The children of the finished context will set their 'parent' attribute to NULL.
 * The zombie children will be finished. */
void X86ContextFinish(X86Context *self, int state)
{
	X86Emu *emu = self->emu;
	X86Context *aux;
	
	/* Context already finished */
	if (X86ContextGetState(self, X86ContextFinished | X86ContextZombie))
		return;
	
	/* If context is waiting for host events, cancel spawned host threads. */
	X86ContextHostThreadSuspendCancel(self);
	X86ContextHostThreadTimerCancel(self);

	/* From now on, all children have lost their parent. If a child is
	 * already zombie, finish it, since its parent won't be able to waitpid it
	 * anymore. */
	DOUBLE_LINKED_LIST_FOR_EACH(emu, context, aux)
	{
		if (aux->parent == self)
		{
			aux->parent = NULL;
			if (X86ContextGetState(aux, X86ContextZombie))
				X86ContextSetState(aux, X86ContextFinished);
		}
	}

	/* Send finish signal to parent */
	if (self->exit_signal && self->parent)
	{
		x86_sys_debug("  sending signal %d to pid %d\n",
			self->exit_signal, self->parent->pid);
		x86_sigset_add(&self->parent->signal_mask_table->pending,
			self->exit_signal);
		X86EmuProcessEventsSchedule(emu);
	}

	/* If clear_child_tid was set, a futex() call must be performed on
	 * that pointer. Also wake up futexes in the robust list. */
	if (self->clear_child_tid)
	{
		unsigned int zero = 0;
		mem_write(self->mem, self->clear_child_tid, 4, &zero);
		X86ContextFutexWake(self, self->clear_child_tid, 1, -1);
	}
	X86ContextExitRobustList(self);

	/* If we are in a signal handler, stop it. */
	if (X86ContextGetState(self, X86ContextHandler))
		X86ContextReturnFromSignalHandler(self);

	/* Finish context */
	X86ContextSetState(self, self->parent ? X86ContextZombie : X86ContextFinished);
	self->exit_code = state;
	X86EmuProcessEventsSchedule(emu);
}
예제 #2
0
void opencl_si_request_work()
{
	if (driver_state.wait_for_ndrange_completion && 
		!list_count(si_emu->running_work_groups) && 
		!list_count(si_emu->waiting_work_groups))
	{
		opencl_debug("ND-Range is complete\n");
		driver_state.ndrange_complete = 1;
	}
	else 
	{
		opencl_debug("SI is ready for more work\n");
		driver_state.ready_for_work = 1;
	}

	X86EmuProcessEventsSchedule(x86_emu);
}
예제 #3
0
/* Suspend a context, using the specified callback function and data to decide
 * whether the process can wake up every time the x86 emulation events are
 * processed. */
void X86ContextSuspend(X86Context *self, X86ContextCanWakeupFunc can_wakeup_callback_func,
	void *can_wakeup_callback_data, X86ContextWakeupFunc wakeup_callback_func,
	void *wakeup_callback_data)
{
	X86Emu *emu = self->emu;

	/* Checks */
	assert(!X86ContextGetState(self, X86ContextSuspended));
	assert(!self->can_wakeup_callback_func);
	assert(!self->can_wakeup_callback_data);

	/* Suspend context */
	self->can_wakeup_callback_func = can_wakeup_callback_func;
	self->can_wakeup_callback_data = can_wakeup_callback_data;
	self->wakeup_callback_func = wakeup_callback_func;
	self->wakeup_callback_data = wakeup_callback_data;
	X86ContextSetState(self, X86ContextSuspended | X86ContextCallback);
	X86EmuProcessEventsSchedule(emu);
}
예제 #4
0
void evg_opencl_command_queue_complete(struct evg_opencl_command_queue_t *command_queue,
	struct evg_opencl_command_t *command)
{
	X86Context *context = command->context;
	struct linked_list_t *command_list;

	/* Check that command is in command queue */
	command_list = command_queue->command_list;
	linked_list_find(command_list, command);
	if (command_list->error_code)
		fatal("%s: command is not in command queue", __FUNCTION__);
	
	/* Remove command */
	linked_list_remove(command_list);

	/* x86 contexts might be waiting for the command queue to get empty
	 * (e.g., suspended in a 'clFinish' call. Check events. */
	assert(context);
	X86EmuProcessEventsSchedule(context->emu);
}
예제 #5
0
/* Finish a context group. This call does a subset of action of the 'x86_ctx_finish'
 * call, but for all parent and child contexts sharing a memory map. */
void X86ContextFinishGroup(X86Context *self, int state)
{
	X86Emu *emu = self->emu;
	X86Context *aux;

	/* Get group parent */
	if (self->group_parent)
		self = self->group_parent;
	assert(!self->group_parent);  /* Only one level */
	
	/* Context already finished */
	if (X86ContextGetState(self, X86ContextFinished | X86ContextZombie))
		return;

	/* Finish all contexts in the group */
	DOUBLE_LINKED_LIST_FOR_EACH(emu, context, aux)
	{
		if (aux->group_parent != self && aux != self)
			continue;

		if (X86ContextGetState(aux, X86ContextZombie))
			X86ContextSetState(aux, X86ContextFinished);
		if (X86ContextGetState(aux, X86ContextHandler))
			X86ContextReturnFromSignalHandler(aux);
		X86ContextHostThreadSuspendCancel(aux);
		X86ContextHostThreadTimerCancel(aux);

		/* Child context of 'ctx' goes to state 'finished'.
		 * Context 'ctx' goes to state 'zombie' or 'finished' if it has a parent */
		if (aux == self)
			X86ContextSetState(aux, aux->parent ? X86ContextZombie : X86ContextFinished);
		else
			X86ContextSetState(aux, X86ContextFinished);
		aux->exit_code = state;
	}

	/* Process events */
	X86EmuProcessEventsSchedule(emu);
}