]> git.llucax.com Git - software/druntime.git/blob - src/compiler/dmd/monitor.c
Changed D 2.0 runtime to account for 'this' being changed from a pointer to a referen...
[software/druntime.git] / src / compiler / dmd / monitor.c
1 // D programming language runtime library
2 // Public Domain
3 // written by Walter Bright, Digital Mars
4 // www.digitalmars.com
5
6 // This is written in C because nobody has written a pthreads interface
7 // to D yet.
8
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <assert.h>
13
14 #if _WIN32
15 #elif linux
16 #define USE_PTHREADS    1
17 #else
18 #endif
19
20 #if _WIN32
21 #include <windows.h>
22 #endif
23
24 #if USE_PTHREADS
25 #include <pthread.h>
26 #endif
27
28 #include "mars.h"
29
30 // This is what the monitor reference in Object points to
31 typedef struct Monitor
32 {
33     void* impl; // for user-level monitors
34     Array devt; // for internal monitors
35
36 #if _WIN32
37     CRITICAL_SECTION mon;
38 #endif
39
40 #if USE_PTHREADS
41     pthread_mutex_t mon;
42 #endif
43 } Monitor;
44
45 #define MONPTR(h)       (&((Monitor *)(h)->monitor)->mon)
46
47 static volatile int inited;
48
49 /* =============================== Win32 ============================ */
50
51 #if _WIN32
52
53 static CRITICAL_SECTION _monitor_critsec;
54
55 void _STI_monitor_staticctor()
56 {
57     if (!inited)
58     {   InitializeCriticalSection(&_monitor_critsec);
59         inited = 1;
60     }
61 }
62
63 void _STD_monitor_staticdtor()
64 {
65     if (inited)
66     {   inited = 0;
67         DeleteCriticalSection(&_monitor_critsec);
68     }
69 }
70
71 void _d_monitor_create(Object *h)
72 {
73     /*
74      * NOTE: Assume this is only called when h->monitor is null prior to the
75      * call.  However, please note that another thread may call this function
76      * at the same time, so we can not assert this here.  Instead, try and
77      * create a lock, and if one already exists then forget about it.
78      */
79
80     //printf("+_d_monitor_create(%p)\n", h);
81     assert(h);
82     Monitor *cs = NULL;
83     EnterCriticalSection(&_monitor_critsec);
84     if (!h->monitor)
85     {
86         cs = (Monitor *)calloc(sizeof(Monitor), 1);
87         assert(cs);
88         InitializeCriticalSection(&cs->mon);
89         h->monitor = (void *)cs;
90         cs = NULL;
91     }
92     LeaveCriticalSection(&_monitor_critsec);
93     if (cs)
94         free(cs);
95     //printf("-_d_monitor_create(%p)\n", h);
96 }
97
98 void _d_monitor_destroy(Object *h)
99 {
100     //printf("+_d_monitor_destroy(%p)\n", h);
101     assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
102     DeleteCriticalSection(MONPTR(h));
103     free((void *)h->monitor);
104     h->monitor = NULL;
105     //printf("-_d_monitor_destroy(%p)\n", h);
106 }
107
108 int _d_monitor_lock(Object *h)
109 {
110     //printf("+_d_monitor_acquire(%p)\n", h);
111     assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
112     EnterCriticalSection(MONPTR(h));
113     //printf("-_d_monitor_acquire(%p)\n", h);
114 }
115
116 void _d_monitor_unlock(Object *h)
117 {
118     //printf("+_d_monitor_release(%p)\n", h);
119     assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
120     LeaveCriticalSection(MONPTR(h));
121     //printf("-_d_monitor_release(%p)\n", h);
122 }
123
124 #endif
125
126 /* =============================== linux ============================ */
127
128 #if USE_PTHREADS
129
130 // Includes attribute fixes from David Friedman's GDC port
131
132 static pthread_mutex_t _monitor_critsec;
133 static pthread_mutexattr_t _monitors_attr;
134
135 void _STI_monitor_staticctor()
136 {
137     if (!inited)
138     {
139         pthread_mutexattr_init(&_monitors_attr);
140         pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE_NP);
141         pthread_mutex_init(&_monitor_critsec, 0);
142         inited = 1;
143     }
144 }
145
146 void _STD_monitor_staticdtor()
147 {
148     if (inited)
149     {   inited = 0;
150         pthread_mutex_destroy(&_monitor_critsec);
151         pthread_mutexattr_destroy(&_monitors_attr);
152     }
153 }
154
155 void _d_monitor_create(Object *h)
156 {
157     /*
158      * NOTE: Assume this is only called when h->monitor is null prior to the
159      * call.  However, please note that another thread may call this function
160      * at the same time, so we can not assert this here.  Instead, try and
161      * create a lock, and if one already exists then forget about it.
162      */
163
164     //printf("+_d_monitor_create(%p)\n", h);
165     assert(h);
166     Monitor *cs = NULL;
167     pthread_mutex_lock(&_monitor_critsec);
168     if (!h->monitor)
169     {
170         cs = (Monitor *)calloc(sizeof(Monitor), 1);
171         assert(cs);
172         pthread_mutex_init(&cs->mon, & _monitors_attr);
173         h->monitor = (void *)cs;
174         cs = NULL;
175     }
176     pthread_mutex_unlock(&_monitor_critsec);
177     if (cs)
178         free(cs);
179     //printf("-_d_monitor_create(%p)\n", h);
180 }
181
182 void _d_monitor_destroy(Object *h)
183 {
184     //printf("+_d_monitor_destroy(%p)\n", h);
185     assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
186     pthread_mutex_destroy(MONPTR(h));
187     free((void *)h->monitor);
188     h->monitor = NULL;
189     //printf("-_d_monitor_destroy(%p)\n", h);
190 }
191
192 int _d_monitor_lock(Object *h)
193 {
194     //printf("+_d_monitor_acquire(%p)\n", h);
195     assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
196     pthread_mutex_lock(MONPTR(h));
197     //printf("-_d_monitor_acquire(%p)\n", h);
198 }
199
200 void _d_monitor_unlock(Object *h)
201 {
202     //printf("+_d_monitor_release(%p)\n", h);
203     assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
204     pthread_mutex_unlock(MONPTR(h));
205     //printf("-_d_monitor_release(%p)\n", h);
206 }
207
208 #endif