blob: e980c371c7b731182eecfb972802d1af9faab08e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#undef __USE_XOPEN
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include "port_mutex.h"
#include "port_atomic.h"
#include "port_thread_internal.h"
volatile port_shared_data_t* port_shared_data = NULL;
static pthread_mutex_t g_shared_data_mutex = PTHREAD_MUTEX_INITIALIZER;
static port_shared_data_t* g_port_shared_data = NULL;
static port_shared_data_t g_port_shared_data_struct;
#ifdef _EM64T_
#define MEM_PROTECT_SIZE 0x400
#elif defined (_IPF_)
#define MEM_PROTECT_SIZE 0
#else /* _IA32_ */
#define MEM_PROTECT_SIZE 0x100
#endif
static int init_psd_structure(port_shared_data_t* data)
{
int err;
pthread_attr_t pthread_attr;
size_t stack_size, guard_size;
memset(data, 0, sizeof(port_shared_data_t));
if ((err = pthread_key_create(&data->tls_key, NULL)) != 0)
return err;
if ((err = pthread_mutex_init(&data->suspend_mutex, NULL)) != 0)
return err;
if ((err = pthread_mutex_init(&data->suspend_init_mutex, NULL)) != 0)
return err;
pthread_attr_init(&pthread_attr);
err = pthread_attr_getstacksize(&pthread_attr, &stack_size);
pthread_attr_destroy(&pthread_attr);
if (err != 0)
return err;
pthread_attr_init(&pthread_attr);
err = pthread_attr_getguardsize(&pthread_attr, &guard_size);
pthread_attr_destroy(&pthread_attr);
if (err != 0)
return err;
if (sem_init(&data->yield_sem, 0, 0) != 0)
return err;
data->foreign_stack_size = stack_size;
data->guard_page_size = guard_size;
data->mem_protect_size = MEM_PROTECT_SIZE;
data->req_type = THREADREQ_NONE;
data->signal_set = FALSE;
data->guard_stack_size = 64*1024;
if (data->guard_stack_size < MINSIGSTKSZ)
data->guard_stack_size =
(MINSIGSTKSZ + guard_size - 1) & ~(guard_size - 1);
return 0;
}
int port_init_shared_data(volatile port_shared_data_t** p_psd)
{
int err = 0;
if (*p_psd)
return 0;
/* Serialize access to avoid multiple initialization */
err = pthread_mutex_lock(&g_shared_data_mutex);
if (err != 0)
return err;
/* If another thread had filled the pointer */
if (*p_psd)
{
pthread_mutex_unlock(&g_shared_data_mutex);
return 0;
}
/* If structure is already initialized */
if (!g_port_shared_data)
{
err = init_psd_structure(&g_port_shared_data_struct);
if (err == 0)
g_port_shared_data = &g_port_shared_data_struct;
}
if (g_port_shared_data)
*p_psd = g_port_shared_data;
pthread_mutex_unlock(&g_shared_data_mutex);
return err;
}
int init_port_shared_data()
{
if (port_shared_data)
return 0;
return port_init_shared_data(&port_shared_data);
}