Skip to content

Commit

Permalink
roll back to a mostly-C version of monitor.
Browse files Browse the repository at this point in the history
  • Loading branch information
braddr committed Feb 7, 2011
1 parent 031f65b commit 6c2f4d1
Show file tree
Hide file tree
Showing 5 changed files with 531 additions and 12 deletions.
176 changes: 176 additions & 0 deletions src/rt/critical.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/**
* Implementation of support routines for synchronized blocks.
*
* Copyright: Copyright Digital Mars 2000 - 2010.
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
* Authors: Walter Bright, Sean Kelly
*/

/* Copyright Digital Mars 2000 - 2010.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/

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

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

// PTHREAD_MUTEX_RECURSIVE is the "standard" symbol,
// while the _NP version is specific to Linux
#if linux
# ifndef PTHREAD_MUTEX_RECURSIVE
# define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
# endif
#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);

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

106 changes: 106 additions & 0 deletions src/rt/mars.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/**
* Common declarations for runtime implementation.
*
* Copyright: Copyright Digital Mars 2000 - 2010.
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
* Authors: Walter Bright, Sean Kelly
*/

/* Copyright Digital Mars 2000 - 2010.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#include <stddef.h>

#if __cplusplus
extern "C" {
#endif

struct ClassInfo;
struct Vtbl;

typedef struct Vtbl
{
size_t len;
void **vptr;
} Vtbl;

typedef struct Interface
{
struct ClassInfo *classinfo;
struct Vtbl vtbl;
int offset;
} Interface;

typedef struct Object
{
void **vptr;
void *monitor;
} Object;

typedef struct ClassInfo
{
Object object;

size_t initlen;
void *init;

size_t namelen;
char *name;

Vtbl vtbl;

size_t interfacelen;
Interface *interfaces;

struct ClassInfo *baseClass;

void *destructor;
void *invariant;

int flags;
} ClassInfo;

typedef struct Throwable
{
Object object;

size_t msglen;
char* msg;

size_t filelen;
char* file;

size_t line;

struct Interface *info;
struct Throwable *next;
} Throwable;

typedef struct Array
{
size_t length;
void *ptr;
} Array;

typedef struct Delegate
{
void *thisptr;
void (*funcptr)();
} Delegate;

void _d_monitorenter(Object *h);
void _d_monitorexit(Object *h);

int _d_isbaseof(ClassInfo *b, ClassInfo *c);
Object *_d_dynamic_cast(Object *o, ClassInfo *ci);

Object * _d_newclass(ClassInfo *ci);
void _d_delclass(Object **p);

void _d_OutOfMemory();

#if __cplusplus
}
#endif
Loading

0 comments on commit 6c2f4d1

Please sign in to comment.