#include <mono/os/gc_wrapper.h>
#include "mono/utils/mono-hash.h"
#endif
+#include <stdio.h>
#include <glib.h>
#include <string.h>
#include <pthread.h>
#include <mono/io-layer/thread-private.h>
#include <mono/io-layer/mono-spinlock.h>
+#if HAVE_VALGRIND_MEMCHECK_H
+#include <valgrind/memcheck.h>
+#endif
+
#undef DEBUG
#undef TLS_DEBUG
g_assert (thr_ret == 0);
/* defaults of 2Mb for 32bits and 4Mb for 64bits */
- if (stacksize == 0)
- stacksize = (SIZEOF_VOID_P / 2) * 1024 *1024;
+ if (stacksize == 0){
+#if HAVE_VALGRIND_MEMCHECK_H
+ if (RUNNING_ON_VALGRIND)
+ stacksize = 1 << 20;
+ else
+ stacksize = (SIZEOF_VOID_P / 2) * 1024 * 1024;
+#else
+ stacksize = (SIZEOF_VOID_P / 2) * 1024 * 1024;
+#endif
+
+ }
#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
thr_ret = pthread_attr_setstacksize(&attr, stacksize);
}
/**
- * Sleep:
+ * SleepEx:
* @ms: The time in milliseconds to suspend for
+ * @alertable: if TRUE, the wait can be interrupted by an APC call
*
* Suspends execution of the current thread for @ms milliseconds. A
* value of zero causes the thread to relinquish its time slice. A
* value of %INFINITE causes an infinite delay.
*/
-void Sleep(guint32 ms)
+guint32 SleepEx(guint32 ms, gboolean alertable)
{
struct timespec req, rem;
int ms_quot, ms_rem;
int ret;
+ gpointer current_thread = NULL;
#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION ": Sleeping for %d ms", ms);
#endif
+ if (alertable) {
+ current_thread = GetCurrentThread ();
+ if (_wapi_thread_apc_pending (current_thread)) {
+ _wapi_thread_dispatch_apc_queue (current_thread);
+ return WAIT_IO_COMPLETION;
+ }
+ }
+
if(ms==0) {
sched_yield();
- return;
+ return 0;
}
/* FIXME: check for INFINITE and sleep forever */
again:
ret=nanosleep(&req, &rem);
+
+ if (alertable && _wapi_thread_apc_pending (current_thread)) {
+ _wapi_thread_dispatch_apc_queue (current_thread);
+ return WAIT_IO_COMPLETION;
+ }
+
if(ret==-1) {
/* Sleep interrupted with rem time remaining */
#ifdef DEBUG
req=rem;
goto again;
}
+
+ return 0;
}
-/* FIXME: implement alertable */
-void SleepEx(guint32 ms, gboolean alertable)
+void Sleep(guint32 ms)
{
- if(alertable==TRUE) {
- g_warning(G_GNUC_PRETTY_FUNCTION ": alertable not implemented");
- }
-
- Sleep(ms);
+ SleepEx(ms, FALSE);
}
gboolean
return FALSE;
}
+guint32 QueueUserAPC (WapiApcProc apc_callback, gpointer handle,
+ gpointer param)
+{
+ struct _WapiHandle_thread *thread_handle;
+ struct _WapiHandlePrivate_thread *thread_private_handle;
+ gboolean ok;
+
+ ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
+ (gpointer *)&thread_handle,
+ (gpointer *)&thread_private_handle);
+ if(ok==FALSE) {
+ g_warning (G_GNUC_PRETTY_FUNCTION
+ ": error looking up thread handle %p", handle);
+ return(0);
+ }
+
+ _wapi_timed_thread_queue_apc (thread_private_handle->thread,
+ apc_callback, param);
+ return(1);
+}
+
+gboolean _wapi_thread_cur_apc_pending (void)
+{
+ return _wapi_thread_apc_pending (GetCurrentThread ());
+}
+
+gboolean _wapi_thread_apc_pending (gpointer handle)
+{
+ struct _WapiHandle_thread *thread_handle;
+ struct _WapiHandlePrivate_thread *thread_private_handle;
+ gboolean ok;
+
+ ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
+ (gpointer *)&thread_handle,
+ (gpointer *)&thread_private_handle);
+ if(ok==FALSE) {
+ g_warning (G_GNUC_PRETTY_FUNCTION
+ ": error looking up thread handle %p", handle);
+ return(FALSE);
+ }
+
+ return _wapi_timed_thread_apc_pending (thread_private_handle->thread);
+}
+
+gboolean _wapi_thread_dispatch_apc_queue (gpointer handle)
+{
+ struct _WapiHandle_thread *thread_handle;
+ struct _WapiHandlePrivate_thread *thread_private_handle;
+ gboolean ok;
+
+ ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
+ (gpointer *)&thread_handle,
+ (gpointer *)&thread_private_handle);
+ if(ok==FALSE) {
+ g_warning (G_GNUC_PRETTY_FUNCTION
+ ": error looking up thread handle %p", handle);
+ return(0);
+ }
+
+ _wapi_timed_thread_dispatch_apc_queue (thread_private_handle->thread);
+ return(1);
+}
+
+
+
#ifdef WITH_INCLUDED_LIBGC
static void GC_suspend_handler (int sig)