static void handle_store(HANDLE thread)
{
+#ifdef THREAD_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION ": thread %p", thread);
+#endif
+
EnterCriticalSection(&threads_mutex);
if(threads==NULL) {
threads=g_ptr_array_new();
static void handle_remove(HANDLE thread)
{
+#ifdef THREAD_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION ": thread %p", thread);
+#endif
+
EnterCriticalSection(&threads_mutex);
g_ptr_array_remove_fast(threads, thread);
LeaveCriticalSection(&threads_mutex);
{
gboolean ret;
- /* FIXME: make sure .net's idea of INFINITE is the same as in C */
+ if(ms== -1) {
+ ms=INFINITE;
+ }
+
ret=WaitForSingleObject(thread, ms);
if(ret==WAIT_OBJECT_0) {
/* Clean up the handle */
new=(MonoThreadsSync *)g_new0(MonoThreadsSync, 1);
new->monitor=CreateMutex(NULL, FALSE, NULL);
+#ifdef THREAD_LOCK_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION ": ThreadsSync mutex created: %p",
+ new->monitor);
+#endif
new->waiters_count=0;
new->was_broadcast=FALSE;
LeaveCriticalSection(&monitor_mutex);
/* Acquire the mutex */
+#ifdef THREAD_LOCK_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION ": Acquiring monitor mutex %p",
+ mon->monitor);
+#endif
ret=WaitForSingleObject(mon->monitor, ms);
if(ret==WAIT_OBJECT_0) {
mon->count++;
mon->tid=0; /* FIXME: check that 0 isnt a valid id */
}
+#ifdef THREAD_LOCK_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION ": Releasing mutex %p", mon->monitor);
+#endif
+
ReleaseMutex(mon->monitor);
}
save_count=mon->count;
while(mon->count>1) {
+#ifdef THREAD_LOCK_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION ": Releasing mutex %p",
+ mon->monitor);
+#endif
+
ReleaseMutex(mon->monitor);
mon->count--;
}
/* We're releasing this mutex */
mon->count=0;
mon->tid=0;
+#ifdef THREAD_LOCK_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION ": Signalling monitor mutex %p",
+ mon->monitor);
+#endif
+
SignalObjectAndWait(mon->monitor, mon->sema, INFINITE, FALSE);
EnterCriticalSection(&mon->waiters_count_lock);
LeaveCriticalSection(&mon->waiters_count_lock);
if(last_waiter) {
+#ifdef THREAD_LOCK_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION ": Waiting for monitor mutex %p",
+ mon->monitor);
+#endif
SignalObjectAndWait(mon->waiters_done, mon->monitor, INFINITE, FALSE);
} else {
+#ifdef THREAD_LOCK_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION ": Waiting for monitor mutex %p",
+ mon->monitor);
+#endif
WaitForSingleObject(mon->monitor, INFINITE);
}
/* Lock the mutex the required number of times */
while(save_count>1) {
+#ifdef THREAD_LOCK_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION
+ ": Waiting for monitor mutex %p", mon->monitor);
+#endif
WaitForSingleObject(mon->monitor, INFINITE);
save_count--;
}
/* FIXME: exitContext isnt documented */
gboolean ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_handles, gint32 ms, gboolean exitContext)
{
- WapiHandle **handles;
+ HANDLE *handles;
guint32 numhandles;
guint32 ret;
guint32 i;
numhandles=mono_array_length(mono_handles);
- handles=g_new0(WapiHandle *, numhandles);
+ handles=g_new0(HANDLE, numhandles);
for(i=0; i<numhandles; i++) {
- handles[i]=mono_array_get(mono_handles, WapiHandle *, i);
+ handles[i]=mono_array_get(mono_handles, HANDLE, i);
+ }
+
+ if(ms== -1) {
+ ms=INFINITE;
}
ret=WaitForMultipleObjects(numhandles, handles, TRUE, ms);
+
+ g_free(handles);
+
if(ret==WAIT_FAILED) {
#ifdef THREAD_WAIT_DEBUG
g_message(G_GNUC_PRETTY_FUNCTION ": Wait failed");
/* FIXME: exitContext isnt documented */
gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms, gboolean exitContext)
{
- WapiHandle **handles;
+ HANDLE *handles;
guint32 numhandles;
guint32 ret;
guint32 i;
numhandles=mono_array_length(mono_handles);
- handles=g_new0(WapiHandle *, numhandles);
+ handles=g_new0(HANDLE, numhandles);
for(i=0; i<numhandles; i++) {
- handles[i]=mono_array_get(mono_handles, WapiHandle *, i);
+ handles[i]=mono_array_get(mono_handles, HANDLE, i);
}
+ if(ms== -1) {
+ ms=INFINITE;
+ }
+
ret=WaitForMultipleObjects(numhandles, handles, FALSE, ms);
+ g_free(handles);
+
#ifdef THREAD_WAIT_DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION ": returning %d", ret);
+ g_message(G_GNUC_PRETTY_FUNCTION ": returning %d", ret);
#endif
return(ret);
}
/* FIXME: exitContext isnt documented */
-gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this, WapiHandle *handle, gint32 ms, gboolean exitContext)
+gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this, HANDLE handle, gint32 ms, gboolean exitContext)
{
guint32 ret;
+#ifdef THREAD_WAIT_DEBUG
+ g_message(G_GNUC_PRETTY_FUNCTION ": waiting for %p", handle);
+#endif
+
+ if(ms== -1) {
+ ms=INFINITE;
+ }
+
ret=WaitForSingleObject(handle, ms);
if(ret==WAIT_FAILED) {
#ifdef THREAD_WAIT_DEBUG
return(TRUE);
}
+HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned,char *name) {
+ return(CreateMutex(NULL,owned,name));
+}
-void mono_thread_init(void)
+void ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ) {
+ ReleaseMutex(handle);
+}
+\r
+HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual,\r
+ MonoBoolean initial,\r
+ char *name) {\r
+ return (CreateEvent(NULL,manual,initial,name));\r
+}\r
+\r
+gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle) {\r
+ return (SetEvent(handle));\r
+}\r
+
+gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle) {\r
+ return (ResetEvent(handle));\r
+}\r
+
+void mono_thread_init(MonoDomain *domain)
{
MonoClass *thread_class;
* object? In theory, I guess the whole program should act as
* though exit() were called :-)
*/
- main_thread = mono_object_new (thread_class);
+ main_thread = mono_object_new (domain, thread_class);
InitializeCriticalSection(&threads_mutex);
InitializeCriticalSection(&monitor_mutex);
* and then the main thread should poll an event and wait for
* any terminated threads, until there are none left.
*/
- for(i=0; i<threads->len; i++) {
+#ifdef THREAD_DEBUG
+ g_message("There are %d threads to join", threads->len);
+#endif
+
+ for(i=0; i<threads->len; i+=MAXIMUM_WAIT_OBJECTS) {
for(j=0; j<MAXIMUM_WAIT_OBJECTS && i+j<threads->len; j++) {
- wait[j]=g_ptr_array_index(threads, i);
+#ifdef THREAD_DEBUG
+ g_message("Waiting for threads %d in slot %d", i+j, j);
+#endif
+ wait[j]=g_ptr_array_index(threads, i+j);
}
+#ifdef THREAD_DEBUG
+ g_message("%d threads to wait for in this batch", j);
+#endif
+
WaitForMultipleObjects(j, wait, TRUE, INFINITE);
}