Files
intel-linux-sgx/sdk/pthread/pthread_tls.cpp
Zhang Lili Z 9ddec08fb9 Linux 2.8 Open Source Gold Release.
Signed-off-by: Zhang Lili Z <lili.z.zhang@intel.com>
2020-01-16 09:56:26 +08:00

203 lines
4.9 KiB
C++

/* $OpenBSD: rthread_cond.c,v 1.5 2019/01/29 17:40:26 mpi Exp $ */
/*
* Copyright (c) 2017 Martin Pieuchot <mpi@openbsd.org>
* Copyright (c) 2012 Philip Guenther <guenther@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <errno.h>
#include "sgx_trts.h"
#include "sgx_spinlock.h"
#include "pthread_imp.h"
#include "internal/se_cdefs.h"
#include "internal/arch.h"
#include "internal/thread_data.h"
#include "trts_internal.h"
#define PTHREAD_DESTRUCTOR_ITERATIONS 4
#define PTHREAD_KEYS_MAX 256
static struct sgx_thread_key rkeys[PTHREAD_KEYS_MAX];
static volatile uint32_t rkeyslock = SGX_SPINLOCK_INITIALIZER;
extern __thread pthread_info pthread_info_tls;
/*
*: thread-specific data key creation
*/
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*))
{
if ( !sgx_is_within_enclave((void *)key, sizeof(pthread_key_t))) {
return EINVAL;
}
static int hint;
int i;
sgx_spin_lock(&rkeyslock);
if (rkeys[hint].used) {
for (i = 0; i < PTHREAD_KEYS_MAX; i++) {
if (!rkeys[i].used) break;
}
if (i == PTHREAD_KEYS_MAX) {
sgx_spin_unlock(&rkeyslock);
return (EAGAIN);
}
hint = i;
}
rkeys[hint].used = 1;
rkeys[hint].destructor = destructor;
*key = hint++;
if (hint >= PTHREAD_KEYS_MAX)
hint = 0;
sgx_spin_unlock(&rkeyslock);
return (0);
}
/*
*: thread-specific data key deletion
*/
int pthread_key_delete(pthread_key_t key)
{
if ( !sgx_is_within_enclave((void *)&key, sizeof(pthread_key_t))) {
return EINVAL;
}
int rv = 0;
if (key < 0 || key >= PTHREAD_KEYS_MAX)
return (EINVAL);
sgx_spin_lock(&rkeyslock);
if (!rkeys[key].used) {
rv = EINVAL;
goto out;
}
rkeys[key].used = 0;
rkeys[key].destructor = NULL;
out:
sgx_spin_unlock(&rkeyslock);
return (rv);
}
static struct sgx_pthread_storage * _pthread_findstorage(pthread_key_t key)
{
struct sgx_pthread_storage *rs;
if (!rkeys[key].used) {
rs = NULL;
return NULL;
}
pthread_info* thread_info = (pthread_info*)&pthread_info_tls;
for (rs = thread_info->m_local_storage; rs; rs = rs->next) {
if (rs->keyid == key)
break;
}
if (!rs) {
rs = (struct sgx_pthread_storage *)calloc(1, sizeof(*rs));
if (!rs)
return NULL;
rs->keyid = key;
rs->data = NULL;
rs->next = thread_info->m_local_storage;
thread_info->m_local_storage = rs;
}
return (rs);
}
/*
*: get a thread-specific data value
*/
void *pthread_getspecific(pthread_key_t key)
{
if ( !sgx_is_within_enclave((void *)&key, sizeof(pthread_key_t))) {
return NULL;
}
struct sgx_pthread_storage *rs;
if (key < 0 || key >= PTHREAD_KEYS_MAX)
return (NULL);
rs = _pthread_findstorage(key);
if (!rs)
return (NULL);
return (rs->data);
}
/*
*: thread-specific data management
*/
int pthread_setspecific(pthread_key_t key, const void *data)
{
if ( !sgx_is_within_enclave((void *)&key, sizeof(pthread_key_t))) {
return EINVAL;
}
struct sgx_pthread_storage *rs;
if (key < 0 || key >= PTHREAD_KEYS_MAX)
return (EINVAL);
rs = _pthread_findstorage(key);
if (!rs)
return (ENOMEM);
rs->data = (void *)data;
return (0);
}
void _pthread_tls_destructors(void)
{
struct sgx_pthread_storage *rs;
int i;
if(NULL == pthread_info_tls.m_pthread)
//do nothing
return;
sgx_spin_lock(&rkeyslock);
for (i = 0; i < PTHREAD_DESTRUCTOR_ITERATIONS; i++) {
for (rs = pthread_info_tls.m_local_storage; rs; rs = rs->next) {
if (!rs->data)
continue;
if (rkeys[rs->keyid].destructor) {
void (*destructor)(void *) = rkeys[rs->keyid].destructor;
void *data = rs->data;
rs->data = NULL;
sgx_spin_unlock(&rkeyslock);
destructor(data);
sgx_spin_lock(&rkeyslock);
}
}
}
for (rs = pthread_info_tls.m_local_storage; rs; rs = pthread_info_tls.m_local_storage) {
pthread_info_tls.m_local_storage = rs->next;
free(rs);
}
sgx_spin_unlock(&rkeyslock);
}