Flush (work in progress)
[mono.git] / mono / io-layer / critical-sections.c
1 /*
2  * critical-sections.c:  Critical sections
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <pthread.h>
13
14 #include <mono/io-layer/wapi.h>
15 #include <mono/io-layer/critical-section-private.h>
16
17 #include "mono-mutex.h"
18
19 #undef DEBUG
20
21 /* A critical section is really just like a lightweight mutex. It
22  * can't be waited for, and doesn't have a handle.
23  */
24
25 /* According to the MSDN docs, the Microsoft implementation spins a
26  * number of times then waits for a semaphore.  I could implement that
27  * here but I'd need a mutex around the critical section structure
28  * anyway.  So I may as well just use a pthread mutex.
29  */
30 static mono_once_t attr_key_once=MONO_ONCE_INIT;
31 static mono_mutexattr_t attr;
32
33 static void attr_init(void)
34 {
35         int ret;
36         
37         ret = mono_mutexattr_init(&attr);
38         g_assert (ret == 0);
39         
40         ret = mono_mutexattr_settype(&attr, MONO_MUTEX_RECURSIVE);
41         g_assert (ret == 0);
42 }
43
44 void _wapi_critical_section_cleanup (void)
45 {
46         mono_mutexattr_destroy (&attr);
47 }
48
49 /**
50  * InitializeCriticalSection:
51  * @section: The critical section to initialise
52  *
53  * Initialises a critical section.
54  */
55 void InitializeCriticalSection(WapiCriticalSection *section)
56 {
57         int ret;
58         
59         mono_once(&attr_key_once, attr_init);
60         ret = mono_mutex_init(&section->mutex, &attr);
61         g_assert (ret == 0);
62 }
63
64 /**
65  * InitializeCriticalSectionAndSpinCount:
66  * @section: The critical section to initialise.
67  * @spincount: The spin count for this critical section.  Not
68  * currently used.
69  *
70  * Initialises a critical section and sets the spin count.  This
71  * implementation just calls InitializeCriticalSection().
72  *
73  * Return value: %TRUE on success, %FALSE otherwise.  (%FALSE never
74  * happens).
75  */
76 gboolean InitializeCriticalSectionAndSpinCount(WapiCriticalSection *section,
77                                                guint32 spincount G_GNUC_UNUSED)
78 {
79         InitializeCriticalSection(section);
80         
81         return(TRUE);
82 }
83
84 /**
85  * DeleteCriticalSection:
86  * @section: The critical section to delete.
87  *
88  * Releases all resources owned by critical section @section.
89  */
90 void DeleteCriticalSection(WapiCriticalSection *section)
91 {
92         int ret;
93         
94         ret = mono_mutex_destroy(&section->mutex);
95         g_assert (ret == 0);
96 }
97
98 /**
99  * SetCriticalSectionSpinCount:
100  * @section: The critical section to set
101  * @spincount: The new spin count for this critical section.  Not
102  * currently used.
103  *
104  * Sets the spin count for the critical section @section.  The spin
105  * count is currently ignored, and set to zero.
106  *
107  * Return value: The previous spin count.  (Currently always zero).
108  */
109 guint32 SetCriticalSectionSpinCount(WapiCriticalSection *section G_GNUC_UNUSED, guint32 spincount G_GNUC_UNUSED)
110 {
111         return(0);
112 }
113
114 /**
115  * TryEnterCriticalSection:
116  * @section: The critical section to try and enter
117  *
118  * Attempts to enter a critical section without blocking.  If
119  * successful the calling thread takes ownership of the critical
120  * section.
121  *
122  * A thread can recursively call EnterCriticalSection() and
123  * TryEnterCriticalSection(), but must call LeaveCriticalSection() an
124  * equal number of times.
125  *
126  * Return value: %TRUE if the thread successfully locked the critical
127  * section, %FALSE otherwise.
128  */
129 gboolean TryEnterCriticalSection(WapiCriticalSection *section)
130 {
131         int ret;
132         
133         ret=mono_mutex_trylock(&section->mutex);
134         if(ret==0) {
135                 return(TRUE);
136         } else {
137                 return(FALSE);
138         }
139 }
140