Skip to content

Commit

Permalink
Fix existing tsan detected errors
Browse files Browse the repository at this point in the history
  • Loading branch information
sherry-yuan committed Feb 4, 2022
1 parent 72cc521 commit 9f5a3c7
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 71 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tsan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
- name: test runtime
run: |
cd build
ctest -v
ctest -R acl_test -v
- name: tsan result
uses: actions/upload-artifact@v2
Expand Down
141 changes: 71 additions & 70 deletions test/acl_command_queue_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,73 @@ static void CL_CALLBACK notify_me(const char *errinfo, const void *private_info,
private_info = private_info; // avoid warning on windows
}

MT_TEST(acl_command_queue, after_context_release) {
acl_set_allow_invalid_type<cl_command_queue>(1);
// OpenCL 1.0 conformance_test_multiples will release the command queues
// after the underlying contexts are gone.

cl_int status;
cl_context context = clCreateContext(0, 1, &m_device[0], 0, 0, &status);
CHECK_EQUAL(CL_SUCCESS, status);
ACL_LOCKED(CHECK(acl_context_is_valid(context)));

status = 42;
cl_command_queue cq0 = clCreateCommandQueue(context, m_device[0], 0, &status);
CHECK(cq0);
CHECK_EQUAL(CL_SUCCESS, status);

status = 95;
cl_command_queue cq1 = clCreateCommandQueue(context, m_device[0], 0, &status);
CHECK(cq1);
CHECK_EQUAL(CL_SUCCESS, status);

// wait until all threads have their context and command queues before
// continuing so that releasing them below won't cause them to be
// immediately reused for another thread
syncThreads();

// Early release of the context!
CHECK_EQUAL(CL_SUCCESS, clReleaseContext(context));

CHECK(cq0);
CHECK_EQUAL(1, acl_ref_count(cq0));
CHECK(cq1);
CHECK_EQUAL(1, acl_ref_count(cq1));

// Should be able to clFinish if there are no commands enqueued.
CHECK_EQUAL(CL_SUCCESS, clFinish(cq0));
CHECK_EQUAL(CL_SUCCESS, clFinish(cq1));
// Should be able to clFlush if there are no commands enqueued.
CHECK_EQUAL(CL_SUCCESS, clFlush(cq0));
CHECK_EQUAL(CL_SUCCESS, clFlush(cq1));

// Should be able to retain....
CHECK_EQUAL(CL_SUCCESS, clRetainCommandQueue(cq0));
CHECK_EQUAL(CL_SUCCESS, clRetainCommandQueue(cq1));
CHECK_EQUAL(2, acl_ref_count(cq0));
CHECK_EQUAL(2, acl_ref_count(cq1));

// Should be able to release...
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq0));
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq1));
CHECK_EQUAL(1, acl_ref_count(cq0));
CHECK_EQUAL(1, acl_ref_count(cq1));

// Should be able to release all the way.
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq0));
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq1));
// Should not access an object after it is freed
// CHECK_EQUAL(0, acl_ref_count(cq0));
// CHECK_EQUAL(0, acl_ref_count(cq1));

// ACL_LOCKED(CHECK(!acl_command_queue_is_valid(cq0)));
// ACL_LOCKED(CHECK(!acl_command_queue_is_valid(cq1)));

// And once it's gone, it's gone.
// CHECK_EQUAL(CL_INVALID_COMMAND_QUEUE, clReleaseCommandQueue(cq0));
// CHECK_EQUAL(CL_INVALID_COMMAND_QUEUE, clReleaseCommandQueue(cq1));
}

MT_TEST(acl_command_queue, create) {
acl_set_allow_invalid_type<cl_command_queue>(1);
cl_int status;
Expand Down Expand Up @@ -387,8 +454,8 @@ MT_TEST(acl_command_queue, create_with_properties) {
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq));
CHECK_EQUAL(1, acl_ref_count(cq));
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq));
CHECK_EQUAL(0, acl_ref_count(cq));
ACL_LOCKED(CHECK(!acl_command_queue_is_valid(cq)));
// CHECK_EQUAL(0, acl_ref_count(cq));
// ACL_LOCKED(CHECK(!acl_command_queue_is_valid(cq)));

