diff options
Diffstat (limited to 'tests/gem_flink_close_race.c')
-rw-r--r-- | tests/gem_flink_close_race.c | 85 |
1 files changed, 85 insertions, 0 deletions
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); +} |