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_fd_offset_table_size;
32 extern gpointer *_wapi_fd_offset_table;
34 extern guint32 _wapi_handle_new_internal (WapiHandleType type);
35 extern gpointer _wapi_handle_new (WapiHandleType type);
36 extern gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
37 gpointer *shared, gpointer *private);
38 extern gpointer _wapi_search_handle (WapiHandleType type,
39 gboolean (*check)(gpointer, gpointer),
41 gpointer *shared, gpointer *private);
42 extern gpointer _wapi_search_handle_namespace (WapiHandleType type,
46 extern void _wapi_handle_ref (gpointer handle);
47 extern void _wapi_handle_unref (gpointer handle);
48 extern guint32 _wapi_handle_scratch_store_internal (guint32 bytes,
50 extern guint32 _wapi_handle_scratch_store (gconstpointer data, guint32 bytes);
51 extern guint32 _wapi_handle_scratch_store_string_array (gchar **data);
52 extern gpointer _wapi_handle_scratch_lookup (guint32 idx);
53 extern gchar **_wapi_handle_scratch_lookup_string_array (guint32 idx);
54 extern void _wapi_handle_scratch_delete_internal (guint32 idx);
55 extern void _wapi_handle_scratch_delete (guint32 idx);
56 extern void _wapi_handle_scratch_delete_string_array (guint32 idx);
57 extern void _wapi_handle_register_capabilities (WapiHandleType type,
58 WapiHandleCapability caps);
59 extern gboolean _wapi_handle_test_capabilities (gpointer handle,
60 WapiHandleCapability caps);
61 extern void _wapi_handle_ops_close_shared (gpointer handle);
62 extern void _wapi_handle_ops_close_private (gpointer handle);
63 extern void _wapi_handle_ops_signal (gpointer handle);
64 extern void _wapi_handle_ops_own (gpointer handle);
65 extern gboolean _wapi_handle_ops_isowned (gpointer handle);
67 extern gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
72 extern void _wapi_handle_unlock_handles (guint32 numhandles,
74 extern int _wapi_handle_wait_signal (void);
75 extern int _wapi_handle_timedwait_signal (struct timespec *timeout);
76 extern int _wapi_handle_wait_signal_handle (gpointer handle);
77 extern int _wapi_handle_timedwait_signal_handle (gpointer handle,
78 struct timespec *timeout);
79 extern gboolean _wapi_handle_process_fork (guint32 cmd, guint32 env,
80 guint32 dir, gboolean inherit,
82 gpointer stdin_handle,
83 gpointer stdout_handle,
84 gpointer stderr_handle,
85 gpointer *process_handle,
86 gpointer *thread_handle,
87 guint32 *pid, guint32 *tid);
89 extern gboolean _wapi_handle_process_kill (pid_t pid, guint32 signo,
91 extern gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode,
92 guint32 new_sharemode,
94 guint32 *old_sharemode,
96 extern void _wapi_handle_set_share (dev_t device, ino_t inode,
97 guint32 sharemode, guint32 access);
99 static inline struct _WapiHandleShared_list *_wapi_handle_get_shared_segment (guint32 segment)
101 struct _WapiHandleShared_list *shared;
104 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
105 (void *)&_wapi_shared_mutex);
106 thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
107 g_assert (thr_ret == 0);
109 shared=_wapi_shared_data[segment];
111 thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
112 g_assert (thr_ret == 0);
113 pthread_cleanup_pop (0);
118 static inline struct _WapiHandlePrivate_list *_wapi_handle_get_private_segment (guint32 segment)
120 struct _WapiHandlePrivate_list *priv;
123 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
124 (void *)&_wapi_shared_mutex);
125 thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
126 g_assert (thr_ret == 0);
128 priv=_wapi_private_data[segment];
130 thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
131 g_assert (thr_ret == 0);
132 pthread_cleanup_pop (0);
137 static inline void _wapi_handle_ensure_mapped (guint32 segment)
142 g_message (G_GNUC_PRETTY_FUNCTION ": checking segment %d is mapped",
144 g_message (G_GNUC_PRETTY_FUNCTION ": _wapi_shm_mapped_segments: %d",
145 _wapi_shm_mapped_segments);
146 if(segment<_wapi_shm_mapped_segments) {
147 g_message (G_GNUC_PRETTY_FUNCTION ": _wapi_handle_get_shared_segment(segment): %p", _wapi_handle_get_shared_segment (segment));
151 if(segment<_wapi_shm_mapped_segments &&
152 _wapi_handle_get_shared_segment (segment)!=NULL) {
157 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
158 (void *)&_wapi_shared_mutex);
159 thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
160 g_assert (thr_ret == 0);
162 if(segment>=_wapi_shm_mapped_segments) {
163 /* Need to extend the arrays. We can't use g_renew
164 * here, because the unmapped segments must be NULL,
165 * and g_renew doesn't initialise the memory it
168 gulong old_len, new_len;
170 old_len=_wapi_shm_mapped_segments;
174 g_message (G_GNUC_PRETTY_FUNCTION
175 ": extending shared array: mapped_segments is %d",
176 _wapi_shm_mapped_segments);
179 _wapi_shared_data=_wapi_g_renew0 (_wapi_shared_data, sizeof(struct _WapiHandleShared_list *) * old_len, sizeof(struct _WapiHandleShared_list *) * new_len);
181 if(_wapi_private_data!=NULL) {
182 /* the daemon doesn't deal with private data */
183 _wapi_private_data=_wapi_g_renew0 (_wapi_private_data, sizeof(struct _WapiHandlePrivate_list *) * old_len, sizeof(struct _WapiHandlePrivate_list *) * new_len);
186 _wapi_shm_mapped_segments=segment+1;
189 if(_wapi_shared_data[segment]==NULL) {
190 /* Need to map it too */
192 g_message (G_GNUC_PRETTY_FUNCTION ": mapping segment %d",
196 _wapi_shared_data[segment]=_wapi_shm_file_map (WAPI_SHM_DATA,
199 if(_wapi_private_data!=NULL) {
200 /* the daemon doesn't deal with private data */
201 _wapi_private_data[segment]=g_new0 (struct _WapiHandlePrivate_list, 1);
205 thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
206 g_assert (thr_ret == 0);
207 pthread_cleanup_pop (0);
210 static inline void _wapi_handle_segment (gpointer handle, guint32 *segment,
213 guint32 h=GPOINTER_TO_UINT (handle);
216 divvy=div (h, _WAPI_HANDLES_PER_SEGMENT);
221 static inline guint32 _wapi_handle_index (guint32 segment, guint32 idx)
223 return((segment*_WAPI_HANDLES_PER_SEGMENT)+idx);
226 static inline gpointer _wapi_handle_fd_offset_to_handle (gpointer fd_handle)
228 int fd = GPOINTER_TO_INT (fd_handle);
231 if (fd >= _wapi_fd_offset_table_size) {
235 handle = _wapi_fd_offset_table[fd];
237 if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
242 g_message (G_GNUC_PRETTY_FUNCTION ": Returning fd offset %d of %p", fd,
249 static inline WapiHandleType _wapi_handle_type (gpointer handle)
254 if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
255 handle = _wapi_handle_fd_offset_to_handle (handle);
258 _wapi_handle_segment (handle, &segment, &idx);
260 if(segment>=_wapi_shm_mapped_segments)
261 return WAPI_HANDLE_UNUSED;
263 return(_wapi_handle_get_shared_segment (segment)->handles[idx].type);
266 static inline void _wapi_handle_fd_offset_store (int fd, gpointer handle)
268 g_assert (fd < _wapi_fd_offset_table_size);
270 if (_wapi_fd_offset_table[fd] != NULL && handle != NULL) {
271 gpointer oldhandle = _wapi_fd_offset_table[fd];
272 struct _WapiHandlePrivate *private_handle;
277 g_message (G_GNUC_PRETTY_FUNCTION
278 ": Reassigning fd offset %d from %p", fd,
282 /* The WapiFDMapped struct at the head of the private
283 * handle data means we don't need to do a full
284 * lookup, and we don't need to know the handle type.
286 g_assert (_wapi_handle_type (oldhandle) == WAPI_HANDLE_FILE ||
287 _wapi_handle_type (oldhandle) == WAPI_HANDLE_CONSOLE ||
288 _wapi_handle_type (oldhandle) == WAPI_HANDLE_PIPE ||
289 _wapi_handle_type (oldhandle) == WAPI_HANDLE_SOCKET);
291 _wapi_handle_segment (oldhandle, &segment, &idx);
292 _wapi_handle_ensure_mapped (segment);
294 private_handle=&_wapi_handle_get_private_segment(segment)->handles[idx];
295 ((WapiFDMapped *)(&private_handle->u))->assigned = FALSE;
298 g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size || handle==NULL);
301 g_message (G_GNUC_PRETTY_FUNCTION ": Assigning fd offset %d to %p", fd,
305 _wapi_fd_offset_table[fd]=handle;
308 static inline void _wapi_handle_set_signal_state (gpointer handle,
314 struct _WapiHandleShared *shared_handle;
317 g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
319 _wapi_handle_segment (handle, &segment, &idx);
320 shared_handle=&_wapi_handle_get_shared_segment (segment)->handles[idx];
323 g_message (G_GNUC_PRETTY_FUNCTION ": setting state of %p to %s (broadcast %s)", handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE");
327 /* Tell everyone blocking on a single handle */
329 /* This function _must_ be called with
330 * handle->signal_mutex locked
332 shared_handle->signalled=state;
334 if(broadcast==TRUE) {
335 thr_ret = pthread_cond_broadcast (&shared_handle->signal_cond);
336 g_assert (thr_ret == 0);
338 thr_ret = pthread_cond_signal (&shared_handle->signal_cond);
339 g_assert (thr_ret == 0);
342 /* Tell everyone blocking on multiple handles that something
345 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
347 struct _WapiHandleShared_list *segment0=_wapi_handle_get_shared_segment (0);
349 pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&segment0->signal_mutex);
350 thr_ret = mono_mutex_lock (&segment0->signal_mutex);
351 g_assert (thr_ret == 0);
353 thr_ret = pthread_cond_broadcast (&segment0->signal_cond);
354 g_assert (thr_ret == 0);
356 thr_ret = mono_mutex_unlock (&segment0->signal_mutex);
357 g_assert (thr_ret == 0);
358 pthread_cleanup_pop (0);
362 struct _WapiHandlePrivate_list *segment0=_wapi_handle_get_private_segment (0);
365 g_message (G_GNUC_PRETTY_FUNCTION ": lock global signal mutex");
368 pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&segment0->signal_mutex);
369 thr_ret = mono_mutex_lock (&segment0->signal_mutex);
370 g_assert (thr_ret == 0);
372 thr_ret = pthread_cond_broadcast (&segment0->signal_cond);
373 g_assert (thr_ret == 0);
376 g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
379 thr_ret = mono_mutex_unlock (&segment0->signal_mutex);
380 g_assert (thr_ret == 0);
381 pthread_cleanup_pop (0);
383 #endif /* _POSIX_THREAD_PROCESS_SHARED */
385 shared_handle->signalled=state;
389 static inline gboolean _wapi_handle_issignalled (gpointer handle)
394 g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
396 _wapi_handle_segment (handle, &segment, &idx);
398 return(_wapi_handle_get_shared_segment (segment)->handles[idx].signalled);
401 static inline int _wapi_handle_lock_signal_mutex (void)
404 g_message (G_GNUC_PRETTY_FUNCTION ": lock global signal mutex");
406 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
407 return(mono_mutex_lock (&_wapi_handle_get_shared_segment (0)->signal_mutex));
409 return(mono_mutex_lock (&_wapi_handle_get_private_segment (0)->signal_mutex));
410 #endif /* _POSIX_THREAD_PROCESS_SHARED */
413 /* the parameter makes it easier to call from a pthread cleanup handler */
414 static inline int _wapi_handle_unlock_signal_mutex (void *unused)
417 g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
419 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
420 return(mono_mutex_unlock (&_wapi_handle_get_shared_segment (0)->signal_mutex));
422 return(mono_mutex_unlock (&_wapi_handle_get_private_segment (0)->signal_mutex));
423 #endif /* _POSIX_THREAD_PROCESS_SHARED */
426 static inline int _wapi_handle_lock_handle (gpointer handle)
431 g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
434 g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle);
437 _wapi_handle_ref (handle);
439 _wapi_handle_segment (handle, &segment, &idx);
441 return(mono_mutex_lock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex));
444 static inline int _wapi_handle_unlock_handle (gpointer handle)
450 g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size);
453 g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle);
456 _wapi_handle_segment (handle, &segment, &idx);
458 ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
460 _wapi_handle_unref (handle);
465 #endif /* _WAPI_HANDLES_PRIVATE_H_ */