// wait until all threads do their checks on the 0-ref-count command
// queue before starting the next iteration of the loop and creating new
Expand Down Expand Up @@ -421,8 +488,8 @@ MT_TEST(acl_command_queue, create_with_properties) {
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq));
CHECK_EQUAL(1, acl_ref_count(cq));
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq));
CHECK_EQUAL(0, acl_ref_count(cq));
ACL_LOCKED(CHECK(!acl_command_queue_is_valid(cq)));
// CHECK_EQUAL(0, acl_ref_count(cq));
// ACL_LOCKED(CHECK(!acl_command_queue_is_valid(cq)));

// wait until all threads do their checks on the 0-ref-count command
// queue before starting the next iteration of the loop and creating new
Expand Down Expand Up @@ -619,72 +686,6 @@ MT_TEST(acl_command_queue, set_prop) {
}
#endif

MT_TEST(acl_command_queue, after_context_release) {
acl_set_allow_invalid_type<cl_command_queue>(1);
// OpenCL 1.0 conformance_test_multiples will release the command queues
// after the underlying contexts are gone.

cl_int status;
cl_context context = clCreateContext(0, 1, &m_device[0], 0, 0, &status);
CHECK_EQUAL(CL_SUCCESS, status);
ACL_LOCKED(CHECK(acl_context_is_valid(context)));

status = 42;
cl_command_queue cq0 = clCreateCommandQueue(context, m_device[0], 0, &status);
CHECK(cq0);
CHECK_EQUAL(CL_SUCCESS, status);

status = 95;
cl_command_queue cq1 = clCreateCommandQueue(context, m_device[0], 0, &status);
CHECK(cq1);
CHECK_EQUAL(CL_SUCCESS, status);

// wait until all threads have their context and command queues before
// continuing so that releasing them below won't cause them to be
// immediately reused for another thread
syncThreads();

// Early release of the context!
CHECK_EQUAL(CL_SUCCESS, clReleaseContext(context));

CHECK(cq0);
CHECK_EQUAL(1, acl_ref_count(cq0));
CHECK(cq1);
CHECK_EQUAL(1, acl_ref_count(cq1));

// Should be able to clFinish if there are no commands enqueued.
CHECK_EQUAL(CL_SUCCESS, clFinish(cq0));
CHECK_EQUAL(CL_SUCCESS, clFinish(cq1));
// Should be able to clFlush if there are no commands enqueued.
CHECK_EQUAL(CL_SUCCESS, clFlush(cq0));
CHECK_EQUAL(CL_SUCCESS, clFlush(cq1));

// Should be able to retain....
CHECK_EQUAL(CL_SUCCESS, clRetainCommandQueue(cq0));
CHECK_EQUAL(CL_SUCCESS, clRetainCommandQueue(cq1));
CHECK_EQUAL(2, acl_ref_count(cq0));
CHECK_EQUAL(2, acl_ref_count(cq1));

// Should be able to release...
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq0));
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq1));
CHECK_EQUAL(1, acl_ref_count(cq0));
CHECK_EQUAL(1, acl_ref_count(cq1));

// Should be able to release all the way.
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq0));
CHECK_EQUAL(CL_SUCCESS, clReleaseCommandQueue(cq1));
CHECK_EQUAL(0, acl_ref_count(cq0));
CHECK_EQUAL(0, acl_ref_count(cq1));

ACL_LOCKED(CHECK(!acl_command_queue_is_valid(cq0)));
ACL_LOCKED(CHECK(!acl_command_queue_is_valid(cq1)));

// And once it's gone, it's gone.
CHECK_EQUAL(CL_INVALID_COMMAND_QUEUE, clReleaseCommandQueue(cq0));
CHECK_EQUAL(CL_INVALID_COMMAND_QUEUE, clReleaseCommandQueue(cq1));
}

// Main Event is in an OOO queue. It has a dependent event in an in-order queue.
// Test that completing the main event, will unblock the dependent event.
MT_TEST(acl_command_queue, mixed_queue_dependencies_1) {
Expand Down

0 comments on commit 9f5a3c7

Please sign in to comment.