diff tango/lib/compiler/llvmdc/critical.c @ 133:44a95ac7368a trunk

[svn r137] Many fixes towards tango.io.Console working, but not quite there yet... In particular, assertions has been fixed to include file/line info, and much more!
author lindquist
date Mon, 14 Jan 2008 05:11:54 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/lib/compiler/llvmdc/critical.c	Mon Jan 14 05:11:54 2008 +0100
@@ -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
+