Fri May 31 16:21:54 CEST 2002 Paolo Molaro <lupus@ximian.com>
[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
16 #include "mono-mutex.h"
17
18 #undef DEBUG
19
20 /* A critical section is really just like a lightweight mutex. It
21  * can't be waited for, and doesn't have a handle.
22  */
23
24 /* According to the MSDN docs, the Microsoft implementation spins a
25  * number of times then waits for a semaphore.  I could implement that
26  * here but I'd need a mutex around the critical section structure
27  * anyway.  So I may as well just use a pthread mutex.
28  */
29 static pthread_once_t attr_key_once=PTHREAD_ONCE_INIT;
30 static mono_mutexattr_t attr;
31
32 static void attr_init(void)
33 {
34         mono_mutexattr_init(&attr);
35         mono_mutexattr_settype(&attr, MONO_MUTEX_RECURSIVE);
36 }
37
38 /**
39  * InitializeCriticalSection:
40  * @section: The critical section to initialise
41  *
42  * Initialises a critical section.
43  */
44 void InitializeCriticalSection(WapiCriticalSection *section)
45 {
46         pthread_once(&attr_key_once, attr_init);
47         mono_mutex_init(&section->mutex, &attr);
48 }
49
50 /**
51  * InitializeCriticalSectionAndSpinCount:
52  * @section: The critical section to initialise.
53  * @spincount: The spin count for this critical section.  Not
54  * currently used.
55  *
56  * Initialises a critical section and sets the spin count.  This
57  * implementation just calls InitializeCriticalSection().
58  *
59  * Return value: %TRUE on success, %FALSE otherwise.  (%FALSE never
60  * happens).
61  */
62 gboolean InitializeCriticalSectionAndSpinCount(WapiCriticalSection *section,
63                                                guint32 spincount G_GNUC_UNUSED)
64 {
65         InitializeCriticalSection(section);
66         
67         return(TRUE);
68 }
69
70 /**
71  * DeleteCriticalSection:
72  * @section: The critical section to delete.
73  *
74  * Releases all resources owned by critical section @section.
75  */
76 void DeleteCriticalSection(WapiCriticalSection *section)
77 {
78         mono_mutex_destroy(&section->mutex);
79 }
80
81 /**
82  * SetCriticalSectionSpinCount:
83  * @section: The critical section to set
84  * @spincount: The new spin count for this critical section.  Not
85  * currently used.
86  *
87  * Sets the spin count for the critical section @section.  The spin
88  * count is currently ignored, and set to zero.
89  *
90  * Return value: The previous spin count.  (Currently always zero).
91  */
92 guint32 SetCriticalSectionSpinCount(WapiCriticalSection *section G_GNUC_UNUSED, guint32 spincount G_GNUC_UNUSED)
93 {
94         return(0);
95 }
96
97 /**
98  * TryEnterCriticalSection:
99  * @section: The critical section to try and enter
100  *
101  * Attempts to enter a critical section without blocking.  If
102  * successful the calling thread takes ownership of the critical
103  * section.
104  *
105  * A thread can recursively call EnterCriticalSection() and
106  * TryEnterCriticalSection(), but must call LeaveCriticalSection() an
107  * equal number of times.
108  *
109  * Return value: %TRUE if the thread successfully locked the critical
110  * section, %FALSE otherwise.
111  */
112 gboolean TryEnterCriticalSection(WapiCriticalSection *section)
113 {
114         int ret;
115         
116         ret=mono_mutex_trylock(&section->mutex);
117         if(ret==0) {
118                 return(TRUE);
119         } else {
120                 return(FALSE);
121         }
122 }
123
124 /**
125  * EnterCriticalSection:
126  * @section: The critical section to enter
127  *
128  * Enters critical section @section, blocking while other threads own
129  * it.  This function doesn't return until the calling thread assumes
130  * ownership of @section.
131  *
132  * A thread can recursively call EnterCriticalSection() and
133  * TryEnterCriticalSection(), but must call LeaveCriticalSection() an
134  * equal number of times.
135  */
136 void EnterCriticalSection(WapiCriticalSection *section)
137 {
138         mono_mutex_lock(&section->mutex);
139 }
140
141 /**
142  * LeaveCriticalSection:
143  * @section: The critical section to leave
144  *
145  * Leaves critical section @section, relinquishing ownership.
146  *
147  * A thread can recursively call EnterCriticalSection() and
148  * TryEnterCriticalSection(), but must call LeaveCriticalSection() an
149  * equal number of times.
150  */
151 void LeaveCriticalSection(WapiCriticalSection *section)
152 {
153         mono_mutex_unlock(&section->mutex);
154 }
155