2 * handles-private.h: Internal operations on handles
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
10 #ifndef _WAPI_HANDLES_PRIVATE_H_
11 #define _WAPI_HANDLES_PRIVATE_H_
16 #include <mono/io-layer/wapi-private.h>
17 #include <mono/io-layer/shared.h>
18 #include <mono/io-layer/misc-private.h>
22 /* Shared threads dont seem to work yet */
23 #undef _POSIX_THREAD_PROCESS_SHARED
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;
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),
38 gpointer *shared, gpointer *private);
39 extern gpointer _wapi_search_handle_namespace (WapiHandleType type,
43 extern void _wapi_handle_ref (gpointer handle);
44 extern void _wapi_handle_unref (gpointer handle);
45 extern guint32 _wapi_handle_scratch_store_internal (guint32 bytes,
47 extern guint32 _wapi_handle_scratch_store (gconstpointer data, guint32 bytes);
48 extern guint32 _wapi_handle_scratch_store_string_array (gchar **data);
49 extern gpointer _wapi_handle_scratch_lookup (guint32 idx);
50 extern gchar **_wapi_handle_scratch_lookup_string_array (guint32 idx);
51 extern void _wapi_handle_scratch_delete_internal (guint32 idx);
52 extern void _wapi_handle_scratch_delete (guint32 idx);
53 extern void _wapi_handle_scratch_delete_string_array (guint32 idx);
54 extern void _wapi_handle_register_capabilities (WapiHandleType type,
55 WapiHandleCapability caps);
56 extern gboolean _wapi_handle_test_capabilities (gpointer handle,
57 WapiHandleCapability caps);
58 extern void _wapi_handle_ops_close_shared (gpointer handle);
59 extern void _wapi_handle_ops_close_private (gpointer handle);
60 extern void _wapi_handle_ops_signal (gpointer handle);
61 extern void _wapi_handle_ops_own (gpointer handle);
62 extern gboolean _wapi_handle_ops_isowned (gpointer handle);
64 extern gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
69 extern void _wapi_handle_unlock_handles (guint32 numhandles,
71 extern int _wapi_handle_wait_signal (void);
72 extern int _wapi_handle_timedwait_signal (struct timespec *timeout);
73 extern int _wapi_handle_wait_signal_handle (gpointer handle);
74 extern int _wapi_handle_timedwait_signal_handle (gpointer handle,
75 struct timespec *timeout);
76 extern gboolean _wapi_handle_process_fork (guint32 cmd, guint32 env,
77 guint32 dir, gboolean inherit,
79 gpointer stdin_handle,
80 gpointer stdout_handle,
81 gpointer stderr_handle,
82 gpointer *process_handle,
83 gpointer *thread_handle,
84 guint32 *pid, guint32 *tid);
86 extern gboolean _wapi_handle_process_kill (pid_t pid, guint32 signo,
88 extern gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode,
89 guint32 new_sharemode,
91 guint32 *old_sharemode,
93 extern void _wapi_handle_set_share (dev_t device, ino_t inode,
94 guint32 sharemode, guint32 access);
96 static inline struct _WapiHandleShared_list *_wapi_handle_get_shared_segment (guint32 segment)
98 struct _WapiHandleShared_list *shared;
101 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
102 (void *)&_wapi_shared_mutex);
103 thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
104 g_assert (thr_ret == 0);
106 shared=_wapi_shared_data[segment];
108 thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
109 g_assert (thr_ret == 0);
110 pthread_cleanup_pop (0);
115 static inline struct _WapiHandlePrivate_list *_wapi_handle_get_private_segment (guint32 segment)
117 struct _WapiHandlePrivate_list *priv;
120 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
121 (void *)&_wapi_shared_mutex);
122 thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
123 g_assert (thr_ret == 0);
125 priv=_wapi_private_data[segment];
127 thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
128 g_assert (thr_ret == 0);
129 pthread_cleanup_pop (0);
134 static inline void _wapi_handle_ensure_mapped (guint32 segment)
139 g_message (G_GNUC_PRETTY_FUNCTION ": checking segment %d is mapped",
141 g_message (G_GNUC_PRETTY_FUNCTION ": _wapi_shm_mapped_segments: %d",
142 _wapi_shm_mapped_segments);
143 if(segment<_wapi_shm_mapped_segments) {
144 g_message (G_GNUC_PRETTY_FUNCTION ": _wapi_handle_get_shared_segment(segment): %p", _wapi_handle_get_shared_segment (segment));
148 if(segment<_wapi_shm_mapped_segments &&
149 _wapi_handle_get_shared_segment (segment)!=NULL) {
154 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
155 (void *)&_wapi_shared_mutex);
156 thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
157 g_assert (thr_ret == 0);
159 if(segment>=_wapi_shm_mapped_segments) {
160 /* Need to extend the arrays. We can't use g_renew
161 * here, because the unmapped segments must be NULL,
162 * and g_renew doesn't initialise the memory it
165 gulong old_len, new_len;
167 old_len=_wapi_shm_mapped_segments;
171 g_message (G_GNUC_PRETTY_FUNCTION
172 ": extending shared array: mapped_segments is %d",
173 _wapi_shm_mapped_segments);
176 _wapi_shared_data=_wapi_g_renew0 (_wapi_shared_data, sizeof(struct _WapiHandleShared_list *) * old_len, sizeof(struct _WapiHandleShared_list *) * new_len);
178 if(_wapi_private_data!=NULL) {
179 /* the daemon doesn't deal with private data */
180 _wapi_private_data=_wapi_g_renew0 (_wapi_private_data, sizeof(struct _WapiHandlePrivate_list *) * old_len, sizeof(struct _WapiHandlePrivate_list *) * new_len);
183 _wapi_shm_mapped_segments=segment+1;
186 if(_wapi_shared_data[segment]==NULL) {
187 /* Need to map it too */
189 g_message (G_GNUC_PRETTY_FUNCTION ": mapping segment %d",
193 _wapi_shared_data[segment]=_wapi_shm_file_map (WAPI_SHM_DATA,
196 if(_wapi_private_data!=NULL) {
197 /* the daemon doesn't deal with private data */
198 _wapi_private_data[segment]=g_new0 (struct _WapiHandlePrivate_list, 1);
202 thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
203 g_assert (thr_ret == 0);
204 pthread_cleanup_pop (0);
207 static inline void _wapi_handle_segment (gpointer handle, guint32 *segment,
210 guint32 h=GPOINTER_TO_UINT (handle);
213 divvy=div (h, _WAPI_HANDLES_PER_SEGMENT);
218 static inline guint32 _wapi_handle_index (guint32 segment, guint32 idx)
220 return((segment*_WAPI_HANDLES_PER_SEGMENT)+idx);
223 static inline WapiHandleType _wapi_handle_type (gpointer handle)
228 _wapi_handle_segment (handle, &segment, &idx);
230 if(segment>=_wapi_shm_mapped_segments)
231 return WAPI_HANDLE_UNUSED;
233 return(_wapi_handle_get_shared_segment (segment)->handles[idx].type);
236 static inline void _wapi_handle_set_signal_state (gpointer handle,
242 struct _WapiHandleShared *shared_handle;
245 _wapi_handle_segment (handle, &segment, &idx);
246 shared_handle=&_wapi_handle_get_shared_segment (segment)->handles[idx];
249 g_message (G_GNUC_PRETTY_FUNCTION ": setting state of %p to %s (broadcast %s)", handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE");
253 /* Tell everyone blocking on a single handle */
255 /* This function _must_ be called with
256 * handle->signal_mutex locked
258 shared_handle->signalled=state;
260 if(broadcast==TRUE) {
261 thr_ret = pthread_cond_broadcast (&shared_handle->signal_cond);
262 g_assert (thr_ret == 0);
264 thr_ret = pthread_cond_signal (&shared_handle->signal_cond);
265 g_assert (thr_ret == 0);
268 /* Tell everyone blocking on multiple handles that something
271 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
273 struct _WapiHandleShared_list *segment0=_wapi_handle_get_shared_segment (0);
275 pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&segment0->signal_mutex);
276 thr_ret = mono_mutex_lock (&segment0->signal_mutex);
277 g_assert (thr_ret == 0);
279 thr_ret = pthread_cond_broadcast (&segment0->signal_cond);
280 g_assert (thr_ret == 0);
282 thr_ret = mono_mutex_unlock (&segment0->signal_mutex);
283 g_assert (thr_ret == 0);
284 pthread_cleanup_pop (0);
288 struct _WapiHandlePrivate_list *segment0=_wapi_handle_get_private_segment (0);
291 g_message (G_GNUC_PRETTY_FUNCTION ": lock global signal mutex");
294 pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&segment0->signal_mutex);
295 thr_ret = mono_mutex_lock (&segment0->signal_mutex);
296 g_assert (thr_ret == 0);
298 thr_ret = pthread_cond_broadcast (&segment0->signal_cond);
299 g_assert (thr_ret == 0);
302 g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
305 thr_ret = mono_mutex_unlock (&segment0->signal_mutex);
306 g_assert (thr_ret == 0);
307 pthread_cleanup_pop (0);
309 #endif /* _POSIX_THREAD_PROCESS_SHARED */
311 shared_handle->signalled=state;
315 static inline gboolean _wapi_handle_issignalled (gpointer handle)
320 _wapi_handle_segment (handle, &segment, &idx);
322 return(_wapi_handle_get_shared_segment (segment)->handles[idx].signalled);
325 static inline int _wapi_handle_lock_signal_mutex (void)
328 g_message (G_GNUC_PRETTY_FUNCTION ": lock global signal mutex");
330 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
331 return(mono_mutex_lock (&_wapi_handle_get_shared_segment (0)->signal_mutex));
333 return(mono_mutex_lock (&_wapi_handle_get_private_segment (0)->signal_mutex));
334 #endif /* _POSIX_THREAD_PROCESS_SHARED */
337 /* the parameter makes it easier to call from a pthread cleanup handler */
338 static inline int _wapi_handle_unlock_signal_mutex (void *unused)
341 g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
343 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
344 return(mono_mutex_unlock (&_wapi_handle_get_shared_segment (0)->signal_mutex));
346 return(mono_mutex_unlock (&_wapi_handle_get_private_segment (0)->signal_mutex));
347 #endif /* _POSIX_THREAD_PROCESS_SHARED */
350 static inline int _wapi_handle_lock_handle (gpointer handle)
356 g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle);
359 _wapi_handle_ref (handle);
361 _wapi_handle_segment (handle, &segment, &idx);
363 return(mono_mutex_lock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex));
366 static inline int _wapi_handle_unlock_handle (gpointer handle)
373 g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle);
376 _wapi_handle_segment (handle, &segment, &idx);
378 ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
380 _wapi_handle_unref (handle);
385 #endif /* _WAPI_HANDLES_PRIVATE_H_ */