diff options
author | Dave Airlie <airlied@redhat.com> | 2012-12-21 11:40:56 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-12-21 11:40:56 +1000 |
commit | 2e7433f87b337116ab848c12b05a1a05891640df (patch) | |
tree | 43e36c2127d238aceab3d401cfb8f3ca66eea307 | |
parent | b96d6623f0d2d2a1a4d46eb9c4293296501f1d97 (diff) |
gem_flink_close_race: attempt to exercise race in close/flinkprime
-rw-r--r-- | tests/Makefile.am | 4 | ||||
-rw-r--r-- | tests/gem_flink_close_race.c | 85 |
2 files changed, 89 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 017e7fe4..6eb2dad3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -69,6 +69,7 @@ TESTS_progs = \ prime_api_intel_radeon \ prime_test_intel_radeon \ prime_test_intel_udl \ + gem_flink_close_race \ $(NULL) # IMPORTANT: The ZZ_ tests need to be run last! @@ -123,6 +124,9 @@ AM_CFLAGS += $(CAIRO_CFLAGS) $(LIBUDEV_CFLAGS) $(GLIB_CFLAGS) gem_fence_thrash_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) gem_fence_thrash_LDADD = $(LDADD) -lpthread +gem_flink_close_race_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) +gem_flink_close_race_LDADD = $(LDADD) -lpthread + prime_test_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS) prime_test_LDADD = $(LDADD) $(DRM_NOUVEAU_LIBS) prime_api_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS) diff --git a/tests/gem_flink_close_race.c b/tests/gem_flink_close_race.c new file mode 100644 index 00000000..d4f4fe86 --- /dev/null +++ b/tests/gem_flink_close_race.c @@ -0,0 +1,85 @@ +/* try and provoke a race between gem flink and close */ + +/* create a GEM object - + flink the object. + + have two threads, a) closing the object, + b) flinking the object, then trying to open it + + if the flink succeeds but the open fails then I believe we have hit the + race as got a global name back for the object that no longer existed. + + For me this only really fails once in 100,000 or so runs or less, + so this acts more like a demonstration of the race than a useful test. +*/ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <pthread.h> +#include "drm.h" +#include "drmtest.h" + +int fd1; + +static void * +worker_thread (void *_arg) +{ + int handle = *(int *)_arg; + struct drm_gem_flink flink; + struct drm_gem_open gem_open; + int ret; + + flink.handle = handle; + ret = ioctl(fd1, DRM_IOCTL_GEM_FLINK, &flink); + if (ret) + return NULL; + + gem_open.name = flink.name; + ret = ioctl(fd1, DRM_IOCTL_GEM_OPEN, &gem_open); + if (ret) { + fprintf(stderr,"open ret for name %d is %d %d\n", gem_open.name, ret, errno); + return (void *)1; + } + + gem_close(fd1, gem_open.handle); + return NULL; +} + +int main(int argc, char **argv) +{ + int i; + uint32_t handle; + int ret; + pthread_t flinker; + struct drm_gem_flink flink; + struct drm_gem_open gem_open; + int name1, name2; + void *retval; + fd1 = drm_open_any(); + + for (i = 0; i < 100000; i++) { + handle = gem_create(fd1, 4096); + + flink.handle = handle; + ret = ioctl(fd1, DRM_IOCTL_GEM_FLINK, &flink); + assert(ret == 0); + + pthread_create(&flinker, NULL, worker_thread, &handle); + + gem_close(fd1, handle); + + pthread_join(flinker, &retval); + if (retval != NULL) + fprintf(stderr,"triggered race on round %d\n", i); + } + close(fd1); +} |