group_join.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /****************************************************************************
  2. * sched/group/group_join.c
  3. *
  4. * Copyright (C) 2013, 2016 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <sched.h>
  40. #include <assert.h>
  41. #include <errno.h>
  42. #include <debug.h>
  43. #include <nuttx/irq.h>
  44. #include <nuttx/kmalloc.h>
  45. #include "sched/sched.h"
  46. #include "group/group.h"
  47. #include "environ/environ.h"
  48. #if defined(HAVE_TASK_GROUP) && !defined(CONFIG_DISABLE_PTHREAD)
  49. /****************************************************************************
  50. * Pre-processor Definitions
  51. ****************************************************************************/
  52. /* Is this worth making a configuration option? */
  53. #define GROUP_REALLOC_MEMBERS 4
  54. /****************************************************************************
  55. * Private Functions
  56. ****************************************************************************/
  57. /****************************************************************************
  58. * Name: group_addmember
  59. *
  60. * Description:
  61. * Add a new member to a group.
  62. *
  63. * Input Parameters:
  64. * group - The task group to add the new member
  65. * pid - The new member
  66. *
  67. * Returned Value:
  68. * 0 (OK) on success; a negated errno value on failure.
  69. *
  70. * Assumptions:
  71. * Called during thread creation and during reparenting in a safe context.
  72. * No special precautions are required here.
  73. *
  74. ****************************************************************************/
  75. #ifdef HAVE_GROUP_MEMBERS
  76. static inline int group_addmember(FAR struct task_group_s *group, pid_t pid)
  77. {
  78. irqstate_t flags;
  79. DEBUGASSERT(group && group->tg_nmembers < UINT8_MAX);
  80. /* Will we need to extend the size of the array of groups? */
  81. if (group->tg_nmembers >= group->tg_mxmembers)
  82. {
  83. FAR pid_t *newmembers;
  84. unsigned int newmax;
  85. /* Yes... reallocate the array of members */
  86. newmax = group->tg_mxmembers + GROUP_REALLOC_MEMBERS;
  87. if (newmax > UINT8_MAX)
  88. {
  89. newmax = UINT8_MAX;
  90. }
  91. newmembers = (FAR pid_t *)
  92. kmm_realloc(group->tg_members, sizeof(pid_t) * newmax);
  93. if (!newmembers)
  94. {
  95. serr("ERROR: Failed to reallocate tg_members\n");
  96. return -ENOMEM;
  97. }
  98. /* Save the new number of members in the reallocated members array.
  99. * We need to make the following atomic because the member list
  100. * may be traversed from an interrupt handler (read-only).
  101. */
  102. flags = enter_critical_section();
  103. group->tg_members = newmembers;
  104. group->tg_mxmembers = newmax;
  105. leave_critical_section(flags);
  106. }
  107. /* Assign this new pid to the group; group->tg_nmembers will be incremented
  108. * by the caller.
  109. */
  110. group->tg_members[group->tg_nmembers] = pid;
  111. return OK;
  112. }
  113. #endif /* HAVE_GROUP_MEMBERS */
  114. /****************************************************************************
  115. * Public Functions
  116. ****************************************************************************/
  117. /****************************************************************************
  118. * Name: group_bind
  119. *
  120. * Description:
  121. * A thread joins the group when it is created. This is a two step process,
  122. * first, the group must bound to the new threads TCB. group_bind() does
  123. * this (at the return from group_join, things are a little unstable: The
  124. * group has been bound, but tg_nmembers has not yet been incremented).
  125. * Then, after the new thread is initialized and has a PID assigned to it,
  126. * group_join() is called, incrementing the tg_nmembers count on the group.
  127. *
  128. * Input Parameters:
  129. * tcb - The TCB of the new "child" task that need to join the group.
  130. *
  131. * Returned Value:
  132. * 0 (OK) on success; a negated errno value on failure.
  133. *
  134. * Assumptions:
  135. * - The parent task from which the group will be inherited is the task at
  136. * the head of the ready to run list.
  137. * - Called during thread creation in a safe context. No special precautions
  138. * are required here.
  139. *
  140. ****************************************************************************/
  141. int group_bind(FAR struct pthread_tcb_s *tcb)
  142. {
  143. FAR struct tcb_s *ptcb = this_task();
  144. DEBUGASSERT(ptcb && tcb && ptcb->group && !tcb->cmn.group);
  145. /* Copy the group reference from the parent to the child */
  146. tcb->cmn.group = ptcb->group;
  147. return OK;
  148. }
  149. /****************************************************************************
  150. * Name: group_join
  151. *
  152. * Description:
  153. * A thread joins the group when it is created. This is a two step process,
  154. * first, the group must bound to the new threads TCB. group_bind() does
  155. * this (at the return from group_join, things are a little unstable: The
  156. * group has been bound, but tg_nmembers has not yet been incremented).
  157. * Then, after the new thread is initialized and has a PID assigned to it,
  158. * group_join() is called, incrementing the tg_nmembers count on the group.
  159. *
  160. * Input Parameters:
  161. * tcb - The TCB of the new "child" task that need to join the group.
  162. *
  163. * Returned Value:
  164. * 0 (OK) on success; a negated errno value on failure.
  165. *
  166. * Assumptions:
  167. * - The parent task from which the group will be inherited is the task at
  168. * the head of the ready to run list.
  169. * - Called during thread creation in a safe context. No special precautions
  170. * are required here.
  171. *
  172. ****************************************************************************/
  173. int group_join(FAR struct pthread_tcb_s *tcb)
  174. {
  175. FAR struct task_group_s *group;
  176. #ifdef HAVE_GROUP_MEMBERS
  177. int ret;
  178. #endif
  179. DEBUGASSERT(tcb && tcb->cmn.group &&
  180. tcb->cmn.group->tg_nmembers < UINT8_MAX);
  181. /* Get the group from the TCB */
  182. group = tcb->cmn.group;
  183. #ifdef HAVE_GROUP_MEMBERS
  184. /* Add the member to the group */
  185. ret = group_addmember(group, tcb->cmn.pid);
  186. if (ret < 0)
  187. {
  188. return ret;
  189. }
  190. #endif
  191. group->tg_nmembers++;
  192. return OK;
  193. }
  194. #endif /* HAVE_TASK_GROUP && !CONFIG_DISABLE_PTHREAD */