sched/pthread: Implement pthread_key_delete(). This involves some minor changes to the group data structure.

This commit is contained in:
Gregory Nutt 2018-12-28 14:21:19 -06:00
parent 0047992349
commit 8b21960ba3
6 changed files with 95 additions and 30 deletions

View File

@ -375,6 +375,21 @@ struct pthread_cleanup_s
}; };
#endif #endif
/* type pthread_keyset_t *********************************************************/
/* Smallest addressable type that can hold the entire configured number of keys */
#if defined(CONFIG_NPTHREAD_KEYS) && CONFIG_NPTHREAD_KEYS > 0
# if CONFIG_NPTHREAD_KEYS > 32
# error Too many pthread keys
# elif CONFIG_NPTHREAD_KEYS > 16
typedef uint32_t pthread_keyset_t;
# elif CONFIG_NPTHREAD_KEYS > 8
typedef uint16_t pthread_keyset_t;
# else
typedef uint8_t pthread_keyset_t;
# endif
#endif
/* struct dspace_s ***************************************************************/ /* struct dspace_s ***************************************************************/
/* This structure describes a reference counted D-Space region. This must be a /* This structure describes a reference counted D-Space region. This must be a
* separately allocated "break-away" structure that can be owned by a task and * separately allocated "break-away" structure that can be owned by a task and
@ -520,7 +535,7 @@ struct task_group_s
FAR struct join_s *tg_jointail; /* Tail of a list of join data */ FAR struct join_s *tg_jointail; /* Tail of a list of join data */
#endif #endif
#if CONFIG_NPTHREAD_KEYS > 0 #if CONFIG_NPTHREAD_KEYS > 0
uint8_t tg_nkeys; /* Number pthread keys allocated */ pthread_keyset_t tg_keyset; /* Set of pthread keys allocated */
#endif #endif
#ifndef CONFIG_DISABLE_SIGNALS #ifndef CONFIG_DISABLE_SIGNALS

View File

