[w32file] Push coop transitions into functions, closer to syscalls (#4370)
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Tue, 14 Feb 2017 16:41:38 +0000 (11:41 -0500)
committerGitHub <noreply@github.com>
Tue, 14 Feb 2017 16:41:38 +0000 (11:41 -0500)
* [w32file] Push coop transitions into functions, closer to syscalls

Previous the coop transitions happened in the icalls and high level
platform-independent functions.  Now they surround syscalls and platform API
calls, instead.

(Among other benefits, this fixes a problem where MoveFile on unix was
implemented in some circumstances in terms of CopyFile which resulted in an
illegal coop transition from blocking to blocking.)

* There is a FIXME with `mono_w32handle_new_fd` and `mono_w32handle_close`: the w32handle API is not coop-friendly yet, so we have to switch to gc safe mode around calls to `w32handle_new_fd` and `w32handle_close`.  In the case of `w32handle_close`, it calls back into the w32file functions `pipe_close`, `console_close` and `file_close`.  So the calls to `close(2)` inside those functions are not surrounded by transitions to GC safe mode - instead they require that we're already in safe mode (as is the case when they're called from w32handle).

mono/metadata/w32file-unix.c
mono/metadata/w32file-win32.c
mono/metadata/w32file.c

index be8b5f70502c4777e5e428c943e711ad8856c64d..4d9e256aca6f470db4a0494d5cf68197f3af8c44 100644 (file)
@@ -78,7 +78,7 @@ typedef struct {
  * 4MB array.
  */
 static GHashTable *file_share_table;
-static mono_mutex_t file_share_mutex;
+static MonoCoopMutex file_share_mutex;
 
 static void
 time_t_to_filetime (time_t timeval, FILETIME *filetime)
@@ -94,7 +94,7 @@ static void
 file_share_release (FileShare *share_info)
 {
        /* Prevent new entries racing with us */
-       mono_os_mutex_lock (&file_share_mutex);
+       mono_coop_mutex_lock (&file_share_mutex);
 
        g_assert (share_info->handle_refs > 0);
        share_info->handle_refs -= 1;
@@ -102,7 +102,7 @@ file_share_release (FileShare *share_info)
        if (share_info->handle_refs == 0)
                g_hash_table_remove (file_share_table, share_info);
 
-       mono_os_mutex_unlock (&file_share_mutex);
+       mono_coop_mutex_unlock (&file_share_mutex);
 }
 
 static gint
@@ -130,7 +130,7 @@ file_share_get (guint64 device, guint64 inode, guint32 new_sharemode, guint32 ne
        gboolean exists = FALSE;
 
        /* Prevent new entries racing with us */
-       mono_os_mutex_lock (&file_share_mutex);
+       mono_coop_mutex_lock (&file_share_mutex);
 
        FileShare tmp;
 
@@ -168,7 +168,7 @@ file_share_get (guint64 device, guint64 inode, guint32 new_sharemode, guint32 ne
                g_hash_table_insert (file_share_table, file_share, file_share);
        }
 
-       mono_os_mutex_unlock (&file_share_mutex);
+       mono_coop_mutex_unlock (&file_share_mutex);
 
        return(exists);
 }
@@ -182,13 +182,19 @@ _wapi_open (const gchar *pathname, gint flags, mode_t mode)
        if (flags & O_CREAT) {
                located_filename = mono_portability_find_file (pathname, FALSE);
                if (located_filename == NULL) {
+                       MONO_ENTER_GC_SAFE;
                        fd = open (pathname, flags, mode);
+                       MONO_EXIT_GC_SAFE;
                } else {
+                       MONO_ENTER_GC_SAFE;
                        fd = open (located_filename, flags, mode);
+                       MONO_EXIT_GC_SAFE;
                        g_free (located_filename);
                }
        } else {
+               MONO_ENTER_GC_SAFE;
                fd = open (pathname, flags, mode);
+               MONO_EXIT_GC_SAFE;
                if (fd == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
                        gint saved_errno = errno;
                        located_filename = mono_portability_find_file (pathname, TRUE);
@@ -198,7 +204,9 @@ _wapi_open (const gchar *pathname, gint flags, mode_t mode)
                                return -1;
                        }
 
+                       MONO_ENTER_GC_SAFE;
                        fd = open (located_filename, flags, mode);
+                       MONO_EXIT_GC_SAFE;
                        g_free (located_filename);
                }
        }
@@ -211,7 +219,9 @@ _wapi_access (const gchar *pathname, gint mode)
 {
        gint ret;
 
+       MONO_ENTER_GC_SAFE;
        ret = access (pathname, mode);
+       MONO_EXIT_GC_SAFE;
        if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
                gint saved_errno = errno;
                gchar *located_filename = mono_portability_find_file (pathname, TRUE);
@@ -221,7 +231,9 @@ _wapi_access (const gchar *pathname, gint mode)
                        return -1;
                }
 
+               MONO_ENTER_GC_SAFE;
                ret = access (located_filename, mode);
+               MONO_EXIT_GC_SAFE;
                g_free (located_filename);
        }
 
@@ -233,7 +245,9 @@ _wapi_chmod (const gchar *pathname, mode_t mode)
 {
        gint ret;
 
+       MONO_ENTER_GC_SAFE;
        ret = chmod (pathname, mode);
+       MONO_EXIT_GC_SAFE;
        if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
                gint saved_errno = errno;
                gchar *located_filename = mono_portability_find_file (pathname, TRUE);
@@ -243,7 +257,9 @@ _wapi_chmod (const gchar *pathname, mode_t mode)
                        return -1;
                }
 
+               MONO_ENTER_GC_SAFE;
                ret = chmod (located_filename, mode);
+               MONO_EXIT_GC_SAFE;
                g_free (located_filename);
        }
 
@@ -255,7 +271,9 @@ _wapi_utime (const gchar *filename, const struct utimbuf *buf)
 {
        gint ret;
 
+       MONO_ENTER_GC_SAFE;
        ret = utime (filename, buf);
+       MONO_EXIT_GC_SAFE;
        if (ret == -1 && errno == ENOENT && IS_PORTABILITY_SET) {
                gint saved_errno = errno;
                gchar *located_filename = mono_portability_find_file (filename, TRUE);
@@ -265,7 +283,9 @@ _wapi_utime (const gchar *filename, const struct utimbuf *buf)
                        return -1;
                }
 
+               MONO_ENTER_GC_SAFE;
                ret = utime (located_filename, buf);
+               MONO_EXIT_GC_SAFE;
                g_free (located_filename);
        }
 
@@ -277,7 +297,9 @@ _wapi_unlink (const gchar *pathname)
 {
        gint ret;
 
+       MONO_ENTER_GC_SAFE;
        ret = unlink (pathname);
+       MONO_EXIT_GC_SAFE;
        if (ret == -1 && (errno == ENOENT || errno == ENOTDIR || errno == EISDIR) && IS_PORTABILITY_SET) {
                gint saved_errno = errno;
                gchar *located_filename = mono_portability_find_file (pathname, TRUE);
@@ -287,7 +309,9 @@ _wapi_unlink (const gchar *pathname)
                        return -1;
                }
 
+               MONO_ENTER_GC_SAFE;
                ret = unlink (located_filename);
+               MONO_EXIT_GC_SAFE;
                g_free (located_filename);
        }
 
