int task_init(FAR _TCB *tcb, const char *name, int priority, main_t entry, const char *argv[]) #endif { int ret; /* Associate file descriptors with the new task */ #if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 if (sched_setuptaskfiles(tcb) != OK) { return ERROR; } #endif /* Clone the parent's task environment */ (void)env_dup(tcb); /* Configure the user provided stack region */ #ifndef CONFIG_CUSTOM_STACK up_use_stack(tcb, stack, stack_size); #endif /* Initialize the task control block */ ret = task_schedsetup(tcb, priority, task_start, entry, TCB_FLAG_TTYPE_TASK); if (ret == OK) { /* Setup to pass parameters to the new task */ (void)task_argsetup(tcb, name, argv); } return ret; }
int task_init(FAR struct tcb_s *tcb, const char *name, int priority, FAR uint32_t *stack, uint32_t stack_size, main_t entry, FAR char * const argv[]) { FAR struct task_tcb_s *ttcb = (FAR struct task_tcb_s *)tcb; int errcode; 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); #endif /* Create a new task group */ #ifdef HAVE_TASK_GROUP ret = group_allocate(ttcb, tcb->flags); if (ret < 0) { errcode = -ret; goto errout; } #endif /* Associate file descriptors with the new task */ #if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 ret = group_setuptaskfiles(ttcb); if (ret < 0) { errcode = -ret; goto errout_with_group; } #endif /* Configure the user provided stack region */ up_use_stack(tcb, stack, stack_size); /* Initialize the task control block */ ret = task_schedsetup(ttcb, priority, task_start, entry, TCB_FLAG_TTYPE_TASK); if (ret < OK) { errcode = -ret; goto errout_with_group; } /* Setup to pass parameters to the new task */ (void)task_argsetup(ttcb, name, argv); /* Now we have enough in place that we can join the group */ #ifdef HAVE_TASK_GROUP ret = group_initialize(ttcb); if (ret < 0) { errcode = -ret; goto errout_with_group; } #endif return OK; errout_with_group: #ifdef HAVE_TASK_GROUP group_leave(tcb); errout: #endif set_errno(errcode); return ERROR; }
static int thread_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; pid_t pid; int errcode; int ret; /* Allocate a TCB for the new task. */ tcb = (FAR struct task_tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s)); if (!tcb) { sdbg("ERROR: Failed to allocate TCB\n"); errcode = ENOMEM; goto errout; } /* Allocate a new task group with privileges appropriate for the parent * thread type. */ #ifdef HAVE_TASK_GROUP ret = group_allocate(tcb, ttype); if (ret < 0) { errcode = -ret; goto errout_with_tcb; } #endif /* Associate file descriptors with the new task */ #if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 ret = group_setuptaskfiles(tcb); if (ret < OK) { errcode = -ret; goto errout_with_tcb; } #endif /* Allocate the stack for the TCB */ ret = up_create_stack((FAR struct tcb_s *)tcb, stack_size, ttype); if (ret < OK) { errcode = -ret; goto errout_with_tcb; } /* Initialize the task control block */ ret = task_schedsetup(tcb, priority, task_start, entry, ttype); if (ret < OK) { errcode = -ret; goto errout_with_tcb; } /* Setup to pass parameters to the new task */ (void)task_argsetup(tcb, name, argv); /* Now we have enough in place that we can join the group */ #ifdef HAVE_TASK_GROUP ret = group_initialize(tcb); if (ret < 0) { errcode = -ret; goto errout_with_tcb; } #endif /* Get the assigned pid before we start the task */ pid = (int)tcb->cmn.pid; /* Activate the task */ ret = task_activate((FAR struct tcb_s *)tcb); if (ret < OK) { errcode = get_errno(); /* The TCB was added to the active task list by task_schedsetup() */ dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); goto errout_with_tcb; } return pid; errout_with_tcb: sched_releasetcb((FAR struct tcb_s *)tcb, ttype); errout: set_errno(errcode); return ERROR; }
FAR struct task_tcb_s *task_vforksetup(start_t retaddr) { struct tcb_s *parent = this_task(); struct task_tcb_s *child; uint8_t ttype; int priority; int ret; DEBUGASSERT(retaddr); /* Get the type of the fork'ed task (kernel or user) */ if ((parent->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL) { /* Fork'ed from a kernel thread */ ttype = TCB_FLAG_TTYPE_KERNEL; } else { /* Fork'ed from a user task or pthread */ ttype = TCB_FLAG_TTYPE_TASK; } /* Allocate a TCB for the child task. */ child = (FAR struct task_tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s)); if (!child) { serr("ERROR: Failed to allocate TCB\n"); set_errno(ENOMEM); return NULL; } /* Allocate a new task group with the same privileges as the parent */ #ifdef HAVE_TASK_GROUP ret = group_allocate(child, parent->flags); if (ret < 0) { goto errout_with_tcb; } #endif /* Associate file descriptors with the new task */ #if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 ret = group_setuptaskfiles(child); if (ret < OK) { goto errout_with_tcb; } #endif /* Get the priority of the parent task */ #ifdef CONFIG_PRIORITY_INHERITANCE priority = parent->base_priority; /* "Normal," unboosted priority */ #else priority = parent->sched_priority; /* Current priority */ #endif /* Initialize the task control block. This calls up_initial_state() */ sinfo("Child priority=%d start=%p\n", priority, retaddr); ret = task_schedsetup(child, priority, retaddr, parent->entry.main, ttype); if (ret < OK) { goto errout_with_tcb; } sinfo("parent=%p, returning child=%p\n", parent, child); return child; errout_with_tcb: sched_releasetcb((FAR struct tcb_s *)child, ttype); set_errno(-ret); return NULL; }
int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr, pthread_startroutine_t start_routine, pthread_addr_t arg) { FAR _TCB *ptcb; FAR join_t *pjoin; int status; int priority; #if CONFIG_RR_INTERVAL > 0 int policy; #endif pid_t pid; /* If attributes were not supplied, use the default attributes */ if (!attr) { attr = &g_default_pthread_attr; } /* Allocate a TCB for the new task. */ ptcb = (FAR _TCB*)kzalloc(sizeof(_TCB)); if (!ptcb) { return ENOMEM; } /* Associate file descriptors with the new task */ status = sched_setuppthreadfiles(ptcb); if (status != OK) { sched_releasetcb(ptcb); return status; } /* Share the parent's envionment */ (void)env_share(ptcb); /* Allocate a detachable structure to support pthread_join logic */ pjoin = (FAR join_t*)kzalloc(sizeof(join_t)); if (!pjoin) { sched_releasetcb(ptcb); return ENOMEM; } /* Allocate the stack for the TCB */ status = up_create_stack(ptcb, attr->stacksize); if (status != OK) { sched_releasetcb(ptcb); sched_free(pjoin); return ENOMEM; } /* Should we use the priority and scheduler specified in the * pthread attributes? Or should we use the current thread's * priority and scheduler? */ if (attr->inheritsched == PTHREAD_INHERIT_SCHED) { /* Get the priority for this thread. */ struct sched_param param; status = sched_getparam(0, ¶m); if (status == OK) { priority = param.sched_priority; } else { priority = SCHED_FIFO; } /* Get the scheduler policy for this thread */ #if CONFIG_RR_INTERVAL > 0 policy = sched_getscheduler(0); if (policy == ERROR) { policy = SCHED_FIFO; } #endif } else { /* Use the priority and scheduler from the attributes */ priority = attr->priority; #if CONFIG_RR_INTERVAL > 0 policy = attr->policy; #endif } /* Mark this task as a pthread (this setting will be needed in * task_schedsetup() when up_initial_state() is called. */ ptcb->flags |= TCB_FLAG_TTYPE_PTHREAD; /* Initialize the task control block */ status = task_schedsetup(ptcb, priority, pthread_start, (main_t)start_routine); if (status != OK) { sched_releasetcb(ptcb); sched_free(pjoin); return EBUSY; } /* Configure the TCB for a pthread receiving on parameter * passed by value */ pthread_argsetup(ptcb, arg); /* Attach the join info to the TCB. */ ptcb->joininfo = (void*)pjoin; /* If round robin scheduling is selected, set the appropriate flag * in the TCB. */ #if CONFIG_RR_INTERVAL > 0 if (policy == SCHED_RR) { ptcb->flags |= TCB_FLAG_ROUND_ROBIN; ptcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; } #endif /* Get the assigned pid before we start the task (who knows what * could happen to ptcb after this!). Copy this ID into the join structure * as well. */ pid = (int)ptcb->pid; pjoin->thread = (pthread_t)pid; /* Initialize the semaphores in the join structure to zero. */ status = sem_init(&pjoin->data_sem, 0, 0); if (status == OK) { status = sem_init(&pjoin->exit_sem, 0, 0); } /* Activate the task */ sched_lock(); if (status == OK) { status = task_activate(ptcb); } if (status == OK) { /* Wait for the task to actually get running and to register * its join_t */ (void)pthread_takesemaphore(&pjoin->data_sem); /* Return the thread information to the caller */ if (thread) *thread = (pthread_t)pid; if (!pjoin->started) status = ERROR; sched_unlock(); (void)sem_destroy(&pjoin->data_sem); } else { sched_unlock(); dq_rem((FAR dq_entry_t*)ptcb, (dq_queue_t*)&g_inactivetasks); (void)sem_destroy(&pjoin->data_sem); (void)sem_destroy(&pjoin->exit_sem); sched_releasetcb(ptcb); sched_free(pjoin); return EIO; } return OK; }
static int thread_create(const char *name, uint8_t type, int priority, main_t entry, const char **argv) #endif { FAR _TCB *tcb; pid_t pid; int ret; /* Allocate a TCB for the new task. */ tcb = (FAR _TCB*)kzalloc(sizeof(_TCB)); if (!tcb) { goto errout; } /* Associate file descriptors with the new task */ #if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0 ret = sched_setuptaskfiles(tcb); if (ret != OK) { goto errout_with_tcb; } #endif /* Clone the parent's task environment */ (void)env_dup(tcb); /* Allocate the stack for the TCB */ #ifndef CONFIG_CUSTOM_STACK ret = up_create_stack(tcb, stack_size); if (ret != OK) { goto errout_with_tcb; } #endif /* Mark the type of this thread (this setting will be needed in * task_schedsetup() when up_initial_state() is called. */ tcb->flags |= type; /* Initialize the task control block */ ret = task_schedsetup(tcb, priority, task_start, entry); if (ret != OK) { goto errout_with_tcb; } /* Setup to pass parameters to the new task */ (void)task_argsetup(tcb, name, argv); /* Get the assigned pid before we start the task */ pid = (int)tcb->pid; /* Activate the task */ ret = task_activate(tcb); if (ret != OK) { /* The TCB was added to the active task list by task_schedsetup() */ dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks); goto errout_with_tcb; } return pid; errout_with_tcb: sched_releasetcb(tcb); errout: errno = ENOMEM; return ERROR; }