diff --git a/arch/arm/src/common/up_releasestack.c b/arch/arm/src/common/up_releasestack.c index 7090916dde2..45ca09df23f 100644 --- a/arch/arm/src/common/up_releasestack.c +++ b/arch/arm/src/common/up_releasestack.c @@ -104,14 +104,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/avr/src/common/up_releasestack.c b/arch/avr/src/common/up_releasestack.c index f1abcd15d90..a687609f2f4 100644 --- a/arch/avr/src/common/up_releasestack.c +++ b/arch/avr/src/common/up_releasestack.c @@ -101,14 +101,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/hc/src/common/up_releasestack.c b/arch/hc/src/common/up_releasestack.c index 5280674c99a..e82184491c9 100644 --- a/arch/hc/src/common/up_releasestack.c +++ b/arch/hc/src/common/up_releasestack.c @@ -101,14 +101,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/mips/src/common/up_releasestack.c b/arch/mips/src/common/up_releasestack.c index d08bc2e6d91..550254874a7 100644 --- a/arch/mips/src/common/up_releasestack.c +++ b/arch/mips/src/common/up_releasestack.c @@ -101,14 +101,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/misoc/src/lm32/lm32_releasestack.c b/arch/misoc/src/lm32/lm32_releasestack.c index 63f4ab8f993..60af9daf50c 100644 --- a/arch/misoc/src/lm32/lm32_releasestack.c +++ b/arch/misoc/src/lm32/lm32_releasestack.c @@ -94,14 +94,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/or1k/src/common/up_releasestack.c b/arch/or1k/src/common/up_releasestack.c index 674c1b05157..82c0555094d 100644 --- a/arch/or1k/src/common/up_releasestack.c +++ b/arch/or1k/src/common/up_releasestack.c @@ -104,14 +104,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/renesas/src/common/up_releasestack.c b/arch/renesas/src/common/up_releasestack.c index 5b309bde16d..13629137209 100644 --- a/arch/renesas/src/common/up_releasestack.c +++ b/arch/renesas/src/common/up_releasestack.c @@ -101,14 +101,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/risc-v/src/common/up_releasestack.c b/arch/risc-v/src/common/up_releasestack.c index dac7cea0d6d..149d3c2988f 100644 --- a/arch/risc-v/src/common/up_releasestack.c +++ b/arch/risc-v/src/common/up_releasestack.c @@ -101,14 +101,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/sim/src/up_releasestack.c b/arch/sim/src/up_releasestack.c index 87a30261264..98d54171f29 100644 --- a/arch/sim/src/up_releasestack.c +++ b/arch/sim/src/up_releasestack.c @@ -81,7 +81,10 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (dtcb->stack_alloc_ptr) { - sched_ufree(dtcb->stack_alloc_ptr); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/x86/src/i486/up_releasestack.c b/arch/x86/src/i486/up_releasestack.c index e83434024ee..ace852c2cc3 100644 --- a/arch/x86/src/i486/up_releasestack.c +++ b/arch/x86/src/i486/up_releasestack.c @@ -101,14 +101,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/xtensa/src/common/xtensa_releasestack.c b/arch/xtensa/src/common/xtensa_releasestack.c index 738da79284a..44768d36647 100644 --- a/arch/xtensa/src/common/xtensa_releasestack.c +++ b/arch/xtensa/src/common/xtensa_releasestack.c @@ -93,14 +93,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/arch/z16/src/common/up_releasestack.c b/arch/z16/src/common/up_releasestack.c index 8d0698ecfdc..6d5f40823cc 100644 --- a/arch/z16/src/common/up_releasestack.c +++ b/arch/z16/src/common/up_releasestack.c @@ -90,7 +90,10 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (dtcb->stack_alloc_ptr) { - sched_ufree(dtcb->stack_alloc_ptr); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } /* Mark the stack freed */ diff --git a/arch/z80/src/common/up_releasestack.c b/arch/z80/src/common/up_releasestack.c index 5862240d1f9..101953d7562 100644 --- a/arch/z80/src/common/up_releasestack.c +++ b/arch/z80/src/common/up_releasestack.c @@ -101,14 +101,20 @@ void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) if (ttype == TCB_FLAG_TTYPE_KERNEL) { - sched_kfree(dtcb->stack_alloc_ptr); + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + 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); + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + sched_ufree(dtcb->stack_alloc_ptr); + } } /* Mark the stack freed */ diff --git a/include/nuttx/pthread.h b/include/nuttx/pthread.h index 27fb5dd99c8..ce1202e8fbe 100644 --- a/include/nuttx/pthread.h +++ b/include/nuttx/pthread.h @@ -71,6 +71,7 @@ 0, /* low_priority */ \ 0, /* max_repl */ \ 0, /* affinity */ \ + NULL, /* stackaddr */ \ PTHREAD_STACK_DEFAULT, /* stacksize */ \ {0, 0}, /* repl_period */ \ {0, 0} /* budget */ \ @@ -83,6 +84,7 @@ PTHREAD_EXPLICIT_SCHED, /* inheritsched */ \ 0, /* low_priority */ \ 0, /* max_repl */ \ + NULL, /* stackaddr */ \ PTHREAD_STACK_DEFAULT, /* stacksize */ \ {0, 0}, /* repl_period */ \ {0, 0}, /* budget */ \ @@ -94,6 +96,7 @@ PTHREAD_DEFAULT_POLICY, /* policy */ \ PTHREAD_EXPLICIT_SCHED, /* inheritsched */ \ 0, /* affinity */ \ + NULL, /* stackaddr */ \ PTHREAD_STACK_DEFAULT, /* stacksize */ \ } #else @@ -102,6 +105,7 @@ PTHREAD_DEFAULT_PRIORITY, /* priority */ \ PTHREAD_DEFAULT_POLICY, /* policy */ \ PTHREAD_EXPLICIT_SCHED, /* inheritsched */ \ + NULL, /* stackaddr */ \ PTHREAD_STACK_DEFAULT, /* stacksize */ \ } #endif diff --git a/include/pthread.h b/include/pthread.h index e70ad06e5be..c97dd1da5f6 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -227,6 +227,7 @@ struct pthread_attr_s cpu_set_t affinity; /* Set of permitted CPUs for the thread */ #endif + FAR void *stackaddr; /* Address of memory to be used as stack */ size_t stacksize; /* Size of the stack allocated for the pthread */ #ifdef CONFIG_SCHED_SPORADIC @@ -406,6 +407,13 @@ int pthread_attr_getaffinity_np(FAR const pthread_attr_t *attr, int pthread_attr_setstacksize(FAR pthread_attr_t *attr, long stacksize); int pthread_attr_getstacksize(FAR const pthread_attr_t *attr, long *stackaddr); +/* Set or obtain stack address and size */ + +int pthread_attr_setstack(FAR pthread_attr_t *attr, + FAR void *stackaddr, long stacksize); +int pthread_attr_getstack(FAR pthread_attr_t *attr, + FAR void **stackaddr, FAR long *stacksize); + /* To create a thread object and runnable thread, a routine must be specified * as the new thread's start routine. An argument may be passed to this * routine, as an untyped address; an untyped address may also be returned as diff --git a/libs/libc/pthread/Make.defs b/libs/libc/pthread/Make.defs index 2c2a824b63a..e8a521b8a3a 100644 --- a/libs/libc/pthread/Make.defs +++ b/libs/libc/pthread/Make.defs @@ -41,6 +41,7 @@ CSRCS += pthread_attr_init.c pthread_attr_destroy.c CSRCS += pthread_attr_setschedpolicy.c pthread_attr_getschedpolicy.c CSRCS += pthread_attr_setinheritsched.c pthread_attr_getinheritsched.c CSRCS += pthread_attr_setstacksize.c pthread_attr_getstacksize.c +CSRCS += pthread_attr_setstack.c pthread_attr_getstack.c CSRCS += pthread_attr_setschedparam.c pthread_attr_getschedparam.c CSRCS += pthread_barrierattr_init.c pthread_barrierattr_destroy.c CSRCS += pthread_barrierattr_getpshared.c pthread_barrierattr_setpshared.c diff --git a/libs/libc/pthread/pthread_attr_getstack.c b/libs/libc/pthread/pthread_attr_getstack.c new file mode 100644 index 00000000000..e2489e2ab65 --- /dev/null +++ b/libs/libc/pthread/pthread_attr_getstack.c @@ -0,0 +1,88 @@ +/**************************************************************************** + * libs/libc/pthread/pthread_attr_getstack.c + * + * Copyright (C) 2018 Pinecone. All rights reserved. + * Author: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_attr_getstack + * + * Description: + * + * Parameters: + * attr + * stacksize + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_getstack(FAR pthread_attr_t *attr, + FAR void **stackaddr, FAR long *stacksize) +{ + int ret; + + linfo("attr=0x%p stackaddr=0x%p stacksize=0x%p\n", attr, stackaddr, stacksize); + + if (!attr || !stackaddr || !stacksize) + { + ret = EINVAL; + } + else + { + *stackaddr = attr->stackaddr; + *stacksize = attr->stacksize; + ret = OK; + } + + linfo("Returning %d\n", ret); + return ret; +} + + diff --git a/libs/libc/pthread/pthread_attr_setstack.c b/libs/libc/pthread/pthread_attr_setstack.c new file mode 100644 index 00000000000..327203db6f8 --- /dev/null +++ b/libs/libc/pthread/pthread_attr_setstack.c @@ -0,0 +1,89 @@ +/**************************************************************************** + * libs/libc/pthread/pthread_attr_setstack.c + * + * Copyright (C) 2018 Pinecone. All rights reserved. + * Author: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_attr_setstack + * + * Description: + * + * Parameters: + * attr + * stackaddr + * stacksize + * + * Return Value: + * 0 if successful. Otherwise, an error code. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_attr_setstack(FAR pthread_attr_t *attr, + FAR void *stackaddr, long stacksize) +{ + int ret; + + linfo("attr=0x%p stackaddr=0x%p stacksize=%ld\n", attr, stackaddr, stacksize); + + if (!attr || !stackaddr || stacksize < PTHREAD_STACK_MIN) + { + ret = EINVAL; + } + else + { + attr->stackaddr = stackaddr; + attr->stacksize = stacksize; + ret = OK; + } + + linfo("Returning %d\n", ret); + return ret; +} + diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c index df03248fd2e..a69c9bccf4d 100644 --- a/sched/pthread/pthread_create.c +++ b/sched/pthread/pthread_create.c @@ -302,10 +302,21 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr, goto errout_with_tcb; } - /* Allocate the stack for the TCB */ + if (attr->stackaddr) + { + /* Use pre-allocated stack */ + + ret = up_use_stack((FAR struct tcb_s *)ptcb, attr->stackaddr, + attr->stacksize); + } + else + { + /* Allocate the stack for the TCB */ + + ret = up_create_stack((FAR struct tcb_s *)ptcb, attr->stacksize, + TCB_FLAG_TTYPE_PTHREAD); + } - ret = up_create_stack((FAR struct tcb_s *)ptcb, attr->stacksize, - TCB_FLAG_TTYPE_PTHREAD); if (ret != OK) { errcode = ENOMEM;