* strtod.c: added missing Long define for big endian systems
[mono.git] / mono / io-layer / handles-private.h
1 /*
2  * handles-private.h:  Internal operations on handles
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.
8  */
9
10 #ifndef _WAPI_HANDLES_PRIVATE_H_
11 #define _WAPI_HANDLES_PRIVATE_H_
12
13 #include <config.h>
14 #include <glib.h>
15
16 #include <mono/io-layer/wapi-private.h>
17 #include <mono/io-layer/shared.h>
18 #include <mono/io-layer/misc-private.h>
19
20 #undef DEBUG
21
22 /* Shared threads dont seem to work yet */
23 #undef _POSIX_THREAD_PROCESS_SHARED
24
25 extern struct _WapiHandleShared_list **_wapi_shared_data;
26 extern struct _WapiHandleScratch *_wapi_shared_scratch;
27 extern struct _WapiHandlePrivate_list **_wapi_private_data;
28 extern pthread_mutex_t _wapi_shared_mutex;
29 extern guint32 _wapi_shm_mapped_segments;
30
31 extern guint32 _wapi_handle_new_internal (WapiHandleType type);
32 extern gpointer _wapi_handle_new (WapiHandleType type);
33 extern gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
34                                      gpointer *shared, gpointer *private);
35 extern gpointer _wapi_search_handle (WapiHandleType type,
36                                      gboolean (*check)(gpointer, gpointer),
37                                      gpointer user_data,
38                                      gpointer *shared, gpointer *private);
39 extern void _wapi_handle_ref (gpointer handle);
40 extern void _wapi_handle_unref (gpointer handle);
41 extern guint32 _wapi_handle_scratch_store_internal (guint32 bytes,
42                                                     gboolean *remap);
43 extern guint32 _wapi_handle_scratch_store (gconstpointer data, guint32 bytes);
44 extern guint32 _wapi_handle_scratch_store_string_array (gchar **data);
45 extern gpointer _wapi_handle_scratch_lookup (guint32 idx);
46 extern gchar **_wapi_handle_scratch_lookup_string_array (guint32 idx);
47 extern void _wapi_handle_scratch_delete_internal (guint32 idx);
48 extern void _wapi_handle_scratch_delete (guint32 idx);
49 extern void _wapi_handle_scratch_delete_string_array (guint32 idx);
50 extern void _wapi_handle_register_capabilities (WapiHandleType type,
51                                                 WapiHandleCapability caps);
52 extern gboolean _wapi_handle_test_capabilities (gpointer handle,
53                                                 WapiHandleCapability caps);
54 extern void _wapi_handle_ops_close_shared (gpointer handle);
55 extern void _wapi_handle_ops_close_private (gpointer handle);
56 extern void _wapi_handle_ops_signal (gpointer handle);
57 extern void _wapi_handle_ops_own (gpointer handle);
58 extern gboolean _wapi_handle_ops_isowned (gpointer handle);
59
60 extern gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
61                                                       gpointer *handles,
62                                                       gboolean waitall,
63                                                       guint32 *retcount,
64                                                       guint32 *lowest);
65 extern void _wapi_handle_unlock_handles (guint32 numhandles,
66                                          gpointer *handles);
67 extern int _wapi_handle_wait_signal (void);
68 extern int _wapi_handle_timedwait_signal (struct timespec *timeout);
69 extern int _wapi_handle_wait_signal_handle (gpointer handle);
70 extern int _wapi_handle_timedwait_signal_handle (gpointer handle,
71                                                  struct timespec *timeout);
72 extern gboolean _wapi_handle_process_fork (guint32 cmd, guint32 env,
73                                            guint32 dir, gboolean inherit,
74                                            guint32 flags,
75                                            gpointer stdin_handle,
76                                            gpointer stdout_handle,
77                                            gpointer stderr_handle,
78                                            gpointer *process_handle,
79                                            gpointer *thread_handle,
80                                            guint32 *pid, guint32 *tid);
81
82 static inline struct _WapiHandleShared_list *_wapi_handle_get_shared_segment (guint32 segment)
83 {
84         struct _WapiHandleShared_list *shared;
85         
86         pthread_mutex_lock (&_wapi_shared_mutex);
87         shared=_wapi_shared_data[segment];
88         pthread_mutex_unlock (&_wapi_shared_mutex);
89
90         return(shared);
91 }
92
93 static inline struct _WapiHandlePrivate_list *_wapi_handle_get_private_segment (guint32 segment)
94 {
95         struct _WapiHandlePrivate_list *priv;
96         
97         pthread_mutex_lock (&_wapi_shared_mutex);
98         priv=_wapi_private_data[segment];
99         pthread_mutex_unlock (&_wapi_shared_mutex);
100         
101         return(priv);
102 }
103
104 static inline void _wapi_handle_ensure_mapped (guint32 segment)
105 {
106 #ifdef DEBUG
107         g_message (G_GNUC_PRETTY_FUNCTION ": checking segment %d is mapped",
108                    segment);
109         g_message (G_GNUC_PRETTY_FUNCTION ": _wapi_shm_mapped_segments: %d",
110                    _wapi_shm_mapped_segments);
111         if(segment<_wapi_shm_mapped_segments) {
112                 g_message (G_GNUC_PRETTY_FUNCTION ": _wapi_handle_get_shared_segment(segment): %p", _wapi_handle_get_shared_segment (segment));
113         }
114 #endif
115
116         if(segment<_wapi_shm_mapped_segments &&
117            _wapi_handle_get_shared_segment (segment)!=NULL) {
118                 /* Got it already */
119                 return;
120         }
121         
122         pthread_mutex_lock (&_wapi_shared_mutex);
123         
124         if(segment>=_wapi_shm_mapped_segments) {
125                 /* Need to extend the arrays.  We can't use g_renew
126                  * here, because the unmapped segments must be NULL,
127                  * and g_renew doesn't initialise the memory it
128                  * returns
129                  */
130                 gulong old_len, new_len;
131                 
132                 old_len=_wapi_shm_mapped_segments;
133                 new_len=segment+1;
134                 
135 #ifdef DEBUG
136                 g_message (G_GNUC_PRETTY_FUNCTION
137                            ": extending shared array: mapped_segments is %d",
138                            _wapi_shm_mapped_segments);
139 #endif
140                 
141                 _wapi_shared_data=_wapi_g_renew0 (_wapi_shared_data, sizeof(struct _WapiHandleShared_list *) * old_len, sizeof(struct _WapiHandleShared_list *) * new_len);
142
143                 if(_wapi_private_data!=NULL) {
144                         /* the daemon doesn't deal with private data */
145                         _wapi_private_data=_wapi_g_renew0 (_wapi_private_data, sizeof(struct _WapiHandlePrivate_list *) * old_len, sizeof(struct _WapiHandlePrivate_list *) * new_len);
146                 }
147                 
148                 _wapi_shm_mapped_segments=segment+1;
149         }
150         
151         if(_wapi_shared_data[segment]==NULL) {
152                 /* Need to map it too */
153 #ifdef DEBUG
154                 g_message (G_GNUC_PRETTY_FUNCTION ": mapping segment %d",
155                            segment);
156 #endif
157
158                 _wapi_shared_data[segment]=_wapi_shm_file_map (WAPI_SHM_DATA,
159                                                                segment, NULL,
160                                                                NULL);
161                 if(_wapi_private_data!=NULL) {
162                         /* the daemon doesn't deal with private data */
163                         _wapi_private_data[segment]=g_new0 (struct _WapiHandlePrivate_list, 1);
164                 }
165         }
166
167         pthread_mutex_unlock (&_wapi_shared_mutex);
168 }
169
170 static inline void _wapi_handle_segment (gpointer handle, guint32 *segment,
171                                          guint32 *idx)
172 {
173         guint32 h=GPOINTER_TO_UINT (handle);
174         div_t divvy;
175
176         divvy=div (h, _WAPI_HANDLES_PER_SEGMENT);
177         *segment=divvy.quot;
178         *idx=divvy.rem;
179 }
180
181 static inline guint32 _wapi_handle_index (guint32 segment, guint32 idx)
182 {
183         return((segment*_WAPI_HANDLES_PER_SEGMENT)+idx);
184 }
185
186 static inline WapiHandleType _wapi_handle_type (gpointer handle)
187 {
188         guint32 idx;
189         guint32 segment;
190         
191         _wapi_handle_segment (handle, &segment, &idx);
192         
193         return(_wapi_handle_get_shared_segment (segment)->handles[idx].type);
194 }
195
196 static inline void _wapi_handle_set_signal_state (gpointer handle,
197                                                   gboolean state,
198                                                   gboolean broadcast)
199 {
200         guint32 idx;
201         guint32 segment;
202         struct _WapiHandleShared *shared_handle;
203         
204         _wapi_handle_segment (handle, &segment, &idx);
205         shared_handle=&_wapi_handle_get_shared_segment (segment)->handles[idx];
206         
207 #ifdef DEBUG
208         g_message (G_GNUC_PRETTY_FUNCTION ": setting state of %p to %s (broadcast %s)", handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE");
209 #endif
210
211         if(state==TRUE) {
212                 /* Tell everyone blocking on a single handle */
213
214                 /* This function _must_ be called with
215                  * handle->signal_mutex locked
216                  */
217                 shared_handle->signalled=state;
218                 
219                 if(broadcast==TRUE) {
220                         pthread_cond_broadcast (&shared_handle->signal_cond);
221                 } else {
222                         pthread_cond_signal (&shared_handle->signal_cond);
223                 }
224
225                 /* Tell everyone blocking on multiple handles that something
226                  * was signalled
227                  */
228 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
229                 {
230                         struct _WapiHandleShared_list *segment0=_wapi_handle_get_shared_segment (0);
231                         mono_mutex_lock (&segment0->signal_mutex);
232                         pthread_cond_broadcast (&segment0->signal_cond);
233                         mono_mutex_unlock (&segment0->signal_mutex);
234                 }
235 #else
236                 {
237                         struct _WapiHandlePrivate_list *segment0=_wapi_handle_get_private_segment (0);
238                         
239 #ifdef DEBUG
240                         g_message (G_GNUC_PRETTY_FUNCTION ": lock global signal mutex");
241 #endif
242
243                         mono_mutex_lock (&segment0->signal_mutex);
244                         pthread_cond_broadcast (&segment0->signal_cond);
245
246 #ifdef DEBUG
247                         g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
248 #endif
249
250                         mono_mutex_unlock (&segment0->signal_mutex);
251                 }
252 #endif /* _POSIX_THREAD_PROCESS_SHARED */
253         } else {
254                 shared_handle->signalled=state;
255         }
256 }
257
258 static inline gboolean _wapi_handle_issignalled (gpointer handle)
259 {
260         guint32 idx;
261         guint32 segment;
262         
263         _wapi_handle_segment (handle, &segment, &idx);
264         
265         return(_wapi_handle_get_shared_segment (segment)->handles[idx].signalled);
266 }
267
268 static inline int _wapi_handle_lock_signal_mutex (void)
269 {
270 #ifdef DEBUG
271         g_message (G_GNUC_PRETTY_FUNCTION ": lock global signal mutex");
272 #endif
273 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
274         return(mono_mutex_lock (&_wapi_handle_get_shared_segment (0)->signal_mutex));
275 #else
276         return(mono_mutex_lock (&_wapi_handle_get_private_segment (0)->signal_mutex));
277 #endif /* _POSIX_THREAD_PROCESS_SHARED */
278 }
279
280 static inline int _wapi_handle_unlock_signal_mutex (void)
281 {
282 #ifdef DEBUG
283         g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
284 #endif
285 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
286         return(mono_mutex_unlock (&_wapi_handle_get_shared_segment (0)->signal_mutex));
287 #else
288         return(mono_mutex_unlock (&_wapi_handle_get_private_segment (0)->signal_mutex));
289 #endif /* _POSIX_THREAD_PROCESS_SHARED */
290 }
291
292 static inline int _wapi_handle_lock_handle (gpointer handle)
293 {
294         guint32 idx;
295         guint32 segment;
296         
297 #ifdef DEBUG
298         g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle);
299 #endif
300
301         _wapi_handle_segment (handle, &segment, &idx);
302         
303         return(mono_mutex_lock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex));
304 }
305
306 static inline int _wapi_handle_unlock_handle (gpointer handle)
307 {
308         guint32 idx;
309         guint32 segment;
310         
311 #ifdef DEBUG
312         g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle);
313 #endif
314
315         _wapi_handle_segment (handle, &segment, &idx);
316         
317         return(mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex));
318 }
319
320 #endif /* _WAPI_HANDLES_PRIVATE_H_ */