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:
parent
0066db82f9
commit
32dde889e2
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
||||
****************************************************************************/
|
||||
|
|
Loading…
Reference in New Issue