Author: dick
Date: 2007-06-13 05:15:08 -0400 (Wed, 13 Jun 2007)
New Revision: 79386
Modified:
trunk/mono/mono/io-layer/ChangeLog
trunk/mono/mono/io-layer/handles-private.h
trunk/mono/mono/io-layer/handles.c
trunk/mono/mono/io-layer/thread-private.h
trunk/mono/mono/io-layer/threads.c
trunk/mono/mono/io-layer/uglify.h
trunk/mono/mono/io-layer/wait.c
Log:
2007-06-13 Dick Porter <[EMAIL PROTECTED]>
* handles.c (timedwait_signal_wait_cond): Alertable waits on
private handles are now interrupted by signalling the same
condition that would end the wait if the handle became signalled,
rather than polling. (Shared handles still have to poll.)
* threads.c (_wapi_thread_queue_apc): Interrupt the thread if it's
waiting on a handle
* handles-private.h (_wapi_handle_current_thread_set_waiting_on):
Helper functions to inform the APC queuing functions when threads
are waiting for handles, and to interrupt the wait.
* wait.c (WaitForMultipleObjectsEx): Need to tell the handle
waiting functions if any of the handles in question are shared
Modified: trunk/mono/mono/io-layer/ChangeLog
===================================================================
--- trunk/mono/mono/io-layer/ChangeLog 2007-06-13 08:26:44 UTC (rev 79385)
+++ trunk/mono/mono/io-layer/ChangeLog 2007-06-13 09:15:08 UTC (rev 79386)
@@ -1,3 +1,20 @@
+2007-06-13 Dick Porter <[EMAIL PROTECTED]>
+
+ * handles.c (timedwait_signal_wait_cond): Alertable waits on
+ private handles are now interrupted by signalling the same
+ condition that would end the wait if the handle became signalled,
+ rather than polling. (Shared handles still have to poll.)
+
+ * threads.c (_wapi_thread_queue_apc): Interrupt the thread if it's
+ waiting on a handle
+
+ * handles-private.h (_wapi_handle_current_thread_set_waiting_on):
+ Helper functions to inform the APC queuing functions when threads
+ are waiting for handles, and to interrupt the wait.
+
+ * wait.c (WaitForMultipleObjectsEx): Need to tell the handle
+ waiting functions if any of the handles in question are shared
+
2007-06-06 Miguel de Icaza <[EMAIL PROTECTED]>
* processes.c (is_managed_binary): Fix for OSX.
Modified: trunk/mono/mono/io-layer/handles-private.h
===================================================================
--- trunk/mono/mono/io-layer/handles-private.h 2007-06-13 08:26:44 UTC (rev
79385)
+++ trunk/mono/mono/io-layer/handles-private.h 2007-06-13 09:15:08 UTC (rev
79386)
@@ -35,6 +35,7 @@
extern struct _WapiFileShareLayout *_wapi_fileshare_layout;
extern guint32 _wapi_fd_reserve;
+extern mono_mutex_t _wapi_alertable_mutex;
extern mono_mutex_t _wapi_global_signal_mutex;
extern pthread_cond_t _wapi_global_signal_cond;
extern int _wapi_sem_id;
@@ -77,8 +78,9 @@
guint32 *lowest);
extern void _wapi_handle_unlock_handles (guint32 numhandles,
gpointer *handles);
-extern int _wapi_handle_wait_signal (void);
-extern int _wapi_handle_timedwait_signal (struct timespec *timeout);
+extern int _wapi_handle_wait_signal (gboolean shared);
+extern int _wapi_handle_timedwait_signal (struct timespec *timeout,
+ gboolean shared);
extern int _wapi_handle_wait_signal_handle (gpointer handle, gboolean
alertable);
extern int _wapi_handle_timedwait_signal_handle (gpointer handle,
struct timespec *timeout,
gboolean alertable);
@@ -169,6 +171,97 @@
}
}
+static inline void _wapi_handle_current_thread_set_waiting_on (gpointer
waiting_on)
+{
+ gpointer current_thread = _wapi_thread_handle_from_id (pthread_self ());
+ struct _WapiHandle_thread *thread;
+ gboolean ok;
+ int thr_ret;
+
+ if (current_thread == NULL) {
+ return;
+ }
+
+ if (_WAPI_SHARED_HANDLE(_wapi_handle_type (waiting_on))) {
+ /* We can't signal shared handles with pthreads, so
+ * just ignore it here so the problem won't arise
+ */
+ return;
+ }
+
+ ok = _wapi_lookup_handle (current_thread, WAPI_HANDLE_THREAD,
+ (gpointer *)&thread);
+ if (ok == FALSE) {
+ return;
+ }
+
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&_wapi_alertable_mutex);
+ thr_ret = mono_mutex_lock (&_wapi_alertable_mutex);
+ g_assert (thr_ret == 0);
+
+ thread->waiting_on = waiting_on;
+
+ thr_ret = mono_mutex_unlock (&_wapi_alertable_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+}
+
+static inline void _wapi_handle_trip_signal (gpointer handle)
+{
+ guint32 idx = GPOINTER_TO_UINT(handle);
+ struct _WapiHandleUnshared *handle_data;
+ int thr_ret;
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ /* Tell everyone blocking on multiple handles that
+ * something was signalled
+ */
+ pthread_cleanup_push ((void(*)(void
*))mono_mutex_unlock_in_cleanup, (void *)&_wapi_global_signal_mutex);
+ thr_ret = mono_mutex_lock (&_wapi_global_signal_mutex);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_cond_broadcast (&_wapi_global_signal_cond);
+ g_assert (thr_ret == 0);
+
+ thr_ret = mono_mutex_unlock (&_wapi_global_signal_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ return;
+ }
+
+ /* handle must be a valid private handle then */
+ if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
+ return;
+ }
+
+ g_assert (!_WAPI_SHARED_HANDLE(_wapi_handle_type (handle)));
+
+ handle_data = &_WAPI_PRIVATE_HANDLES(idx);
+
+#ifdef DEBUG
+ g_message ("%s: tripping condition of %p", __func__, handle);
+#endif
+
+ /* Tell everyone blocking on a single handle */
+
+ /* This function _must_ be called with handle->signal_mutex
+ * unlocked
+ */
+
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
(void *)&handle_data->signal_mutex);
+ thr_ret = mono_mutex_lock (&handle_data->signal_mutex);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_cond_broadcast (&handle_data->signal_cond);
+ g_assert (thr_ret == 0);
+
+ thr_ret = mono_mutex_unlock (&handle_data->signal_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+}
+
static inline void _wapi_shared_handle_set_signal_state (gpointer handle,
gboolean state)
{
Modified: trunk/mono/mono/io-layer/handles.c
===================================================================
--- trunk/mono/mono/io-layer/handles.c 2007-06-13 08:26:44 UTC (rev 79385)
+++ trunk/mono/mono/io-layer/handles.c 2007-06-13 09:15:08 UTC (rev 79386)
@@ -106,6 +106,7 @@
guint32 _wapi_fd_reserve;
+mono_mutex_t _wapi_alertable_mutex;
mono_mutex_t _wapi_global_signal_mutex;
pthread_cond_t _wapi_global_signal_cond;
@@ -220,6 +221,9 @@
thr_ret = mono_mutex_init(&_wapi_global_signal_mutex, NULL);
g_assert (thr_ret == 0);
+ thr_ret = mono_mutex_init (&_wapi_alertable_mutex, NULL);
+ g_assert (thr_ret == 0);
+
/* Using g_atexit here instead of an explicit function call in
* a cleanup routine lets us cope when a third-party library
* calls exit (eg if an X client loses the connection to its
@@ -1401,47 +1405,76 @@
}
}
-static int timedwait_signal_poll_cond (pthread_cond_t *cond, mono_mutex_t
*mutex, struct timespec *timeout, gboolean alertable)
+static int timedwait_signal_wait_cond (pthread_cond_t *cond, mono_mutex_t
*mutex, struct timespec *timeout, gboolean alertable, gpointer waiting_on)
{
- struct timespec fake_timeout;
int ret;
- if (!alertable) {
- if (timeout)
- ret=mono_cond_timedwait (cond, mutex, timeout);
- else
- ret=mono_cond_wait (cond, mutex);
+#ifdef DEBUG
+ g_message ("%s: %s wait on %p", __func__,
alertable?"Alertable":"Non-alertable", waiting_on);
+#endif
+
+ if (alertable && waiting_on != NULL) {
+ /* set up the object that can interrupt us */
+ _wapi_handle_current_thread_set_waiting_on (waiting_on);
+ }
+
+ if (timeout) {
+ ret = mono_cond_timedwait (cond, mutex, timeout);
} else {
- _wapi_calc_timeout (&fake_timeout, 100);
+ ret = mono_cond_wait (cond, mutex);
+ }
- if (timeout != NULL && ((fake_timeout.tv_sec > timeout->tv_sec)
||
-
(fake_timeout.tv_sec == timeout->tv_sec &&
-
fake_timeout.tv_nsec > timeout->tv_nsec))) {
- /* Real timeout is less than 100ms time */
- ret=mono_cond_timedwait (cond, mutex, timeout);
- } else {
- ret=mono_cond_timedwait (cond, mutex, &fake_timeout);
+ if (alertable && waiting_on != NULL) {
+ /* Unset the object that can interrupt us */
+ _wapi_handle_current_thread_set_waiting_on (NULL);
+ }
+
+ return(ret);
+}
- /* Mask the fake timeout, this will cause
- * another poll if the cond was not really signaled
+static int timedwait_signal_poll (gpointer handle, struct timespec *timeout)
+{
+ if (timeout != NULL) {
+ struct timespec fake_timeout;
+ _wapi_calc_timeout (&fake_timeout, 100);
+
+ if ((fake_timeout.tv_sec > timeout->tv_sec) ||
+ (fake_timeout.tv_sec == timeout->tv_sec &&
+ fake_timeout.tv_nsec > timeout->tv_nsec)) {
+ /* FIXME: Real timeout is less than 100ms
+ * time, but is it really worth calculating to
+ * the exact ms?
*/
- if (ret==ETIMEDOUT) {
- ret=0;
+ _wapi_handle_spin (100);
+
+ if (handle != INVALID_HANDLE_VALUE &&
+ WAPI_SHARED_HANDLE_DATA(handle).signalled == TRUE) {
+ return (0);
+ } else {
+ return (ETIMEDOUT);
}
}
}
-
- return(ret);
+ _wapi_handle_spin (100);
+ return(0);
}
-int _wapi_handle_wait_signal (void)
+int _wapi_handle_wait_signal (gboolean shared)
{
- return timedwait_signal_poll_cond (&_wapi_global_signal_cond,
&_wapi_global_signal_mutex, NULL, TRUE);
+ if (shared) {
+ return(timedwait_signal_poll (INVALID_HANDLE_VALUE, NULL));
+ } else {
+ return(timedwait_signal_wait_cond (&_wapi_global_signal_cond,
&_wapi_global_signal_mutex, NULL, TRUE, INVALID_HANDLE_VALUE));
+ }
}
-int _wapi_handle_timedwait_signal (struct timespec *timeout)
+int _wapi_handle_timedwait_signal (struct timespec *timeout, gboolean shared)
{
- return timedwait_signal_poll_cond (&_wapi_global_signal_cond,
&_wapi_global_signal_mutex, timeout, TRUE);
+ if (shared) {
+ return(timedwait_signal_poll (INVALID_HANDLE_VALUE, timeout));
+ } else {
+ return(timedwait_signal_wait_cond (&_wapi_global_signal_cond,
&_wapi_global_signal_mutex, timeout, TRUE, INVALID_HANDLE_VALUE));
+ }
}
int _wapi_handle_wait_signal_handle (gpointer handle, gboolean alertable)
@@ -1465,32 +1498,10 @@
if (WAPI_SHARED_HANDLE_DATA(handle).signalled == TRUE) {
return (0);
}
- if (timeout != NULL) {
- struct timespec fake_timeout;
- _wapi_calc_timeout (&fake_timeout, 100);
-
- if ((fake_timeout.tv_sec > timeout->tv_sec) ||
- (fake_timeout.tv_sec == timeout->tv_sec &&
- fake_timeout.tv_nsec > timeout->tv_nsec)) {
- /* FIXME: Real timeout is less than
- * 100ms time, but is it really worth
- * calculating to the exact ms?
- */
- _wapi_handle_spin (100);
-
- if (WAPI_SHARED_HANDLE_DATA(handle).signalled
== TRUE) {
- return (0);
- } else {
- return (ETIMEDOUT);
- }
- }
- }
- _wapi_handle_spin (100);
- return (0);
-
+ return(timedwait_signal_poll (handle, timeout));
} else {
guint32 idx = GPOINTER_TO_UINT(handle);
- return timedwait_signal_poll_cond
(&_WAPI_PRIVATE_HANDLES(idx).signal_cond,
&_WAPI_PRIVATE_HANDLES(idx).signal_mutex, timeout, alertable);
+ return timedwait_signal_wait_cond
(&_WAPI_PRIVATE_HANDLES(idx).signal_cond,
&_WAPI_PRIVATE_HANDLES(idx).signal_mutex, timeout, alertable, handle);
}
}
Modified: trunk/mono/mono/io-layer/thread-private.h
===================================================================
--- trunk/mono/mono/io-layer/thread-private.h 2007-06-13 08:26:44 UTC (rev
79385)
+++ trunk/mono/mono/io-layer/thread-private.h 2007-06-13 09:15:08 UTC (rev
79386)
@@ -59,6 +59,7 @@
guint32 (*start_routine)(gpointer arg);
gpointer start_arg;
GSList *apc_queue;
+ gpointer waiting_on;
};
typedef struct
Modified: trunk/mono/mono/io-layer/threads.c
===================================================================
--- trunk/mono/mono/io-layer/threads.c 2007-06-13 08:26:44 UTC (rev 79385)
+++ trunk/mono/mono/io-layer/threads.c 2007-06-13 09:15:08 UTC (rev 79386)
@@ -1059,6 +1059,23 @@
thr_ret = mono_mutex_unlock (&apc_mutex);
g_assert (thr_ret == 0);
pthread_cleanup_pop (0);
+
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&_wapi_alertable_mutex);
+ thr_ret = mono_mutex_lock (&_wapi_alertable_mutex);
+ g_assert (thr_ret == 0);
+
+ if (thread->waiting_on != NULL) {
+ /* this thread is in an alertable wait, so trip the
+ * pthread_cond_t of the object the thread is waiting
+ * on so wait will be interrupted
+ */
+ _wapi_handle_trip_signal (thread->waiting_on);
+ }
+
+ thr_ret = mono_mutex_unlock (&_wapi_alertable_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
}
gboolean _wapi_thread_apc_pending (gpointer handle)
Modified: trunk/mono/mono/io-layer/uglify.h
===================================================================
--- trunk/mono/mono/io-layer/uglify.h 2007-06-13 08:26:44 UTC (rev 79385)
+++ trunk/mono/mono/io-layer/uglify.h 2007-06-13 09:15:08 UTC (rev 79386)
@@ -31,6 +31,7 @@
typedef gint32 LONG;
typedef guint32 ULONG;
typedef gint32 *PLONG;
+typedef guint32 *ULONG_PTR;
typedef guint64 LONGLONG;
typedef gunichar2 TCHAR;
typedef size_t SIZE_T;
Modified: trunk/mono/mono/io-layer/wait.c
===================================================================
--- trunk/mono/mono/io-layer/wait.c 2007-06-13 08:26:44 UTC (rev 79385)
+++ trunk/mono/mono/io-layer/wait.c 2007-06-13 09:15:08 UTC (rev 79386)
@@ -539,7 +539,7 @@
gboolean alertable)
{
GHashTable *dups;
- gboolean duplicate = FALSE, bogustype = FALSE, done;
+ gboolean duplicate = FALSE, bogustype = FALSE, done, have_shared =
FALSE;
guint32 count, lowest;
struct timespec abstime;
guint i;
@@ -602,6 +602,10 @@
bogustype = TRUE;
}
+ if (_WAPI_SHARED_HANDLE (_wapi_handle_type (handles[i]))) {
+ have_shared = TRUE;
+ }
+
g_hash_table_insert (dups, handles[i], handles[i]);
_wapi_handle_ops_prewait (handles[i]);
}
@@ -672,9 +676,9 @@
g_assert (thr_ret == 0);
if (timeout == INFINITE) {
- ret = _wapi_handle_wait_signal ();
+ ret = _wapi_handle_wait_signal (have_shared);
} else {
- ret = _wapi_handle_timedwait_signal (&abstime);
+ ret = _wapi_handle_timedwait_signal (&abstime,
have_shared);
}
#ifdef DEBUG
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches