Merge revisions 41642:42764 into this branch
authorDick Porter <dick@acm.org>
Sun, 10 Apr 2005 20:49:04 +0000 (20:49 -0000)
committerDick Porter <dick@acm.org>
Sun, 10 Apr 2005 20:49:04 +0000 (20:49 -0000)
svn path=/branches/dick/io-layer-no-daemon/; revision=42767

12 files changed:
mono/io-layer/ChangeLog
mono/io-layer/atomic.c
mono/io-layer/atomic.h
mono/io-layer/collection.c
mono/io-layer/io-layer.h
mono/io-layer/io-private.h
mono/io-layer/io.c
mono/io-layer/sockets.c
mono/io-layer/sockets.h
mono/io-layer/threads.c
mono/io-layer/threads.h
mono/io-layer/timed-thread.c

index d55ec04fb4a9b8ede98a0cc9f32ca19f8f7cec8e..31f34abc7bb88898a2322de9cdea088dc9f20c1e 100644 (file)
@@ -1,3 +1,25 @@
+2005-04-07 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * io-private.h:
+       * threads.c:
+       * threads.h:
+       * io.c:
+       * sockets.c:
+       * sockets.h: removed dead code that deals with async IO.
+
+2005-03-30  Zoltan Varga  <vargaz@freemail.hu>
+
+       * atomic.c (InterlockedIncrement): Fix fallback implementation of
+       InterlockedIncrement and InterlockedDecrement. Fixes #74228.
+
+2005-03-29  Sebastien Pouliot  <sebastien@ximian.com>
+
+       * io-layer.h: Add required header files for compiling with VS.NET.
+
+2005-03-17 Miguel de Icaza <miguel@novell.com>
+
+       * io.c: don't fail on NFS when there are no more locks available.
+
 2005-03-09  Dick Porter  <dick@ximian.com>
 
        * error.c (_wapi_get_win32_file_error): ENFILE and EMFILE should
index 8a7bebea1a8cf1ab95773bbcde73c115f27c9a1c..af26fff174ae7d4a903af61ffbd2cf608d7d2e67 100644 (file)
@@ -91,8 +91,8 @@ gint32 InterlockedIncrement(volatile gint32 *dest)
                              (void *)&spin);
        thr_ret = pthread_mutex_lock(&spin);
        g_assert (thr_ret == 0);
-       
-       *dest++;
+
+       (*dest)++;
        ret= *dest;
        
        thr_ret = pthread_mutex_unlock(&spin);
@@ -115,7 +115,7 @@ gint32 InterlockedDecrement(volatile gint32 *dest)
        thr_ret = pthread_mutex_lock(&spin);
        g_assert (thr_ret == 0);
        
-       *dest--;
+       (*dest)--;
        ret= *dest;
        
        thr_ret = pthread_mutex_unlock(&spin);
index c11f06ad02b6205fe0f335e67df1dde6b313b9bb..0b44c59cf3b47f3ba1b3b7da5702775badf7a687 100644 (file)
@@ -464,7 +464,7 @@ static inline gint32 InterlockedCompareExchange(volatile gint32 *dest,
 
 static inline gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
 {
-       gint32 tmp;
+       gint32 tmp = 0;
 
        __asm__ __volatile__ ("\n1:\n\t"
                              "lwarx  %0, 0, %2\n\t"
index f32f793b5210d239665ab79077e639e8a446b880..4a8c216fc069eef407158df3b0bd293089637ce6 100644 (file)
@@ -35,6 +35,13 @@ static gpointer collection_thread (gpointer unused G_GNUC_UNUSED)
                _wapi_handle_update_refs ();
                nanosleep (&sleepytime, NULL);
        }
+
+#ifndef __GNUC__
+       /* Even though we tell gcc that this function doesn't return,
+        * other compilers won't see that.
+        */
+       return(NULL);
+#endif
 }
 
 void _wapi_collection_init (void)
index 00b351fea212c251b44c38b6f4b81b623a9c5cfb..f8315fe9984bba87ae2cbc3a08c43233be876665 100644 (file)
 #define UNICODE
 #define _UNICODE
 #define __USE_W32_SOCKETS
-#include <w32api.h>
+#include <winsock2.h>
 #include <windows.h>
+#include <WinBase.h>
 #include <ws2tcpip.h>
 #include <psapi.h>
+#include <shlobj.h>
 #else  /* EVERYONE ELSE */
 #include "mono/io-layer/wapi.h"
 #include "mono/io-layer/uglify.h"
index fedf8f2c856dc009c703197999cb491af395b699..a517a317fb66409cb4fc98f4ee4ae5db7e6a47ca 100644 (file)
@@ -36,8 +36,6 @@ struct _WapiHandle_file
        guint32 fileaccess;
        guint32 sharemode;
        guint32 attrs;
-       gboolean async;
-       WapiOverlappedCB callback;
 };
 
 struct _WapiHandle_find
