sched/pthread: Implement pthread_key_delete(). This involves some minor changes to the group data structure.
This commit is contained in:
parent
0047992349
commit
8b21960ba3
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user