示例#1
0
文件: task.c 项目: respu/MainMemory
/* Destroy a task. The task should not run at the moment and it
 * should be absolutely guaranteed from being used afterwards. */
void
mm_task_destroy(struct mm_task *task)
{
	ENTER();
	ASSERT(task->state == MM_TASK_INVALID || task->state == MM_TASK_BLOCKED);
	ASSERT((task->flags & (MM_TASK_WAITING | MM_TASK_READING | MM_TASK_WRITING)) == 0);

	// Destroy the ports.
	while (!mm_list_empty(&task->ports)) {
		// TODO: ensure that ports are not referenced from elsewhere.
		struct mm_list *link = mm_list_head(&task->ports);
		struct mm_port *port = containerof(link, struct mm_port, ports);
		mm_port_destroy(port);
	}

	// Free the dynamic memory.
	mm_task_free_chunks(task);

	// Free the stack.
	mm_stack_destroy(task->stack_base, task->stack_size);

	// At last free the task struct.
	mm_pool_free(&mm_task_pool, task);

	LEAVE();
}
示例#2
0
文件: task.c 项目: respu/MainMemory
/* Free task-local dynamic memory. */
static void
mm_task_free_chunks(struct mm_task *task)
{
	ENTER();

	while (!mm_list_empty(&task->chunks)) {
		struct mm_list *link = mm_list_delete_head(&task->chunks);
		mm_local_free(link);
	}

	LEAVE();
}
示例#3
0
struct mm_timeq_entry *
mm_timeq_getmin(struct mm_timeq *timeq)
{
	struct mm_timeq_entry *entry;

restart:
	if (!mm_list_empty(&timeq->fe)) {

		struct mm_link *link = mm_list_head(&timeq->fe);
		entry = containerof(link, struct mm_timeq_entry, queue);
		DEBUG("fe entry: %p", entry);

	} else {
		while (timeq->t1_index < timeq->t1_count
示例#4
0
mm_task_combiner_execute(struct mm_task_combiner *combiner,
			 mm_combiner_routine_t routine, uintptr_t data)
{
	ENTER();

	// Disable cancellation as the enqueue algorithm cannot be
	// safely undone if interrupted in the middle.
	int cancelstate;
	mm_task_setcancelstate(MM_TASK_CANCEL_DISABLE, &cancelstate);

	// Get per-core queue of pending requests.
	mm_core_t core = mm_core_self();
	struct mm_list *wait_queue = MM_THREAD_LOCAL_DEREF(core, combiner->wait_queue);

	// Add the current request to the per-core queue.
	struct mm_task *task = mm_task_selfptr();
	task->flags |= MM_TASK_COMBINING;
	mm_list_append(wait_queue, &task->wait_queue);

	// Wait until the current request becomes the head of the
	// per-core queue.
	while (mm_list_head(wait_queue) != &task->wait_queue)
		mm_task_block();

	mm_combiner_execute(&combiner->combiner, routine, data);

	// Remove the request from the per-core queue.
	mm_list_delete(&task->wait_queue);
	task->flags &= ~MM_TASK_COMBINING;

	// If the per-core queue is not empty then let its new head take
	// the next turn.
	if (!mm_list_empty(wait_queue)) {
		struct mm_link *link = mm_list_head(wait_queue);
		task = containerof(link, struct mm_task, wait_queue);
		mm_task_run(task);
	}

	// Restore cancellation.
	mm_task_setcancelstate(cancelstate, NULL);

	LEAVE();
}
示例#5
0
文件: task.c 项目: respu/MainMemory
/* Create a new task. */
struct mm_task *
mm_task_create(const struct mm_task_attr *attr,
	       mm_routine_t start, mm_value_t start_arg)
{
	ENTER();

	// Check to see if called from the bootstrap context.
	bool boot = (mm_core == NULL);

	struct mm_task *task = NULL;
	// Try to reuse a dead task.
	if (likely(!boot) && !mm_list_empty(&mm_core->dead)) {
		// Get the last dead task.
		struct mm_list *link = mm_list_head(&mm_core->dead);
		struct mm_task *dead = containerof(link, struct mm_task, queue);

		// Check it against the required stack size.
		uint32_t stack_size = (attr != NULL
				       ? attr->stack_size
				       : MM_TASK_STACK_SIZE);
		if (dead->stack_size == stack_size) {
			// The dead task is just good.
			mm_list_delete(link);
			task = dead;
		} else if (dead->stack_size != MM_TASK_STACK_SIZE) {
			// The dead task has an unusual stack, free it.
			mm_stack_destroy(dead->stack_base, dead->stack_size);
			dead->stack_base = NULL;
			// Now use that task.
			mm_list_delete(link);
			task = dead;
		} else {
			// A task with unusual stack size is requested, leave
			// the dead task alone, it is likely to be reused the
			// next time.
		}
	}
	// Allocate a new task if needed.
	if (task == NULL)
		task = mm_task_new();

	// Initialize the task info.
	mm_task_set_attr(task, attr);
	task->start = start;
	task->start_arg = start_arg;

	// Allocate a new stack if needed.
	if (task->stack_base == NULL)
		task->stack_base = mm_stack_create(task->stack_size, MM_PAGE_SIZE);

	// Setup the task entry point on its own stack and queue it for
	// execution unless bootstrapping in which case it will be done
	// later in a special way.
	if (likely(!boot)) {
		mm_stack_init(&task->stack_ctx, mm_task_entry,
			      task->stack_base, task->stack_size);
		mm_task_run(task);
	}

	LEAVE();
	return task;
}