@@ -301,9 +325,13 @@ _wapi_rename (const gchar *oldpath, const gchar *newpath)
        gchar *located_newpath = mono_portability_find_file (newpath, FALSE);
 
        if (located_newpath == NULL) {
+               MONO_ENTER_GC_SAFE;
                ret = rename (oldpath, newpath);
+               MONO_EXIT_GC_SAFE;
        } else {
+               MONO_ENTER_GC_SAFE;
                ret = rename (oldpath, located_newpath);
+               MONO_EXIT_GC_SAFE;
 
                if (ret == -1 && (errno == EISDIR || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR || errno == EXDEV) && IS_PORTABILITY_SET) {
                        gint saved_errno = errno;
@@ -317,7 +345,9 @@ _wapi_rename (const gchar *oldpath, const gchar *newpath)
                                return -1;
                        }
 
+                       MONO_ENTER_GC_SAFE;
                        ret = rename (located_oldpath, located_newpath);
+                       MONO_EXIT_GC_SAFE;
                        g_free (located_oldpath);
                }
                g_free (located_newpath);
@@ -331,7 +361,9 @@ _wapi_stat (const gchar *path, struct stat *buf)
 {
        gint ret;
 
+       MONO_ENTER_GC_SAFE;
        ret = stat (path, buf);
+       MONO_EXIT_GC_SAFE;
        if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
                gint saved_errno = errno;
                gchar *located_filename = mono_portability_find_file (path, TRUE);
@@ -341,7 +373,9 @@ _wapi_stat (const gchar *path, struct stat *buf)
                        return -1;
                }
 
+               MONO_ENTER_GC_SAFE;
                ret = stat (located_filename, buf);
+               MONO_EXIT_GC_SAFE;
                g_free (located_filename);
        }
 
@@ -353,7 +387,9 @@ _wapi_lstat (const gchar *path, struct stat *buf)
 {
        gint ret;
 
+       MONO_ENTER_GC_SAFE;
        ret = lstat (path, buf);
+       MONO_EXIT_GC_SAFE;
        if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
                gint saved_errno = errno;
                gchar *located_filename = mono_portability_find_file (path, TRUE);
@@ -377,9 +413,13 @@ _wapi_mkdir (const gchar *pathname, mode_t mode)
        gchar *located_filename = mono_portability_find_file (pathname, FALSE);
 
        if (located_filename == NULL) {
+               MONO_ENTER_GC_SAFE;
                ret = mkdir (pathname, mode);
+               MONO_EXIT_GC_SAFE;
        } else {
+               MONO_ENTER_GC_SAFE;
                ret = mkdir (located_filename, mode);
+               MONO_EXIT_GC_SAFE;
                g_free (located_filename);
        }
 
@@ -391,7 +431,9 @@ _wapi_rmdir (const gchar *pathname)
 {
        gint ret;
 
+       MONO_ENTER_GC_SAFE;
        ret = rmdir (pathname);
+       MONO_EXIT_GC_SAFE;
        if (ret == -1 && (errno == ENOENT || errno == ENOTDIR || errno == ENAMETOOLONG) && IS_PORTABILITY_SET) {
                gint saved_errno = errno;
                gchar *located_filename = mono_portability_find_file (pathname, TRUE);
@@ -401,7 +443,9 @@ _wapi_rmdir (const gchar *pathname)
                        return -1;
                }
 
+               MONO_ENTER_GC_SAFE;
                ret = rmdir (located_filename);
+               MONO_EXIT_GC_SAFE;
                g_free (located_filename);
        }
 
@@ -413,7 +457,9 @@ _wapi_chdir (const gchar *path)
 {
        gint ret;
 
+       MONO_ENTER_GC_SAFE;
        ret = chdir (path);
+       MONO_EXIT_GC_SAFE;
        if (ret == -1 && (errno == ENOENT || errno == ENOTDIR || errno == ENAMETOOLONG) && IS_PORTABILITY_SET) {
                gint saved_errno = errno;
                gchar *located_filename = mono_portability_find_file (path, TRUE);
@@ -423,7 +469,9 @@ _wapi_chdir (const gchar *path)
                        return -1;
                }
 
+               MONO_ENTER_GC_SAFE;
                ret = chdir (located_filename);
+               MONO_EXIT_GC_SAFE;
                g_free (located_filename);
        }
 
@@ -479,7 +527,9 @@ _wapi_g_dir_open (const gchar *path, guint flags, GError **error)
 {
        GDir *ret;
 
+       MONO_ENTER_GC_SAFE;
        ret = g_dir_open (path, flags, error);
+       MONO_EXIT_GC_SAFE;
        if (ret == NULL && ((*error)->code == G_FILE_ERROR_NOENT || (*error)->code == G_FILE_ERROR_NOTDIR || (*error)->code == G_FILE_ERROR_NAMETOOLONG) && IS_PORTABILITY_SET) {
                gchar *located_filename = mono_portability_find_file (path, TRUE);
                GError *tmp_error = NULL;
@@ -488,7 +538,9 @@ _wapi_g_dir_open (const gchar *path, guint flags, GError **error)
                        return(NULL);
                }
 
+               MONO_ENTER_GC_SAFE;
                ret = g_dir_open (located_filename, flags, &tmp_error);
+               MONO_EXIT_GC_SAFE;
                g_free (located_filename);
                if (tmp_error == NULL) {
                        g_clear_error (error);
@@ -622,7 +674,9 @@ _wapi_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist)
                gchar *pattern2 = g_strndup (pattern, strlen (pattern) - 2);
                gint result2;
 
+               MONO_ENTER_GC_SAFE;
                g_dir_rewind (dir);
+               MONO_EXIT_GC_SAFE;
                result2 = mono_w32file_unix_glob (dir, pattern2, flags | W32FILE_UNIX_GLOB_APPEND | W32FILE_UNIX_GLOB_UNIQUE, &glob_buf);
 
                g_free (pattern2);
@@ -632,7 +686,9 @@ _wapi_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist)
                }
        }
 
+       MONO_ENTER_GC_SAFE;
        g_dir_close (dir);
+       MONO_EXIT_GC_SAFE;
        if (glob_buf.gl_pathc == 0) {
                return(0);
        } else if (result != 0) {
@@ -1043,6 +1099,7 @@ static void _wapi_set_last_path_error_from_errno (const gchar *dir,
  */
 static void file_close (gpointer handle, gpointer data)
 {
+       MONO_REQ_GC_SAFE_MODE; /* FIXME: after mono_w32handle_close is coop-aware, change this to UNSAFE_MODE and switch to SAFE around close() below */
        MonoW32HandleFile *file_handle = (MonoW32HandleFile *)data;
        gint fd = file_handle->fd;
        
@@ -1122,7 +1179,9 @@ file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread
        }
 
        do {
+               MONO_ENTER_GC_SAFE;
                ret = read (fd, buffer, numbytes);
+               MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
                        
@@ -1179,7 +1238,9 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt
                 * because we only do advisory locking on POSIX
                 * systems
                 */
+               MONO_ENTER_GC_SAFE;
                current_pos = lseek (fd, (off_t)0, SEEK_CUR);
+               MONO_EXIT_GC_SAFE;
                if (current_pos == -1) {
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
                                   handle, strerror (errno));
@@ -1195,7 +1256,9 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt
        }
                
        do {
+               MONO_ENTER_GC_SAFE;
                ret = write (fd, buffer, numbytes);
+               MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
        
@@ -1246,7 +1309,9 @@ static gboolean file_flush(gpointer handle)
                return(FALSE);
        }
 
+       MONO_ENTER_GC_SAFE;
        ret=fsync(fd);
+       MONO_EXIT_GC_SAFE;
        if (ret==-1) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of handle %p error: %s", __func__, handle,
                          strerror(errno));
@@ -1323,9 +1388,13 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
 
 #ifdef PLATFORM_ANDROID
        /* bionic doesn't support -D_FILE_OFFSET_BITS=64 */
+       MONO_ENTER_GC_SAFE;
        newpos=lseek64(fd, offset, whence);
+       MONO_EXIT_GC_SAFE;
 #else
+       MONO_ENTER_GC_SAFE;
        newpos=lseek(fd, offset, whence);
+       MONO_EXIT_GC_SAFE;
 #endif
        if(newpos==-1) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on handle %p returned error %s",
@@ -1389,7 +1458,9 @@ static gboolean file_setendoffile(gpointer handle)
         * than the length, truncate the file.
         */
        
+       MONO_ENTER_GC_SAFE;
        ret=fstat(fd, &statbuf);
+       MONO_EXIT_GC_SAFE;
        if(ret==-1) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
                           handle, strerror(errno));
