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
/* 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 ***************************************************************/
/* 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
@ -520,7 +535,7 @@ struct task_group_s
FAR struct join_s *tg_jointail; /* Tail of a list of join data */
#endif
#if CONFIG_NPTHREAD_KEYS > 0
uint8_t tg_nkeys; /* Number pthread keys allocated */
pthread_keyset_t tg_keyset; /* Set of pthread keys allocated */
#endif
#ifndef CONFIG_DISABLE_SIGNALS

View File

@ -616,8 +616,10 @@ config NPTHREAD_KEYS
int "Maximum number of pthread keys"
default 4 if !DISABLE_PTHREAD
default 0 if DISABLE_PTHREAD
range 0 32
---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

View File

@ -1,7 +1,7 @@
/****************************************************************************
* 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>
*
* 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 void *ret = NULL;
DEBUGASSERT(group);
DEBUGASSERT(group != NULL && (unsigned)key < CONFIG_NPTHREAD_KEYS);
/* 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. */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* 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>
*
* Redistribution and use in source and binary forms, with or without
@ -44,6 +44,8 @@
#include <assert.h>
#include <debug.h>
#include <nuttx/irq.h>
#include "sched/sched.h"
#include "pthread/pthread.h"
@ -66,23 +68,23 @@
* associated with all defined keys in the new thread.
*
* Input Parameters:
* key = A pointer to the key to create.
* destructor = An optional destructor() function that may be associated
* with each key that is invoked when a thread exits. However, this
* argument is ignored in the current implementation.
* key - A pointer to the key to create.
* destructor - An optional destructor() function that may be associated
* with each key that is invoked when a thread exits.
* However, this argument is ignored in the current
* implementation.
*
* Returned Value:
* If successful, the pthread_key_create() function will store the newly
* 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
* thread-specific data key, or the system-imposed limit on the total
* number of keys pers process {PTHREAD_KEYS_MAX} has been exceeded
* EAGAIN - The system lacked sufficient resources to create another
* thread-specific data key, or the system-imposed limit on
* the total number of keys pers process {PTHREAD_KEYS_MAX}
* has been exceeded
* ENONMEM - Insufficient memory exists to create the key.
*
* Assumptions:
*
* POSIX Compatibility:
* - 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
FAR struct tcb_s *rtcb = this_task();
FAR struct task_group_s *group = rtcb->group;
irqstate_t flags;
int candidate;
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;

View File

@ -1,7 +1,7 @@
/****************************************************************************
* 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>
*
* Redistribution and use in source and binary forms, with or without
@ -43,6 +43,9 @@
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include "sched/sched.h"
#include "pthread/pthread.h"
/****************************************************************************
@ -58,7 +61,7 @@
* does nothing in the present implementation.
*
* Input Parameters:
* key = the key to delete
* key - the key to delete
*
* Returned Value:
* Always returns ENOSYS.
@ -71,6 +74,33 @@
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;
#endif
}

View File

@ -1,7 +1,7 @@
/****************************************************************************
* 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>
*
* 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;
int ret = EINVAL;
DEBUGASSERT(group);
DEBUGASSERT(group != NULL && (unsigned)key < CONFIG_NPTHREAD_KEYS);
/* 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. */