From 8e0046a738070ca3c5441222da241a0582103fe7 Mon Sep 17 00:00:00 2001 From: Alexander Slobodeniuk Date: Tue, 16 Apr 2024 23:08:51 +0200 Subject: [PATCH] tests/d3d11: add concurrency test for gstd3d11device We suspect that it's not thread safe to just create and destroy the device from any thread, particularly because of D3D11CreateDevice, that is not documented as thread-safe. While D3D11CreateDevice is usually protected from outside by the gst_d3d11_ensure_element_data, it still can cross with the Release() method of another device. Part-of: --- .../tests/check/libs/d3d11device.cpp | 56 +++++++++++++++++++ .../gst-plugins-bad/tests/check/meson.build | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/tests/check/libs/d3d11device.cpp b/subprojects/gst-plugins-bad/tests/check/libs/d3d11device.cpp index 4d18803f22..30b89f9adf 100644 --- a/subprojects/gst-plugins-bad/tests/check/libs/d3d11device.cpp +++ b/subprojects/gst-plugins-bad/tests/check/libs/d3d11device.cpp @@ -186,6 +186,61 @@ check_d3d11_available (void) return TRUE; } +static gboolean stopping = FALSE; + +static gpointer +test_device_new_concurrency_thread (gpointer) +{ + GstVideoInfo in_info, out_info; + + gst_video_info_set_format (&in_info, GST_VIDEO_FORMAT_I420, 320, 240); + gst_video_info_set_format (&out_info, GST_VIDEO_FORMAT_RGBx, 1920, 1080); + + while (!g_atomic_int_get (&stopping)) { + GstD3D11Converter *converter; + GstD3D11Device *device = gst_d3d11_device_new (0, D3D11_CREATE_DEVICE_BGRA_SUPPORT); + + gst_d3d11_device_lock (device); + converter = gst_d3d11_converter_new (device, &in_info, &out_info, + gst_structure_new ("converter-config", + GST_D3D11_CONVERTER_OPT_BACKEND, GST_TYPE_D3D11_CONVERTER_BACKEND, + GST_D3D11_CONVERTER_BACKEND_SHADER, + GST_D3D11_CONVERTER_OPT_GAMMA_MODE, + GST_TYPE_VIDEO_GAMMA_MODE, GST_VIDEO_GAMMA_MODE_NONE, + GST_D3D11_CONVERTER_OPT_PRIMARIES_MODE, + GST_TYPE_VIDEO_PRIMARIES_MODE, GST_VIDEO_PRIMARIES_MODE_NONE, + nullptr)); + gst_d3d11_device_unlock (device); + + g_usleep (g_random_int_range (10, 1000)); + + gst_d3d11_device_lock (device); + gst_object_unref (converter); + gst_d3d11_device_unlock (device); + + gst_object_unref (device); + } + + return NULL; +} + +GST_START_TEST (test_device_new_concurrency) +{ +#define NUM_THREADS 32 + GThread *threads[NUM_THREADS]; + + for (int t = 0; t < NUM_THREADS; t++) + threads[t] = g_thread_new (NULL, test_device_new_concurrency_thread, NULL); + + g_usleep (20 * G_TIME_SPAN_SECOND); + g_atomic_int_set (&stopping, TRUE); + for (int t = 0; t < NUM_THREADS; t++) + g_thread_join(threads[t]); + +} + +GST_END_TEST; + static Suite * d3d11device_suite (void) { @@ -200,6 +255,7 @@ d3d11device_suite (void) tcase_add_test (tc_basic, test_device_new); tcase_add_test (tc_basic, test_device_for_adapter_luid); tcase_add_test (tc_basic, test_device_new_wrapped); + tcase_add_test (tc_basic, test_device_new_concurrency); out: return s; diff --git a/subprojects/gst-plugins-bad/tests/check/meson.build b/subprojects/gst-plugins-bad/tests/check/meson.build index 248aea0ca4..fda83b43ab 100644 --- a/subprojects/gst-plugins-bad/tests/check/meson.build +++ b/subprojects/gst-plugins-bad/tests/check/meson.build @@ -109,7 +109,7 @@ base_tests = [ [['libs/vkinstance.c'], not gstvulkan_dep.found(), [gstvulkan_dep]], [['libs/vkimagebufferpool.c'], not gstvulkan_dep.found(), [gstvulkan_dep]], [['libs/vkvideodecode.c'], not gstvulkan_dep.found() or vulkan_conf.get('GST_VULKAN_HAVE_VIDEO_EXTENSIONS') != 1, [gstvulkan_dep]], - [['libs/d3d11device.cpp'], not gstd3d11_dep.found(), [gstd3d11_dep]], + [['libs/d3d11device.cpp'], not gstd3d11_dep.found(), [gstd3d11_dep, gstvideo_dep]], [['libs/d3d11memory.c'], not gstd3d11_dep.found(), [gstd3d11_dep]], [['libs/cudamemory.c'], not gstcuda_dep.found(), [gstcuda_dep, gstcuda_stub_dep]], ]