diff --git a/sched/task/task_create.c b/sched/task/task_create.c index c2259bea8ad..ea640f09934 100644 --- a/sched/task/task_create.c +++ b/sched/task/task_create.c @@ -72,92 +72,41 @@ static int nxthread_create(FAR const char *name, uint8_t ttype, int priority, int stack_size, main_t entry, FAR char * const argv[]) { - FAR struct task_tcb_s *tcb; + FAR struct tcb_s *tcb; pid_t pid; int ret; /* Allocate a TCB for the new task. */ - tcb = (FAR struct task_tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s)); + tcb = (FAR struct tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s)); if (!tcb) { serr("ERROR: Failed to allocate TCB\n"); return -ENOMEM; } - /* Allocate a new task group with privileges appropriate for the parent - * thread type. - */ + /* Setup the task type */ - ret = group_allocate(tcb, ttype); - if (ret < 0) - { - goto errout_with_tcb; - } + tcb->flags = ttype; -#if 0 /* No... there are side effects */ - /* Associate file descriptors with the new task. Exclude kernel threads; - * kernel threads do not have file or socket descriptors. They must use - * SYSLOG for output and the low-level psock interfaces for network I/O. - */ + /* Initialize the task */ - if (ttype != TCB_FLAG_TTYPE_KERNEL) -#endif - { - ret = group_setuptaskfiles(tcb); - if (ret < OK) - { - goto errout_with_tcb; - } - } - - /* Allocate the stack for the TCB */ - - ret = up_create_stack((FAR struct tcb_s *)tcb, stack_size, ttype); + ret = nxtask_init(tcb, name, priority, NULL, stack_size, entry, argv); if (ret < OK) { - goto errout_with_tcb; - } - - /* Initialize the task control block */ - - ret = nxtask_setup_scheduler(tcb, priority, nxtask_start, entry, ttype); - if (ret < OK) - { - goto errout_with_tcb; - } - - /* Setup to pass parameters to the new task */ - - nxtask_setup_arguments(tcb, name, argv); - - /* Now we have enough in place that we can join the group */ - - ret = group_initialize(tcb); - if (ret < 0) - { - goto errout_with_active; + kmm_free(tcb); + return ret; } /* Get the assigned pid before we start the task */ - pid = (int)tcb->cmn.pid; + pid = tcb->pid; /* Activate the task */ - nxtask_activate((FAR struct tcb_s *)tcb); - return pid; + nxtask_activate(tcb); -errout_with_active: - /* The TCB was added to the inactive task list by - * nxtask_setup_scheduler(). - */ - - dq_rem((FAR dq_entry_t *)tcb, (FAR dq_queue_t *)&g_inactivetasks); - -errout_with_tcb: - nxsched_release_tcb((FAR struct tcb_s *)tcb, ttype); - return ret; + return (int)pid; } /**************************************************************************** diff --git a/sched/task/task_init.c b/sched/task/task_init.c index 1d097a06b0b..1d0b2f75ebe 100644 --- a/sched/task/task_init.c +++ b/sched/task/task_init.c @@ -87,13 +87,13 @@ int nxtask_init(FAR struct tcb_s *tcb, const char *name, int priority, main_t entry, FAR char * const argv[]) { FAR struct task_tcb_s *ttcb = (FAR struct task_tcb_s *)tcb; + uint8_t ttype = tcb->flags & TCB_FLAG_TTYPE_MASK; int ret; /* Only tasks and kernel threads can be initialized in this way */ #ifndef CONFIG_DISABLE_PTHREAD - DEBUGASSERT(tcb && - (tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD); + DEBUGASSERT(tcb && ttype != TCB_FLAG_TTYPE_PTHREAD); #endif /* Create a new task group */ @@ -101,7 +101,7 @@ int nxtask_init(FAR struct tcb_s *tcb, const char *name, int priority, ret = group_allocate(ttcb, tcb->flags); if (ret < 0) { - goto errout; + return ret; } /* Associate file descriptors with the new task */ @@ -112,14 +112,28 @@ int nxtask_init(FAR struct tcb_s *tcb, const char *name, int priority, goto errout_with_group; } - /* Configure the user provided stack region */ + if (stack) + { + /* Use pre-allocated stack */ - up_use_stack(tcb, stack, stack_size); + ret = up_use_stack(tcb, stack, stack_size); + } + else + { + /* Allocate the stack for the TCB */ + + ret = up_create_stack(tcb, stack_size, ttype); + } + + if (ret < OK) + { + goto errout_with_group; + } /* Initialize the task control block */ - ret = nxtask_setup_scheduler(ttcb, priority, nxtask_start, entry, - TCB_FLAG_TTYPE_TASK); + ret = nxtask_setup_scheduler(ttcb, priority, nxtask_start, + entry, ttype); if (ret < OK) { goto errout_with_group; @@ -132,17 +146,41 @@ int nxtask_init(FAR struct tcb_s *tcb, const char *name, int priority, /* Now we have enough in place that we can join the group */ ret = group_initialize(ttcb); - if (ret < 0) + if (ret == OK) { - goto errout_with_group; + return ret; } - return OK; + /* The TCB was added to the inactive task list by + * nxtask_setup_scheduler(). + */ + + dq_rem((FAR dq_entry_t *)tcb, (FAR dq_queue_t *)&g_inactivetasks); errout_with_group: + + if (!stack && tcb->stack_alloc_ptr) + { +#ifdef CONFIG_BUILD_KERNEL + /* If the exiting thread is not a kernel thread, then it has an + * address environment. Don't bother to release the stack memory + * in this case... There is no point since the memory lies in the + * user memory region that will be destroyed anyway (and the + * address environment has probably already been destroyed at + * this point.. so we would crash if we even tried it). But if + * this is a privileged group, when we still have to release the + * memory using the kernel allocator. + */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) +#endif + { + up_release_stack(tcb, ttype); + } + } + group_leave(tcb); -errout: return ret; }