9
0
Fork 0

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
This commit is contained in:
patacongo 2013-02-03 16:43:58 +00:00
parent 0066db82f9
commit 32dde889e2
21 changed files with 307 additions and 216 deletions

View File

@ -503,7 +503,7 @@ static void stdio_test(void)
* ostest_main
****************************************************************************/
int ostest_main(int argc, char *argv[])
int ostest_main(int argc, FAR char *argv[])
{
int result;
@ -546,9 +546,11 @@ int ostest_main(int argc, char *argv[])
/* Verify that we can spawn a new task */
#ifndef CONFIG_CUSTOM_STACK
result = task_create("ostest", PRIORITY, STACKSIZE, user_main, g_argv);
result = task_create("ostest", PRIORITY, STACKSIZE, user_main,
(FAR char * const *)g_argv);
#else
result = task_create("ostest", PRIORITY, user_main, g_argv);
result = task_create("ostest", PRIORITY, user_main,
(FAR char * const *)g_argv);
#endif
if (result == ERROR)
{

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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.
*/

View File

@ -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;
}

View File

@ -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;
@ -121,6 +122,76 @@ static bool pthread_notifywaiters(FAR join_t *pjoin)
return false;
}
/************************************************************************
* 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 */

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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. */

View File

@ -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);
}
/****************************************************************************

View File

@ -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;
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C" {
#else
#define EXTERN extern
#endif
struct task_group_s; /* Forward reference */
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);
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

View File

@ -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;
}

View File

@ -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. */

View File

@ -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. */

View File

@ -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 */

View File

@ -48,6 +48,14 @@
#include "group_internal.h"
#include "spawn_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef CONFIG_POSIX_SPAWN_PROXY_STACKSIZE
# define CONFIG_POSIX_SPAWN_PROXY_STACKSIZE 1024
#endif
/****************************************************************************
* Private Types
****************************************************************************/