int group_allocate(FAR _TCB *tcb) { int ret; DEBUGASSERT(tcb && !tcb->group); /* Allocate the group structure and assign it to the TCB */ tcb->group = (FAR struct task_group_s *)kzalloc(sizeof(struct task_group_s)); if (!tcb->group) { return -ENOMEM; } /* Assign the group a unique ID. If g_gidcounter were to wrap before we * finish with task creation, that would be a problem. */ #ifdef HAVE_GROUP_MEMBERS group_assigngid(tcb->group); #endif /* Duplicate the parent tasks envionment */ ret = env_dup(tcb->group); if (ret < 0) { kfree(tcb->group); tcb->group = NULL; return ret; } return OK; }
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 group_allocate(FAR struct task_tcb_s *tcb) { FAR struct task_group_s *group; int ret; DEBUGASSERT(tcb && !tcb->cmn.group); /* Allocate the group structure and assign it to the TCB */ group = (FAR struct task_group_s *)kzalloc(sizeof(struct task_group_s)); if (!group) { return -ENOMEM; } #if CONFIG_NFILE_STREAMS > 0 && defined(CONFIG_NUTTX_KERNEL) && \ defined(CONFIG_MM_KERNEL_HEAP) /* In a flat, single-heap build. The stream list is allocated with the * group structure. But in a kernel build with a kernel allocator, it * must be separately allocated using a user-space allocator. */ group->tg_streamlist = (FAR struct streamlist *) kuzalloc(sizeof(struct streamlist)); if (!group->tg_streamlist) { kfree(group); return -ENOMEM; } #endif /* Attach the group to the TCB */ tcb->cmn.group = group; #if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) /* Assign the group a unique ID. If g_gidcounter were to wrap before we * finish with task creation, that would be a problem. */ group_assigngid(group); #endif /* Duplicate the parent tasks environment */ ret = env_dup(group); if (ret < 0) { #if CONFIG_NFILE_STREAMS > 0 && defined(CONFIG_NUTTX_KERNEL) && \ defined(CONFIG_MM_KERNEL_HEAP) kufree(group->tg_streamlist); #endif kfree(group); tcb->cmn.group = NULL; return ret; } /* Initialize the pthread join semaphore */ #ifndef CONFIG_DISABLE_PTHREAD (void)sem_init(&group->tg_joinsem, 0, 1); #endif return OK; }
int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype) { FAR struct task_group_s *group; int ret; DEBUGASSERT(tcb && !tcb->cmn.group); /* Allocate the group structure and assign it to the TCB */ group = (FAR struct task_group_s *)kmm_zalloc(sizeof(struct task_group_s)); if (!group) { return -ENOMEM; } #if CONFIG_NFILE_STREAMS > 0 && (defined(CONFIG_BUILD_PROTECTED) || \ defined(CONFIG_BUILD_KERNEL)) && defined(CONFIG_MM_KERNEL_HEAP) /* If this group is being created for a privileged thread, then all elements * of the group must be created for privileged access. */ if ((ttype & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL) { group->tg_flags |= GROUP_FLAG_PRIVILEGED; } /* In a flat, single-heap build. The stream list is allocated with the * group structure. But in a kernel build with a kernel allocator, it * must be separately allocated using a user-space allocator. */ group->tg_streamlist = (FAR struct streamlist *) group_zalloc(group, sizeof(struct streamlist)); if (!group->tg_streamlist) { kmm_free(group); return -ENOMEM; } #endif /* Attach the group to the TCB */ tcb->cmn.group = group; #if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) /* Assign the group a unique ID. If g_gidcounter were to wrap before we * finish with task creation, that would be a problem. */ group_assigngid(group); #endif /* Duplicate the parent tasks environment */ ret = env_dup(group); if (ret < 0) { #if CONFIG_NFILE_STREAMS > 0 && (defined(CONFIG_BUILD_PROTECTED) || \ defined(CONFIG_BUILD_KERNEL)) && defined(CONFIG_MM_KERNEL_HEAP) group_free(group, group->tg_streamlist); #endif kmm_free(group); tcb->cmn.group = NULL; return ret; } /* Initialize the pthread join semaphore */ #ifndef CONFIG_DISABLE_PTHREAD (void)sem_init(&group->tg_joinsem, 0, 1); #endif 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; }