@@ -48,10 +46,4 @@ struct _WapiHandle_find
        size_t count;
 };
 
-G_BEGIN_DECLS
-extern gboolean _wapi_io_add_callback (gpointer handle,
-                                      WapiOverlappedCB callback,
-                                      guint64 flags);
-G_END_DECLS
-
 #endif /* _WAPI_IO_PRIVATE_H_ */
index e76c7cef020c98c1ddc7bdc9598c4e1af5867cb2..46076c046b989be1c9e5d5a1f7e88d6b119e7f36 100644 (file)
 #include <stdio.h>
 #include <utime.h>
 
-#ifndef PLATFORM_WIN32
-#ifdef HAVE_AIO_H
-#include <aio.h>
-#define USE_AIO        1
-#elif defined(HAVE_SYS_AIO_H)
-#include <sys/aio.h>
-#define USE_AIO 1
-#else
-#undef USE_AIO
-#endif
-#endif
-
 #include <mono/io-layer/wapi.h>
 #include <mono/io-layer/wapi-private.h>
 #include <mono/io-layer/handles-private.h>
@@ -274,38 +262,6 @@ static WapiFileType file_getfiletype(void)
        return(FILE_TYPE_DISK);
 }
 
-#ifdef USE_AIO
-typedef struct {
-       struct aiocb *aio;
-       WapiOverlapped *overlapped;
-       WapiOverlappedCB callback;
-} notifier_data_t;
-
-#define SIGPTR(a) a.SIGVAL_PTR
-
-static void
-async_notifier (union sigval sig)
-{
-       notifier_data_t *ndata = SIGPTR (sig);
-       guint32 error;
-       guint32 numbytes;
-
-       error = aio_return (ndata->aio);
-       if (error < 0) {
-               error = _wapi_get_win32_file_error (error);
-               numbytes = 0;
-       } else {
-               numbytes = error;
-               error = 0;
-       }
-
-       ndata->callback (error, numbytes, ndata->overlapped);
-       g_free (ndata->aio);
-       g_free (ndata);
-}
-
-#endif /* USE_AIO */
-
 static gboolean file_read(gpointer handle, gpointer buffer,
                          guint32 numbytes, guint32 *bytesread,
                          WapiOverlapped *overlapped)
@@ -339,86 +295,27 @@ static gboolean file_read(gpointer handle, gpointer buffer,
                return(FALSE);
        }
 
