diff --git a/ChangeLog b/ChangeLog index b0d3f904e71c12217178e5a57b085b2534e33ffa..bddcb4367bb8646ecec1d4ee5c2ec37b5bcae50e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4402,4 +4402,7 @@ big, initial checkin. The next step will be to add logic to allocate stacks for kernel threads from protected kernel memory and all other task types from unprotected user memory (2013-03-20). - + * arch/*/src/common/up_createstack.c, up_use_stack.c, and + up_release_stack.c: If creating or releasing the stack for a kernel + thread, use the kernel allocator so that the kernel thread stacks + are protected from user application meddling (2013-03-20). diff --git a/arch/arm/src/common/up_createstack.c b/arch/arm/src/common/up_createstack.c index 65eb91159bdc38f1da6f1c2e9ce0334a7bda1bb3..634fb9d61f38a213d85f290ca8ee6aca0b366c85 100644 --- a/arch/arm/src/common/up_createstack.c +++ b/arch/arm/src/common/up_createstack.c @@ -146,17 +146,19 @@ static void *memset32(void *s, uint32_t c, size_t n) int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { - /* Is there already a stack allocated of a different size? */ + /* 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. + */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { - /* Yes.. free it */ + /* Yes.. Release the old stack */ - sched_ufree(tcb->stack_alloc_ptr); - tcb->stack_alloc_ptr = NULL; + up_release_stack(tcb, ttype); } - /* Do we need to allocate a stack? */ + /* Do we need to allocate a new stack? */ if (!tcb->stack_alloc_ptr) { @@ -164,12 +166,32 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) * then create a zeroed stack to make stack dumps easier to trace. */ +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { +#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) + tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); +#else + tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); +#endif + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) - tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); #else - tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); #endif + } + #ifdef CONFIG_DEBUG + /* Was the allocation successful? */ + if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); @@ -218,7 +240,7 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) */ #if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) - memset32(tcb->stack_alloc_ptr, 0xDEADBEEF, tcb->adj_stack_size/4); + memset32(tcb->stack_alloc_ptr, 0xdeadbeef, tcb->adj_stack_size/4); #endif up_ledon(LED_STACKCREATED); diff --git a/arch/arm/src/common/up_releasestack.c b/arch/arm/src/common/up_releasestack.c index 711022f93e45f6720bd2ad80930554966f1183d5..9ab872d3328e497489ac9252cf2267ea3abd4f13 100644 --- a/arch/arm/src/common/up_releasestack.c +++ b/arch/arm/src/common/up_releasestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/common/up_releasestack.c * - * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -91,11 +91,31 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { + /* Is there a stack allocated? */ + if (dtcb->stack_alloc_ptr) { - sched_ufree(dtcb->stack_alloc_ptr); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } + + /* Mark the stack freed */ + dtcb->stack_alloc_ptr = NULL; } + /* The size of the allocated stack is now zero */ + dtcb->adj_stack_size = 0; } diff --git a/arch/arm/src/common/up_usestack.c b/arch/arm/src/common/up_usestack.c index a141006bbdaf18e52d90a800a99178be16f3329a..a45ec99b57b45582b1c5c43161bb8e50ddc113ff 100644 --- a/arch/arm/src/common/up_usestack.c +++ b/arch/arm/src/common/up_usestack.c @@ -121,12 +121,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) size_t top_of_stack; size_t size_of_stack; + /* Is there already a stack allocated? */ + if (tcb->stack_alloc_ptr) { - sched_ufree(tcb->stack_alloc_ptr); + /* Yes... Release the old stack allocation */ + + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); } - /* Save the stack allocation */ + /* Save the new stack allocation */ tcb->stack_alloc_ptr = stack; diff --git a/arch/avr/src/avr/up_createstack.c b/arch/avr/src/avr/up_createstack.c index 60f6dceec98466bedcb9a11274d3065925ed5fa9..98423be1f0970cd75c5bedb49b4dc1048838a81f 100644 --- a/arch/avr/src/avr/up_createstack.c +++ b/arch/avr/src/avr/up_createstack.c @@ -105,30 +105,52 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { - /* Is there already a stack allocated of a different size? */ + /* 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. + */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { - /* Yes.. free it */ + /* Yes.. Release the old stack */ - sched_ufree(tcb->stack_alloc_ptr); - tcb->stack_alloc_ptr = NULL; + up_release_stack(tcb, ttype); } - /* Do we need to allocate a stack? */ - + /* Do we need to allocate a new stack? */ + if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), * then create a zeroed stack to make stack dumps easier to trace. */ +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) - tcb->stack_alloc_ptr = (FAR void *)kuzalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); #else - tcb->stack_alloc_ptr = (FAR void *)kumalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); #endif + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + +#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) + tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); +#else + tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); +#endif + } + #ifdef CONFIG_DEBUG + /* Was the allocation successful? */ + if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); diff --git a/arch/avr/src/avr/up_usestack.c b/arch/avr/src/avr/up_usestack.c index ebd911fb25da8e3a4fd4f4a76e535bdc452b0d29..629ad6cf021f28823b189ec6490de89730371813 100644 --- a/arch/avr/src/avr/up_usestack.c +++ b/arch/avr/src/avr/up_usestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/avr/src/avr/up_usestack.c * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -98,12 +98,12 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) if (tcb->stack_alloc_ptr) { - /* Yes.. free it */ + /* Yes.. Release the old stack allocation */ - sched_ufree(tcb->stack_alloc_ptr); + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); } - /* Save the stack allocation */ + /* Save the new stack allocation */ tcb->stack_alloc_ptr = stack; diff --git a/arch/avr/src/avr32/up_createstack.c b/arch/avr/src/avr32/up_createstack.c index da7e8788c57c3fb5bca80b72c5268a9a85737d37..76ed2c0f5e0aec3ecdd9a55fcaaf16d68a170dbd 100644 --- a/arch/avr/src/avr32/up_createstack.c +++ b/arch/avr/src/avr32/up_createstack.c @@ -104,30 +104,52 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { - /* Is there already a stack allocated of a different size? */ + /* 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. + */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { - /* Yes.. free it */ + /* Yes.. Release the old stack */ - sched_ufree(tcb->stack_alloc_ptr); - tcb->stack_alloc_ptr = NULL; + up_release_stack(tcb, ttype); } - /* Do we need to allocate a stack? */ - + /* Do we need to allocate a new stack? */ + if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), * then create a zeroed stack to make stack dumps easier to trace. */ +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) - tcb->stack_alloc_ptr = (FAR void *)kuzalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); #else - tcb->stack_alloc_ptr = (FAR void *)kumalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); #endif + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + +#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) + tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); +#else + tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); +#endif + } + #ifdef CONFIG_DEBUG + /* Was the allocation successful? */ + if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); diff --git a/arch/avr/src/avr32/up_usestack.c b/arch/avr/src/avr32/up_usestack.c index 86cdc2de402eb294c83b2ca1259cd2673a713904..e71be16e7e17f94dcb975a7be48e11ed1aa5a3bd 100644 --- a/arch/avr/src/avr32/up_usestack.c +++ b/arch/avr/src/avr32/up_usestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/avr/src/avr32/up_usestack.c * - * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Copyright (C) 2010, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -94,12 +94,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) size_t top_of_stack; size_t size_of_stack; + /* Is there already a stack allocated? */ + if (tcb->stack_alloc_ptr) { - sched_ufree(tcb->stack_alloc_ptr); + /* Yes.. Release the old stack allocation */ + + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); } - /* Save the stack allocation */ + /* Save the new stack allocation */ tcb->stack_alloc_ptr = stack; diff --git a/arch/avr/src/common/up_releasestack.c b/arch/avr/src/common/up_releasestack.c index 7d3e6f28c2a6c042397793b2ca7dc7b85ab753e2..ec172bd5e4e4ab8149803ca50779401371afc8e6 100644 --- a/arch/avr/src/common/up_releasestack.c +++ b/arch/avr/src/common/up_releasestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/avr/src/common/up_releasestack.c * - * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Copyright (C) 2010, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -91,12 +91,32 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { + /* Is there a stack allocated? */ + if (dtcb->stack_alloc_ptr) { - sched_ufree(dtcb->stack_alloc_ptr); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } + + /* Mark the stack freed */ + dtcb->stack_alloc_ptr = NULL; } + /* The size of the allocated stack is now zero */ + dtcb->adj_stack_size = 0; } diff --git a/arch/hc/src/common/up_createstack.c b/arch/hc/src/common/up_createstack.c index a8b192c4bc2926d67739241a9c4a10536f558966..d7050f5122dbd52a46f2a515e006b37efe2e1d2f 100644 --- a/arch/hc/src/common/up_createstack.c +++ b/arch/hc/src/common/up_createstack.c @@ -101,30 +101,52 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { - /* Is there already a stack allocated of a different size? */ + /* 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. + */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { - /* Yes.. free it */ + /* Yes.. Release the old stack */ - sched_ufree(tcb->stack_alloc_ptr); - tcb->stack_alloc_ptr = NULL; + up_release_stack(tcb, ttype); } - /* Do we need to allocate a stack? */ - + /* Do we need to allocate a new stack? */ + if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), * then create a zeroed stack to make stack dumps easier to trace. */ +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) - tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); #else - tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); #endif + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + +#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) + tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); +#else + tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); +#endif + } + #ifdef CONFIG_DEBUG + /* Was the allocation successful? */ + if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); diff --git a/arch/hc/src/common/up_releasestack.c b/arch/hc/src/common/up_releasestack.c index f8c2fa142d15b49b077d96f3ef08eaf251cf4274..800e0ccb5ad52fcae225ece4aaf2029e06736256 100644 --- a/arch/hc/src/common/up_releasestack.c +++ b/arch/hc/src/common/up_releasestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/hc/src/common/up_releasestack.c * - * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -92,11 +92,31 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { + /* Is there a stack allocated? */ + if (dtcb->stack_alloc_ptr) { - sched_ufree(dtcb->stack_alloc_ptr); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } + + /* Mark the stack freed */ + dtcb->stack_alloc_ptr = NULL; } + /* The size of the allocated stack is now zero */ + dtcb->adj_stack_size = 0; } diff --git a/arch/hc/src/common/up_usestack.c b/arch/hc/src/common/up_usestack.c index 7f3c8fc6690b73dc86b71381cd42d95614338f89..047ba2e9a56e4743c1c8ecd79f5113760a7ed6b5 100644 --- a/arch/hc/src/common/up_usestack.c +++ b/arch/hc/src/common/up_usestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/hc/src/common/up_usestack.c * - * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -93,13 +93,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) size_t top_of_stack; size_t size_of_stack; + /* Is there already a stack allocated? */ + if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { - sched_ufree(tcb->stack_alloc_ptr); - tcb->stack_alloc_ptr = NULL; + /* Yes.. Release the old stack allocation */ + + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); } - /* Save the stack allocation */ + /* Save the new stack allocation */ tcb->stack_alloc_ptr = stack; diff --git a/arch/mips/src/common/up_createstack.c b/arch/mips/src/common/up_createstack.c index b228e80619792033a38fe3aaf60683377459f33a..6109797a34d5fe1cdd6c01e191554011247c0da0 100644 --- a/arch/mips/src/common/up_createstack.c +++ b/arch/mips/src/common/up_createstack.c @@ -122,30 +122,52 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { - /* Is there already a stack allocated of a different size? */ + /* 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. + */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { - /* Yes.. free it */ + /* Yes.. Release the old stack */ - sched_ufree(tcb->stack_alloc_ptr); - tcb->stack_alloc_ptr = NULL; + up_release_stack(tcb, ttype); } - /* Do we need to allocate a stack? */ - + /* Do we need to allocate a new stack? */ + if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), * then create a zeroed stack to make stack dumps easier to trace. */ +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) - tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); #else - tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); #endif + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + +#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) + tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); +#else + tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); +#endif + } + #ifdef CONFIG_DEBUG + /* Was the allocation successful? */ + if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); diff --git a/arch/mips/src/common/up_releasestack.c b/arch/mips/src/common/up_releasestack.c index 3ce46bebdcade13e2395cffdcf51661c0a1e8b32..f1cb44c230aa522e74f6ab1eaa1967bebe2c80c2 100644 --- a/arch/mips/src/common/up_releasestack.c +++ b/arch/mips/src/common/up_releasestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/mips/src/common/up_releasestack.c * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -91,11 +91,31 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { + /* Is there a stack allocated? */ + if (dtcb->stack_alloc_ptr) { - sched_ufree(dtcb->stack_alloc_ptr); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } + + /* Mark the stack freed */ + dtcb->stack_alloc_ptr = NULL; } + /* The size of the allocated stack is now zero */ + dtcb->adj_stack_size = 0; } diff --git a/arch/mips/src/common/up_usestack.c b/arch/mips/src/common/up_usestack.c index fe1d27818ddb925180a6acf6979adfa8ce67c688..b636a51d787dd1209c28e7cd7b853b79caa3f555 100644 --- a/arch/mips/src/common/up_usestack.c +++ b/arch/mips/src/common/up_usestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/mips/src/common/up_usestack.c * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -94,12 +94,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) size_t top_of_stack; size_t size_of_stack; + /* Is there already a stack allocated? */ + if (tcb->stack_alloc_ptr) { - sched_ufree(tcb->stack_alloc_ptr); + /* Yes.. Release the old stack allocation */ + + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); } - /* Save the stack allocation */ + /* Save the new stack allocation */ tcb->stack_alloc_ptr = stack; diff --git a/arch/rgmp/src/nuttx.c b/arch/rgmp/src/nuttx.c index 3dc5310062a35434e00db9beb16ec5db55521a13..79f97fcfca443e2d9e497754543672bc44ced7b8 100644 --- a/arch/rgmp/src/nuttx.c +++ b/arch/rgmp/src/nuttx.c @@ -66,11 +66,11 @@ static inline void up_switchcontext(struct tcb_s *ctcb, struct tcb_s *ntcb) { // do nothing if two tasks are the same if (ctcb == ntcb) - return; + return; // this function can not be called in interrupt if (up_interrupt_context()) { - panic("%s: try to switch context in interrupt\n", __func__); + panic("%s: try to switch context in interrupt\n", __func__); } // start switch @@ -81,19 +81,19 @@ static inline void up_switchcontext(struct tcb_s *ctcb, struct tcb_s *ntcb) void up_initialize(void) { extern pidhash_t g_pidhash[]; - extern void vdev_init(void); + extern void vdev_init(void); extern void nuttx_arch_init(void); // intialize the current_task to g_idletcb current_task = g_pidhash[PIDHASH(0)].tcb; - // OS memory alloc system is ready - use_os_kmalloc = 1; + // OS memory alloc system is ready + use_os_kmalloc = 1; // rgmp vdev init - vdev_init(); + vdev_init(); - nuttx_arch_init(); + nuttx_arch_init(); // enable interrupt local_irq_enable(); @@ -106,13 +106,14 @@ void up_idle(void) void up_allocate_heap(void **heap_start, size_t *heap_size) { - void *boot_freemem = boot_alloc(0, sizeof(int)); + void *boot_freemem = boot_alloc(0, sizeof(int)); *heap_start = boot_freemem; *heap_size = KERNBASE + kmem_size - (uint32_t)boot_freemem; } int up_create_stack(struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { + uint32_t *stack_alloc_ptr; int ret = ERROR; size_t *adj_stack_ptr; @@ -123,18 +124,27 @@ int up_create_stack(struct tcb_s *tcb, size_t stack_size, uint8_t ttype) /* Allocate the memory for the stack */ - uint32_t *stack_alloc_ptr = (uint32_t*)kumalloc(adj_stack_size); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) { + stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); + } else +#endif + { + stack_alloc_ptr = (uint32_t*)kumalloc(adj_stack_size); + } if (stack_alloc_ptr) { - /* This is the address of the last word in the allocation */ + /* This is the address of the last word in the allocation */ - adj_stack_ptr = &stack_alloc_ptr[adj_stack_words - 1]; + adj_stack_ptr = &stack_alloc_ptr[adj_stack_words - 1]; - /* Save the values in the TCB */ + /* Save the values in the TCB */ - tcb->adj_stack_size = adj_stack_size; - tcb->stack_alloc_ptr = stack_alloc_ptr; - tcb->adj_stack_ptr = (void *)((unsigned int)adj_stack_ptr & ~7); - ret = OK; + tcb->adj_stack_size = adj_stack_size; + tcb->stack_alloc_ptr = stack_alloc_ptr; + tcb->adj_stack_ptr = (void *)((unsigned int)adj_stack_ptr & ~7); + ret = OK; } return ret; } @@ -160,13 +170,28 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) void up_release_stack(struct tcb_s *dtcb, uint8_t ttype) { - if (dtcb->stack_alloc_ptr) { - kufree(dtcb->stack_alloc_ptr); - } + /* Is there a stack allocated? */ + + if (dtcb->stack_alloc_ptr) { +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) { + kfree(dtcb->stack_alloc_ptr); + } else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ - dtcb->stack_alloc_ptr = NULL; - dtcb->adj_stack_size = 0; - dtcb->adj_stack_ptr = NULL; + kufree(dtcb->stack_alloc_ptr); + } + } + + /* Mark the stack freed */ + + dtcb->stack_alloc_ptr = NULL; + dtcb->adj_stack_size = 0; + dtcb->adj_stack_ptr = NULL; } /**************************************************************************** @@ -196,43 +221,43 @@ void up_block_task(struct tcb_s *tcb, tstate_t task_state) { /* Verify that the context switch can be performed */ if ((tcb->task_state < FIRST_READY_TO_RUN_STATE) || - (tcb->task_state > LAST_READY_TO_RUN_STATE)) { - warn("%s: task sched error\n", __func__); - return; + (tcb->task_state > LAST_READY_TO_RUN_STATE)) { + warn("%s: task sched error\n", __func__); + return; } else { - struct tcb_s *rtcb = current_task; - bool switch_needed; - - /* Remove the tcb task from the ready-to-run list. If we - * are blocking the task at the head of the task list (the - * most likely case), then a context switch to the next - * ready-to-run task is needed. In this case, it should - * also be true that rtcb == tcb. - */ - switch_needed = sched_removereadytorun(tcb); - - /* Add the task to the specified blocked task list */ - sched_addblocked(tcb, (tstate_t)task_state); - - /* Now, perform the context switch if one is needed */ - if (switch_needed) { - struct tcb_s *nexttcb; - // this part should not be executed in interrupt context - if (up_interrupt_context()) { - panic("%s: %d\n", __func__, __LINE__); - } - // If there are any pending tasks, then add them to the g_readytorun - // task list now. It should be the up_realease_pending() called from - // sched_unlock() to do this for disable preemption. But it block - // itself, so it's OK. - if (g_pendingtasks.head) { - warn("Disable preemption failed for task block itself\n"); - sched_mergepending(); - } - nexttcb = (struct tcb_s*)g_readytorun.head; - // context switch - up_switchcontext(rtcb, nexttcb); + struct tcb_s *rtcb = current_task; + bool switch_needed; + + /* Remove the tcb task from the ready-to-run list. If we + * are blocking the task at the head of the task list (the + * most likely case), then a context switch to the next + * ready-to-run task is needed. In this case, it should + * also be true that rtcb == tcb. + */ + switch_needed = sched_removereadytorun(tcb); + + /* Add the task to the specified blocked task list */ + sched_addblocked(tcb, (tstate_t)task_state); + + /* Now, perform the context switch if one is needed */ + if (switch_needed) { + struct tcb_s *nexttcb; + // this part should not be executed in interrupt context + if (up_interrupt_context()) { + panic("%s: %d\n", __func__, __LINE__); + } + // If there are any pending tasks, then add them to the g_readytorun + // task list now. It should be the up_realease_pending() called from + // sched_unlock() to do this for disable preemption. But it block + // itself, so it's OK. + if (g_pendingtasks.head) { + warn("Disable preemption failed for task block itself\n"); + sched_mergepending(); + } + nexttcb = (struct tcb_s*)g_readytorun.head; + // context switch + up_switchcontext(rtcb, nexttcb); } } } @@ -256,31 +281,31 @@ void up_unblock_task(struct tcb_s *tcb) { /* Verify that the context switch can be performed */ if ((tcb->task_state < FIRST_BLOCKED_STATE) || - (tcb->task_state > LAST_BLOCKED_STATE)) { - warn("%s: task sched error\n", __func__); - return; + (tcb->task_state > LAST_BLOCKED_STATE)) { + warn("%s: task sched error\n", __func__); + return; } else { - struct tcb_s *rtcb = current_task; + struct tcb_s *rtcb = current_task; - /* Remove the task from the blocked task list */ - sched_removeblocked(tcb); + /* Remove the task from the blocked task list */ + sched_removeblocked(tcb); - /* Reset its timeslice. This is only meaningful for round - * robin tasks but it doesn't here to do it for everything - */ + /* Reset its timeslice. This is only meaningful for round + * robin tasks but it doesn't here to do it for everything + */ #if CONFIG_RR_INTERVAL > 0 - tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; + tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; #endif - - // Add the task in the correct location in the prioritized - // g_readytorun task list. - if (sched_addreadytorun(tcb) && !up_interrupt_context()) { - /* The currently active task has changed! */ - struct tcb_s *nexttcb = (struct tcb_s*)g_readytorun.head; - // context switch - up_switchcontext(rtcb, nexttcb); - } + + // Add the task in the correct location in the prioritized + // g_readytorun task list. + if (sched_addreadytorun(tcb) && !up_interrupt_context()) { + /* The currently active task has changed! */ + struct tcb_s *nexttcb = (struct tcb_s*)g_readytorun.head; + // context switch + up_switchcontext(rtcb, nexttcb); + } } } @@ -295,11 +320,11 @@ void up_release_pending(void) /* Merge the g_pendingtasks list into the g_readytorun task list */ if (sched_mergepending()) { - /* The currently active task has changed! */ - struct tcb_s *nexttcb = (struct tcb_s*)g_readytorun.head; + /* The currently active task has changed! */ + struct tcb_s *nexttcb = (struct tcb_s*)g_readytorun.head; - // context switch - up_switchcontext(rtcb, nexttcb); + // context switch + up_switchcontext(rtcb, nexttcb); } } @@ -308,54 +333,54 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) /* Verify that the caller is sane */ if (tcb->task_state < FIRST_READY_TO_RUN_STATE || - tcb->task_state > LAST_READY_TO_RUN_STATE + tcb->task_state > LAST_READY_TO_RUN_STATE #if SCHED_PRIORITY_MIN > UINT8_MIN - || priority < SCHED_PRIORITY_MIN + || priority < SCHED_PRIORITY_MIN #endif #if SCHED_PRIORITY_MAX < UINT8_MAX - || priority > SCHED_PRIORITY_MAX + || priority > SCHED_PRIORITY_MAX #endif - ) { - warn("%s: task sched error\n", __func__); - return; + ) { + warn("%s: task sched error\n", __func__); + return; } else { - struct tcb_s *rtcb = current_task; - bool switch_needed; - - /* Remove the tcb task from the ready-to-run list. - * sched_removereadytorun will return true if we just - * remove the head of the ready to run list. - */ - switch_needed = sched_removereadytorun(tcb); - - /* Setup up the new task priority */ - tcb->sched_priority = (uint8_t)priority; - - /* Return the task to the specified blocked task list. - * sched_addreadytorun will return true if the task was - * added to the new list. We will need to perform a context - * switch only if the EXCLUSIVE or of the two calls is non-zero - * (i.e., one and only one the calls changes the head of the - * ready-to-run list). - */ - switch_needed ^= sched_addreadytorun(tcb); - - /* Now, perform the context switch if one is needed */ - if (switch_needed && !up_interrupt_context()) { - struct tcb_s *nexttcb; - // If there are any pending tasks, then add them to the g_readytorun - // task list now. It should be the up_realease_pending() called from - // sched_unlock() to do this for disable preemption. But it block - // itself, so it's OK. - if (g_pendingtasks.head) { - warn("Disable preemption failed for reprioritize task\n"); - sched_mergepending(); + struct tcb_s *rtcb = current_task; + bool switch_needed; + + /* Remove the tcb task from the ready-to-run list. + * sched_removereadytorun will return true if we just + * remove the head of the ready to run list. + */ + switch_needed = sched_removereadytorun(tcb); + + /* Setup up the new task priority */ + tcb->sched_priority = (uint8_t)priority; + + /* Return the task to the specified blocked task list. + * sched_addreadytorun will return true if the task was + * added to the new list. We will need to perform a context + * switch only if the EXCLUSIVE or of the two calls is non-zero + * (i.e., one and only one the calls changes the head of the + * ready-to-run list). + */ + switch_needed ^= sched_addreadytorun(tcb); + + /* Now, perform the context switch if one is needed */ + if (switch_needed && !up_interrupt_context()) { + struct tcb_s *nexttcb; + // If there are any pending tasks, then add them to the g_readytorun + // task list now. It should be the up_realease_pending() called from + // sched_unlock() to do this for disable preemption. But it block + // itself, so it's OK. + if (g_pendingtasks.head) { + warn("Disable preemption failed for reprioritize task\n"); + sched_mergepending(); } - nexttcb = (struct tcb_s*)g_readytorun.head; - // context switch - up_switchcontext(rtcb, nexttcb); + nexttcb = (struct tcb_s*)g_readytorun.head; + // context switch + up_switchcontext(rtcb, nexttcb); } } } @@ -387,26 +412,26 @@ void up_assert(const uint8_t *filename, int line) // which will stop the OS // if in user space just terminate the task if (up_interrupt_context() || current_task->pid == 0) { - panic("%s: %d\n", __func__, __LINE__); + panic("%s: %d\n", __func__, __LINE__); } else { - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } } void up_assert_code(const uint8_t *filename, int line, int code) { fprintf(stderr, "Assertion failed at file:%s line: %d error code: %d\n", - filename, line, code); + filename, line, code); // in interrupt context or idle task means kernel error // which will stop the OS // if in user space just terminate the task if (up_interrupt_context() || current_task->pid == 0) { - panic("%s: %d\n", __func__, __LINE__); + panic("%s: %d\n", __func__, __LINE__); } else { - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } } @@ -417,38 +442,38 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) { /* Refuse to handle nested signal actions */ if (!tcb->xcp.sigdeliver) { - int flags; - - /* Make sure that interrupts are disabled */ - local_irq_save(flags); - - // First, handle some special cases when the signal is - // being delivered to the currently executing task. - if (tcb == current_task) { - // CASE 1: We are not in an interrupt handler and - // a task is signalling itself for some reason. - if (!up_interrupt_context()) { - // In this case just deliver the signal now. - sigdeliver(tcb); - } - // CASE 2: We are in an interrupt handler AND the - // interrupted task is the same as the one that - // must receive the signal. - else { - tcb->xcp.sigdeliver = sigdeliver; + int flags; + + /* Make sure that interrupts are disabled */ + local_irq_save(flags); + + // First, handle some special cases when the signal is + // being delivered to the currently executing task. + if (tcb == current_task) { + // CASE 1: We are not in an interrupt handler and + // a task is signalling itself for some reason. + if (!up_interrupt_context()) { + // In this case just deliver the signal now. + sigdeliver(tcb); + } + // CASE 2: We are in an interrupt handler AND the + // interrupted task is the same as the one that + // must receive the signal. + else { + tcb->xcp.sigdeliver = sigdeliver; } } - // Otherwise, we are (1) signaling a task is not running - // from an interrupt handler or (2) we are not in an - // interrupt handler and the running task is signalling - // some non-running task. - else { - tcb->xcp.sigdeliver = sigdeliver; - push_xcptcontext(&tcb->xcp); + // Otherwise, we are (1) signaling a task is not running + // from an interrupt handler or (2) we are not in an + // interrupt handler and the running task is signalling + // some non-running task. + else { + tcb->xcp.sigdeliver = sigdeliver; + push_xcptcontext(&tcb->xcp); } - local_irq_restore(flags); + local_irq_restore(flags); } } @@ -458,7 +483,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) bool up_interrupt_context(void) { if (nest_irq) - return true; + return true; return false; } @@ -497,7 +522,7 @@ void up_sigdeliver(struct Trapframe *tf) void up_cxxinitialize(void) { - rgmp_cxx_init(); + rgmp_cxx_init(); } #endif diff --git a/arch/sh/src/common/up_createstack.c b/arch/sh/src/common/up_createstack.c index 3ffdc30509eb57602ad2fe5982e420360d2b594c..5a22fd3e6e6d758886ebd9938a9e3714c7487503 100644 --- a/arch/sh/src/common/up_createstack.c +++ b/arch/sh/src/common/up_createstack.c @@ -101,30 +101,52 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { - /* Is there already a stack allocated of a different size? */ + /* 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. + */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { - /* Yes.. free it */ + /* Yes.. Release the old stack */ - sched_ufree(tcb->stack_alloc_ptr); - tcb->stack_alloc_ptr = NULL; + up_release_stack(tcb, ttype); } - /* Do we need to allocate a stack? */ - + /* Do we need to allocate a new stack? */ + if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), * then create a zeroed stack to make stack dumps easier to trace. */ +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) - tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); #else - tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); #endif + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + +#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) + tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); +#else + tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); +#endif + } + #ifdef CONFIG_DEBUG + /* Was the allocation successful? */ + if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); diff --git a/arch/sh/src/common/up_releasestack.c b/arch/sh/src/common/up_releasestack.c index 83257811870587c4d8ed3244203091fdafc9b0e8..e88e06d5232a790a958e3884ae5896b0914ed6d2 100644 --- a/arch/sh/src/common/up_releasestack.c +++ b/arch/sh/src/common/up_releasestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/sh/src/common/up_releasestack.c * - * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -91,11 +91,31 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { + /* Is there a stack allocated? */ + if (dtcb->stack_alloc_ptr) { - sched_ufree(dtcb->stack_alloc_ptr); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } + + /* Mark the stack freed */ + dtcb->stack_alloc_ptr = NULL; } + /* The size of the allocated stack is now zero */ + dtcb->adj_stack_size = 0; } diff --git a/arch/sh/src/common/up_usestack.c b/arch/sh/src/common/up_usestack.c index 7c2b9586ea0d370b6377c948de1f423bc34c87fc..bcce3261cdc850819650744cc7408fd864e8f17d 100644 --- a/arch/sh/src/common/up_usestack.c +++ b/arch/sh/src/common/up_usestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/sh/src/common/up_usestack.c * - * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -94,13 +94,17 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) size_t top_of_stack; size_t size_of_stack; + /* Is there already a stack allocated? */ + if (tcb->stack_alloc_ptr) { - sched_ufree(tcb->stack_alloc_ptr); - } + /* Yes.. Release the old stack allocation */ - /* Save the stack allocation */ + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); + } + /* Save the new stack allocation */ + tcb->stack_alloc_ptr = stack; /* The Arm7Tdmi uses a push-down stack: the stack grows diff --git a/arch/sim/src/up_createstack.c b/arch/sim/src/up_createstack.c index fe9986e65fa1243d8fc6d988f5650d949c197377..4115dd4ede149912f3ab7382ac5d0d3ba88322bf 100644 --- a/arch/sim/src/up_createstack.c +++ b/arch/sim/src/up_createstack.c @@ -102,6 +102,7 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { + uint32_t *stack_alloc_ptr; int ret = ERROR; /* Move up to next even word boundary if necessary */ @@ -111,7 +112,21 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) /* Allocate the memory for the stack */ - uint32_t *stack_alloc_ptr = (uint32_t*)kumalloc(adj_stack_size); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); + } + else +#endif + { + stack_alloc_ptr = (uint32_t*)kumalloc(adj_stack_size); + } + + /* Was the allocation successful? */ + if (stack_alloc_ptr) { /* This is the address of the last word in the allocation */ diff --git a/arch/sim/src/up_releasestack.c b/arch/sim/src/up_releasestack.c index 56413f341822ba42a11e93667835469530863df2..248f6b712c2f51ce89735645cfd057a95bb84911 100644 --- a/arch/sim/src/up_releasestack.c +++ b/arch/sim/src/up_releasestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * up_releasestack.c * - * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -93,11 +93,28 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { + /* Is there a stack allocated? */ + if (dtcb->stack_alloc_ptr) { - free(dtcb->stack_alloc_ptr); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } } + /* Mark the stack freed */ + dtcb->stack_alloc_ptr = NULL; dtcb->adj_stack_size = 0; dtcb->adj_stack_ptr = NULL; diff --git a/arch/x86/src/i486/up_createstack.c b/arch/x86/src/i486/up_createstack.c index bcce5fdcc43342556639e38e4a30e0f794f69a74..ae394dea6f332f11f075b11a11e86316009b9fcb 100644 --- a/arch/x86/src/i486/up_createstack.c +++ b/arch/x86/src/i486/up_createstack.c @@ -103,30 +103,52 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { - /* Is there already a stack allocated of a different size? */ + /* 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. + */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { - /* Yes.. free it */ + /* Yes.. Release the old stack */ - sched_ufree(tcb->stack_alloc_ptr); - tcb->stack_alloc_ptr = NULL; + up_release_stack(tcb, ttype); } - /* Do we need to allocate a stack? */ - + /* Do we need to allocate a new stack? */ + if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), * then create a zeroed stack to make stack dumps easier to trace. */ +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) - tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); #else - tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); #endif + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + +#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) + tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); +#else + tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); +#endif + } + #ifdef CONFIG_DEBUG + /* Was the allocation successful? */ + if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); diff --git a/arch/x86/src/i486/up_releasestack.c b/arch/x86/src/i486/up_releasestack.c index 0aa43ce58c795df1e88ae1018af8fa5d223310ab..8d264641f842de1d28e31b93e3e1d9df752991f1 100644 --- a/arch/x86/src/i486/up_releasestack.c +++ b/arch/x86/src/i486/up_releasestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/x86/src/common/up_releasestack.c * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -91,11 +91,31 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { + /* Is there a stack allocated? */ + if (dtcb->stack_alloc_ptr) { - sched_ufree(dtcb->stack_alloc_ptr); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } + + /* Mark the stack freed */ + dtcb->stack_alloc_ptr = NULL; } + /* The size of the allocated stack is now zero */ + dtcb->adj_stack_size = 0; } diff --git a/arch/x86/src/i486/up_usestack.c b/arch/x86/src/i486/up_usestack.c index f972d895064f04a2c9d17de2999f02a6c7c098a2..b391599315ca4d8020ae4e70ea97ae12ca43a53d 100644 --- a/arch/x86/src/i486/up_usestack.c +++ b/arch/x86/src/i486/up_usestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/x86/src/common/up_usestack.c * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -94,12 +94,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) size_t top_of_stack; size_t size_of_stack; + /* Is there already a stack allocated? */ + if (tcb->stack_alloc_ptr) { - sched_ufree(tcb->stack_alloc_ptr); + /* Yes.. Release the old stack allocation */ + + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); } - /* Save the stack allocation */ + /* Save the new stack allocation */ tcb->stack_alloc_ptr = stack; diff --git a/arch/z16/src/common/up_createstack.c b/arch/z16/src/common/up_createstack.c index d523181692315868fe5c71ae8adbfefd192afe2f..2bd3a89514cef52a76edc57ca54ba5c30e1350d3 100644 --- a/arch/z16/src/common/up_createstack.c +++ b/arch/z16/src/common/up_createstack.c @@ -102,30 +102,52 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { - /* Is there already a stack allocated of a different size? */ + /* 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. + */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { - /* Yes.. free it */ + /* Yes.. Release the old stack */ - sched_ufree(tcb->stack_alloc_ptr); - tcb->stack_alloc_ptr = NULL; + up_release_stack(tcb, ttype); } - /* Do we need to allocate a stack? */ - + /* Do we need to allocate a new stack? */ + if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), * then create a zeroed stack to make stack dumps easier to trace. */ +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) - tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); #else - tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); #endif + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + +#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) + tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); +#else + tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); +#endif + } + #ifdef CONFIG_DEBUG + /* Was the allocation successful? */ + if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); diff --git a/arch/z16/src/common/up_releasestack.c b/arch/z16/src/common/up_releasestack.c index 84cc4be7d346530600f79c5cca34b1c05b086ecd..3d0842a5bd4c462bde8613a58c1daf2a6942b865 100644 --- a/arch/z16/src/common/up_releasestack.c +++ b/arch/z16/src/common/up_releasestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * common/up_releasestack.c * - * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -91,11 +91,31 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { + /* Is there a stack allocated? */ + if (dtcb->stack_alloc_ptr) { - sched_ufree(dtcb->stack_alloc_ptr); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } + + /* Mark the stack freed */ + dtcb->stack_alloc_ptr = NULL; } + /* The size of the allocated stack is now zero */ + dtcb->adj_stack_size = 0; } diff --git a/arch/z16/src/common/up_usestack.c b/arch/z16/src/common/up_usestack.c index 6396ce9c270c595396d2f870caf72f154134e7e6..7b5effc45f9dacf947373d09e8071dbbf7af2346 100644 --- a/arch/z16/src/common/up_usestack.c +++ b/arch/z16/src/common/up_usestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/z16/common/up_usestack.c * - * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -94,12 +94,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) size_t top_of_stack; size_t size_of_stack; + /* Is there already a stack allocated? */ + if (tcb->stack_alloc_ptr) { - sched_ufree(tcb->stack_alloc_ptr); + /* Yes.. Release the old stack allocation */ + + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); } - /* Save the stack allocation */ + /* Save the new stack allocation */ tcb->stack_alloc_ptr = stack; diff --git a/arch/z80/src/common/up_createstack.c b/arch/z80/src/common/up_createstack.c index 1e47b09bdf454de6de4ac9d0d704610548fc25e3..a36a8aa7bfc434ab88e4870a8bd9138f7da0b760 100644 --- a/arch/z80/src/common/up_createstack.c +++ b/arch/z80/src/common/up_createstack.c @@ -101,30 +101,52 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { - /* Is there already a stack allocated of a different size? */ + /* 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. + */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { - /* Yes.. free it */ + /* Yes.. Release the old stack */ - sched_ufree(tcb->stack_alloc_ptr); - tcb->stack_alloc_ptr = NULL; + up_release_stack(tcb, ttype); } - /* Do we need to allocate a stack? */ - + /* Do we need to allocate a new stack? */ + if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), * then create a zeroed stack to make stack dumps easier to trace. */ +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) - tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); #else - tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); + tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); #endif + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + +#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) + tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); +#else + tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); +#endif + } + #ifdef CONFIG_DEBUG + /* Was the allocation successful? */ + if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); diff --git a/arch/z80/src/common/up_releasestack.c b/arch/z80/src/common/up_releasestack.c index beefc474451c8165f97a3330da1d80fb438801d0..92c7bbd0a680360c081eb3c6bfb7f0bb6038c8bc 100644 --- a/arch/z80/src/common/up_releasestack.c +++ b/arch/z80/src/common/up_releasestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * common/up_releasestack.c * - * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -91,11 +91,31 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { + /* Is there a stack allocated? */ + if (dtcb->stack_alloc_ptr) { - sched_ufree(dtcb->stack_alloc_ptr); +#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } + + /* Mark the stack freed */ + dtcb->stack_alloc_ptr = NULL; } + /* The size of the allocated stack is now zero */ + dtcb->adj_stack_size = 0; } diff --git a/arch/z80/src/common/up_usestack.c b/arch/z80/src/common/up_usestack.c index 8d322e7056428eaec82d17a3918ee83f851054ea..095b4f5d532387d81bb0b8a2611a6985e56599df 100644 --- a/arch/z80/src/common/up_usestack.c +++ b/arch/z80/src/common/up_usestack.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/z80/src/common/up_usestack.c * - * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -93,12 +93,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) size_t top_of_stack; size_t size_of_stack; + /* Is there already a stack allocated? */ + if (tcb->stack_alloc_ptr) { - sched_ufree(tcb->stack_alloc_ptr); + /* Yes.. Release the old stack allocation */ + + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); } - /* Save the stack allocation */ + /* Save the new stack allocation */ tcb->stack_alloc_ptr = stack;