2
0
Эх сурвалжийг харах

2002-03-21 Dick Porter <[email protected]>

	* semaphores.c: Fix a problem when waiting for one or more
	semaphores, and another semaphore is Released (all waiting
	semaphores assumed they were signalled)

svn path=/trunk/mono/; revision=3257
Dick Porter 24 жил өмнө
parent
commit
0e7a3aabca

+ 6 - 0
mono/io-layer/ChangeLog

@@ -1,3 +1,9 @@
+2002-03-21  Dick Porter  <[email protected]>
+
+	* semaphores.c: Fix a problem when waiting for one or more
+	semaphores, and another semaphore is Released (all waiting
+	semaphores assumed they were signalled)
+
 2002-03-29  Dan Lewis <[email protected]>
 
 	* io.h, io.c, uglify.h: added MoveFile, CopyFile, CreateDirectory,

+ 78 - 2
mono/io-layer/semaphores.c

@@ -69,11 +69,19 @@ static gboolean sema_wait(WapiHandle *handle, WapiHandle *signal, guint32 ms)
 	int ret;
 	
 	mono_mutex_lock(&sem_mutex);
+
+#ifdef DEBUG
+	g_message(G_GNUC_PRETTY_FUNCTION ": Sem %p val %d ms %d", handle,
+		  sem_handle->val, ms);
+#endif
 	
 	/* Signal this handle after we have obtained the semaphore
 	 * global lock
 	 */
 	if(signal!=NULL) {
+#ifdef DEBUG
+		g_message(G_GNUC_PRETTY_FUNCTION ": signalling %p", signal);
+#endif
 		signal->ops->signal(signal);
 	}
 	
@@ -98,16 +106,63 @@ static gboolean sema_wait(WapiHandle *handle, WapiHandle *signal, guint32 ms)
 	}
 	
 	if(ms==INFINITE) {
+#ifdef DEBUG
+		g_message(G_GNUC_PRETTY_FUNCTION ": wait for %p INFINITE",
+			  sem_handle);
+#endif
+	try_again_infinite:
 		ret=mono_cond_wait(&sem_cond, &sem_mutex);
-		waited=TRUE;
+		if(ret==0) {
+			/* See if we were signalled (it might have been
+			 * another semaphore)
+			 */
+			if(sem_handle->val>0) {
+#ifdef DEBUG
+				g_message(G_GNUC_PRETTY_FUNCTION
+					  ": sem %p has been signalled",
+					  sem_handle);
+#endif
+			 	waited=TRUE;
+			} else {
+#ifdef DEBUG
+				g_message(G_GNUC_PRETTY_FUNCTION
+					  ": sem %p not signalled",
+					  sem_handle);
+#endif
+				goto try_again_infinite;
+			}
+		}
 	} else {
 		struct timespec timeout;
 
+#ifdef DEBUG
+		g_message(G_GNUC_PRETTY_FUNCTION ": wait for %p for %d ms",
+			  sem_handle, ms);
+#endif
+
 		_wapi_calc_timeout(&timeout, ms);
 		
+	try_again_timed:
 		ret=mono_cond_timedwait(&sem_cond, &sem_mutex, &timeout);
 		if(ret==0) {
-			waited=TRUE;
+			/* See if we were signalled (it might have been
+			 * another semaphore)
+			 */
+			if(sem_handle->val>0) {
+#ifdef DEBUG
+				g_message(G_GNUC_PRETTY_FUNCTION
+					  ": sem %p has been signalled",
+					  sem_handle);
+#endif
+				waited=TRUE;
+			} else {
+#ifdef DEBUG
+				g_message(G_GNUC_PRETTY_FUNCTION
+					  ": sem %p not signalled",
+					  sem_handle);
+#endif
+				goto try_again_timed;
+			}
 		} else {
 			/* ret might be ETIMEDOUT for timeout, or
 			 * other for error */
@@ -118,7 +173,18 @@ static gboolean sema_wait(WapiHandle *handle, WapiHandle *signal, guint32 ms)
 end:
 	if(waited==TRUE) {
 		sem_handle->val--;
+#ifdef DEBUG
+		g_message(G_GNUC_PRETTY_FUNCTION
+			  ": Waited TRUE, sem %p val now %d", sem_handle,
+			  sem_handle->val);
+#endif
 	}
+#ifdef DEBUG
+	else {
+		g_message(G_GNUC_PRETTY_FUNCTION ": Waited FALSE, sem %p",
+			  sem_handle);
+	}
+#endif
 	
 	mono_mutex_unlock(&sem_mutex);
 	return(waited);
@@ -332,6 +398,11 @@ gboolean ReleaseSemaphore(WapiHandle *handle, gint32 count, gint32 *prevcount)
 	
 	
 	mono_mutex_lock(&sem_mutex);
+
+#ifdef DEBUG
+	g_message(G_GNUC_PRETTY_FUNCTION ": sem %p val %d count %d",
+		  sem_handle, sem_handle->val, count);
+#endif
 	
 	/* Do this before checking for count overflow, because overflowing max
 	 * is a listed technique for finding the current value
@@ -353,6 +424,11 @@ gboolean ReleaseSemaphore(WapiHandle *handle, gint32 count, gint32 *prevcount)
 	sem_handle->val+=count;
 	pthread_cond_broadcast(&sem_cond);
 	ret=TRUE;
+
+#ifdef DEBUG
+	g_message(G_GNUC_PRETTY_FUNCTION ": sem %p val now %d", sem_handle,
+		  sem_handle->val);
+#endif
 	
 end:
 	mono_mutex_unlock(&sem_mutex);

+ 3 - 2
mono/io-layer/wait.c

@@ -354,8 +354,9 @@ guint32 WaitForSingleObject(WapiHandle *handle, guint32 timeout)
 	if(wait==TRUE) {
 		/* Object signalled before timeout expired */
 #ifdef DEBUG
-		g_message(G_GNUC_PRETTY_FUNCTION ": Object %p signalled",
-			  handle);
+		g_message(G_GNUC_PRETTY_FUNCTION
+			  ": Object %p (type %d) signalled", handle,
+			  handle->type);
 #endif
 		return(WAIT_OBJECT_0);
 	} else {