aboutsummaryrefslogtreecommitdiff
path: root/nuttx/sched/group_join.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/sched/group_join.c')
-rw-r--r--nuttx/sched/group_join.c103
1 files changed, 92 insertions, 11 deletions
diff --git a/nuttx/sched/group_join.c b/nuttx/sched/group_join.c
index 987c1ba87..9dcea6599 100644
--- a/nuttx/sched/group_join.c
+++ b/nuttx/sched/group_join.c
@@ -41,8 +41,11 @@
#include <sched.h>
#include <assert.h>
+#include <errno.h>
#include <debug.h>
+#include <nuttx/kmalloc.h>
+
#include "os_internal.h"
#ifdef HAVE_TASK_GROUP
@@ -50,6 +53,9 @@
/*****************************************************************************
* Pre-processor Definitions
*****************************************************************************/
+/* Is this worth making a configuration option? */
+
+#define GROUP_REALLOC_MEMBERS 4
/*****************************************************************************
* Private Types
@@ -68,19 +74,21 @@
*****************************************************************************/
/*****************************************************************************
- * Name: group_join
+ * Name: group_bind
*
* Description:
- * Copy the group structure reference from one TCB to another, incrementing
- * the refrence count on the group. This function is called when a pthread
- * is produced within the task group so that the pthread can share the
- * resources of the task group.
+ * A thread joins the group when it is created. This is a two step process,
+ * first, the group must bound to the new threads TCB. group_bind() does
+ * this (at the return from group_join, things are a little unstable: The
+ * group has been bound, but tg_nmembers hs not yet been incremented).
+ * Then, after the new thread is initialized and has a PID assigned to it,
+ * group_join() is called, incrementing the tg_nmembers count on the group.
*
* Parameters:
* tcb - The TCB of the new "child" task that need to join the group.
*
* Return Value:
- * None
+ * 0 (OK) on success; a negated errno value on failure.
*
* Assumptions:
* - The parent task from which the group will be inherited is the task at
@@ -90,18 +98,91 @@
*
*****************************************************************************/
-void group_join(FAR _TCB *tcb)
+int group_bind(FAR _TCB *tcb)
{
FAR _TCB *ptcb = (FAR _TCB *)g_readytorun.head;
DEBUGASSERT(ptcb && tcb && ptcb->group && !tcb->group);
- /* Copy the group reference from the parent to the child, incrementing the
- * reference count.
- */
+ /* Copy the group reference from the parent to the child */
tcb->group = ptcb->group;
- ptcb->group->tg_crefs++;
+ return OK;
+}
+
+/*****************************************************************************
+ * Name: group_join
+ *
+ * Description:
+ * A thread joins the group when it is created. This is a two step process,
+ * first, the group must bound to the new threads TCB. group_bind() does
+ * this (at the return from group_join, things are a little unstable: The
+ * group has been bound, but tg_nmembers hs not yet been incremented).
+ * Then, after the new thread is initialized and has a PID assigned to it,
+ * group_join() is called, incrementing the tg_nmembers count on the group.
+ *
+ * Parameters:
+ * tcb - The TCB of the new "child" task that need to join the group.
+ *
+ * Return Value:
+ * 0 (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ * - The parent task from which the group will be inherited is the task at
+ * the thead of the ready to run list.
+ * - Called during thread creation in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+int group_join(FAR _TCB *tcb)
+{
+#ifdef HAVE_GROUP_MEMBERS
+ FAR struct task_group_s *group;
+
+ DEBUGASSERT(tcb && tcb->group &&
+ tcb->group->tg_nmembers < UINT8_MAX);
+
+ /* Get the group from the TCB */
+
+ group = tcb->group;
+
+ /* Will we need to extend the size of the array of groups? */
+
+ if (group->tg_nmembers >= group->tg_mxmembers)
+ {
+ FAR pid_t *newmembers;
+ unsigned int newmax;
+
+ /* Yes... reallocate the array of members */
+
+ newmax = group->tg_mxmembers + GROUP_REALLOC_MEMBERS;
+ if (newmax > UINT8_MAX)
+ {
+ newmax = UINT8_MAX;
+ }
+
+ newmembers = (FAR pid_t *)
+ krealloc(group->tg_members, sizeof(pid_t) * newmax);
+
+ if (!newmembers)
+ {
+ return -ENOMEM;
+ }
+
+ /* Save the new number of members in the reallocated members array */
+
+ group->tg_members = newmembers;
+ group->tg_mxmembers = newmax;
+ }
+
+ /* Assign this new pid to the group. */
+
+ group->tg_members[group->tg_nmembers] = tcb->pid;
+#endif
+
+ group->tg_nmembers++;
+ return OK;
}
#endif /* HAVE_TASK_GROUP */