add ability to have thread-specific data on windows, pthreads, solaris threads,
and non-threaded builds This commit was SVN r15492.
Этот коммит содержится в:
родитель
b6c60dfc07
Коммит
c5d0066c27
@ -25,9 +25,11 @@ headers += \
|
||||
threads/mutex.h \
|
||||
threads/mutex_unix.h \
|
||||
threads/mutex_windows.h \
|
||||
threads/threads.h
|
||||
threads/threads.h \
|
||||
threads/tsd.h
|
||||
|
||||
libopen_pal_la_SOURCES += \
|
||||
threads/condition.c \
|
||||
threads/mutex.c \
|
||||
threads/thread.c
|
||||
threads/thread.c \
|
||||
threads/tsd.c
|
||||
|
107
opal/threads/tsd.c
Обычный файл
107
opal/threads/tsd.c
Обычный файл
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Los Alamos National Security, LLC. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#include "opal/threads/tsd.h"
|
||||
|
||||
#if !OMPI_HAVE_POSIX_THREADS && !OMPI_HAVE_SOLARIS_THREADS && !defined(__WINDOWS__)
|
||||
|
||||
#define TSD_ENTRIES 32
|
||||
|
||||
struct tsd_entry_t {
|
||||
bool used;
|
||||
void *value;
|
||||
opal_tsd_destructor_t destructor;
|
||||
};
|
||||
typedef struct tsd_entry_t tsd_entry_t;
|
||||
|
||||
static tsd_entry_t entries[TSD_ENTRIES];
|
||||
static bool atexit_registered = false;
|
||||
|
||||
void
|
||||
run_destructors(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 i < TSD_ENTRIES ; ++i) {
|
||||
opal_tsd_destructor_t destructor;
|
||||
void *value;
|
||||
|
||||
destructor = entries[i].destructor;
|
||||
value = entries[i].value;
|
||||
|
||||
entries[i].used = false;
|
||||
entries[i].destructor = NULL;
|
||||
entries[i].value = NULL;
|
||||
|
||||
destructor(value);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
opal_tsd_key_create(opal_tsd_key_t *key,
|
||||
opal_tsd_destructor_t destructor)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!atexit_registered) {
|
||||
atexit_registered = true;
|
||||
if (0 != atexit(run_destructors)) {
|
||||
return OPAL_ERR_TEMP_OUT_OF_RESOURCE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0 ; i < TSD_ENTRIES ; ++i) {
|
||||
if (entries[i].used == false) {
|
||||
entries[i].used = true;
|
||||
entries[i].value = NULL;
|
||||
entries[i].destructor = destructor;
|
||||
*key = i;
|
||||
}
|
||||
}
|
||||
if (i == TSD_ENTRIES) return ENOMEM;
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
opal_tsd_key_delete(opal_tsd_key_t key)
|
||||
{
|
||||
if (!entries[key].used) return OPAL_ERR_BAD_PARAM;
|
||||
|
||||
entries[key].used = false;
|
||||
entries[key].value = NULL;
|
||||
entries[key].destructor = NULL;
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
opal_tsd_setspecific(opal_tsd_key_t key, void *value)
|
||||
{
|
||||
if (!entries[key].used) return OPAL_ERR_BAD_PARAM;
|
||||
entries[key].value = value;
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
opal_tsd_getspecific(opal_tsd_key_t key, void **valuep)
|
||||
{
|
||||
if (!entries[key].used) return OPAL_ERR_BAD_PARAM;
|
||||
*valuep = entries[key].value;
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
251
opal/threads/tsd.h
Обычный файл
251
opal/threads/tsd.h
Обычный файл
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Los Alamos National Security, LLC. All rights
|
||||
* reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OPAL_THREADS_TSD_H
|
||||
#define OPAL_THREADS_TSD_H
|
||||
|
||||
#if OMPI_HAVE_POSIX_THREADS
|
||||
#include <pthread.h>
|
||||
#elif OMPI_HAVE_SOLARIS_THREADS
|
||||
#include <thread.h>
|
||||
#endif
|
||||
|
||||
#include "opal/constants.h"
|
||||
|
||||
BEGIN_C_DECLS
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Thread Specific Datastore Interface
|
||||
*
|
||||
* Functions for providing thread-specific datastore capabilities.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Prototype for callback when tsd data is being destroyed
|
||||
*/
|
||||
typedef void (*opal_tsd_destructor_t)(void *value);
|
||||
|
||||
#if defined(DOXYGEN)
|
||||
|
||||
/**
|
||||
* Typedef for thread-specific data key
|
||||
*/
|
||||
typedef void* opal_tsd_key_t;
|
||||
|
||||
|
||||
/**
|
||||
* Create thread-specific data key
|
||||
*
|
||||
* Create a thread-specific data key visible to all threads in the
|
||||
* current process. The returned key is valid in all threads,
|
||||
* although the values bound to the key by opal_tsd_setspecific() are
|
||||
* allocated on a per-thread basis and persist for the life of the
|
||||
* calling thread.
|
||||
*
|
||||
* Upon key creation, the value NULL is associated with the new key in
|
||||
* all active threads. When a new thread is created, the value NULL
|
||||
* is associated with all defined keys in the new thread.
|
||||
*
|
||||
* The destructor parameter may be NULL. At thread exit, if
|
||||
* destructor is non-NULL AND the thread has a non-NULL value
|
||||
* associated with the key, the function is called with the current
|
||||
* value as its argument.
|
||||
*
|
||||
* @param key[out] The key for accessing thread-specific data
|
||||
* @param destructor[in] Cleanup function to call when a thread exits
|
||||
*
|
||||
* @retval OPAL_SUCCESS Success
|
||||
* @retval EAGAIN The system lacked the necessary resource to
|
||||
* create another thread specific data key
|
||||
* @retval ENOMEM Insufficient memory exists to create the key
|
||||
*/
|
||||
int opal_tsd_key_create(opal_tsd_key_t *key,
|
||||
opal_tsd_destructor_t destructor);
|
||||
|
||||
|
||||
/**
|
||||
* Delete a thread-specific data key
|
||||
*
|
||||
* Delete a thread-specific data key previously returned by
|
||||
* opal_tsd_key_create(). The destructor associated with the key is
|
||||
* not fired in any thread and memory cleanup is the responsibility of
|
||||
* the caller.
|
||||
*
|
||||
* @note Unlike pthread_key_delete, this function should not be called
|
||||
* from within a destructor. It can not be universally supported at
|
||||
* this time.
|
||||
*
|
||||
* @param key[in] The key for accessing thread-specific data
|
||||
*
|
||||
* @retval OPAL_SUCCESS Success
|
||||
* @retval EINVAL Invalid key
|
||||
*/
|
||||
int opal_tsd_key_delete(opal_tsd_key_t key);
|
||||
|
||||
|
||||
/**
|
||||
* Set a thread-specific data value
|
||||
*
|
||||
* Associates value with key in the current thread. The value for the
|
||||
* key in other threads is not changed. Different threads may assign
|
||||
* different values to the same key.
|
||||
*
|
||||
* @note This function should not be called within
|
||||
* opal_tsd_key_delete().
|
||||
*
|
||||
* @param key[in] Thread specific data key to modify
|
||||
* @param value[in] Value to associate with key
|
||||
*
|
||||
* @retval OPAL_SUCCESS Success
|
||||
* @retval ENOMEM Insufficient memory exists to associate the
|
||||
* value with the key
|
||||
* @retval EINVAL Invalid key
|
||||
*/
|
||||
int opal_tsd_setspecific(opal_tsd_key_t key, void *value);
|
||||
|
||||
|
||||
/**
|
||||
* Get a thread-specific data value
|
||||
*
|
||||
* Get the data associated with the given key, as set by
|
||||
* opal_tsd_setspecific(). If opal_tsd_setspecific() hasn't been
|
||||
* called in the current thread with the given key, NULL is returned
|
||||
* in valuep.
|
||||
*
|
||||
* @param key[in] Thread specific data key to modify
|
||||
* @param value[out] Value to associate with key
|
||||
*
|
||||
* @retval OPAL_SUCCESS Success
|
||||
* @retval ENOMEM Insufficient memory exists to associate the
|
||||
* value with the key
|
||||
* @retval EINVAL Invalid key
|
||||
*/
|
||||
int opal_tsd_getspecific(opal_tsd_key_t key, void **valuep);
|
||||
|
||||
#elif OMPI_HAVE_POSIX_THREADS
|
||||
|
||||
typedef pthread_key_t opal_tsd_key_t;
|
||||
|
||||
static inline int
|
||||
opal_tsd_key_create(opal_tsd_key_t *key,
|
||||
opal_tsd_destructor_t destructor)
|
||||
{
|
||||
return pthread_key_create(key, destructor);
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_tsd_key_delete(opal_tsd_key_t key)
|
||||
{
|
||||
return pthread_key_delete(key);
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_tsd_setspecific(opal_tsd_key_t key, void *value)
|
||||
{
|
||||
return pthread_setspecific(key, value);
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_tsd_getspecific(opal_tsd_key_t key, void **valuep)
|
||||
{
|
||||
*valuep = pthread_getspecific(key);
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
#elif OMPI_HAVE_SOLARIS_THREADS
|
||||
|
||||
typedef thread_key_t opal_tsd_key_t;
|
||||
|
||||
static inline int
|
||||
opal_tsd_key_create(opal_tsd_key_t *key,
|
||||
opal_tsd_destructor_t destructor)
|
||||
{
|
||||
return thr_keycreate(key, destructor);
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_tsd_key_delete(opal_tsd_key_t key)
|
||||
{
|
||||
OPAL_SUCCESS
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_tsd_setspecific(opal_tsd_key_t key, void *value)
|
||||
{
|
||||
return thr_setspecific(key, value);
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_tsd_getspecific(opal_tsd_key_t key, void **valuep)
|
||||
{
|
||||
return thr_getspecific(key, valuep);
|
||||
}
|
||||
|
||||
#elif defined(__WINDOWS__)
|
||||
|
||||
/* BWB - FIX ME - this is still not quite right -- we also need to
|
||||
implement support for running the destructors when a thread exits,
|
||||
but I'm not sure we have a framework for doing that just yet. */
|
||||
|
||||
typedef DWORD opal_tsd_key_t;
|
||||
|
||||
static inline int
|
||||
opal_tsd_key_create(opal_tsd_key_t *key,
|
||||
opal_tsd_destructor_t destructor)
|
||||
{
|
||||
*key = TlsAlloc();
|
||||
|
||||
return (*key == TLS_OUT_OF_INDEXES) ? OPAL_ERROR : OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_tsd_key_delete(opal_tsd_key_t key)
|
||||
{
|
||||
key = TlsFree(key);
|
||||
|
||||
return (key == 0) ? OPAL_ERROR : OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_tsd_setspecific(opal_tsd_key_t key, void *value)
|
||||
{
|
||||
BOOL ret = TlsSetValue(key, (LPVOID) value);
|
||||
|
||||
return (ret) ? OPAL_SUCCESS : OPAL_ERROR;
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_tsd_getspecific(opal_tsd_key_t key, void **valuep)
|
||||
{
|
||||
*valuep = TlsGetValue(key);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef int opal_tsd_key_t;
|
||||
|
||||
int opal_tsd_key_create(opal_tsd_key_t *key,
|
||||
opal_tsd_destructor_t destructor);
|
||||
|
||||
int opal_tsd_key_delete(opal_tsd_key_t key);
|
||||
|
||||
int opal_tsd_setspecific(opal_tsd_key_t key, void *value);
|
||||
|
||||
int opal_tsd_getspecific(opal_tsd_key_t key, void **valuep);
|
||||
|
||||
#endif
|
||||
|
||||
END_C_DECLS
|
||||
|
||||
#endif /* OPAL_MTHREADS_TSD_H */
|
Загрузка…
x
Ссылка в новой задаче
Block a user