-       if (file_handle->async == FALSE) {
-               do {
-                       ret=read(fd, buffer, numbytes);
-               } while (ret==-1 && errno==EINTR &&
-                        !_wapi_thread_cur_apc_pending());
+       do {
+               ret = read (fd, buffer, numbytes);
+       } while (ret == -1 && errno == EINTR &&
+                !_wapi_thread_cur_apc_pending());
                        
-               if(ret==-1) {
-                       gint err = errno;
-
-#ifdef DEBUG
-                       g_message("%s: read of handle %p error: %s", __func__,
-                                 handle, strerror(err));
-#endif
-                       SetLastError (_wapi_get_win32_file_error (err));
-                       return(FALSE);
-               }
-               
-               if(bytesread!=NULL) {
-                       *bytesread=ret;
-               }
-               
-               return(TRUE);
-       }
-
-#ifndef USE_AIO
-       SetLastError (ERROR_NOT_SUPPORTED);
-       return FALSE;
-#else
-       if (overlapped == NULL || file_handle->callback == NULL) {
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return FALSE;
-       }
-
-       {
-       struct aiocb *aio;
-       int result;
-       notifier_data_t *ndata;
-
-       ndata = g_new0 (notifier_data_t, 1);
-       aio = g_new0 (struct aiocb, 1);
-       ndata->overlapped = overlapped;
-       ndata->aio = aio;
-       ndata->callback = file_handle->callback;
-
-       aio->aio_fildes = fd;
-       aio->aio_lio_opcode = LIO_READ;
-       aio->aio_nbytes = numbytes;
-       aio->aio_offset = overlapped->Offset + (((gint64) overlapped->OffsetHigh) << 32);
-       aio->aio_buf = buffer;
-       aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
-       aio->aio_sigevent.sigev_notify_function = async_notifier;
-       SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
-
-       result = aio_read (aio);
-       if (result == -1) {
-               _wapi_set_last_error_from_errno ();
-               return FALSE;
-       }
+       if(ret==-1) {
+               gint err = errno;
 
-       result = aio_error (aio);
 #ifdef DEBUG
-       g_print ("aio_error (read) returned %d for %d\n", result, fd);
+               g_message("%s: read of handle %p error: %s", __func__,
+                         handle, strerror(err));
 #endif
-       if (result == 0) {
-               numbytes = aio_return (aio);
-#ifdef DEBUG
-               g_print ("numbytes %d for %d\n", numbytes, fd);
-#endif
-       } else {
-               errno = result;
-               _wapi_set_last_error_from_errno ();
-               return FALSE;
+               SetLastError (_wapi_get_win32_file_error (err));
+               return(FALSE);
        }
-
-       if (bytesread)
-               *bytesread = numbytes;
-
-       return TRUE;
+               
+       if (bytesread != NULL) {
+               *bytesread = ret;
        }
-#endif
+               
+       return(TRUE);
 }
 
 static gboolean file_write(gpointer handle, gconstpointer buffer,
@@ -428,6 +325,7 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
        struct _WapiHandle_file *file_handle;
        gboolean ok;
        int ret;
+       off_t current_pos;
        int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
@@ -453,112 +351,49 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
                return(FALSE);
        }
        
-       if (file_handle->async == FALSE) {
-               off_t current_pos;
-               
-               /* Need to lock the region we're about to write to,
-                * because we only do advisory locking on POSIX
-                * systems
-                */
-               current_pos = lseek (fd, (off_t)0, SEEK_CUR);
-               if (current_pos == -1) {
+       /* Need to lock the region we're about to write to, because we
+        * only do advisory locking on POSIX systems
+        */
+       current_pos = lseek (fd, (off_t)0, SEEK_CUR);
+       if (current_pos == -1) {
 #ifdef DEBUG
-                       g_message ("%s: handle %p lseek failed: %s", __func__,
-                                  handle, strerror (errno));
+               g_message ("%s: handle %p lseek failed: %s", __func__, handle,
+                          strerror (errno));
 #endif
-                       _wapi_set_last_error_from_errno ();
-                       return(FALSE);
-               }
+               _wapi_set_last_error_from_errno ();
+               return(FALSE);
+       }
                
-               if (_wapi_lock_file_region (fd, current_pos,
-                                           numbytes) == FALSE) {
-                       /* The error has already been set */
-                       return(FALSE);
-               }
+       if (_wapi_lock_file_region (fd, current_pos, numbytes) == FALSE) {
+               /* The error has already been set */
+               return(FALSE);
+       }
                
-               do {
-                       ret=write(fd, buffer, numbytes);
-               } while (ret==-1 && errno==EINTR &&
-                        !_wapi_thread_cur_apc_pending());
+       do {
+               ret = write (fd, buffer, numbytes);
+       } while (ret == -1 && errno == EINTR &&
+                !_wapi_thread_cur_apc_pending());
 
-               _wapi_unlock_file_region (fd, current_pos, numbytes);
+       _wapi_unlock_file_region (fd, current_pos, numbytes);
 
-               if (ret == -1) {
-                       if (errno == EINTR) {
-                               ret = 0;
-                       } else {
-                               _wapi_set_last_error_from_errno ();
+       if (ret == -1) {
+               if (errno == EINTR) {
+                       ret = 0;
+               } else {
+                       _wapi_set_last_error_from_errno ();
                                
 #ifdef DEBUG
-                               g_message("%s: write of handle %p error: %s",
-                                         __func__, handle, strerror(errno));
+                       g_message("%s: write of handle %p error: %s",
+                                 __func__, handle, strerror(errno));
 #endif
 
-                               return(FALSE);
-                       }
-               }
-               if(byteswritten!=NULL) {
-                       *byteswritten=ret;
+                       return(FALSE);
                }
-               return(TRUE);
-       }
-
-#ifndef USE_AIO
-       SetLastError (ERROR_NOT_SUPPORTED);
-       return FALSE;
-#else
-       if (overlapped == NULL || file_handle->callback == NULL) {
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return FALSE;
-       }
-
-       {
-       struct aiocb *aio;
-       int result;
-       notifier_data_t *ndata;
-
-       ndata = g_new0 (notifier_data_t, 1);
-       aio = g_new0 (struct aiocb, 1);
-       ndata->overlapped = overlapped;
-       ndata->aio = aio;
-       ndata->callback = file_handle->callback;
-
-       aio->aio_fildes = fd;
-       aio->aio_lio_opcode = LIO_WRITE;
-       aio->aio_nbytes = numbytes;
-       aio->aio_offset = overlapped->Offset + (((gint64) overlapped->OffsetHigh) << 32);
-       aio->aio_buf = (gpointer) buffer;
-       aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
-       aio->aio_sigevent.sigev_notify_function = async_notifier;
-       SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
-
-       result = aio_write (aio);
-       if (result == -1) {
-               _wapi_set_last_error_from_errno ();
-               return FALSE;
        }
-
-       result = aio_error (aio);
-#ifdef DEBUG
-       g_print ("aio_error (write) returned %d for %d\n", result, fd);
-#endif
-       if (result == 0) {
-               numbytes = aio_return (aio);
-#ifdef DEBUG
-       g_print ("numbytes %d for %d\n", numbytes, fd);
-#endif
-       } else {
-               errno = result;
-               _wapi_set_last_error_from_errno ();
-               return FALSE;
+       if (byteswritten != NULL) {
+               *byteswritten = ret;
        }
-
-       if (byteswritten)
-               *byteswritten = numbytes;
-
-       return TRUE;
-       }
-#endif
+       return(TRUE);
 }
 
 static gboolean file_flush(gpointer handle)
@@ -1595,9 +1430,10 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        gpointer handle;
        int flags=convert_flags(fileaccess, createmode);
        /*mode_t perms=convert_perms(sharemode);*/
-       /* we don't use sharemode, because that relates to sharing of the file
-        * when the file is open and is already handled by other code, perms instead
-        * are the on-disk permissions and this is a sane default.
+       /* we don't use sharemode, because that relates to sharing of
+        * the file when the file is open and is already handled by
+        * other code, perms instead are the on-disk permissions and
+        * this is a sane default.
         */
        mode_t perms=0644;
        gchar *filename;
@@ -1704,7 +1540,6 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                return(INVALID_HANDLE_VALUE);
        }
        
-       file_handle.async = ((attrs & FILE_FLAG_OVERLAPPED) != 0);
        file_handle.filename = filename;
 
        if(security!=NULL) {
@@ -3600,51 +3435,6 @@ guint32 GetTempPath (guint32 len, gunichar2 *buf)
        return(ret);
 }
 
-gboolean
-_wapi_io_add_callback (gpointer handle,
-                      WapiOverlappedCB callback,
-                      guint64 flags G_GNUC_UNUSED)
-{
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       int thr_ret;
-       gboolean ret = FALSE;
-       
-       ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                                 (gpointer *) &file_handle);
-
-       if (ok == FALSE) {
-               ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
-                                         (gpointer *) &file_handle);
-
-       }
-
-       if (ok == FALSE || file_handle->async == FALSE) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
-                             handle);
-       thr_ret = _wapi_handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-       
-       if (file_handle->callback != NULL) {
-               SetLastError (ERROR_INVALID_PARAMETER);
-               goto cleanup;
-       }
-       ret = TRUE;
-       
-       file_handle->callback = callback;
-
-cleanup:
-       thr_ret = _wapi_handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-       pthread_cleanup_pop (0);
-
-       return(ret);
-}
-
 gint32
 GetLogicalDriveStrings (guint32 len, gunichar2 *buf)
 {
@@ -3745,6 +3535,14 @@ static gboolean _wapi_lock_file_region (int fd, off_t offset, off_t length)
 #endif
 
        if (ret == -1) {
+               /*
+                * if locks are not available (NFS for example),
+                * ignore the error
+                */
+               if (errno == ENOLCK) {
+                       return (TRUE);
+               }
+               
                SetLastError (ERROR_LOCK_VIOLATION);
                return(FALSE);
        }
index e585714a00c6bc34198352087a95f3e26edb07fb..701bbd4cebba94dc62e0c73cababd81c1eee7828 100644 (file)
 #include <signal.h>
 #endif
 
-#ifndef PLATFORM_WIN32
-#ifdef HAVE_AIO_H
-#include <aio.h>
-#define USE_AIO        1
-#elif defined(HAVE_SYS_AIO_H)
-#include <sys/aio.h>
-#define USE_AIO 1
-#else
-#undef USE_AIO
-#endif
-#endif
-
 #include <mono/io-layer/wapi.h>
 #include <mono/io-layer/wapi-private.h>
 #include <mono/io-layer/socket-private.h>
@@ -960,109 +948,3 @@ void _wapi_FD_SET(guint32 fd, fd_set *set)
        FD_SET (fd, set);
 }
 
