From 8bb82da3fe0e14ca4645ec47ad8e8709aec75485 Mon Sep 17 00:00:00 2001 From: Kyle Brenneman Date: Thu, 5 Sep 2019 14:58:53 -0600 Subject: [PATCH] tests: Add some threading tests for libGLdispatch. Added a new test, testgldispatchthread, which tests some of the thread-handling stuff in libGLdispatch. --- tests/Makefile.am | 10 ++ tests/testgldispatchthread.c | 275 ++++++++++++++++++++++++++++++++++ tests/testgldispatchthread.sh | 4 + 3 files changed, 289 insertions(+) create mode 100644 tests/testgldispatchthread.c create mode 100755 tests/testgldispatchthread.sh diff --git a/tests/Makefile.am b/tests/Makefile.am index 2ae6ce2..4ed7f06 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -71,6 +71,16 @@ testgldispatch_LDADD += dummy/libpatchentrypoints.la testgldispatch_LDADD += $(top_builddir)/src/util/libutils_misc.la testgldispatch_LDADD += $(PTHREAD_LIBS) +TESTS += testgldispatchthread.sh +check_PROGRAMS += testgldispatchthread +testgldispatchthread_SOURCES = \ + testgldispatchthread.c +testgldispatchthread_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/GLdispatch \ + $(PTHREAD_CFLAGS) +testgldispatchthread_LDADD = $(top_builddir)/src/GLdispatch/libGLdispatch.la + # Start of GLX-specific tests. # Notes that the TESTS_GLX variable must be defined outside the conditional, so # that we can include the test scripts in the EXTRA_DIST package. Otherwise, diff --git a/tests/testgldispatchthread.c b/tests/testgldispatchthread.c new file mode 100644 index 0000000..271bbe7 --- /dev/null +++ b/tests/testgldispatchthread.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2019, NVIDIA CORPORATION. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * unaltered in all copies or substantial portions of the Materials. + * Any additions, deletions, or changes to the original source files + * must be clearly indicated in accompanying documentation. + * + * If only executable code is distributed, then the accompanying + * documentation must state that "this software is based in part on the + * work of the Khronos Group." + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define VENDOR_COUNT 2 +#define THREAD_COUNT 4 +#define CALL_COUNT 1 + +typedef struct { + int vendorID; + __GLdispatchTable *dispatch; +} VendorInfo; + +typedef struct { + __GLdispatchThreadState dispatchThreadState; + + pthread_t thread; + VendorInfo *vendor; + + int callCountStatic; + int callCountEarly; + int callCountLate; + GLboolean destroyed; +} ThreadState; + +typedef void (* pfn_glVertex3fv) (const GLfloat *v); + +static sem_t mainSemaphore; +static sem_t threadSemaphore; +static pfn_glVertex3fv ptr_glVertex3fv = NULL; +static pfn_glVertex3fv ptr_glTestFuncEarly = NULL; +static pfn_glVertex3fv ptr_glTestFuncLate = NULL; + +static ThreadState *GetCurrentThreadState(void) +{ + __GLdispatchThreadState *ts = __glDispatchGetCurrentThreadState(); + if (ts == NULL) { + printf("__glDispatchGetCurrentThreadState failed\n"); + } + return (ThreadState *) ts; +} + +static void dummy_glVertex3fv(const GLfloat *v) +{ + ThreadState *ts = GetCurrentThreadState(); + ts->callCountStatic++; +} + +static void glTestFuncEarlyDUMMY(const GLfloat *v) +{ + ThreadState *ts = GetCurrentThreadState(); + ts->callCountEarly++; +} +static void glTestFuncLateDUMMY(const GLfloat *v) +{ + ThreadState *ts = GetCurrentThreadState(); + ts->callCountLate++; +} + +static void *VendorGetProcAddressCallback(const char *procName, void *param) +{ + if (strcmp(procName, "glVertex3fv") == 0) { + return dummy_glVertex3fv; + } else if (strcmp(procName, "glTestFuncEarlyDUMMY") == 0) { + return glTestFuncEarlyDUMMY; + } else if (strcmp(procName, "glTestFuncLateDUMMY") == 0) { + return glTestFuncLateDUMMY; + } else { + return NULL; + } +} + +static void ThreadDestroyedCallback(__GLdispatchThreadState *dispatchThreadState) +{ + ThreadState *ts = (ThreadState *) dispatchThreadState; + ts->destroyed = GL_TRUE; +} + +static void *ThreadProc(void *param) +{ + ThreadState *ts = (ThreadState *) param; + int i; + + ts->dispatchThreadState.threadDestroyedCallback = ThreadDestroyedCallback; + + if (!__glDispatchMakeCurrent(&ts->dispatchThreadState, + ts->vendor->dispatch, ts->vendor->vendorID, + NULL)) { + printf("__glDispatchMakeCurrent failed\n"); + exit(1); + } + + // Notify the main thread that we're ready. + if (sem_post(&mainSemaphore) != 0) { + printf("sem_post failed\n"); + exit(1); + } + + // Wait for the main thread to finish calling __glDispatchGetProcAddress. + if (sem_wait(&threadSemaphore) != 0) { + printf("sem_wait failed\n"); + exit(1); + } + + for (i=0; i