@@ -1398,7 +1469,9 @@ static gboolean file_setendoffile(gpointer handle)
                return(FALSE);
        }
 
+       MONO_ENTER_GC_SAFE;
        pos=lseek(fd, (off_t)0, SEEK_CUR);
+       MONO_EXIT_GC_SAFE;
        if(pos==-1) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
                          handle, strerror(errno));
@@ -1422,7 +1495,9 @@ static gboolean file_setendoffile(gpointer handle)
                 * drop this write.
                 */
                do {
+                       MONO_ENTER_GC_SAFE;
                        ret = write (fd, "", 1);
+                       MONO_EXIT_GC_SAFE;
                } while (ret == -1 && errno == EINTR &&
                         !mono_thread_info_is_interrupt_state (info));
 
@@ -1434,7 +1509,9 @@ static gboolean file_setendoffile(gpointer handle)
                }
 
                /* And put the file position back after the write */
+               MONO_ENTER_GC_SAFE;
                ret = lseek (fd, pos, SEEK_SET);
+               MONO_EXIT_GC_SAFE;
                if (ret == -1) {
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p second lseek failed: %s",
                                   __func__, handle, strerror(errno));
@@ -1451,7 +1528,9 @@ static gboolean file_setendoffile(gpointer handle)
         * byte to the end of the file
         */
        do {
+               MONO_ENTER_GC_SAFE;
                ret=ftruncate(fd, pos);
+               MONO_EXIT_GC_SAFE;
        }
        while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info)); 
        if(ret==-1) {
@@ -1500,7 +1579,9 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
         */
        mono_w32error_set_last (ERROR_SUCCESS);
        
+       MONO_ENTER_GC_SAFE;
        ret = fstat(fd, &statbuf);
+       MONO_EXIT_GC_SAFE;
        if (ret == -1) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
                           handle, strerror(errno));
@@ -1513,7 +1594,11 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
 #ifdef BLKGETSIZE64
        if (S_ISBLK(statbuf.st_mode)) {
                guint64 bigsize;
-               if (ioctl(fd, BLKGETSIZE64, &bigsize) < 0) {
+               gint res;
+               MONO_ENTER_GC_SAFE;
+               res = ioctl (fd, BLKGETSIZE64, &bigsize);
+               MONO_EXIT_GC_SAFE;
+               if (res < 0) {
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ioctl BLKGETSIZE64 failed: %s",
                                   __func__, handle, strerror(errno));
 
@@ -1580,7 +1665,9 @@ static gboolean file_getfiletime(gpointer handle, FILETIME *create_time,
                return(FALSE);
        }
        
+       MONO_ENTER_GC_SAFE;
        ret=fstat(fd, &statbuf);
+       MONO_EXIT_GC_SAFE;
        if(ret==-1) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
                          strerror(errno));
@@ -1671,7 +1758,9 @@ static gboolean file_setfiletime(gpointer handle,
        /* Get the current times, so we can put the same times back in
         * the event that one of the FileTime structs is NULL
         */
+       MONO_ENTER_GC_SAFE;
        ret=fstat (fd, &statbuf);
+       MONO_EXIT_GC_SAFE;
        if(ret==-1) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
                          strerror(errno));
@@ -1746,6 +1835,7 @@ static gboolean file_setfiletime(gpointer handle,
 
 static void console_close (gpointer handle, gpointer data)
 {
+       MONO_REQ_GC_SAFE_MODE; /* FIXME: after mono_w32handle_close is coop-aware, change this to UNSAFE_MODE and switch to SAFE around close() below */
        MonoW32HandleFile *console_handle = (MonoW32HandleFile *)data;
        gint fd = console_handle->fd;
        
@@ -1812,7 +1902,9 @@ console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesr
        }
        
        do {
+               MONO_ENTER_GC_SAFE;
                ret=read(fd, buffer, numbytes);
+               MONO_EXIT_GC_SAFE;
        } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
 
        if(ret==-1) {
@@ -1861,7 +1953,9 @@ console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *
        }
        
        do {
+               MONO_ENTER_GC_SAFE;
                ret = write(fd, buffer, numbytes);
+               MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
 
@@ -1896,6 +1990,7 @@ static gsize find_typesize (void)
 
 static void pipe_close (gpointer handle, gpointer data)
 {
+       MONO_REQ_GC_SAFE_MODE; /* FIXME: after mono_w32handle_close is coop-aware, change this to UNSAFE_MODE and switch to SAFE around close() below */
        MonoW32HandleFile *pipe_handle = (MonoW32HandleFile*)data;
        gint fd = pipe_handle->fd;
 
@@ -1964,7 +2059,9 @@ pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesrea
                   numbytes, handle);
 
        do {
+               MONO_ENTER_GC_SAFE;
                ret=read(fd, buffer, numbytes);
+               MONO_EXIT_GC_SAFE;
        } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
                
        if (ret == -1) {
@@ -2023,7 +2120,9 @@ pipe_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt
                   handle);
 
        do {
+               MONO_ENTER_GC_SAFE;
                ret = write (fd, buffer, numbytes);
+               MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
 
@@ -2271,19 +2370,25 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
 
                mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES);
                
+               MONO_ENTER_GC_SAFE;
                close (fd);
+               MONO_EXIT_GC_SAFE;
                g_free (filename);
                
                return(INVALID_HANDLE_VALUE);
        }
 
+       MONO_ENTER_GC_SAFE;
        ret = fstat (fd, &statbuf);
+       MONO_EXIT_GC_SAFE;
        if (ret == -1) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__,
                           filename, strerror (errno));
                _wapi_set_last_error_from_errno ();
                g_free (filename);
+               MONO_ENTER_GC_SAFE;
                close (fd);
+               MONO_EXIT_GC_SAFE;
                
                return(INVALID_HANDLE_VALUE);
        }
@@ -2299,7 +2404,9 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
                         &file_handle.share_info) == FALSE) {
                mono_w32error_set_last (ERROR_SHARING_VIOLATION);
                g_free (filename);
+               MONO_ENTER_GC_SAFE;
                close (fd);
+               MONO_EXIT_GC_SAFE;
                
                return (INVALID_HANDLE_VALUE);
        }
