arm_createstack.c: Save tcb->adj_stack_size without tls overhead.
This commit is contained in:
parent
b5f429c88b
commit
87614e2efd
@ -102,26 +102,26 @@
|
||||
|
||||
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
{
|
||||
/* Add the size of the TLS information structure */
|
||||
size_t alloc_size;
|
||||
|
||||
stack_size += sizeof(struct tls_info_s);
|
||||
/* Add the size of the TLS information structure and align */
|
||||
|
||||
alloc_size = STACK_ALIGN_UP(stack_size + sizeof(struct tls_info_s));
|
||||
|
||||
#ifdef CONFIG_TLS_ALIGNED
|
||||
/* The allocated stack size must not exceed the maximum possible for the
|
||||
* TLS feature.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(stack_size <= TLS_MAXSTACK);
|
||||
if (stack_size >= TLS_MAXSTACK)
|
||||
DEBUGASSERT(alloc_size <= TLS_MAXSTACK);
|
||||
if (alloc_size > TLS_MAXSTACK)
|
||||
{
|
||||
stack_size = TLS_MAXSTACK;
|
||||
alloc_size = TLS_MAXSTACK;
|
||||
stack_size = alloc_size - sizeof(struct tls_info_s);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Is there already a stack allocated of a different size? Because of
|
||||
* alignment issues, stack_size might erroneously appear to be of a
|
||||
* different size. Fortunately, this is not a critical operation.
|
||||
*/
|
||||
/* Is there already a stack allocated of a different size? */
|
||||
|
||||
if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size)
|
||||
{
|
||||
@ -146,7 +146,7 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
if (ttype == TCB_FLAG_TTYPE_KERNEL)
|
||||
{
|
||||
tcb->stack_alloc_ptr =
|
||||
(uint32_t *)kmm_memalign(TLS_STACK_ALIGN, stack_size);
|
||||
(uint32_t *)kmm_memalign(TLS_STACK_ALIGN, alloc_size);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -154,7 +154,7 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
/* Use the user-space allocator if this is a task or pthread */
|
||||
|
||||
tcb->stack_alloc_ptr =
|
||||
(uint32_t *)kumm_memalign(TLS_STACK_ALIGN, stack_size);
|
||||
(uint32_t *)kumm_memalign(TLS_STACK_ALIGN, alloc_size);
|
||||
}
|
||||
|
||||
#else /* CONFIG_TLS_ALIGNED */
|
||||
@ -163,14 +163,16 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
|
||||
if (ttype == TCB_FLAG_TTYPE_KERNEL)
|
||||
{
|
||||
tcb->stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size);
|
||||
tcb->stack_alloc_ptr =
|
||||
(uint32_t *)kmm_memalign(CONFIG_STACK_ALIGNMENT, alloc_size);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Use the user-space allocator if this is a task or pthread */
|
||||
|
||||
tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size);
|
||||
tcb->stack_alloc_ptr =
|
||||
(uint32_t *)kumm_memalign(CONFIG_STACK_ALIGNMENT, alloc_size);
|
||||
}
|
||||
#endif /* CONFIG_TLS_ALIGNED */
|
||||
|
||||
@ -188,39 +190,21 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
|
||||
if (tcb->stack_alloc_ptr)
|
||||
{
|
||||
#if defined(CONFIG_STACK_COLORATION)
|
||||
uintptr_t stack_base;
|
||||
#endif
|
||||
size_t top_of_stack;
|
||||
size_t size_of_stack;
|
||||
|
||||
/* The ARM uses a push-down stack: the stack grows toward lower
|
||||
* addresses in memory. The stack pointer register, points to
|
||||
* the lowest, valid work address (the "top" of the stack). Items
|
||||
* on the stack are referenced as positive word offsets from sp.
|
||||
*/
|
||||
|
||||
top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4;
|
||||
|
||||
/* The ARM stack must be aligned to 8-byte alignment for EABI.
|
||||
* If necessary top_of_stack must be rounded down to the next
|
||||
* boundary
|
||||
/* Since both stack_alloc_ptr and alloc_size are in
|
||||
* CONFIG_STACK_ALIGNMENT, and the stack ptr is decremented before
|
||||
* the first write, we can directly save our variables to struct
|
||||
* tcb_s.
|
||||
*/
|
||||
|
||||
top_of_stack = STACK_ALIGN_DOWN(top_of_stack);
|
||||
|
||||
/* The size of the stack in bytes is then the difference between
|
||||
* the top and the bottom of the stack (+4 because if the top
|
||||
* is the same as the bottom, then the size is one 32-bit element).
|
||||
* The size need not be aligned.
|
||||
*/
|
||||
|
||||
size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;
|
||||
|
||||
/* Save the adjusted stack values in the struct tcb_s */
|
||||
|
||||
tcb->adj_stack_ptr = (uint32_t *)top_of_stack;
|
||||
tcb->adj_stack_size = size_of_stack;
|
||||
tcb->adj_stack_size = stack_size;
|
||||
tcb->adj_stack_ptr = (FAR void *)((uintptr_t)tcb->stack_alloc_ptr +
|
||||
alloc_size);
|
||||
|
||||
/* Initialize the TLS data structure */
|
||||
|
||||
@ -232,11 +216,8 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
* water marks.
|
||||
*/
|
||||
|
||||
stack_base = (uintptr_t)tcb->stack_alloc_ptr +
|
||||
sizeof(struct tls_info_s);
|
||||
stack_size = tcb->adj_stack_size -
|
||||
sizeof(struct tls_info_s);
|
||||
arm_stack_color((FAR void *)stack_base, stack_size);
|
||||
arm_stack_color((FAR void *)((uintptr_t)tcb->adj_stack_ptr -
|
||||
tcb->adj_stack_size), tcb->adj_stack_size);
|
||||
|
||||
#endif /* CONFIG_STACK_COLORATION */
|
||||
|
||||
|
@ -87,9 +87,6 @@
|
||||
|
||||
int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size)
|
||||
{
|
||||
size_t top_of_stack;
|
||||
size_t size_of_stack;
|
||||
|
||||
#ifdef CONFIG_TLS_ALIGNED
|
||||
/* Make certain that the user provided stack is properly aligned */
|
||||
|
||||
@ -105,51 +102,54 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size)
|
||||
up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK);
|
||||
}
|
||||
|
||||
/* The ARM uses a push-down stack: the stack grows toward lower
|
||||
* addresses in memory. The stack pointer register, points to
|
||||
* the lowest, valid work address (the "top" of the stack). Items
|
||||
* on the stack are referenced as positive word offsets from sp.
|
||||
*/
|
||||
|
||||
/* We align all sizes and pointer to CONFIG_STACK_ALIGNMENT.
|
||||
* Since the stack ptr is decremented before
|
||||
* the first write, we can directly save our variables to struct
|
||||
* tcb_s.
|
||||
*/
|
||||
|
||||
/* Save the new stack allocation */
|
||||
|
||||
tcb->stack_alloc_ptr = stack;
|
||||
|
||||
/* The ARM uses a push-down stack: the stack grows toward lower addresses
|
||||
* in memory. The stack pointer register, points to the lowest, valid
|
||||
* work address (the "top" of the stack). Items on the stack are
|
||||
* referenced as positive word offsets from sp.
|
||||
*/
|
||||
/* Align stack top */
|
||||
|
||||
top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4;
|
||||
tcb->adj_stack_ptr =
|
||||
(FAR void *)STACK_ALIGN_DOWN((uintptr_t)stack + stack_size);
|
||||
|
||||
/* The ARM stack must be aligned to 8-byte alignment for EABI.
|
||||
* If necessary top_of_stack must be rounded down to the next
|
||||
* boundary
|
||||
*/
|
||||
/* Offset by tls_size */
|
||||
|
||||
top_of_stack = STACK_ALIGN_DOWN(top_of_stack);
|
||||
stack = (FAR void *)((uintptr_t)stack + sizeof(struct tls_info_s));
|
||||
|
||||
/* The size of the stack in bytes is then the difference between
|
||||
* the top and the bottom of the stack (+4 because if the top
|
||||
* is the same as the bottom, then the size is one 32-bit element).
|
||||
* The size need not be aligned.
|
||||
*/
|
||||
/* Is there enough room for at least TLS ? */
|
||||
|
||||
size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;
|
||||
if ((uintptr_t)stack <= (uintptr_t)tcb->adj_stack_ptr)
|
||||
{
|
||||
tcb->adj_stack_size = (uintptr_t)tcb->adj_stack_ptr - (uintptr_t)stack;
|
||||
|
||||
/* Save the adjusted stack values in the struct tcb_s */
|
||||
/* Initialize the TLS data structure */
|
||||
|
||||
tcb->adj_stack_ptr = (uint32_t *)top_of_stack;
|
||||
tcb->adj_stack_size = size_of_stack;
|
||||
memset(tcb->stack_alloc_ptr, 0, sizeof(struct tls_info_s));
|
||||
|
||||
/* Initialize the TLS data structure */
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
/* If stack debug is enabled, then fill the stack with a
|
||||
* recognizable value that we can use later to test for high
|
||||
* water marks.
|
||||
*/
|
||||
|
||||
memset(tcb->stack_alloc_ptr, 0, sizeof(struct tls_info_s));
|
||||
arm_stack_color((FAR void *)((uintptr_t)tcb->adj_stack_ptr -
|
||||
tcb->adj_stack_size), tcb->adj_stack_size);
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
/* If stack debug is enabled, then fill the stack with a recognizable
|
||||
* value that we can use later to test for high water marks.
|
||||
*/
|
||||
#endif /* CONFIG_STACK_COLORATION */
|
||||
|
||||
arm_stack_color((FAR void *)((uintptr_t)tcb->stack_alloc_ptr +
|
||||
sizeof(struct tls_info_s)),
|
||||
tcb->adj_stack_size - sizeof(struct tls_info_s));
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
|
||||
return OK;
|
||||
return ERROR;
|
||||
}
|
||||
|
@ -126,12 +126,9 @@ pid_t up_vfork(const struct vfork_s *context)
|
||||
|
||||
sinfo("TCBs: Parent=%p Child=%p\n", parent, child);
|
||||
|
||||
/* Get the size of the parent task's stack. Due to alignment operations,
|
||||
* the adjusted stack size may be smaller than the stack size originally
|
||||
* requested.
|
||||
*/
|
||||
/* Get the size of the parent task's stack. */
|
||||
|
||||
stacksize = parent->adj_stack_size + CONFIG_STACK_ALIGNMENT - 1;
|
||||
stacksize = parent->adj_stack_size;
|
||||
|
||||
/* Allocate the stack for the TCB */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user