* Makefile (MCS) [PROFILE=default]: Force testing of 'mcs'.
[mono.git] / mono / io-layer / handles.c
index cbab985e62e216041430fc759cf302bf5d763a77..a1c3dde13efd889a11789b6069411d2e8b706dbb 100644 (file)
@@ -90,13 +90,6 @@ static void shared_init (void)
        _wapi_shared_data=g_new0 (struct _WapiHandleShared_list *, 1);
        _wapi_private_data=g_new0 (struct _WapiHandlePrivate_list *, 1);
 
-       /* Build this array at runtime, because I'm guessing that
-        * getdtablesize() won't be a fixed value on all systems (or
-        * why would it be a function rather than a constant define?)
-        */
-       _wapi_fd_offset_table_size=getdtablesize ();
-       _wapi_fd_offset_table=g_new0 (gpointer, _wapi_fd_offset_table_size);
-       
 attach_again:
 
 #ifndef DISABLE_SHARED_HANDLES
@@ -156,6 +149,9 @@ attach_again:
                                
                                goto attach_again;
                        }
+               } else {
+                       _wapi_fd_offset_table_size = _wapi_shared_data[0]->fd_offset_table_size;
+                       _wapi_fd_offset_table=g_new0 (gpointer, _wapi_fd_offset_table_size);
                }
        }
 
@@ -168,6 +164,10 @@ attach_again:
                _wapi_shared_data[0]->num_segments=1;
 
                _wapi_shared_scratch=g_new0 (struct _WapiHandleScratch, 1);
+
+               _wapi_fd_offset_table_size=getdtablesize ();
+               _wapi_fd_offset_table=g_new0 (gpointer,
+                                             _wapi_fd_offset_table_size);
        }
        _wapi_private_data[0]=g_new0 (struct _WapiHandlePrivate_list, 1);
        _wapi_shm_mapped_segments=1;
@@ -250,6 +250,7 @@ guint32 _wapi_handle_new_internal (WapiHandleType type)
        guint32 i, j;
        static guint32 last=1;
        int thr_ret;
+       guint32 num_segments = _wapi_handle_get_shared_segment (0)->num_segments;
        
        /* A linear scan should be fast enough.  Start from the last
         * allocation, assuming that handles are allocated more often
@@ -260,8 +261,7 @@ guint32 _wapi_handle_new_internal (WapiHandleType type)
 #endif
 again:
        _wapi_handle_segment (GUINT_TO_POINTER (last), &segment, &idx);
-       for(i=segment; i<_wapi_handle_get_shared_segment (0)->num_segments;
-           i++) {
+       for(i=segment; i < num_segments; i++) {
                if(i!=segment) {
                        idx=0;
                }
@@ -272,8 +272,17 @@ again:
                        /* Make sure we dont try and assign the
                         * handles that would clash with fds
                         */
-                       if (i==0 && j < _wapi_fd_offset_table_size) {
-                               j = _wapi_fd_offset_table_size;
+                       if ((i * _WAPI_HANDLES_PER_SEGMENT + j) < _wapi_fd_offset_table_size) {
+                               i = _wapi_fd_offset_table_size / _WAPI_HANDLES_PER_SEGMENT;
+                               j = _wapi_fd_offset_table_size - (i * _WAPI_HANDLES_PER_SEGMENT);
+                               
+                               if (i >= num_segments) {
+                                       /* Need to get the caller to
+                                        * add more shared segments
+                                        */
+                                       return(0);
+                               }
+                               
                                continue;
                        }
                        
@@ -349,8 +358,7 @@ again:
                thr_ret = pthread_mutex_lock (&scan_mutex);
                g_assert (thr_ret == 0);
                
-               handle_idx=_wapi_handle_new_internal (type);
-               if(handle_idx==0) {
+               while ((handle_idx = _wapi_handle_new_internal (type)) == 0) {
                        /* Try and get a new segment, and have another go */
                        segment=_wapi_handle_get_shared_segment (0)->num_segments;
                        _wapi_handle_ensure_mapped (segment);
@@ -358,7 +366,6 @@ again:
                        if(_wapi_handle_get_shared_segment (segment)!=NULL) {
                                /* Got a new segment */
                                _wapi_handle_get_shared_segment (0)->num_segments++;
-                               handle_idx=_wapi_handle_new_internal (type);
                        } else {
                                /* Map failed.  Just return 0 meaning
                                 * "out of handles"
@@ -698,6 +705,7 @@ void _wapi_handle_unref (gpointer handle)
 
                _wapi_handle_ops_close_private (handle);
                _wapi_handle_get_shared_segment (segment)->handles[idx].type=WAPI_HANDLE_UNUSED;
+               _wapi_handle_get_private_segment (segment)->handles[idx].type=WAPI_HANDLE_UNUSED;
                
                /* Destroy the mutex and cond var.  We hope nobody
                 * tried to grab them between the handle unlock and
@@ -1334,6 +1342,10 @@ gboolean CloseHandle(gpointer handle)
                handle = _wapi_handle_fd_offset_to_handle (handle);
        }
 
+       if (handle == NULL) {
+               return(FALSE);
+       }
+
        _wapi_handle_unref (handle);
        
        return(TRUE);
@@ -1372,10 +1384,16 @@ again:
                        struct timespec sleepytime;
                        
 #ifdef DEBUG
-                       g_message (G_GNUC_PRETTY_FUNCTION ": attempt failed for %p", handle);
+                       g_message (G_GNUC_PRETTY_FUNCTION ": attempt failed for %p: %s", handle, strerror (ret));
 #endif
 
                        while(i--) {
+                               handle = handles[i];
+               
+                               if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) {
+                                       handle = _wapi_handle_fd_offset_to_handle (handle);
+                               }
+
                                _wapi_handle_segment (handle, &segment, &idx);
                                thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
                                g_assert (thr_ret == 0);
@@ -1690,9 +1708,26 @@ gboolean _wapi_handle_process_fork (guint32 cmd, guint32 env, guint32 dir,
                 * exec_errno will be set, and the handle will be
                 * signalled immediately.
                 */
-               if(process_handle==0 || thread_handle==0) {
+               if(*process_handle==0 || *thread_handle==0) {
                        return(FALSE);
                } else {
+                       /* This call returns new handles, so we need to do
+                        * a little bookkeeping
+                        */
+                       if (_wapi_private_data != NULL) {
+                               guint32 segment, idx;
+
+                               _wapi_handle_segment (*process_handle,
+                                                     &segment, &idx);
+                               _wapi_handle_ensure_mapped (segment);
+                               _wapi_handle_get_private_segment (segment)->handles[idx].type = WAPI_HANDLE_PROCESS;
+
+                               _wapi_handle_segment (*thread_handle,
+                                                     &segment, &idx);
+                               _wapi_handle_ensure_mapped (segment);
+                               _wapi_handle_get_private_segment (segment)->handles[idx].type = WAPI_HANDLE_THREAD;
+                       }
+
                        return(TRUE);
                }
        } else {