view runtime/internal/critical.c @ 1605:1d5721f9ae18

[WIP] Merge DMD r251: bugzilla 111 (appending a dchar to a char[]) This patch needs some work in the code generation, because of the runtime changes (functions "_d_arrayappendcd" and "_d_arrayappendwd" are added). This doesn't affect existing code though, it just makes with patch a little useless, because something like this: char [] s; s ~= '\u6211'; That failed to compile with a nice error message previously to this change, now fails with and ugly error message (a failed assertion). Apparently there is a regression introduced by this patch too, when compiling Dil I get this assertion message: ldc: /home/luca/tesis/ldc/gen/statements.cpp:132: virtual void ReturnStatement::toIR(IRState*): Assertion `p->topfunc()->getReturnType() == llvm::Type::getVoidTy(gIR->context())' failed. 0 ldc 0x08a91628 Thank god we have bisecting capabilities in VCSs now ;) --- dmd/expression.c | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 41 insertions(+), 6 deletions(-)
author Leandro Lucarella <llucax@gmail.com>
date Wed, 06 Jan 2010 15:18:19 -0300
parents aa953cc960b6
children
line wrap: on
line source

/*
 * 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