mirror of
https://github.com/dlang/phobos.git
synced 2025-05-04 17:11:26 +03:00
158 lines
3.4 KiB
C
158 lines
3.4 KiB
C
// Copyright (C) 2000-2004 by Digital Mars, www.digitalmars.com
|
|
// All Rights Reserved
|
|
// Written by Walter Bright
|
|
|
|
/* ================================= 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
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.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;
|
|
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
|
|
|