Esempio n. 1
0
/**
 *
 * @brief Create a new kernel execution thread
 *
 * This function is utilized to create execution threads for both fiber
 * threads and kernel tasks.
 *
 * The "thread control block" (TCS) is carved from the "end" of the specified
 * thread stack memory.
 *
 * @param pStackmem the pointer to aligned stack memory
 * @param stackSize the stack size in bytes
 * @param pEntry thread entry point routine
 * @param parameter1 first param to entry point
 * @param parameter2 second param to entry point
 * @param parameter3 third param to entry point
 * @param priority  thread priority
 * @param options thread options: USE_FP, USE_SSE
 *
 *
 * @return opaque pointer to initialized TCS structure
 */
void _new_thread(char *pStackMem, unsigned stackSize, _thread_entry_t pEntry,
		 void *parameter1, void *parameter2, void *parameter3,
		 int priority, unsigned options)
{
	unsigned long *pInitialThread;

#ifdef CONFIG_INIT_STACKS
	memset(pStackMem, 0xaa, stackSize);
#endif

	/* carve the thread entry struct from the "base" of the stack */

	pInitialThread =
		(unsigned long *)STACK_ROUND_DOWN(pStackMem + stackSize);

	/*
	 * Create an initial context on the stack expected by the _Swap()
	 * primitive.
	 * Given that both task and fibers execute at privilege 0, the
	 * setup for both threads are equivalent.
	 */

	/* push arguments required by _thread_entry() */

	*--pInitialThread = (unsigned long)parameter3;
	*--pInitialThread = (unsigned long)parameter2;
	*--pInitialThread = (unsigned long)parameter1;
	*--pInitialThread = (unsigned long)pEntry;

	/* push initial EFLAGS; only modify IF and IOPL bits */

	*--pInitialThread = (EflagsGet() & ~EFLAGS_MASK) | EFLAGS_INITIAL;

#ifdef CONFIG_GDB_INFO

	/*
	 * Arrange for the _thread_entry_wrapper() function to be called
	 * to adjust the stack before _thread_entry() is invoked.
	 */

	*--pInitialThread = (unsigned long)_thread_entry_wrapper;

#else /* CONFIG_GDB_INFO */

	*--pInitialThread = (unsigned long)_thread_entry;

#endif /* CONFIG_GDB_INFO */

	/*
	 * note: stack area for edi, esi, ebx, ebp, and eax registers can be
	 * left
	 * uninitialized, since _thread_entry() doesn't care about the values
	 * of these registers when it begins execution
	 */

	/*
	 * For kernel tasks and fibers the thread the thread control struct (TCS)
	 * is located at the "low end" of memory set aside for the thread's stack.
	 */

	_new_thread_internal(pStackMem, stackSize, priority, options);
}
Esempio n. 2
0
void _NewContext(
	char *pStackMem,      /* pointer to aligned stack memory */
	unsigned stackSize,   /* size of stack in bytes */
	_ContextEntry pEntry, /* context entry point function */
	void *parameter1, /* first parameter to context entry point function */
	void *parameter2, /* second parameter to context entry point function */
	void *parameter3, /* third parameter to context entry point function */
	int priority,     /* context priority */
	unsigned options  /* context options: USE_FP, USE_SSE */
	)
{
	unsigned long *pInitialContext;

#ifdef CONFIG_INIT_STACKS
    k_memset(pStackMem, 0xaa, stackSize);
#endif

	/* carve the context entry struct from the "base" of the stack */

	pInitialContext =
		(unsigned long *)STACK_ROUND_DOWN(pStackMem + stackSize);

	/*
	 * Create an initial context on the stack expected by the _Swap()
	 * primitive.
	 * Given that both task and fiber contexts execute at privilege 0, the
	 * setup for both contexts are equivalent.
	 */

	/* push arguments required by _context_entry() */

	*--pInitialContext = (unsigned long)parameter3;
	*--pInitialContext = (unsigned long)parameter2;
	*--pInitialContext = (unsigned long)parameter1;
	*--pInitialContext = (unsigned long)pEntry;

	/* push initial EFLAGS; only modify IF and IOPL bits */

	*--pInitialContext = (EflagsGet() & ~EFLAGS_MASK) | EFLAGS_INITIAL;

#ifdef CONFIG_GDB_INFO

	/*
	 * Arrange for the _ContextEntryWrapper() function to be called
	 * to adjust the stack before _context_entry() is invoked.
	 */

	*--pInitialContext = (unsigned long)_ContextEntryWrapper;

#else /* CONFIG_GDB_INFO */

	*--pInitialContext = (unsigned long)_context_entry;

#endif /* CONFIG_GDB_INFO */

	/*
	 * note: stack area for edi, esi, ebx, ebp, and eax registers can be
	 * left
	 * uninitialized, since _context_entry() doesn't care about the values
	 * of these registers when it begins execution
	 */

	/*
	 * For kernel tasks and fibers the context the context control struct
	 * (CCS)
	 * is located at the "low end" of memory set aside for the context's
	 * stack
	 */

	_NewContextInternal(pStackMem, stackSize, priority, options);
}