-#ifdef USE_AIO
-
-typedef struct {
-       struct aiocb *aio;
-       gpointer ares;
-       SocketAsyncCB callback;
-} notifier_data_t;
-
-#define SIGPTR(a) a.SIGVAL_PTR
-
-static void
-async_notifier (union sigval sig)
-{
-       notifier_data_t *ndata = SIGPTR (sig);
-       guint32 error;
-       guint32 numbytes;
-
-       error = aio_return (ndata->aio);
-       if (error < 0) {
-               error = _wapi_get_win32_file_error (error);
-               numbytes = 0;
-       } else {
-               numbytes = error;
-               error = 0;
-       }
-
-       ndata->callback (error, numbytes, ndata->ares);
-       g_free (ndata->aio);
-       g_free (ndata);
-}
-
-static gboolean
-do_aio_call (gboolean is_read, gpointer handle, gpointer buffer,
-               guint32 numbytes, guint32 *out_bytes,
-               gpointer ares,
-               SocketAsyncCB callback)
-{
-       int fd = GPOINTER_TO_UINT (handle);
-       struct aiocb *aio;
-       int result;
-       notifier_data_t *ndata;
-       
-       if (handle == NULL ||
-           _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
-               WSASetLastError (WSAENOTSOCK);
-               return FALSE;
-       }
-
-       ndata = g_new0 (notifier_data_t, 1);
-       aio = g_new0 (struct aiocb, 1);
-       ndata->ares = ares;
-       ndata->aio = aio;
-       ndata->callback = callback;
-
-       aio->aio_fildes = fd;
-       aio->aio_lio_opcode = (is_read) ? LIO_READ : LIO_WRITE;
-       aio->aio_nbytes = numbytes;
-       aio->aio_offset = 0;
-       aio->aio_buf = buffer;
-       aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
-       aio->aio_sigevent.sigev_notify_function = async_notifier;
-       SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
-
-       if (is_read) {
-               result = aio_read (aio);
-       } else {
-               result = aio_write (aio);
-       }
-
-       if (result == -1) {
-               WSASetLastError (errno_to_WSA (errno, "do_aio_call"));
-               return FALSE;
-       }
-
-       result = aio_error (aio);
-       if (result == 0) {
-               numbytes = aio_return (aio);
-       } else {
-               WSASetLastError (errno_to_WSA (result, "do_aio_call"));
-               return FALSE;
-       }
-
-       if (out_bytes)
-               *out_bytes = numbytes;
-
-       return TRUE;
-}
-
-gboolean _wapi_socket_async_read (gpointer handle, gpointer buffer,
-                                 guint32 numbytes,
-                                 guint32 *bytesread, gpointer ares,
-                                 SocketAsyncCB callback)
-{
-       return do_aio_call (TRUE, handle, buffer, numbytes, bytesread, ares, callback);
-}
-
-gboolean _wapi_socket_async_write (gpointer handle, gpointer buffer,
-                                 guint32 numbytes,
-                                 guint32 *byteswritten, gpointer ares,
-                                 SocketAsyncCB callback)
-{
-       return do_aio_call (FALSE, handle, buffer, numbytes, byteswritten, ares, callback);
-}
-
-#endif /* USE_AIO */
-
index 19268c9b68b8f831c46bcc2beb3372859260a9da..371c63e50d1980830134f152a55fe929679fb969 100644 (file)
@@ -49,18 +49,4 @@ extern int WSAIoctl (guint32 handle, gint32 command,
                     gchar *output, gint o_len, glong *written,
                     void *unused1, void *unused2);
 
