浏览代码

Fix case when handle gets unregistered just before we check whether there are arbitered waiters

Samuel Thibault 8 年之前
父节点
当前提交
bd9d103c1a
共有 2 个文件被更改,包括 34 次插入8 次删除
  1. 22 0
      src/core/dependencies/data_arbiter_concurrency.c
  2. 12 8
      src/core/dependencies/data_concurrency.c

+ 22 - 0
src/core/dependencies/data_arbiter_concurrency.c

@@ -545,9 +545,31 @@ void _starpu_notify_arbitered_dependencies(starpu_data_handle_t handle)
 #ifndef LOCK_OR_DELEGATE
 		STARPU_PTHREAD_MUTEX_UNLOCK(&arbiter->mutex);
 #endif
+
+		/* No waiter, just remove our reference */
+		_starpu_spin_lock(&handle->header_lock);
+		STARPU_ASSERT(handle->refcnt > 0);
+		handle->refcnt--;
+		STARPU_ASSERT(handle->busy_count > 0);
+		handle->busy_count--;
+		if (_starpu_data_check_not_busy(handle))
+			/* Handle was even destroyed, don't unlock it.  */
+			return;
+		_starpu_spin_unlock(&handle->header_lock);
 		return;
 	}
 
+	/* There is a waiter, remove our reference */
+	_starpu_spin_lock(&handle->header_lock);
+	STARPU_ASSERT(handle->refcnt > 0);
+	handle->refcnt--;
+	STARPU_ASSERT(handle->busy_count > 0);
+	handle->busy_count--;
+	/* There should be at least one busy_count reference for the waiter
+	 * (thus we don't risk to see the handle disappear below) */
+	STARPU_ASSERT(handle->busy_count > 0);
+	_starpu_spin_unlock(&handle->header_lock);
+
 	/* Note: we may be putting back our own requests, so avoid looping by
 	 * extracting the list */
 	struct _starpu_data_requester_list l = handle->arbitered_req_list;

+ 12 - 8
src/core/dependencies/data_concurrency.c

@@ -362,17 +362,11 @@ static unsigned unlock_one_requester(struct _starpu_data_requester *r)
 int _starpu_notify_data_dependencies(starpu_data_handle_t handle)
 {
 	_starpu_spin_checklocked(&handle->header_lock);
-	/* A data access has finished so we remove a reference. */
-	STARPU_ASSERT(handle->refcnt > 0);
-	handle->refcnt--;
-	STARPU_ASSERT(handle->busy_count > 0);
-	handle->busy_count--;
-	if (_starpu_data_check_not_busy(handle))
-		/* Handle was destroyed, nothing left to do.  */
-		return 1;
 
 	if (handle->arbiter)
 	{
+		/* Keep our reference for now, _starpu_notify_arbitered_dependencies
+		 * will drop it when it needs to */
 		STARPU_ASSERT(_starpu_data_requester_list_empty(&handle->req_list));
 		STARPU_ASSERT(_starpu_data_requester_list_empty(&handle->reduction_req_list));
 		_starpu_spin_unlock(&handle->header_lock);
@@ -381,6 +375,16 @@ int _starpu_notify_data_dependencies(starpu_data_handle_t handle)
 		/* We have already unlocked */
 		return 1;
 	}
+
+	/* A data access has finished so we remove a reference. */
+	STARPU_ASSERT(handle->refcnt > 0);
+	handle->refcnt--;
+	STARPU_ASSERT(handle->busy_count > 0);
+	handle->busy_count--;
+	if (_starpu_data_check_not_busy(handle))
+		/* Handle was destroyed, nothing left to do.  */
+		return 1;
+
 	STARPU_ASSERT(_starpu_data_requester_list_empty(&handle->arbitered_req_list));
 
 	/* In case there is a pending reduction, and that this is the last