#ifdef HAVE_SEMAPHORE_H
#include <semaphore.h>
#endif
+#include <errno.h>
#include <mono/io-layer/processes.h>
static pthread_key_t timed_thread_key;
static mono_once_t timed_thread_once = MONO_ONCE_INIT;
+static mono_mutex_t apc_mutex;
+
static void timed_thread_init(void)
{
thr_ret = pthread_key_create(&timed_thread_key, NULL);
g_assert (thr_ret == 0);
+
+ thr_ret = mono_mutex_init(&apc_mutex, NULL);
+ g_assert (thr_ret == 0);
}
void _wapi_timed_thread_exit(guint32 exitstatus)
}
thread=(TimedThread *)specific;
+
+ if(thread->exit_routine!=NULL) {
+ thread->exit_routine(exitstatus, thread->exit_userdata);
+ }
pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
(void *)&thread->join_mutex);
thread->exitstatus=exitstatus;
thread->exiting=TRUE;
-
- if(thread->exit_routine!=NULL) {
- thread->exit_routine(exitstatus, thread->exit_userdata);
- }
thr_ret = pthread_cond_signal(&thread->exit_cond);
g_assert (thr_ret == 0);
thread->exit_userdata = exit_userdata;
thread->exitstatus = 0;
thread->exiting = FALSE;
+ thread->apc_queue = NULL;
*threadp = thread;
thr_ret = pthread_cond_init(&thread->exit_cond, NULL);
g_assert (thr_ret == 0);
- thr_ret = sem_init (&thread->suspend_sem, 0, 0);
+ thr_ret = MONO_SEM_INIT (&thread->suspend_sem, 0);
g_assert (thr_ret != -1);
- thr_ret = sem_init (&thread->suspended_sem, 0, 0);
+ thr_ret = MONO_SEM_INIT (&thread->suspended_sem, 0);
g_assert (thr_ret != -1);
thread->exit_routine = exit_routine;
if(exitstatus!=NULL) {
*exitstatus = thread->exitstatus;
}
+
+ _wapi_timed_thread_destroy (thread);
}
return(result);
}
exit (-1);
}
- MONO_SEM_WAIT (&thread->suspend_sem);
+ while (MONO_SEM_WAIT (&thread->suspend_sem) != 0 && errno == EINTR);
}
void _wapi_timed_thread_resume (TimedThread *thread)
{
MONO_SEM_POST (&thread->suspend_sem);
}
+
+void _wapi_timed_thread_queue_apc (TimedThread *thread,
+ guint32 (*apc_callback)(gpointer), gpointer param)
+{
+ ApcInfo *apc;
+ int thr_ret;
+
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&apc_mutex);
+ thr_ret = mono_mutex_lock(&apc_mutex);
+ g_assert (thr_ret == 0);
+
+ apc = (ApcInfo *)g_new(ApcInfo, 1);
+ apc->callback = apc_callback;
+ apc->param = param;
+ thread->apc_queue = g_slist_append (thread->apc_queue, apc);
+
+ thr_ret = mono_mutex_unlock(&apc_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+}
+
+gboolean _wapi_timed_thread_apc_pending (TimedThread *thread)
+{
+ return thread->apc_queue != NULL;
+}
+
+void _wapi_timed_thread_dispatch_apc_queue (TimedThread *thread)
+{
+ ApcInfo* apc;
+ GSList *list;
+ int thr_ret;
+
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&apc_mutex);
+ thr_ret = mono_mutex_lock(&apc_mutex);
+ g_assert (thr_ret == 0);
+
+ list = thread->apc_queue;
+ thread->apc_queue = NULL;
+
+ thr_ret = mono_mutex_unlock(&apc_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ while (list != NULL) {
+ apc = (ApcInfo*)list->data;
+ apc->callback (apc->param);
+ g_free (apc);
+ list = g_slist_next (list);
+ }
+ g_slist_free (list);
+}
+