-#ifndef PLATFORM_WIN32
-typedef void (*SocketAsyncCB) (guint32 error, guint32 numbytes, gpointer ares);
-
-gboolean _wapi_socket_async_read (gpointer handle, gpointer buffer,
-                                 guint32 numbytes,
-                                 guint32 *bytesread, gpointer ares,
-                                 SocketAsyncCB callback);
-
-gboolean _wapi_socket_async_write (gpointer handle, gpointer buffer,
-                                 guint32 numbytes,
-                                 guint32 *bytesread, gpointer ares,
-                                 SocketAsyncCB callback);
-#endif
-
 #endif /* _WAPI_SOCKETS_H_ */
index 942657911cfde104c89fa899af791552203ea4dc..5f52c1178fe41bfb4f0b69de3b745cdc335ddd3f 100644 (file)
@@ -855,21 +855,6 @@ void Sleep(guint32 ms)
        SleepEx(ms, FALSE);
 }
 
-gboolean
-BindIoCompletionCallback (gpointer handle,
-                         WapiOverlappedCB callback,
-                         guint64 flags)
-{
-       WapiHandleType type;
-       
-       type = _wapi_handle_type (handle);
-       if (type == WAPI_HANDLE_FILE || type == WAPI_HANDLE_PIPE)
-               return _wapi_io_add_callback (handle, callback, flags);
-
-       SetLastError (ERROR_NOT_SUPPORTED);
-       return FALSE;
-}
-
 guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle, 
                                        gpointer param)
 {
index b9602c8373ce0ed584ee6888fe901b291b1d94f9..996788b9d487ed822ca876c0a728663a291fdd5b 100644 (file)
@@ -55,10 +55,6 @@ extern gpointer TlsGetValue(guint32 idx);
 extern gboolean TlsSetValue(guint32 idx, gpointer value);
 extern void Sleep(guint32 ms);
 extern guint32 SleepEx(guint32 ms, gboolean alertable);
-extern gboolean BindIoCompletionCallback (gpointer handle,
-                                         WapiOverlappedCB callback,
-                                         guint64 flags);
-
 extern guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer thread_handle, 
                                        gpointer param);
 
index e4f7e276e3d9367ba34fd3635add7cdc3ec6fc82..f6a745eb7c264e180980a7379caf945d226a4ef6 100644 (file)
@@ -132,6 +132,13 @@ static void *timed_thread_start_routine(gpointer args)
        }
        
        _wapi_timed_thread_exit(thread->start_routine(thread->arg));
+
+#ifndef __GNUC__
+       /* Even though we tell gcc that this function doesn't return,
+        * other compilers won't see that.
+        */
+       return(NULL);
+#endif
 }
 
 /* Allocate a thread which can be used with timed_thread_join().