Mercurial > projects > ldc
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 |