@@ -2308,7 +2415,9 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No space in the share table", __func__);
 
                mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES);
+               MONO_ENTER_GC_SAFE;
                close (fd);
+               MONO_EXIT_GC_SAFE;
                g_free (filename);
                
                return(INVALID_HANDLE_VALUE);
@@ -2322,15 +2431,24 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
        file_handle.attrs=attrs;
 
 #ifdef HAVE_POSIX_FADVISE
-       if (attrs & FILE_FLAG_SEQUENTIAL_SCAN)
+       if (attrs & FILE_FLAG_SEQUENTIAL_SCAN) {
+               MONO_ENTER_GC_SAFE;
                posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
-       if (attrs & FILE_FLAG_RANDOM_ACCESS)
+               MONO_EXIT_GC_SAFE;
+       }
+       if (attrs & FILE_FLAG_RANDOM_ACCESS) {
+               MONO_ENTER_GC_SAFE;
                posix_fadvise (fd, 0, 0, POSIX_FADV_RANDOM);
+               MONO_EXIT_GC_SAFE;
+       }
 #endif
 
 #ifdef F_RDAHEAD
-       if (attrs & FILE_FLAG_SEQUENTIAL_SCAN)
+       if (attrs & FILE_FLAG_SEQUENTIAL_SCAN) {
+               MONO_ENTER_GC_SAFE;
                fcntl(fd, F_RDAHEAD, 1);
+               MONO_EXIT_GC_SAFE;
+       }
 #endif
 
 #ifndef S_ISFIFO
@@ -2348,11 +2466,15 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
                handle_type = MONO_W32HANDLE_FILE;
        }
 
+       MONO_ENTER_GC_SAFE; /* FIXME: mono_w32handle_new_fd should be updated with coop transitions */
        handle = mono_w32handle_new_fd (handle_type, fd, &file_handle);
+       MONO_EXIT_GC_SAFE;
        if (handle == INVALID_HANDLE_VALUE) {
                g_warning ("%s: error creating file handle", __func__);
                g_free (filename);
+               MONO_ENTER_GC_SAFE;
                close (fd);
+               MONO_EXIT_GC_SAFE;
                
                mono_w32error_set_last (ERROR_GEN_FAILURE);
                return(INVALID_HANDLE_VALUE);
@@ -2366,7 +2488,14 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
 gboolean
 mono_w32file_close (gpointer handle)
 {
-       return mono_w32handle_close (handle);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       /* FIXME: we transition here and not in file_close, pipe_close,
+        * console_close because w32handle_close is not coop aware yet, but it
+        * calls back into w32file. */
+       res = mono_w32handle_close (handle);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean mono_w32file_delete(const gunichar2 *name)
@@ -2580,7 +2709,9 @@ write_file (gint src_fd, gint dest_fd, struct stat *st_src, gboolean report_erro
        buf = (gchar *) g_malloc (buf_size);
 
        for (;;) {
+               MONO_ENTER_GC_SAFE;
                remain = read (src_fd, buf, buf_size);
+               MONO_EXIT_GC_SAFE;
                if (remain < 0) {
                        if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
                                continue;
@@ -2597,7 +2728,10 @@ write_file (gint src_fd, gint dest_fd, struct stat *st_src, gboolean report_erro
 
                wbuf = buf;
                while (remain > 0) {
-                       if ((n = write (dest_fd, wbuf, remain)) < 0) {
+                       MONO_ENTER_GC_SAFE;
+                       n = write (dest_fd, wbuf, remain);
+                       MONO_EXIT_GC_SAFE;
+                       if (n < 0) {
                                if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
                                        continue;
 
@@ -2626,6 +2760,7 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex
        struct utimbuf dest_time;
        gboolean ret = TRUE;
        gint ret_utime;
+       gint syscall_res;
        
        if(name==NULL) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
@@ -2673,12 +2808,17 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex
                return(FALSE);
        }
 
-       if (fstat (src_fd, &st) < 0) {
+       MONO_ENTER_GC_SAFE;
+       syscall_res = fstat (src_fd, &st);
+       MONO_EXIT_GC_SAFE;
+       if (syscall_res < 0) {
                _wapi_set_last_error_from_errno ();
 
                g_free (utf8_src);
                g_free (utf8_dest);
+               MONO_ENTER_GC_SAFE;
                close (src_fd);
+               MONO_EXIT_GC_SAFE;
                
                return(FALSE);
        }
@@ -2691,7 +2831,9 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex
 
                g_free (utf8_src);
                g_free (utf8_dest);
+               MONO_ENTER_GC_SAFE;
                close (src_fd);
+               MONO_EXIT_GC_SAFE;
 
                mono_w32error_set_last (ERROR_SHARING_VIOLATION);
                return (FALSE);
@@ -2719,7 +2861,9 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex
 
                g_free (utf8_src);
                g_free (utf8_dest);
+               MONO_ENTER_GC_SAFE;
                close (src_fd);
+               MONO_EXIT_GC_SAFE;
 
                return(FALSE);
        }
@@ -2732,7 +2876,9 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex
        
        dest_time.modtime = st.st_mtime;
        dest_time.actime = st.st_atime;
+       MONO_ENTER_GC_SAFE;
        ret_utime = utime (utf8_dest, &dest_time);
+       MONO_EXIT_GC_SAFE;
        if (ret_utime == -1)
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, strerror(errno));
        
@@ -2812,14 +2958,20 @@ replace_cleanup:
        g_free (utf8_replacedFileName);
        g_free (utf8_replacementFileName);
        g_free (utf8_backupFileName);
-       if (backup_fd != -1)
+       if (backup_fd != -1) {
+               MONO_ENTER_GC_SAFE;
                close (backup_fd);
-       if (replaced_fd != -1)
+               MONO_EXIT_GC_SAFE;
+       }
+       if (replaced_fd != -1) {
+               MONO_ENTER_GC_SAFE;
                close (replaced_fd);
+               MONO_EXIT_GC_SAFE;
+       }
        return ret;
 }
 
-static mono_mutex_t stdhandle_mutex;
+static MonoCoopMutex stdhandle_mutex;
 
 static gpointer
 _wapi_stdhandle_create (gint fd, const gchar *name)
@@ -2932,7 +3084,7 @@ mono_w32file_get_std_handle (gint stdhandle)
 
        handle = GINT_TO_POINTER (fd);
 
-       mono_os_mutex_lock (&stdhandle_mutex);
+       mono_coop_mutex_lock (&stdhandle_mutex);
 
        ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
                                  (gpointer *)&file_handle);
@@ -2950,8 +3102,8 @@ mono_w32file_get_std_handle (gint stdhandle)
        }
        
   done:
-       mono_os_mutex_unlock (&stdhandle_mutex);
-       
+       mono_coop_mutex_unlock (&stdhandle_mutex);
+
        return(handle);
 }
 
@@ -3731,7 +3883,9 @@ mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs)
                if ((buf.st_mode & S_IROTH) != 0)
                        exec_mask |= S_IXOTH;
 
+               MONO_ENTER_GC_SAFE;
                result = chmod (utf8_name, buf.st_mode | exec_mask);
+               MONO_EXIT_GC_SAFE;
        }
        /* Don't bother to reset executable (might need to change this
         * policy)
@@ -3818,7 +3972,9 @@ mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
        
        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating pipe", __func__);
 
+       MONO_ENTER_GC_SAFE;
        ret=pipe (filedes);
+       MONO_EXIT_GC_SAFE;
        if(ret==-1) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: %s", __func__,
                           strerror (errno));
@@ -3833,8 +3989,10 @@ mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
 
                mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES);
                
+               MONO_ENTER_GC_SAFE;
                close (filedes[0]);
                close (filedes[1]);
+               MONO_EXIT_GC_SAFE;
                
                return(FALSE);
        }
@@ -3847,8 +4005,10 @@ mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
                                           &pipe_read_handle);
        if (read_handle == INVALID_HANDLE_VALUE) {
                g_warning ("%s: error creating pipe read handle", __func__);
+               MONO_ENTER_GC_SAFE;
                close (filedes[0]);
                close (filedes[1]);
+               MONO_EXIT_GC_SAFE;
                mono_w32error_set_last (ERROR_GEN_FAILURE);
                
                return(FALSE);
@@ -3862,8 +4022,10 @@ mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
                g_warning ("%s: error creating pipe write handle", __func__);
                mono_w32handle_unref (read_handle);
                
+               MONO_ENTER_GC_SAFE;
                close (filedes[0]);
                close (filedes[1]);
+               MONO_EXIT_GC_SAFE;
                mono_w32error_set_last (ERROR_GEN_FAILURE);
                
                return(FALSE);
@@ -3887,15 +4049,21 @@ mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
        gint size, n, i;
        gunichar2 *dir;
        glong length, total = 0;
-       
+       gint syscall_res;
+
+       MONO_ENTER_GC_SAFE;
        n = getfsstat (NULL, 0, MNT_NOWAIT);
+       MONO_EXIT_GC_SAFE;
        if (n == -1)
                return 0;
        size = n * sizeof (struct statfs);
        stats = (struct statfs *) g_malloc (size);
        if (stats == NULL)
                return 0;
-       if (getfsstat (stats, size, MNT_NOWAIT) == -1){
+       MONO_ENTER_GC_SAFE;
+       syscall_res = getfsstat (stats, size, MNT_NOWAIT);
+       MONO_EXIT_GC_SAFE;
+       if (syscall_res == -1){
                g_free (stats);
                return 0;
        }
@@ -3982,11 +4150,15 @@ mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
        gboolean (*parser)(guint32, gunichar2*, LinuxMountInfoParseState*) = NULL;
 
        memset (buf, 0, len * sizeof (gunichar2));
+       MONO_ENTER_GC_SAFE;
        fd = open ("/proc/self/mountinfo", O_RDONLY);
+       MONO_EXIT_GC_SAFE;
        if (fd != -1)
                parser = GetLogicalDriveStrings_MountInfo;
        else {
+               MONO_ENTER_GC_SAFE;
                fd = open ("/proc/mounts", O_RDONLY);
+               MONO_EXIT_GC_SAFE;
                if (fd != -1)
                        parser = GetLogicalDriveStrings_Mounts;
        }
@@ -4000,7 +4172,12 @@ mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
        state.field_number = 1;
        state.delimiter = ' ';
 
-       while ((state.nbytes = read (fd, state.buffer, GET_LOGICAL_DRIVE_STRINGS_BUFFER)) > 0) {
+       while (1) {
+               MONO_ENTER_GC_SAFE;
+               state.nbytes = read (fd, state.buffer, GET_LOGICAL_DRIVE_STRINGS_BUFFER);
+               MONO_EXIT_GC_SAFE;
+               if (!(state.nbytes > 0))
+                       break;
                state.buffer_index = 0;
 
                while ((*parser)(len, buf, &state)) {
@@ -4022,8 +4199,11 @@ mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
        ret = state.total;
 
   done_and_out:
-       if (fd != -1)
+       if (fd != -1) {
+               MONO_ENTER_GC_SAFE;
                close (fd);
+               MONO_EXIT_GC_SAFE;
+       }
        return ret;
 }
 
@@ -4256,15 +4436,25 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf)
        /* Sigh, mntent and friends don't work well.
         * It stops on the first line that doesn't begin with a '/'.
         * (linux 2.6.5, libc 2.3.2.ds1-12) - Gonz */
+       MONO_ENTER_GC_SAFE;
        fp = fopen ("/etc/mtab", "rt");
+       MONO_EXIT_GC_SAFE;
        if (fp == NULL) {
+               MONO_ENTER_GC_SAFE;
                fp = fopen ("/etc/mnttab", "rt");
+               MONO_EXIT_GC_SAFE;
                if (fp == NULL)
                        return 1;
        }
 
        ptr = buf;
-       while (fgets (buffer, 512, fp) != NULL) {
+       while (1) {
+               gchar *fgets_res;
+               MONO_ENTER_GC_SAFE;
+               fgets_res = fgets (buffer, 512, fp);
+               MONO_EXIT_GC_SAFE;
+               if (!fgets_res)
+                       break;
                if (*buffer != '/')
                        continue;
 
@@ -4278,7 +4468,9 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf)
                dir = g_utf8_to_utf16 (*(splitted + 1), -1, NULL, &length, NULL);
                g_strfreev (splitted);
                if (total + length + 1 > len) {
+                       MONO_ENTER_GC_SAFE;
                        fclose (fp);
+                       MONO_EXIT_GC_SAFE;
                        g_free (dir);
                        return len * 2; /* guess */
                }
@@ -4288,7 +4480,9 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf)
                total += length + 1;
        }
 
