From 0d9fb476ea6f347c48a3ac8c2d98251467421203 Mon Sep 17 00:00:00 2001 From: patacongo Date: Tue, 5 Feb 2013 19:50:37 +0000 Subject: Moving pending signals to task group; Logic to recover some MQ resources on pthread_cacancel or task_delete; Now obeys rules for delivering signals to a process with threads git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5613 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/sched/group_leave.c | 137 +++++++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 62 deletions(-) (limited to 'nuttx/sched/group_leave.c') diff --git a/nuttx/sched/group_leave.c b/nuttx/sched/group_leave.c index 43a79c9bb..b3d2f20f8 100644 --- a/nuttx/sched/group_leave.c +++ b/nuttx/sched/group_leave.c @@ -49,6 +49,7 @@ #include #include "env_internal.h" +#include "sig_internal.h" #include "pthread_internal.h" #include "mq_internal.h" #include "group_internal.h" @@ -156,6 +157,12 @@ static inline void group_release(FAR struct task_group_s *group) group_removechildren(group); #endif +#ifndef CONFIG_DISABLE_SIGNALS + /* Release pending signals */ + + sig_release(group); +#endif + #ifndef CONFIG_DISABLE_PTHREAD /* Release pthread resources */ @@ -216,6 +223,74 @@ static inline void group_release(FAR struct task_group_s *group) sched_free(group); } +/***************************************************************************** + * Name: group_removemember + * + * Description: + * Remove a member from a group. + * + * Parameters: + * group - The group from which to remove the member. + * pid - The member to be removed. + * + * Return Value: + * On success, returns the number of members remaining in the group (>=0). + * Can fail only if the member is not found in the group. On failure, + * returns -ENOENT + * + * Assumptions: + * Called during task deletion and also from the reparenting logic, both + * in a safe context. No special precautions are required here. + * + *****************************************************************************/ + +#ifdef HAVE_GROUP_MEMBERS +static inline int group_removemember(FAR struct task_group_s *group, pid_t pid) +{ + irqstate_t flags; + int i; + + DEBUGASSERT(group); + + /* Find the member in the array of members and remove it */ + + for (i = 0; i < group->tg_nmembers; i++) + { + /* Does this member have the matching pid */ + + if (group->tg_members[i] == pid) + { + /* Yes.. break out of the loop. We don't do the actual + * removal here, instead we re-test i and do the adjustments + * outside of the loop. We do this because we want the + * DEBUGASSERT to work properly. + */ + + break; + } + } + + /* Now, test if we found the task in the array of members. */ + + if (i < group->tg_nmembers) + { + /* Remove the member from the array of members. This must be an + * atomic operation because the member array may be accessed from + * interrupt handlers (read-only). + */ + + flags = irqsave(); + group->tg_members[i] = group->tg_members[group->tg_nmembers - 1]; + group->tg_nmembers--; + irqrestore(flags); + + return group->tg_nmembers; + } + + return -ENOENT; +} +#endif /* HAVE_GROUP_MEMBERS */ + /***************************************************************************** * Public Functions *****************************************************************************/ @@ -315,66 +390,4 @@ void group_leave(FAR struct tcb_s *tcb) } #endif /* HAVE_GROUP_MEMBERS */ - -/***************************************************************************** - * Name: group_removemember - * - * Description: - * Remove a member from a group. - * - * Parameters: - * group - The group from which to remove the member. - * pid - The member to be removed. - * - * Return Value: - * On success, returns the number of members remaining in the group (>=0). - * Can fail only if the member is not found in the group. On failure, - * returns -ENOENT - * - * Assumptions: - * Called during task deletion and also from the reparenting logic, both - * in a safe context. No special precautions are required here. - * - *****************************************************************************/ - -#ifdef HAVE_GROUP_MEMBERS -int group_removemember(FAR struct task_group_s *group, pid_t pid) -{ - int i; - - DEBUGASSERT(group); - - /* Find the member in the array of members and remove it */ - - for (i = 0; i < group->tg_nmembers; i++) - { - /* Does this member have the matching pid */ - - if (group->tg_members[i] == pid) - { - /* Yes.. break out of the loop. We don't do the actual - * removal here, instead we re-test i and do the adjustments - * outside of the loop. We do this because we want the - * DEBUGASSERT to work properly. - */ - - break; - } - } - - /* Now, test if we found the task in the array of members. */ - - if (i < group->tg_nmembers) - { - /* Remove the member from the array of members */ - - group->tg_members[i] = group->tg_members[group->tg_nmembers - 1]; - group->tg_nmembers--; - return group->tg_nmembers; - } - - return -ENOENT; -} -#endif /* HAVE_GROUP_MEMBERS */ - #endif /* HAVE_TASK_GROUP */ -- cgit v1.2.3