]> git.llucax.com Git - software/druntime.git/blob - src/compiler/dmd/critical.c
First commit of the D Runtime Project. This includes a fully functional runtime...
[software/druntime.git] / src / compiler / dmd / critical.c
1 /*
2  * Placed into the Public Domain
3  * written by Walter Bright, Digital Mars
4  * www.digitalmars.com
5  */
6
7 /* ================================= Win32 ============================ */
8
9 #if _WIN32
10
11 #include        <windows.h>
12
13 /******************************************
14  * Enter/exit critical section.
15  */
16
17 /* We don't initialize critical sections unless we actually need them.
18  * So keep a linked list of the ones we do use, and in the static destructor
19  * code, walk the list and release them.
20  */
21
22 typedef struct D_CRITICAL_SECTION
23 {
24     struct D_CRITICAL_SECTION *next;
25     CRITICAL_SECTION cs;
26 } D_CRITICAL_SECTION;
27
28 static D_CRITICAL_SECTION *dcs_list;
29 static D_CRITICAL_SECTION critical_section;
30 static volatile int inited;
31
32 void _d_criticalenter(D_CRITICAL_SECTION *dcs)
33 {
34     if (!dcs->next)
35     {
36         EnterCriticalSection(&critical_section.cs);
37         if (!dcs->next) // if, in the meantime, another thread didn't set it
38         {
39             dcs->next = dcs_list;
40             dcs_list = dcs;
41             InitializeCriticalSection(&dcs->cs);
42         }
43         LeaveCriticalSection(&critical_section.cs);
44     }
45     EnterCriticalSection(&dcs->cs);
46 }
47
48 void _d_criticalexit(D_CRITICAL_SECTION *dcs)
49 {
50     LeaveCriticalSection(&dcs->cs);
51 }
52
53 void _STI_critical_init()
54 {
55     if (!inited)
56     {   InitializeCriticalSection(&critical_section.cs);
57         dcs_list = &critical_section;
58         inited = 1;
59     }
60 }
61
62 void _STD_critical_term()
63 {
64     if (inited)
65     {   inited = 0;
66         while (dcs_list)
67         {
68             DeleteCriticalSection(&dcs_list->cs);
69             dcs_list = dcs_list->next;
70         }
71     }
72 }
73
74 #endif
75
76 /* ================================= linux ============================ */
77
78 #if linux
79
80 #include        <stdio.h>
81 #include        <stdlib.h>
82 #include        <pthread.h>
83
84 /******************************************
85  * Enter/exit critical section.
86  */
87
88 /* We don't initialize critical sections unless we actually need them.
89  * So keep a linked list of the ones we do use, and in the static destructor
90  * code, walk the list and release them.
91  */
92
93 typedef struct D_CRITICAL_SECTION
94 {
95     struct D_CRITICAL_SECTION *next;
96     pthread_mutex_t cs;
97 } D_CRITICAL_SECTION;
98
99 static D_CRITICAL_SECTION *dcs_list;
100 static D_CRITICAL_SECTION critical_section;
101 static pthread_mutexattr_t _criticals_attr;
102
103 void _STI_critical_init(void);
104 void _STD_critical_term(void);
105
106 void _d_criticalenter(D_CRITICAL_SECTION *dcs)
107 {
108     if (!dcs_list)
109     {   _STI_critical_init();
110         atexit(_STD_critical_term);
111     }
112     //printf("_d_criticalenter(dcs = x%x)\n", dcs);
113     if (!dcs->next)
114     {
115         pthread_mutex_lock(&critical_section.cs);
116         if (!dcs->next) // if, in the meantime, another thread didn't set it
117         {
118             dcs->next = dcs_list;
119             dcs_list = dcs;
120             pthread_mutex_init(&dcs->cs, &_criticals_attr);
121         }
122         pthread_mutex_unlock(&critical_section.cs);
123     }
124     pthread_mutex_lock(&dcs->cs);
125 }
126
127 void _d_criticalexit(D_CRITICAL_SECTION *dcs)
128 {
129     //printf("_d_criticalexit(dcs = x%x)\n", dcs);
130     pthread_mutex_unlock(&dcs->cs);
131 }
132
133 void _STI_critical_init()
134 {
135     if (!dcs_list)
136     {   //printf("_STI_critical_init()\n");
137         pthread_mutexattr_init(&_criticals_attr);
138         pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP);
139
140         // The global critical section doesn't need to be recursive
141         pthread_mutex_init(&critical_section.cs, 0);
142         dcs_list = &critical_section;
143     }
144 }
145
146 void _STD_critical_term()
147 {
148     if (dcs_list)
149     {   //printf("_STI_critical_term()\n");
150         while (dcs_list)
151         {
152             //printf("\tlooping... %x\n", dcs_list);
153             pthread_mutex_destroy(&dcs_list->cs);
154             dcs_list = dcs_list->next;
155         }
156     }
157 }
158
159 #endif