+       MONO_ENTER_GC_SAFE;
        fclose (fp);
+       MONO_EXIT_GC_SAFE;
        return total;
 /* Commented out, does not work with my mtab!!! - Gonz */
 #ifdef NOTENABLED /* HAVE_MNTENT_H */
@@ -4299,18 +4493,30 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf)
        glong len, total = 0;
        
 
+       MONO_ENTER_GC_SAFE;
        fp = setmntent ("/etc/mtab", "rt");
+       MONO_EXIT_GC_SAFE;
        if (fp == NULL) {
+               MONO_ENTER_GC_SAFE;
                fp = setmntent ("/etc/mnttab", "rt");
+               MONO_EXIT_GC_SAFE;
                if (fp == NULL)
                        return;
        }
 
        ptr = buf;
-       while ((mnt = getmntent (fp)) != NULL) {
+       while (1) {
+               MONO_ENTER_GC_SAFE;
+               mnt = getmntent (fp);
+               MONO_EXIT_GC_SAFE;
+               if (mnt == NULL)
+                       break;
                g_print ("GOT %s\n", mnt->mnt_dir);
                dir = g_utf8_to_utf16 (mnt->mnt_dir, &len, NULL, NULL, NULL);
                if (total + len + 1 > len) {
+                       MONO_ENTER_GC_SAFE;
+                       endmntent (fp);
+                       MONO_EXIT_GC_SAFE;
                        return len * 2; /* guess */
                }
 
@@ -4319,7 +4525,9 @@ GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf)
                total += len + 1;
        }
 
+       MONO_ENTER_GC_SAFE;
        endmntent (fp);
+       MONO_EXIT_GC_SAFE;
        return total;
 }
 #endif
