diff runtime/internal/critical.c @ 443:44f08170f4ef

Removed tango from the repository and instead added a runtime dir with the files needed to patch and build tango from svn. Reworked the LLVMDC specific pragmas.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Fri, 01 Aug 2008 00:32:06 +0200
parents
children 02fb65cddc3e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/critical.c	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,160 @@
+/*
+ * 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
+
+#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
+