comparison druntime/src/compiler/dmd/critical.c @ 1458:e0b2d67cfe7c

Added druntime (this should be removed once it works).
author Robert Clipsham <robert@octarineparrot.com>
date Tue, 02 Jun 2009 17:43:06 +0100
parents
children
comparison
equal deleted inserted replaced
1456:7b218ec1044f 1458:e0b2d67cfe7c
1 /**
2 * Implementation of support routines for synchronized blocks.
3 *
4 * Copyright: Copyright Digital Mars 2000 - 2009.
5 * License: <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
6 * Authors: Walter Bright, Sean Kelly
7 *
8 * Copyright Digital Mars 2000 - 2009.
9 * Distributed under the Boost Software License, Version 1.0.
10 * (See accompanying file LICENSE_1_0.txt or copy at
11 * http://www.boost.org/LICENSE_1_0.txt)
12 */
13
14 /* ================================= Win32 ============================ */
15
16 #if _WIN32
17
18 #include <windows.h>
19
20 /******************************************
21 * Enter/exit critical section.
22 */
23
24 /* We don't initialize critical sections unless we actually need them.
25 * So keep a linked list of the ones we do use, and in the static destructor
26 * code, walk the list and release them.
27 */
28
29 typedef struct D_CRITICAL_SECTION
30 {
31 struct D_CRITICAL_SECTION *next;
32 CRITICAL_SECTION cs;
33 } D_CRITICAL_SECTION;
34
35 static D_CRITICAL_SECTION *dcs_list;
36 static D_CRITICAL_SECTION critical_section;
37 static volatile int inited;
38
39 void _d_criticalenter(D_CRITICAL_SECTION *dcs)
40 {
41 if (!dcs->next)
42 {
43 EnterCriticalSection(&critical_section.cs);
44 if (!dcs->next) // if, in the meantime, another thread didn't set it
45 {
46 dcs->next = dcs_list;
47 dcs_list = dcs;
48 InitializeCriticalSection(&dcs->cs);
49 }
50 LeaveCriticalSection(&critical_section.cs);
51 }
52 EnterCriticalSection(&dcs->cs);
53 }
54
55 void _d_criticalexit(D_CRITICAL_SECTION *dcs)
56 {
57 LeaveCriticalSection(&dcs->cs);
58 }
59
60 void _STI_critical_init()
61 {
62 if (!inited)
63 { InitializeCriticalSection(&critical_section.cs);
64 dcs_list = &critical_section;
65 inited = 1;
66 }
67 }
68
69 void _STD_critical_term()
70 {
71 if (inited)
72 { inited = 0;
73 while (dcs_list)
74 {
75 DeleteCriticalSection(&dcs_list->cs);
76 dcs_list = dcs_list->next;
77 }
78 }
79 }
80
81 #endif
82
83 /* ================================= linux ============================ */
84
85 #if linux || __APPLE__
86
87 #include <stdio.h>
88 #include <stdlib.h>
89 #include <pthread.h>
90
91 // PTHREAD_MUTEX_RECURSIVE is the "standard" symbol,
92 // while the _NP version is specific to Linux
93 #ifndef PTHREAD_MUTEX_RECURSIVE
94 # define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
95 #endif
96
97 /******************************************
98 * Enter/exit critical section.
99 */
100
101 /* We don't initialize critical sections unless we actually need them.
102 * So keep a linked list of the ones we do use, and in the static destructor
103 * code, walk the list and release them.
104 */
105
106 typedef struct D_CRITICAL_SECTION
107 {
108 struct D_CRITICAL_SECTION *next;
109 pthread_mutex_t cs;
110 } D_CRITICAL_SECTION;
111
112 static D_CRITICAL_SECTION *dcs_list;
113 static D_CRITICAL_SECTION critical_section;
114 static pthread_mutexattr_t _criticals_attr;
115
116 void _STI_critical_init(void);
117 void _STD_critical_term(void);
118
119 void _d_criticalenter(D_CRITICAL_SECTION *dcs)
120 {
121 if (!dcs_list)
122 { _STI_critical_init();
123 atexit(_STD_critical_term);
124 }
125 //printf("_d_criticalenter(dcs = x%x)\n", dcs);
126 if (!dcs->next)
127 {
128 pthread_mutex_lock(&critical_section.cs);
129 if (!dcs->next) // if, in the meantime, another thread didn't set it
130 {
131 dcs->next = dcs_list;
132 dcs_list = dcs;
133 pthread_mutex_init(&dcs->cs, &_criticals_attr);
134 }
135 pthread_mutex_unlock(&critical_section.cs);
136 }
137 pthread_mutex_lock(&dcs->cs);
138 }
139
140 void _d_criticalexit(D_CRITICAL_SECTION *dcs)
141 {
142 //printf("_d_criticalexit(dcs = x%x)\n", dcs);
143 pthread_mutex_unlock(&dcs->cs);
144 }
145
146 void _STI_critical_init()
147 {
148 if (!dcs_list)
149 { //printf("_STI_critical_init()\n");
150 pthread_mutexattr_init(&_criticals_attr);
151 pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE);
152
153 // The global critical section doesn't need to be recursive
154 pthread_mutex_init(&critical_section.cs, 0);
155 dcs_list = &critical_section;
156 }
157 }
158
159 void _STD_critical_term()
160 {
161 if (dcs_list)
162 { //printf("_STI_critical_term()\n");
163 while (dcs_list)
164 {
165 //printf("\tlooping... %x\n", dcs_list);
166 pthread_mutex_destroy(&dcs_list->cs);
167 dcs_list = dcs_list->next;
168 }
169 }
170 }
171
172 #endif
173