@@ -4359,11 +4567,15 @@ mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_byte
 
        do {
 #ifdef HAVE_STATVFS
+               MONO_ENTER_GC_SAFE;
                ret = statvfs (utf8_path_name, &fsstat);
+               MONO_EXIT_GC_SAFE;
                isreadonly = ((fsstat.f_flag & ST_RDONLY) == ST_RDONLY);
                block_size = fsstat.f_frsize;
 #elif defined(HAVE_STATFS)
+               MONO_ENTER_GC_SAFE;
                ret = statfs (utf8_path_name, &fsstat);
+               MONO_EXIT_GC_SAFE;
 #if defined (MNT_RDONLY)
                isreadonly = ((fsstat.f_flags & MNT_RDONLY) == MNT_RDONLY);
 #elif defined (MS_RDONLY)
@@ -4601,8 +4813,12 @@ static guint32
 GetDriveTypeFromPath (const gchar *utf8_root_path_name)
 {
        struct statfs buf;
-       
-       if (statfs (utf8_root_path_name, &buf) == -1)
+       gint res;
+
+       MONO_ENTER_GC_SAFE;
+       res = statfs (utf8_root_path_name, &buf);
+       MONO_EXIT_GC_SAFE;
+       if (res == -1)
                return DRIVE_UNKNOWN;
 #if PLATFORM_MACOSX
        return _wapi_get_drive_type (buf.f_fstypename);
@@ -4619,15 +4835,25 @@ GetDriveTypeFromPath (const gchar *utf8_root_path_name)
        gchar buffer [512];
        gchar **splitted;
 
+       MONO_ENTER_GC_SAFE;
        fp = fopen ("/etc/mtab", "rt");
+       MONO_EXIT_GC_SAFE;
        if (fp == NULL) {
+               MONO_ENTER_GC_SAFE;
                fp = fopen ("/etc/mnttab", "rt");
+               MONO_EXIT_GC_SAFE;
                if (fp == NULL) 
                        return(DRIVE_UNKNOWN);
        }
 
        drive_type = DRIVE_NO_ROOT_DIR;
-       while (fgets (buffer, 512, fp) != NULL) {
+       while (1) {
+               gchar *fgets_res;
+               MONO_ENTER_GC_SAFE;
+               fgets_res = fgets (buffer, 512, fp);
+               MONO_EXIT_GC_SAFE;
+               if (fgets_res == NULL)
+                       break;
                splitted = g_strsplit (buffer, " ", 0);
                if (!*splitted || !*(splitted + 1) || !*(splitted + 2)) {
                        g_strfreev (splitted);
@@ -4650,7 +4876,9 @@ GetDriveTypeFromPath (const gchar *utf8_root_path_name)
                g_strfreev (splitted);
        }
 
+       MONO_ENTER_GC_SAFE;
        fclose (fp);
+       MONO_EXIT_GC_SAFE;
        return drive_type;
 }
 #endif
@@ -4694,7 +4922,11 @@ get_fstypename (gchar *utfpath)
 #if __linux__
        _wapi_drive_type *current;
 #endif
-       if (statfs (utfpath, &stat) == -1)
+       gint statfs_res;
+       MONO_ENTER_GC_SAFE;
+       statfs_res = statfs (utfpath, &stat);
+       MONO_EXIT_GC_SAFE;
+       if (statfs_res == -1)
                return NULL;
 #if PLATFORM_MACOSX
        return g_strdup (stat.f_fstypename);
@@ -4815,8 +5047,8 @@ UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 le
 void
 mono_w32file_init (void)
 {
-       mono_os_mutex_init (&stdhandle_mutex);
-       mono_os_mutex_init (&file_share_mutex);
+       mono_coop_mutex_init (&stdhandle_mutex);
+       mono_coop_mutex_init (&file_share_mutex);
 
        mono_w32handle_register_ops (MONO_W32HANDLE_FILE,    &_wapi_file_ops);
        mono_w32handle_register_ops (MONO_W32HANDLE_CONSOLE, &_wapi_console_ops);
@@ -4835,7 +5067,7 @@ mono_w32file_init (void)
 void
 mono_w32file_cleanup (void)
 {
-       mono_os_mutex_destroy (&file_share_mutex);
+       mono_coop_mutex_destroy (&file_share_mutex);
 
        if (file_share_table)
                g_hash_table_destroy (file_share_table);
@@ -4846,14 +5078,9 @@ mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error)
 {
        gboolean result;
 
-       MONO_ENTER_GC_SAFE;
-
        result = MoveFile (path, dest);
        if (!result)
                *error = mono_w32error_get_last ();
-
-       MONO_EXIT_GC_SAFE;
-
        return result;
 }
 
@@ -4862,14 +5089,10 @@ mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32
 {
        gboolean result;
 
-       MONO_ENTER_GC_SAFE;
-
        result = CopyFile (path, dest, !overwrite);
        if (!result)
                *error = mono_w32error_get_last ();
 
-       MONO_EXIT_GC_SAFE;
-
        return result;
 }
 
@@ -4878,14 +5101,9 @@ mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName,
 {
        gboolean result;
 
-       MONO_ENTER_GC_SAFE;
-
        result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
        if (!result)
                *error = mono_w32error_get_last ();
-
-       MONO_EXIT_GC_SAFE;
-
        return result;
 }
 
@@ -4895,15 +5113,11 @@ mono_w32file_get_file_size (gpointer handle, gint32 *error)
        gint64 length;
        guint32 length_hi;
 
-       MONO_ENTER_GC_SAFE;
-
        length = GetFileSize (handle, &length_hi);
        if(length==INVALID_FILE_SIZE) {
                *error=mono_w32error_get_last ();
        }
 
-       MONO_EXIT_GC_SAFE;
-
        return length | ((gint64)length_hi << 32);
 }
 
@@ -4912,14 +5126,9 @@ mono_w32file_lock (gpointer handle, gint64 position, gint64 length, gint32 *erro
 {
        gboolean result;
 
-       MONO_ENTER_GC_SAFE;
-
        result = LockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
        if (!result)
                *error = mono_w32error_get_last ();
-
-       MONO_EXIT_GC_SAFE;
-
        return result;
 }
 
@@ -4928,49 +5137,26 @@ mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *er
 {
        gboolean result;
 
-       MONO_ENTER_GC_SAFE;
-
        result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
        if (!result)
                *error = mono_w32error_get_last ();
-
-       MONO_EXIT_GC_SAFE;
-
        return result;
 }
 
 gpointer
 mono_w32file_get_console_input (void)
 {
-       gpointer handle;
-
-       MONO_ENTER_GC_SAFE;
-       handle = mono_w32file_get_std_handle (STD_INPUT_HANDLE);
-       MONO_EXIT_GC_SAFE;
-
-       return handle;
+       return mono_w32file_get_std_handle (STD_INPUT_HANDLE);
 }
 
 gpointer
 mono_w32file_get_console_output (void)
 {
-       gpointer handle;
-
-       MONO_ENTER_GC_SAFE;
-       handle = mono_w32file_get_std_handle (STD_OUTPUT_HANDLE);
-       MONO_EXIT_GC_SAFE;
-
-       return handle;
+       return mono_w32file_get_std_handle (STD_OUTPUT_HANDLE);
 }
 
 gpointer
 mono_w32file_get_console_error (void)
 {
-       gpointer handle;
-
-       MONO_ENTER_GC_SAFE;
-       handle = mono_w32file_get_std_handle (STD_ERROR_HANDLE);
-       MONO_EXIT_GC_SAFE;
-
-       return handle;
+       return mono_w32file_get_std_handle (STD_ERROR_HANDLE);
 }
index 953f7926c76a72175b3fef48d6eee9f0efbb344a..df96ee154476d9e9bef3fcc681eee2c772b22a90 100644 (file)
@@ -53,109 +53,181 @@ void ves_icall_System_IO_MonoIO_DumpHandles (void)
 gpointer
 mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs)
 {
-       return CreateFile (name, fileaccess, sharemode, NULL, createmode, attrs, NULL);
+       gpointer res;
+       MONO_ENTER_GC_SAFE;
+       res = CreateFile (name, fileaccess, sharemode, NULL, createmode, attrs, NULL);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_close (gpointer handle)
 {
-       return CloseHandle (handle);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = CloseHandle (handle);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_delete (const gunichar2 *name)
 {
-       return DeleteFile (name);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = DeleteFile (name);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
 {
-       return ReadFile (handle, buffer, numbytes, bytesread, NULL);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = ReadFile (handle, buffer, numbytes, bytesread, NULL);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
 {
-       return WriteFile (handle, buffer, numbytes, byteswritten, NULL);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = WriteFile (handle, buffer, numbytes, byteswritten, NULL);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_flush (gpointer handle)
 {
-       return FlushFileBuffers (handle);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = FlushFileBuffers (handle);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_truncate (gpointer handle)
 {
-       return SetEndOfFile (handle);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = SetEndOfFile (handle);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 guint32
 mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method)
 {
-       return SetFilePointer (handle, movedistance, highmovedistance, method);
+       guint32 res;
+       MONO_ENTER_GC_SAFE;
+       res = SetFilePointer (handle, movedistance, highmovedistance, method);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gint
 mono_w32file_get_type (gpointer handle)
 {
-       return GetFileType (handle);
+       gint res;
+       MONO_ENTER_GC_SAFE;
+       res = GetFileType (handle);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_get_times (gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time)
 {
-       return GetFileTime (handle, create_time, access_time, write_time);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = GetFileTime (handle, create_time, access_time, write_time);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_set_times (gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time)
 {
-       return SetFileTime (handle, create_time, access_time, write_time);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = SetFileTime (handle, create_time, access_time, write_time);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_filetime_to_systemtime (const FILETIME *file_time, SYSTEMTIME *system_time)
 {
-       return FileTimeToSystemTime (file_time, system_time);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = FileTimeToSystemTime (file_time, system_time);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gpointer
 mono_w32file_find_first (const gunichar2 *pattern, WIN32_FIND_DATA *find_data)
 {
-       return FindFirstFile (pattern, find_data);
+       gpointer res;
+       MONO_ENTER_GC_SAFE;
+       res = FindFirstFile (pattern, find_data);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_find_next (gpointer handle, WIN32_FIND_DATA *find_data)
 {
-       return FindNextFile (handle, find_data);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = FindNextFile (handle, find_data);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_find_close (gpointer handle)
 {
-       return FindClose (handle);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = FindClose (handle);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_create_directory (const gunichar2 *name)
 {
-       return CreateDirectory (name, NULL);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = CreateDirectory (name, NULL);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_remove_directory (const gunichar2 *name)
 {
-       return RemoveDirectory (name);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = RemoveDirectory (name);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 guint32
 mono_w32file_get_attributes (const gunichar2 *name)
 {
-       return GetFileAttributes (name);
+       guint32 res;
+       MONO_ENTER_GC_SAFE;
+       res = GetFileAttributes (name);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
@@ -164,7 +236,9 @@ mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat)
        gboolean result;
        WIN32_FILE_ATTRIBUTE_DATA data;
 
+       MONO_ENTER_GC_SAFE;
        result = GetFileAttributesEx (name, GetFileExInfoStandard, &data);
+       MONO_EXIT_GC_SAFE;
        if (result) {
                stat->attributes = data.dwFileAttributes;
                stat->creation_time = (gint64) ((((guint64) data.ftCreationTime.dwHighDateTime) << 32) + data.ftCreationTime.dwLowDateTime);
@@ -179,29 +253,45 @@ mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat)
 gboolean
 mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs)
 {
-       return SetFileAttributes (name, attrs);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = SetFileAttributes (name, attrs);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 guint32
 mono_w32file_get_cwd (guint32 length, gunichar2 *buffer)
 {
-       return GetCurrentDirectory (length, buffer);
+       guint32 res;
+       MONO_ENTER_GC_SAFE;
+       res = GetCurrentDirectory (length, buffer);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_set_cwd (const gunichar2 *path)
 {
-       return SetCurrentDirectory (path);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = SetCurrentDirectory (path);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
 mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
 {
+       gboolean res;
        SECURITY_ATTRIBUTES attr;
        attr.nLength = sizeof(SECURITY_ATTRIBUTES);
        attr.bInheritHandle = TRUE;
        attr.lpSecurityDescriptor = NULL;
-       return CreatePipe (readpipe, writepipe, &attr, size);
+       MONO_ENTER_GC_SAFE;
+       res = CreatePipe (readpipe, writepipe, &attr, size);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean
@@ -212,7 +302,9 @@ mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_byte
        ULARGE_INTEGER *wapi_total_number_of_bytes;
        ULARGE_INTEGER *wapi_total_number_of_free_bytes;
 
+       MONO_ENTER_GC_SAFE;
        result = GetDiskFreeSpaceEx (path_name, wapi_free_bytes_avail, wapi_total_number_of_bytes, wapi_total_number_of_free_bytes);
+       MONO_EXIT_GC_SAFE;
        if (result) {
                if (free_bytes_avail)
                        *free_bytes_avail = wapi_free_bytes_avail->QuadPart;
@@ -228,7 +320,11 @@ mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_byte
 gboolean
 mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumename, gint volumesize, gint *outserial, gint *maxcomp, gint *fsflags, gunichar2 *fsbuffer, gint fsbuffersize)
 {
-       return GetVolumeInformation (path, volumename, volumesize, outserial, maxcomp, fsflags, fsbuffer, fsbuffersize);
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       res = GetVolumeInformation (path, volumename, volumesize, outserial, maxcomp, fsflags, fsbuffer, fsbuffersize);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
@@ -316,19 +412,31 @@ mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *er
 HANDLE
 mono_w32file_get_console_input (void)
 {
-       return GetStdHandle (STD_INPUT_HANDLE);
+       HANDLE res;
+       MONO_ENTER_GC_SAFE;
+       res = GetStdHandle (STD_INPUT_HANDLE);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 HANDLE
 mono_w32file_get_console_output (void)
 {
-       return GetStdHandle (STD_OUTPUT_HANDLE);
+       HANDLE res;
+       MONO_ENTER_GC_SAFE;
+       res = GetStdHandle (STD_OUTPUT_HANDLE);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 HANDLE
 mono_w32file_get_console_error (void)
 {
-       return GetStdHandle (STD_ERROR_HANDLE);
+       HANDLE res;
+       MONO_ENTER_GC_SAFE;
+       res = GetStdHandle (STD_ERROR_HANDLE);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gint64
@@ -352,13 +460,21 @@ mono_w32file_get_file_size (gpointer handle, gint32 *error)
 guint32
 mono_w32file_get_drive_type (const gunichar2 *root_path_name)
 {
-       return GetDriveType (root_path_name);
+       guint32 res;
+       MONO_ENTER_GC_SAFE;
+       res = GetDriveType (root_path_name);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gint32
 mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
 {
-       return GetLogicalDriveStrings (len, buf);
+       gint32 res;
+       MONO_ENTER_GC_SAFE;
+       res = GetLogicalDriveStrings (len, buf);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
index d24506afd4ee1a71b1a8096c1f6f790e466d9412..d1511ac15a11c576a3552efc7c76ed642799cded 100644 (file)
@@ -258,7 +258,6 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
        
        *error=ERROR_SUCCESS;
        
@@ -267,7 +266,6 @@ ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
                *error=mono_w32error_get_last ();
        }
 
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -275,7 +273,6 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
        
        *error=ERROR_SUCCESS;
        
@@ -284,7 +281,6 @@ ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
                *error=mono_w32error_get_last ();
        }
 
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -392,9 +388,7 @@ ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
        
        *ioerror = ERROR_SUCCESS;
 
-       MONO_ENTER_GC_SAFE;
        names = get_filesystem_entries (mono_string_chars (path), mono_string_chars (path_with_pattern), attrs, mask, ioerror);
-       MONO_EXIT_GC_SAFE;
 
        if (!names) {
                // If there's no array and no error, then return an empty array.
@@ -533,9 +527,7 @@ ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
        ifh->find_handle = find_handle;
        ifh->utf8_path = mono_string_to_utf8_checked (path, &error);
        if (mono_error_set_pending_exception (&error)) {
-               MONO_ENTER_GC_SAFE;
                mono_w32file_find_close (find_handle);
-               MONO_EXIT_GC_SAFE;
                g_free (ifh);
                return NULL;
        }
@@ -583,14 +575,12 @@ ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
        IncrementalFind *ifh = (IncrementalFind *)handle;
        gint32 error;
 
-       MONO_ENTER_GC_SAFE;
        if (mono_w32file_find_close (ifh->find_handle) == FALSE){
                error = mono_w32error_get_last ();
        } else
                error = ERROR_SUCCESS;
        g_free (ifh->utf8_path);
        g_free (ifh);
-       MONO_EXIT_GC_SAFE;
 
        return error;
 }
@@ -692,7 +682,6 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
        
        *error=ERROR_SUCCESS;
        
@@ -701,7 +690,6 @@ ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
                *error=mono_w32error_get_last ();
        }
        
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -709,8 +697,6 @@ gint32
 ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
 {
        gint32 ret;
-       MONO_ENTER_GC_SAFE;
-
        *error=ERROR_SUCCESS;
        
        ret=get_file_attributes (mono_string_chars (path));
@@ -725,8 +711,6 @@ ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
          /* if(ret==INVALID_FILE_ATTRIBUTES) { */
                *error=mono_w32error_get_last ();
        }
-       
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -735,8 +719,6 @@ ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
                                              gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
-       
        *error=ERROR_SUCCESS;
        
        ret=mono_w32file_set_attributes (mono_string_chars (path),
@@ -744,8 +726,6 @@ ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
        if(ret==FALSE) {
                *error=mono_w32error_get_last ();
        }
-
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -753,7 +733,6 @@ gint32
 ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
 
        *error=ERROR_SUCCESS;
        
@@ -765,7 +744,6 @@ ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
                *error=mono_w32error_get_last ();
        }
        
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -773,7 +751,6 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat, gint32 *error)
 {
        gboolean result;
-       MONO_ENTER_GC_SAFE;
 
        *error=ERROR_SUCCESS;
        
@@ -784,7 +761,6 @@ ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat, gint
                memset (stat, 0, sizeof (MonoIOStat));
        }
 
-       MONO_EXIT_GC_SAFE;
        return result;
 }
 
@@ -796,7 +772,6 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
        HANDLE ret;
        int attributes, attrs;
        gunichar2 *chars;
-       MONO_ENTER_GC_SAFE;
 
        chars = mono_string_chars (filename);   
        *error=ERROR_SUCCESS;
@@ -835,7 +810,6 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
                *error=mono_w32error_get_last ();
        } 
        
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -843,16 +817,12 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
-
        *error=ERROR_SUCCESS;
        
        ret=mono_w32file_close (handle);
        if(ret==FALSE) {
                *error=mono_w32error_get_last ();
        }
-       
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -876,9 +846,7 @@ ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
 
        buffer = mono_array_addr (dest, guchar, dest_offset);
 
-       MONO_ENTER_GC_SAFE;
        result = mono_w32file_read (handle, buffer, count, &n);
-       MONO_EXIT_GC_SAFE;
 
        if (!result) {
                *error=mono_w32error_get_last ();
@@ -907,9 +875,7 @@ ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
        }
        
        buffer = mono_array_addr (src, guchar, src_offset);
-       MONO_ENTER_GC_SAFE;
        result = mono_w32file_write (handle, buffer, count, &n);
-       MONO_EXIT_GC_SAFE;
 
        if (!result) {
                *error=mono_w32error_get_last ();
@@ -924,7 +890,6 @@ ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
                                 gint32 *error)
 {
        gint32 offset_hi;
-       MONO_ENTER_GC_SAFE;
 
        *error=ERROR_SUCCESS;
        
@@ -936,7 +901,6 @@ ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
                *error=mono_w32error_get_last ();
        }
 
-       MONO_EXIT_GC_SAFE;
        return offset | ((gint64)offset_hi << 32);
 }
 
@@ -944,7 +908,6 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
 
        *error=ERROR_SUCCESS;
        
@@ -953,7 +916,6 @@ ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
                *error=mono_w32error_get_last ();
        }
        
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -1022,7 +984,6 @@ ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
        const FILETIME *creation_filetime;
        const FILETIME *access_filetime;
        const FILETIME *write_filetime;
-       MONO_ENTER_GC_SAFE;
 
        *error=ERROR_SUCCESS;
        
@@ -1046,7 +1007,6 @@ ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
                *error=mono_w32error_get_last ();
        }
 
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -1073,9 +1033,7 @@ ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle
 {
        gboolean ret;
 
-       MONO_ENTER_GC_SAFE;
        ret=mono_w32file_create_pipe (read_handle, write_handle, 0);
-       MONO_EXIT_GC_SAFE;
 
        if(ret==FALSE) {
                *error = mono_w32error_get_last ();
@@ -1093,15 +1051,15 @@ ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE
        /* This is only used on Windows */
        gboolean ret;
        
-       MONO_ENTER_GC_SAFE;
 #ifdef HOST_WIN32
+       MONO_ENTER_GC_SAFE;
        ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
+       MONO_EXIT_GC_SAFE;
 #else
        mono_w32handle_ref (source_handle);
        *target_handle = source_handle;
        ret = TRUE;
 #endif
-       MONO_EXIT_GC_SAFE;
 
        if(ret==FALSE) {
                *error = mono_w32error_get_last ();
@@ -1209,15 +1167,17 @@ mono_filesize_from_path (MonoString *string)
        char *path = mono_string_to_utf8_checked (string, &error);
        mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
 
+       gint stat_res;
        MONO_ENTER_GC_SAFE;
-       if (stat (path, &buf) == -1)
+       stat_res = stat (path, &buf);
+       MONO_EXIT_GC_SAFE;
+       if (stat_res == -1)
                res = -1;
        else
                res = (gint64)buf.st_size;
 
        g_free (path);
 
-       MONO_EXIT_GC_SAFE;
        return res;
 }