@ -616,8 +616,10 @@ config NPTHREAD_KEYS
int "Maximum number of pthread keys" int "Maximum number of pthread keys"
default 4 if !DISABLE_PTHREAD default 4 if !DISABLE_PTHREAD
default 0 if DISABLE_PTHREAD default 0 if DISABLE_PTHREAD
range 0 32
---help--- ---help---
The number of items of thread-specific data that can be retained The number of items of thread-specific data that can be retained.
The value zero disables support for pthread-specific data.
if !DISABLE_PTHREAD if !DISABLE_PTHREAD

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* sched/pthread/pthread_getspecific.c * sched/pthread/pthread_getspecific.c
* *
* Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2009, 2013, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -88,11 +88,11 @@ FAR void *pthread_getspecific(pthread_key_t key)
FAR struct task_group_s *group = rtcb->group; FAR struct task_group_s *group = rtcb->group;
FAR void *ret = NULL; FAR void *ret = NULL;
DEBUGASSERT(group); DEBUGASSERT(group != NULL && (unsigned)key < CONFIG_NPTHREAD_KEYS);
/* Check if the key is valid. */ /* Check if the key is valid. */
if (key < group->tg_nkeys) if (key < CONFIG_NPTHREAD_KEYS && (group->tg_keyset & (1 << key)) != 0)
{ {
/* Return the stored value. */ /* Return the stored value. */

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* sched/pthread/pthread_keycreate.c * sched/pthread/pthread_keycreate.c
* *
* Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2013, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -44,6 +44,8 @@
#include <assert.h> #include <assert.h>
#include <debug.h> #include <debug.h>
#include <nuttx/irq.h>
#include "sched/sched.h" #include "sched/sched.h"
#include "pthread/pthread.h" #include "pthread/pthread.h"
@ -66,23 +68,23 @@
* associated with all defined keys in the new thread. * associated with all defined keys in the new thread.
* *
* Input Parameters: * Input Parameters:
* key = A pointer to the key to create. * key - A pointer to the key to create.
* destructor = An optional destructor() function that may be associated * destructor - An optional destructor() function that may be associated
* with each key that is invoked when a thread exits. However, this * with each key that is invoked when a thread exits.
* argument is ignored in the current implementation. * However, this argument is ignored in the current
* implementation.
* *
* Returned Value: * Returned Value:
* If successful, the pthread_key_create() function will store the newly * If successful, the pthread_key_create() function will store the newly
* created key value at *key and return zero (OK). Otherwise, an error * created key value at *key and return zero (OK). Otherwise, an error
* number will bereturned to indicate the error: * number will be returned to indicate the error:
* *
* EAGAIN - The system lacked sufficient resources to create another * EAGAIN - The system lacked sufficient resources to create another
* thread-specific data key, or the system-imposed limit on the total * thread-specific data key, or the system-imposed limit on
* number of keys pers process {PTHREAD_KEYS_MAX} has been exceeded * the total number of keys pers process {PTHREAD_KEYS_MAX}
* has been exceeded
* ENONMEM - Insufficient memory exists to create the key. * ENONMEM - Insufficient memory exists to create the key.
* *
* Assumptions:
*
* POSIX Compatibility: * POSIX Compatibility:
* - The present implementation ignores the destructor argument. * - The present implementation ignores the destructor argument.
* *
@ -94,25 +96,41 @@ int pthread_key_create(FAR pthread_key_t *key,
#if CONFIG_NPTHREAD_KEYS > 0 #if CONFIG_NPTHREAD_KEYS > 0
FAR struct tcb_s *rtcb = this_task(); FAR struct tcb_s *rtcb = this_task();
FAR struct task_group_s *group = rtcb->group; FAR struct task_group_s *group = rtcb->group;
irqstate_t flags;
int candidate;
int ret = EAGAIN; int ret = EAGAIN;
DEBUGASSERT(group); DEBUGASSERT(key != NULL && group != NULL);
/* Check if we have exceeded the system-defined number of keys. */ /* Search for an unused key. This is done in a critical section here to
* avoid concurrent modification of the group keyset.
*/
if (group->tg_nkeys < PTHREAD_KEYS_MAX) flags = spin_lock_irqsave();
for (candidate = 0; candidate < PTHREAD_KEYS_MAX; candidate++)
{ {
/* Return the key value */ /* Is this candidate key available? */
*key = group->tg_nkeys; pthread_keyset_t mask = (1 << candidate);
if ((group->tg_keyset & mask) == 0)
{
/* Yes.. allocate the key and break out of the loop */
/* Increment the count of global keys. */ group->tg_keyset |= mask;
break;
}
}
group->tg_nkeys++; spin_unlock_irqrestore(flags);
/* Return success. */ /* Check if found a valid key. */
ret = OK; if (candidate < PTHREAD_KEYS_MAX)
{
/* Yes.. Return the key value and success */
*key = candidate;
ret = OK;
} }
return ret; return ret;

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* sched/pthread/pthread_keydelete.c * sched/pthread/pthread_keydelete.c
* *
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2009, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -43,6 +43,9 @@
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
#include <nuttx/irq.h>
#include "sched/sched.h"
#include "pthread/pthread.h" #include "pthread/pthread.h"
/**************************************************************************** /****************************************************************************
@ -58,7 +61,7 @@
* does nothing in the present implementation. * does nothing in the present implementation.
* *
* Input Parameters: * Input Parameters:
* key = the key to delete * key - the key to delete
* *
* Returned Value: * Returned Value:
* Always returns ENOSYS. * Always returns ENOSYS.
@ -71,6 +74,33 @@
int pthread_key_delete(pthread_key_t key) int pthread_key_delete(pthread_key_t key)
{ {
#if CONFIG_NPTHREAD_KEYS > 0
FAR struct tcb_s *rtcb = this_task();
FAR struct task_group_s *group = rtcb->group;
pthread_keyset_t mask;
irqstate_t flags;
int ret = EINVAL;
DEBUGASSERT((unsigned)key < PTHREAD_KEYS_MAX && group != NULL);
if ((unsigned)key < PTHREAD_KEYS_MAX)
{
/* This is done in a critical section here to avoid concurrent
* modification of the group keyset.
*/
mask = (1 << key);
flags = spin_lock_irqsave();
DEBUGASSERT((group->tg_keyset & mask) != 0);
group->tg_keyset &= ~mask;
spin_unlock_irqrestore(flags);
ret = OK;
}
return ret;
#else
return ENOSYS; return ENOSYS;
#endif
} }

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* sched/pthread/pthread_setspecific.c * sched/pthread/pthread_setspecific.c
* *
* Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2013, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -99,11 +99,11 @@ int pthread_setspecific(pthread_key_t key, FAR const void *value)
FAR struct task_group_s *group = rtcb->group; FAR struct task_group_s *group = rtcb->group;
int ret = EINVAL; int ret = EINVAL;
DEBUGASSERT(group); DEBUGASSERT(group != NULL && (unsigned)key < CONFIG_NPTHREAD_KEYS);
/* Check if the key is valid. */ /* Check if the key is valid. */
if (key < group->tg_nkeys) if (key < CONFIG_NPTHREAD_KEYS && (group->tg_keyset & (1 << key)) != 0)
{ {
/* Store the data in the TCB. */ /* Store the data in the TCB. */