summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-02-03 16:43:58 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-02-03 16:43:58 +0000
commit32dde889e28f1e15c4a97f3e701800ba22ab849d (patch)
tree83fc8fbb0fcef9302298d1ccb819cfba26ec8825 /nuttx
parent0066db82f921ad84a9017242396e37259f3d71f4 (diff)
downloadpx4-nuttx-32dde889e28f1e15c4a97f3e701800ba22ab849d.tar.gz
px4-nuttx-32dde889e28f1e15c4a97f3e701800ba22ab849d.tar.bz2
px4-nuttx-32dde889e28f1e15c4a97f3e701800ba22ab849d.zip
Move pthread join and key creation data into the task group
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5602 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/ChangeLog3
-rw-r--r--nuttx/include/nuttx/sched.h16
-rw-r--r--nuttx/sched/Makefile3
-rw-r--r--nuttx/sched/group_create.c21
-rw-r--r--nuttx/sched/group_find.c2
-rw-r--r--nuttx/sched/group_internal.h6
-rw-r--r--nuttx/sched/group_leave.c6
-rw-r--r--nuttx/sched/pthread_cancel.c6
-rw-r--r--nuttx/sched/pthread_completejoin.c98
-rw-r--r--nuttx/sched/pthread_create.c33
-rw-r--r--nuttx/sched/pthread_detach.c23
-rw-r--r--nuttx/sched/pthread_findjoininfo.c17
-rw-r--r--nuttx/sched/pthread_getspecific.c8
-rw-r--r--nuttx/sched/pthread_initialize.c36
-rw-r--r--nuttx/sched/pthread_internal.h52
-rw-r--r--nuttx/sched/pthread_join.c28
-rw-r--r--nuttx/sched/pthread_keycreate.c14
-rw-r--r--nuttx/sched/pthread_setspecific.c9
-rw-r--r--nuttx/sched/task_getgroup.c (renamed from nuttx/sched/pthread_removejoininfo.c)126
-rw-r--r--nuttx/sched/task_spawn.c8
20 files changed, 302 insertions, 213 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index c3e16607f..6e2f5bd02 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -4106,4 +4106,5 @@
task_create().
* Corrected all argv[] arguments. Should be char * const *, not
const char **.
-
+ * sched/pthread* and include/nuttx/sched: Move pthread join data
+ and pthread key calculation data into the "task group" structure.
diff --git a/nuttx/include/nuttx/sched.h b/nuttx/include/nuttx/sched.h
index f8b4eb0dc..75c478220 100644
--- a/nuttx/include/nuttx/sched.h
+++ b/nuttx/include/nuttx/sched.h
@@ -273,6 +273,12 @@ struct dspace_s
*/
#ifdef HAVE_TASK_GROUP
+
+#ifndef CONFIG_DISABLE_PTHREAD
+struct join_s; /* Forward reference */
+ /* Defined in pthread_internal.h */
+#endif
+
struct task_group_s
{
#ifdef HAVE_GROUP_MEMBERS
@@ -296,6 +302,16 @@ struct task_group_s
FAR struct child_status_s *tg_children; /* Head of a list of child status */
#endif
+ /* Pthreads *******************************************************************/
+
+#ifndef CONFIG_DISABLE_PTHREAD
+ /* Pthread join Info: */
+ sem_t tg_joinsem; /* Mutually exclusive access to join data */
+ FAR struct join_s *tg_joinhead; /* Head of a list of join data */
+ FAR struct join_s *tg_jointail; /* Tail of a list of join data */
+ uint8_t tg_nkeys; /* Number pthread keys allocated */
+#endif
+
/* Environment variables ******************************************************/
#ifndef CONFIG_DISABLE_ENVIRON
diff --git a/nuttx/sched/Makefile b/nuttx/sched/Makefile
index 0b0173306..780549abf 100644
--- a/nuttx/sched/Makefile
+++ b/nuttx/sched/Makefile
@@ -86,6 +86,7 @@ endif
GRP_SRCS = group_create.c group_join.c group_leave.c group_find.c
GRP_SRCS += group_setupstreams.c group_setupidlefiles.c group_setuptaskfiles.c
+GRP_SRCS += task_getgroup.c
ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
GRP_SRCS += task_reparent.c
@@ -145,7 +146,7 @@ PTHREAD_SRCS += pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwa
PTHREAD_SRCS += pthread_cancel.c pthread_setcancelstate.c
PTHREAD_SRCS += pthread_keycreate.c pthread_setspecific.c pthread_getspecific.c pthread_keydelete.c
PTHREAD_SRCS += pthread_initialize.c pthread_completejoin.c pthread_findjoininfo.c
-PTHREAD_SRCS += pthread_removejoininfo.c pthread_once.c pthread_setschedprio.c
+PTHREAD_SRCS += pthread_once.c pthread_setschedprio.c
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
PTHREAD_SRCS += pthread_condtimedwait.c pthread_kill.c pthread_sigmask.c
diff --git a/nuttx/sched/group_create.c b/nuttx/sched/group_create.c
index 24f6923aa..58eb60606 100644
--- a/nuttx/sched/group_create.c
+++ b/nuttx/sched/group_create.c
@@ -176,36 +176,47 @@ void group_assigngid(FAR struct task_group_s *group)
int group_allocate(FAR _TCB *tcb)
{
+ FAR struct task_group_s *group;
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)
+ group = (FAR struct task_group_s *)kzalloc(sizeof(struct task_group_s));
+ if (!group)
{
return -ENOMEM;
}
+ /* Attach the group to the TCB */
+
+ tcb->group = group;
+
/* 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);
+ group_assigngid(group);
#endif
/* Duplicate the parent tasks envionment */
- ret = env_dup(tcb->group);
+ ret = env_dup(group);
if (ret < 0)
{
- kfree(tcb->group);
+ kfree(group);
tcb->group = NULL;
return ret;
}
+ /* Initialize the pthread join semaphore */
+
+#ifndef CONFIG_DISABLE_PTHREAD
+ (void)sem_init(&group->tg_joinsem, 0, 1);
+#endif
+
return OK;
}
diff --git a/nuttx/sched/group_find.c b/nuttx/sched/group_find.c
index eb3989223..8683990dd 100644
--- a/nuttx/sched/group_find.c
+++ b/nuttx/sched/group_find.c
@@ -90,7 +90,7 @@
* Return Value:
* On success, a pointer to the group task structure is returned. This
* function can fail only if there is no group that corresponds to the
- * groupd ID.
+ * group ID.
*
* Assumptions:
* Called during when signally tasks in a safe context. No special
diff --git a/nuttx/sched/group_internal.h b/nuttx/sched/group_internal.h
index ca6aacff7..c949968cf 100644
--- a/nuttx/sched/group_internal.h
+++ b/nuttx/sched/group_internal.h
@@ -88,6 +88,12 @@ int group_addmember(FAR struct task_group_s *group, pid_t pid);
int group_removemember(FAR struct task_group_s *group, pid_t pid);
#endif
+/* Convenience functions */
+
+FAR struct task_group_s *task_getgroup(pid_t pid);
+
+/* Signaling group members */
+
#ifndef CONFIG_DISABLE_SIGNALS
int group_signal(FAR struct task_group_s *group, FAR siginfo_t *info);
#endif
diff --git a/nuttx/sched/group_leave.c b/nuttx/sched/group_leave.c
index 4dec30633..d87420d1c 100644
--- a/nuttx/sched/group_leave.c
+++ b/nuttx/sched/group_leave.c
@@ -154,6 +154,12 @@ static inline void group_release(FAR struct task_group_s *group)
group_removechildren(group);
#endif
+ /* Free pthread join data */
+
+#ifndef CONFIG_DISABLE_PTHREAD
+ (void)sem_destroy(&group->tg_joinsem);
+#endif
+
/* Free all file-related resources now. We really need to close files as
* soon as possible while we still have a functioning task.
*/
diff --git a/nuttx/sched/pthread_cancel.c b/nuttx/sched/pthread_cancel.c
index 5e34eeaba..4dd209aeb 100644
--- a/nuttx/sched/pthread_cancel.c
+++ b/nuttx/sched/pthread_cancel.c
@@ -1,7 +1,7 @@
/**************************************************************************
* sched/pthread_cancel.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -93,7 +93,9 @@ int pthread_cancel(pthread_t thread)
tcb = sched_gettcb((pid_t)thread);
if (!tcb)
{
- /* The pid does not correspond to any known thread */
+ /* The pid does not correspond to any known thread. The thread
+ * has probably already exited.
+ */
return ESRCH;
}
diff --git a/nuttx/sched/pthread_completejoin.c b/nuttx/sched/pthread_completejoin.c
index 7c5191034..86f4eac3d 100644
--- a/nuttx/sched/pthread_completejoin.c
+++ b/nuttx/sched/pthread_completejoin.c
@@ -1,7 +1,7 @@
/************************************************************************
* sched/pthread_completejoin.c
*
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@
#include <debug.h>
#include "os_internal.h"
+#include "group_internal.h"
#include "pthread_internal.h"
/************************************************************************
@@ -78,7 +79,7 @@
*
************************************************************************/
-static bool pthread_notifywaiters(FAR join_t *pjoin)
+static bool pthread_notifywaiters(FAR struct join_s *pjoin)
{
int ntasks_waiting;
int status;
@@ -122,6 +123,76 @@ static bool pthread_notifywaiters(FAR join_t *pjoin)
}
/************************************************************************
+ * Name: pthread_removejoininfo
+ *
+ * Description:
+ * Remove a join structure from the local data set.
+ *
+ * Parameters:
+ * pid
+ *
+ * Return Value:
+ * None.
+ *
+ * Assumptions:
+ * The caller has provided protection from re-entrancy.
+ *
+ ************************************************************************/
+
+static void pthread_removejoininfo(FAR struct task_group_s *group,
+ pid_t pid)
+{
+ FAR struct join_s *prev;
+ FAR struct join_s *join;
+
+ /* Find the entry with the matching pid */
+
+ for (prev = NULL, join = group->tg_joinhead;
+ (join && (pid_t)join->thread != pid);
+ prev = join, join = join->next);
+
+ /* Remove it from the data set. */
+
+ /* First check if this is the entry at the head of the list. */
+
+ if (join)
+ {
+ if (!prev)
+ {
+ /* Check if this is the only entry in the list */
+
+ if (!join->next)
+ {
+ group->tg_joinhead = NULL;
+ group->tg_jointail = NULL;
+ }
+
+ /* Otherwise, remove it from the head of the list */
+
+ else
+ {
+ group->tg_joinhead = join->next;
+ }
+ }
+
+ /* It is not at the head of the list, check if it is at the tail. */
+
+ else if (!join->next)
+ {
+ group->tg_jointail = prev;
+ prev->next = NULL;
+ }
+
+ /* No, remove it from the middle of the list. */
+
+ else
+ {
+ prev->next = join->next;
+ }
+ }
+}
+
+/************************************************************************
* Public Functions
************************************************************************/
@@ -147,18 +218,20 @@ static bool pthread_notifywaiters(FAR join_t *pjoin)
int pthread_completejoin(pid_t pid, FAR void *exit_value)
{
- FAR join_t *pjoin;
+ FAR struct task_group_s *group = task_getgroup(pid);
+ FAR struct join_s *pjoin;
- svdbg("pid=%d exit_value=%p\n", pid, exit_value);
+ svdbg("pid=%d exit_value=%p group=%p\n", pid, exit_value, group);
+ DEBUGASSERT(group);
/* First, find thread's structure in the private data set. */
- (void)pthread_takesemaphore(&g_join_semaphore);
- pjoin = pthread_findjoininfo(pid);
+ (void)pthread_takesemaphore(&group->tg_joinsem);
+ pjoin = pthread_findjoininfo(group, pid);
if (!pjoin)
{
sdbg("Could not find join info, pid=%d\n", pid);
- (void)pthread_givesemaphore(&g_join_semaphore);
+ (void)pthread_givesemaphore(&group->tg_joinsem);
return ERROR;
}
else
@@ -182,14 +255,14 @@ int pthread_completejoin(pid_t pid, FAR void *exit_value)
if (!waiters && pjoin->detached)
{
- pthread_destroyjoin(pjoin);
+ pthread_destroyjoin(group, pjoin);
}
/* Giving the following semaphore will allow the waiters
* to call pthread_destroyjoin.
*/
- (void)pthread_givesemaphore(&g_join_semaphore);
+ (void)pthread_givesemaphore(&group->tg_joinsem);
}
return OK;
@@ -207,17 +280,18 @@ int pthread_completejoin(pid_t pid, FAR void *exit_value)
* no thread ever calls pthread_join. In case, there is a memory leak!
*
* Assumptions:
- * The caller holds g_join_semaphore
+ * The caller holds tg_joinsem
*
************************************************************************/
-void pthread_destroyjoin(FAR join_t *pjoin)
+void pthread_destroyjoin(FAR struct task_group_s *group,
+ FAR struct join_s *pjoin)
{
sdbg("pjoin=0x%p\n", pjoin);
/* Remove the join info from the set of joins */
- (void)pthread_removejoininfo((pid_t)pjoin->thread);
+ pthread_removejoininfo(group, (pid_t)pjoin->thread);
/* Destroy its semaphores */
diff --git a/nuttx/sched/pthread_create.c b/nuttx/sched/pthread_create.c
index 48a0788a6..82a5bc271 100644
--- a/nuttx/sched/pthread_create.c
+++ b/nuttx/sched/pthread_create.c
@@ -147,7 +147,7 @@ static void pthread_argsetup(FAR _TCB *tcb, pthread_addr_t arg)
* Name: pthread_addjoininfo
*
* Description:
- * Add a join_t to the local data set.
+ * Add a join structure to the local data set.
*
* Parameters:
* pjoin
@@ -160,27 +160,27 @@ static void pthread_argsetup(FAR _TCB *tcb, pthread_addr_t arg)
*
****************************************************************************/
-static void pthread_addjoininfo(FAR join_t *pjoin)
+static inline void pthread_addjoininfo(FAR struct task_group_s *group,
+ FAR struct join_s *pjoin)
{
pjoin->next = NULL;
- if (!g_pthread_tail)
+ if (!group->tg_jointail)
{
- g_pthread_head = pjoin;
+ group->tg_joinhead = pjoin;
}
else
{
- g_pthread_tail->next = pjoin;
+ group->tg_jointail->next = pjoin;
}
- g_pthread_tail = pjoin;
+ group->tg_jointail = pjoin;
}
/****************************************************************************
* Name: pthread_start
*
* Description:
- * This function is the low level entry point into the
- * pthread
+ * This function is the low level entry point into the pthread
*
* Parameters:
* None
@@ -190,16 +190,19 @@ static void pthread_addjoininfo(FAR join_t *pjoin)
static void pthread_start(void)
{
FAR _TCB *ptcb = (FAR _TCB*)g_readytorun.head;
- FAR join_t *pjoin = (FAR join_t*)ptcb->joininfo;
+ FAR struct task_group_s *group = ptcb->group;
+ FAR struct join_s *pjoin = (FAR struct join_s*)ptcb->joininfo;
pthread_addr_t exit_status;
+ DEBUGASSERT(group && pjoin);
+
/* Sucessfully spawned, add the pjoin to our data set.
* Don't re-enable pre-emption until this is done.
*/
- (void)pthread_takesemaphore(&g_join_semaphore);
- pthread_addjoininfo(pjoin);
- (void)pthread_givesemaphore(&g_join_semaphore);
+ (void)pthread_takesemaphore(&group->tg_joinsem);
+ pthread_addjoininfo(group, pjoin);
+ (void)pthread_givesemaphore(&group->tg_joinsem);
/* Report to the spawner that we successfully started. */
@@ -245,7 +248,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
pthread_startroutine_t start_routine, pthread_addr_t arg)
{
FAR _TCB *ptcb;
- FAR join_t *pjoin;
+ FAR struct join_s *pjoin;
int priority;
#if CONFIG_RR_INTERVAL > 0
int policy;
@@ -298,7 +301,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
/* Allocate a detachable structure to support pthread_join logic */
- pjoin = (FAR join_t*)kzalloc(sizeof(join_t));
+ pjoin = (FAR struct join_s*)kzalloc(sizeof(struct join_s));
if (!pjoin)
{
errcode = ENOMEM;
@@ -424,7 +427,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
if (ret == OK)
{
/* Wait for the task to actually get running and to register
- * its join_t
+ * its join structure.
*/
(void)pthread_takesemaphore(&pjoin->data_sem);
diff --git a/nuttx/sched/pthread_detach.c b/nuttx/sched/pthread_detach.c
index a959d94b3..6c4b17bee 100644
--- a/nuttx/sched/pthread_detach.c
+++ b/nuttx/sched/pthread_detach.c
@@ -1,7 +1,7 @@
/************************************************************************
* sched/pthread_detach.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -43,9 +43,11 @@
#include <stdbool.h>
#include <pthread.h>
#include <errno.h>
+#include <assert.h>
#include <debug.h>
#include "os_internal.h"
+#include "group_internal.h"
#include "pthread_internal.h"
/************************************************************************
@@ -79,6 +81,10 @@
* A thread object may be "detached" to specify that the return value
* and completion status will not be requested.
*
+ * The caller's task/thread must belong to the same "task group" as the
+ * pthread is (or was) a member of. The thread may or may not still
+ * be running.
+ *
* Parameters:
* thread
*
@@ -91,15 +97,18 @@
int pthread_detach(pthread_t thread)
{
- FAR join_t *pjoin;
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+ FAR struct task_group_s *group = rtcb->group;
+ FAR struct join_s *pjoin;
int ret;
- sdbg("Thread=%d\n", thread);
+ sdbg("Thread=%d group=%p\n", thread, group);
+ DEBUGASSERT(group);
/* Find the entry associated with this pthread. */
- (void)pthread_takesemaphore(&g_join_semaphore);
- pjoin = pthread_findjoininfo((pid_t)thread);
+ (void)pthread_takesemaphore(&group->tg_joinsem);
+ pjoin = pthread_findjoininfo(group, (pid_t)thread);
if (!pjoin)
{
sdbg("Could not find thread entry\n");
@@ -113,7 +122,7 @@ int pthread_detach(pthread_t thread)
{
/* YES.. just remove the thread entry. */
- pthread_destroyjoin(pjoin);
+ pthread_destroyjoin(group, pjoin);
}
else
{
@@ -130,7 +139,7 @@ int pthread_detach(pthread_t thread)
ret = OK;
}
- (void)pthread_givesemaphore(&g_join_semaphore);
+ (void)pthread_givesemaphore(&group->tg_joinsem);
sdbg("Returning %d\n", ret);
return ret;
diff --git a/nuttx/sched/pthread_findjoininfo.c b/nuttx/sched/pthread_findjoininfo.c
index 584ed8f96..8bcb4e407 100644
--- a/nuttx/sched/pthread_findjoininfo.c
+++ b/nuttx/sched/pthread_findjoininfo.c
@@ -1,7 +1,7 @@
/************************************************************************
* pthread_findjoininfo.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,7 @@
#include <sys/types.h>
+#include "group_internal.h"
#include "pthread_internal.h"
/************************************************************************
@@ -71,10 +72,11 @@
* Name: thread_findjoininfo
*
* Description:
- * Find a join_t to the local data set.
+ * Find a join structure in a local data set.
*
* Parameters:
- * pid
+ * group - The that the pid is (or was) a member of of
+ * pid - The ID of the pthread
*
* Return Value:
* None or pointer to the found entry.
@@ -84,13 +86,16 @@
*
************************************************************************/
-FAR join_t *pthread_findjoininfo(pid_t pid)
+FAR struct join_s *pthread_findjoininfo(FAR struct task_group_s *group,
+ pid_t pid)
{
- FAR join_t *pjoin;
+ FAR struct join_s *pjoin;
+
+ DEBUGASSERT(group);
/* Find the entry with the matching pid */
- for (pjoin = g_pthread_head;
+ for (pjoin = group->tg_joinhead;
(pjoin && (pid_t)pjoin->thread != pid);
pjoin = pjoin->next);
diff --git a/nuttx/sched/pthread_getspecific.c b/nuttx/sched/pthread_getspecific.c
index eeead14fa..c6c61fed6 100644
--- a/nuttx/sched/pthread_getspecific.c
+++ b/nuttx/sched/pthread_getspecific.c
@@ -1,7 +1,7 @@
/************************************************************************
* sched/pthread_getspecific.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,7 @@
#include <sched.h>
#include <errno.h>
+#include <assert.h>
#include <debug.h>
#include "os_internal.h"
@@ -104,11 +105,14 @@ FAR void *pthread_getspecific(pthread_key_t key)
{
#if CONFIG_NPTHREAD_KEYS > 0
FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
+ FAR struct task_group_s *group = rtcb->group;
FAR void *ret = NULL;
+ DEBUGASSERT(group);
+
/* Check if the key is valid. */
- if (key < g_pthread_num_keys)
+ if (key < group->tg_nkeys)
{
/* Return the stored value. */
diff --git a/nuttx/sched/pthread_initialize.c b/nuttx/sched/pthread_initialize.c
index 09db1d50e..71b13ebdc 100644
--- a/nuttx/sched/pthread_initialize.c
+++ b/nuttx/sched/pthread_initialize.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread_initialize.c
*
- * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2010, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -57,25 +57,6 @@
* Global Variables
****************************************************************************/
-/* This is the head of a private singly linked list. It
- * is used to retain information about the spawned threads.
- */
-
-FAR join_t *g_pthread_head = NULL;
-FAR join_t *g_pthread_tail = NULL;
-
-/* Mutually exclusive access to this data set is enforced with
- * the following (un-named) semaphore.
- */
-
-sem_t g_join_semaphore;
-
-/* This keys track of the number of global keys that have been
- * allocated.
- */
-
-uint8_t g_pthread_num_keys;
-
/****************************************************************************
* Private Variables
****************************************************************************/
@@ -92,7 +73,9 @@ uint8_t g_pthread_num_keys;
* Name: pthread_initialize
*
* Description:
- * This is an internal OS function called only at power-up boot time.
+ * This is an internal OS function called only at power-up boot time. It
+ * no longer does anything since all of the pthread data structures have
+ * been moved into the "task group"
*
* Parameters:
* None
@@ -106,17 +89,6 @@ uint8_t g_pthread_num_keys;
void pthread_initialize(void)
{
- /* Initialize some global variables */
-
- g_pthread_head = NULL;
- g_pthread_tail = NULL;
- g_pthread_num_keys = 0;
-
- /* Initialize the join semaphore to one (to support one-at-
- * a-time access to private data sets).
- */
-
- (void)sem_init(&g_join_semaphore, 0, 1);
}
/****************************************************************************
diff --git a/nuttx/sched/pthread_internal.h b/nuttx/sched/pthread_internal.h
index ca70ab291..b5c4c3743 100644
--- a/nuttx/sched/pthread_internal.h
+++ b/nuttx/sched/pthread_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread_internal.h
*
- * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -75,53 +75,37 @@ struct join_s
sem_t exit_sem; /* Implements join */
sem_t data_sem; /* Implements join */
pthread_addr_t exit_value; /* Returned data */
-
};
-typedef struct join_s join_t;
-
/****************************************************************************
* Public Variables
****************************************************************************/
-/* This is the head of a private singly linked list. It is used to retain
- * information about the spawned threads.
- */
-
-extern FAR join_t *g_pthread_head;
-extern FAR join_t *g_pthread_tail;
-
-/* Mutually exclusive access to this data set is enforced with the following
- * (un-named) semaphore.
- */
-
-extern sem_t g_join_semaphore;
-
-/* This keys track of the number of global keys that have been allocated. */
-
-extern uint8_t g_pthread_num_keys;
-
-/****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
#ifdef __cplusplus
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
-EXTERN void weak_function pthread_initialize(void);
-EXTERN int pthread_completejoin(pid_t pid, FAR void *exit_value);
-EXTERN void pthread_destroyjoin(FAR join_t *pjoin);
-EXTERN FAR join_t *pthread_findjoininfo(pid_t pid);
-EXTERN int pthread_givesemaphore(sem_t *sem);
-EXTERN FAR join_t *pthread_removejoininfo(pid_t pid);
-EXTERN int pthread_takesemaphore(sem_t *sem);
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+struct task_group_s; /* Forward reference */
+
+void weak_function pthread_initialize(void);
+int pthread_completejoin(pid_t pid, FAR void *exit_value);
+void pthread_destroyjoin(FAR struct task_group_s *group,
+ FAR struct join_s *pjoin);
+FAR struct join_s *pthread_findjoininfo(FAR struct task_group_s *group,
+ pid_t pid);
+int pthread_givesemaphore(sem_t *sem);
+int pthread_takesemaphore(sem_t *sem);
#ifdef CONFIG_MUTEX_TYPES
-EXTERN int pthread_mutexattr_verifytype(int type);
+int pthread_mutexattr_verifytype(int type);
#endif
#undef EXTERN
diff --git a/nuttx/sched/pthread_join.c b/nuttx/sched/pthread_join.c
index d3f648dc7..e5ff56734 100644
--- a/nuttx/sched/pthread_join.c
+++ b/nuttx/sched/pthread_join.c
@@ -1,7 +1,7 @@
/****************************************************************************
* pthread_join.c
*
- * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2008, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -44,6 +44,7 @@
#include <debug.h>
#include "os_internal.h"
+#include "group_internal.h"
#include "pthread_internal.h"
/****************************************************************************
@@ -77,6 +78,10 @@
* A thread can await termination of another thread and retrieve the
* return value of the thread.
*
+ * The caller's task/thread must belong to the same "task group" as the
+ * pthread is (or was) a member of. The thread may or may not still
+ * be running.
+ *
* Parameters:
* thread
* pexit_value
@@ -97,10 +102,13 @@
int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
{
- FAR join_t *pjoin;
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+ FAR struct task_group_s *group = rtcb->group;
+ FAR struct join_s *pjoin;
int ret;
- sdbg("thread=%d\n", thread);
+ sdbg("thread=%d group=%p\n", thread, group);
+ DEBUGASSERT(group);
/* First make sure that this is not an attempt to join to
* ourself.
@@ -117,7 +125,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
* because it will also attempt to get this semaphore.
*/
- (void)pthread_takesemaphore(&g_join_semaphore);
+ (void)pthread_takesemaphore(&group->tg_joinsem);
/* Find the join information associated with this thread.
* This can fail for one of three reasons: (1) There is no
@@ -126,7 +134,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
* was detached and has exited.
*/
- pjoin = pthread_findjoininfo((pid_t)thread);
+ pjoin = pthread_findjoininfo(group, (pid_t)thread);
if (!pjoin)
{
/* Determine what kind of error to return */
@@ -151,7 +159,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
ret = EINVAL;
}
- (void)pthread_givesemaphore(&g_join_semaphore);
+ (void)pthread_givesemaphore(&group->tg_joinsem);
}
else
{
@@ -192,7 +200,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
* semaphore.
*/
- (void)pthread_givesemaphore(&g_join_semaphore);
+ (void)pthread_givesemaphore(&group->tg_joinsem);
/* Take the thread's thread exit semaphore. We will sleep here
* until the thread exits. We need to exercise caution because
@@ -220,7 +228,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
* pthread_destroyjoin is called.
*/
- (void)pthread_takesemaphore(&g_join_semaphore);
+ (void)pthread_takesemaphore(&group->tg_joinsem);
}
/* Pre-emption is okay now. The logic still cannot be re-entered
@@ -235,10 +243,10 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
if (--pjoin->crefs <= 0)
{
- (void)pthread_destroyjoin(pjoin);
+ (void)pthread_destroyjoin(group, pjoin);
}
- (void)pthread_givesemaphore(&g_join_semaphore);
+ (void)pthread_givesemaphore(&group->tg_joinsem);
ret = OK;
}
diff --git a/nuttx/sched/pthread_keycreate.c b/nuttx/sched/pthread_keycreate.c
index 7579e4c11..db09d035f 100644
--- a/nuttx/sched/pthread_keycreate.c
+++ b/nuttx/sched/pthread_keycreate.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread_keycreate.c
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,8 +41,10 @@
#include <sched.h>
#include <errno.h>
+#include <assert.h>
#include <debug.h>
+#include "os_internal.h"
#include "pthread_internal.h"
/****************************************************************************
@@ -109,19 +111,23 @@
int pthread_key_create(FAR pthread_key_t *key, CODE void (*destructor)(void*))
{
#if CONFIG_NPTHREAD_KEYS > 0
+ FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
+ FAR struct task_group_s *group = rtcb->group;
int ret = EAGAIN;
+ DEBUGASSERT(group);
+
/* Check if we have exceeded the system-defined number of keys. */
- if (g_pthread_num_keys < PTHREAD_KEYS_MAX)
+ if (group->tg_nkeys < PTHREAD_KEYS_MAX)
{
/* Return the key value */
- *key = g_pthread_num_keys;
+ *key = group->tg_nkeys;
/* Increment the count of global keys. */
- g_pthread_num_keys++;
+ group->tg_nkeys++;
/* Return success. */
diff --git a/nuttx/sched/pthread_setspecific.c b/nuttx/sched/pthread_setspecific.c
index 33fb4aeeb..8d32772ef 100644
--- a/nuttx/sched/pthread_setspecific.c
+++ b/nuttx/sched/pthread_setspecific.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/pthread_setspecific.c
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,9 @@
#include <sched.h>
#include <errno.h>
+#include <assert.h>
#include <debug.h>
+
#include "os_internal.h"
#include "pthread_internal.h"
@@ -114,11 +116,14 @@ int pthread_setspecific(pthread_key_t key, FAR void *value)
{
#if CONFIG_NPTHREAD_KEYS > 0
FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
+ FAR struct task_group_s *group = rtcb->group;
int ret = EINVAL;
+ DEBUGASSERT(group);
+
/* Check if the key is valid. */
- if (key < g_pthread_num_keys)
+ if (key < group->tg_nkeys)
{
/* Store the data in the TCB. */
diff --git a/nuttx/sched/pthread_removejoininfo.c b/nuttx/sched/task_getgroup.c
index defc02991..fc5bd166e 100644
--- a/nuttx/sched/pthread_removejoininfo.c
+++ b/nuttx/sched/task_getgroup.c
@@ -1,7 +1,7 @@
-/************************************************************************
- * sched/pthread_removejoininfo.c
+/*****************************************************************************
+ * sched/task_getgroup.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -31,107 +31,75 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
- ************************************************************************/
+ *****************************************************************************/
-/************************************************************************
+/*****************************************************************************
* Included Files
- ************************************************************************/
+ *****************************************************************************/
-#include <sys/types.h>
-#include "pthread_internal.h"
+#include <nuttx/config.h>
-/************************************************************************
- * Definitions
- ************************************************************************/
+#include <sched.h>
-/************************************************************************
- * Private Type Declarations
- ************************************************************************/
+#include "os_internal.h"
+#include "group_internal.h"
-/************************************************************************
- * Global Variables
- ************************************************************************/
+#ifdef HAVE_TASK_GROUP
-/************************************************************************
- * Private Variables
- ************************************************************************/
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
-/************************************************************************
+/*****************************************************************************
+ * Private Types
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Data
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Public Data
+ *****************************************************************************/
+
+/*****************************************************************************
* Private Functions
- ************************************************************************/
+ *****************************************************************************/
-/************************************************************************
+/*****************************************************************************
* Public Functions
- ************************************************************************/
+ *****************************************************************************/
-/************************************************************************
- * Name: pthread_removejoininfo
+/*****************************************************************************
+ * Name: task_getgroup
*
* Description:
- * Remove a join_t from the local data set.
+ * Given a task ID, return the group structure of this task.
*
* Parameters:
- * pid
+ * pid - The task ID to use in the lookup.
*
* Return Value:
- * None or pointer to the found entry.
+ * On success, a pointer to the group task structure is returned. This
+ * function can fail only if there is no group that corresponds to the
+ * groupd ID.
*
* Assumptions:
- * The caller has provided protection from re-entrancy.
+ * Called during when signally tasks in a safe context. No special
+ * precautions should be required here. However, extra care is taken when
+ * accessing the global g_grouphead list.
*
- ************************************************************************/
+ *****************************************************************************/
-FAR join_t *pthread_removejoininfo(pid_t pid)
+FAR struct task_group_s *task_getgroup(pid_t pid)
{
- FAR join_t *prev;
- FAR join_t *join;
-
- /* Find the entry with the matching pid */
-
- for (prev = NULL, join = g_pthread_head;
- (join && (pid_t)join->thread != pid);
- prev = join, join = join->next);
-
- /* Remove it from the data set. */
-
- /* First check if this is the entry at the head of the list. */
-
- if (join)
+ FAR _TCB *tcb = sched_gettcb(pid);
+ if (tcb)
{
- if (!prev)
- {
- /* Check if this is the only entry in the list */
-
- if (!join->next)
- {
- g_pthread_head = NULL;
- g_pthread_tail = NULL;
- }
-
- /* Otherwise, remove it from the head of the list */
-
- else
- {
- g_pthread_head = join->next;
- }
- }
-
- /* It is not at the head of the list, check if it is at the tail. */
-
- else if (!join->next)
- {
- g_pthread_tail = prev;
- prev->next = NULL;
- }
-
- /* No, remove it from the middle of the list. */
-
- else
- {
- prev->next = join->next;
- }
+ return tcb->group;
}
- return join;
+ return NULL;
}
+#endif /* HAVE_TASK_GROUP */
diff --git a/nuttx/sched/task_spawn.c b/nuttx/sched/task_spawn.c
index 61a835c91..ec6408df1 100644
--- a/nuttx/sched/task_spawn.c
+++ b/nuttx/sched/task_spawn.c
@@ -49,6 +49,14 @@
#include "spawn_internal.h"
/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_POSIX_SPAWN_PROXY_STACKSIZE
+# define CONFIG_POSIX_SPAWN_PROXY_STACKSIZE 1024
+#endif
+
+/****************************************************************************
* Private Types
****************************************************************************/