Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}