mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-04 17:11:44 +03:00
164 lines
3.6 KiB
C
164 lines
3.6 KiB
C
/*
|
|
* Placed into the Public Domain
|
|
* written by Walter Bright, Digital Mars
|
|
* www.digitalmars.com
|
|
*/
|
|
|
|
/* ================================= Win32 ============================ */
|
|
|
|
#if _WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
/******************************************
|
|
* Enter/exit critical section.
|
|
*/
|
|
|
|
/* We don't initialize critical sections unless we actually need them.
|
|
* So keep a linked list of the ones we do use, and in the static destructor
|
|
* code, walk the list and release them.
|
|
*/
|
|
|
|
typedef struct D_CRITICAL_SECTION
|
|
{
|
|
struct D_CRITICAL_SECTION *next;
|
|
CRITICAL_SECTION cs;
|
|
} D_CRITICAL_SECTION;
|
|
|
|
static D_CRITICAL_SECTION *dcs_list;
|
|
static D_CRITICAL_SECTION critical_section;
|
|
static volatile int inited;
|
|
|
|
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
|
|
{
|
|
if (!dcs->next)
|
|
{
|
|
EnterCriticalSection(&critical_section.cs);
|
|
if (!dcs->next) // if, in the meantime, another thread didn't set it
|
|
{
|
|
dcs->next = dcs_list;
|
|
dcs_list = dcs;
|
|
InitializeCriticalSection(&dcs->cs);
|
|
}
|
|
LeaveCriticalSection(&critical_section.cs);
|
|
}
|
|
EnterCriticalSection(&dcs->cs);
|
|
}
|
|
|
|
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
|
{
|
|
LeaveCriticalSection(&dcs->cs);
|
|
}
|
|
|
|
void _STI_critical_init()
|
|
{
|
|
if (!inited)
|
|
{ InitializeCriticalSection(&critical_section.cs);
|
|
dcs_list = &critical_section;
|
|
inited = 1;
|
|
}
|
|
}
|
|
|
|
void _STD_critical_term()
|
|
{
|
|
if (inited)
|
|
{ inited = 0;
|
|
while (dcs_list)
|
|
{
|
|
DeleteCriticalSection(&dcs_list->cs);
|
|
dcs_list = dcs_list->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/* ================================= linux ============================ */
|
|
|
|
#if linux || __APPLE__ || __FreeBSD__ || (defined(__SVR4) && defined (__sun))
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
|
|
#if !linux
|
|
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
|
|
#endif
|
|
|
|
/******************************************
|
|
* Enter/exit critical section.
|
|
*/
|
|
|
|
/* We don't initialize critical sections unless we actually need them.
|
|
* So keep a linked list of the ones we do use, and in the static destructor
|
|
* code, walk the list and release them.
|
|
*/
|
|
|
|
typedef struct D_CRITICAL_SECTION
|
|
{
|
|
struct D_CRITICAL_SECTION *next;
|
|
pthread_mutex_t cs;
|
|
} D_CRITICAL_SECTION;
|
|
|
|
static D_CRITICAL_SECTION *dcs_list;
|
|
static D_CRITICAL_SECTION critical_section;
|
|
static pthread_mutexattr_t _criticals_attr;
|
|
|
|
void _STI_critical_init(void);
|
|
void _STD_critical_term(void);
|
|
|
|
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
|
|
{
|
|
if (!dcs_list)
|
|
{ _STI_critical_init();
|
|
atexit(_STD_critical_term);
|
|
}
|
|
//printf("_d_criticalenter(dcs = x%x)\n", dcs);
|
|
if (!dcs->next)
|
|
{
|
|
pthread_mutex_lock(&critical_section.cs);
|
|
if (!dcs->next) // if, in the meantime, another thread didn't set it
|
|
{
|
|
dcs->next = dcs_list;
|
|
dcs_list = dcs;
|
|
pthread_mutex_init(&dcs->cs, &_criticals_attr);
|
|
}
|
|
pthread_mutex_unlock(&critical_section.cs);
|
|
}
|
|
pthread_mutex_lock(&dcs->cs);
|
|
}
|
|
|
|
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
|
{
|
|
//printf("_d_criticalexit(dcs = x%x)\n", dcs);
|
|
pthread_mutex_unlock(&dcs->cs);
|
|
}
|
|
|
|
void _STI_critical_init()
|
|
{
|
|
if (!dcs_list)
|
|
{ //printf("_STI_critical_init()\n");
|
|
pthread_mutexattr_init(&_criticals_attr);
|
|
pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
|
|
|
// The global critical section doesn't need to be recursive
|
|
pthread_mutex_init(&critical_section.cs, 0);
|
|
dcs_list = &critical_section;
|
|
}
|
|
}
|
|
|
|
void _STD_critical_term()
|
|
{
|
|
if (dcs_list)
|
|
{ //printf("_STI_critical_term()\n");
|
|
while (dcs_list)
|
|
{
|
|
//printf("\tlooping... %x\n", dcs_list);
|
|
pthread_mutex_destroy(&dcs_list->cs);
|
|
dcs_list = dcs_list->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|