From 24bbca9237cbb6bd5e85db839dc517db65e693e8 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 24 Jul 2013 09:46:57 +0200 Subject: [PATCH] tests/gem_flink_race: actually make it somewhat useful - Enable subtest support. - Add a check for the same flink name in the racing threads, which is an issue one of my recent patches actually fixes. - Add the test I've actually wanted to write which races an flink against gem close (with no open in between). That one does indeed leak. - Readd the leak check, but note that this needs a fixed kernel. Otherwise the leak counter will be utter garbage. Signed-off-by: Daniel Vetter --- tests/Makefile.am | 2 +- tests/gem_flink_race.c | 118 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 10 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 5ad38fd..a59c25f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -25,6 +25,7 @@ TESTS_progs_M = \ gem_exec_nop \ gem_fence_thrash \ gem_flink \ + gem_flink_race \ gem_gtt_concurrent_blit \ gem_linear_blits \ gem_mmap_gtt \ @@ -61,7 +62,6 @@ TESTS_progs = \ gem_exec_faulting_reloc \ gem_exec_lut_handle \ gem_fenced_exec_thrash \ - gem_flink_race \ gem_gtt_cpu_tlb \ gem_gtt_speed \ gem_hangcheck_forcewake \ diff --git a/tests/gem_flink_race.c b/tests/gem_flink_race.c index a8bbfd3..522c92d 100644 --- a/tests/gem_flink_race.c +++ b/tests/gem_flink_race.c @@ -24,6 +24,7 @@ * Daniel Vetter */ +#define _GNU_SOURCE #include #include #include @@ -47,7 +48,26 @@ volatile int pls_die = 0; int fd; -static void *thread_fn(void *p) +static int get_object_count(void) +{ + FILE *file; + int ret, scanned; + int device = drm_get_card(0); + char *path; + + ret = asprintf(&path, "/sys/kernel/debug/dri/%d/i915_gem_objects", device); + assert(ret != -1); + + file = fopen(path, "r"); + + scanned = fscanf(file, "%i objects,", &ret); + assert(scanned == 1); + + return ret; +} + + +static void *thread_fn_flink_name(void *p) { struct drm_gem_open open_struct; int ret; @@ -57,24 +77,25 @@ static void *thread_fn(void *p) open_struct.name = 1; ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &open_struct); - if (ret == 0) + if (ret == 0) { + uint32_t name = gem_flink(fd, open_struct.handle); + + assert(name == 1); + gem_close(fd, open_struct.handle); - else + } else assert(errno == ENOENT); } return (void *)0; } -int main(int argc, char **argv) +static void test_flink_name(void) { - int num_threads; pthread_t *threads; - int r, i; + int r, i, num_threads; void *status; - drmtest_skip_on_simulation(); - num_threads = sysconf(_SC_NPROCESSORS_ONLN) - 1; if (!num_threads) num_threads = 1; @@ -85,7 +106,8 @@ int main(int argc, char **argv) assert(fd >= 0); for (i = 0; i < num_threads; i++) { - r = pthread_create(&threads[i], NULL, thread_fn, NULL); + r = pthread_create(&threads[i], NULL, + thread_fn_flink_name, NULL); assert(r == 0); } @@ -110,6 +132,84 @@ int main(int argc, char **argv) assert(fd >= 0); close(fd); +} + +static void *thread_fn_flink_close(void *p) +{ + struct drm_gem_flink flink; + struct drm_gem_close close_bo; + uint32_t handle; + + while (!pls_die) { + /* We want to race gem close against flink on handle one.*/ + handle = gem_create(fd, 4096); + if (handle != 1) + gem_close(fd, handle); + + /* raw ioctl since we expect this to fail */ + flink.handle = 1; + ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); + + close_bo.handle = 1; + ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo); + } + + return (void *)0; +} + +static void test_flink_close(void) +{ + pthread_t *threads; + int r, i, num_threads; + int obj_count = get_object_count(); + void *status; + + num_threads = sysconf(_SC_NPROCESSORS_ONLN) - 1; + if (!num_threads) + num_threads = 1; + + threads = calloc(num_threads, sizeof(pthread_t)); + + fd = drm_open_any(); + assert(fd >= 0); + + for (i = 0; i < num_threads; i++) { + r = pthread_create(&threads[i], NULL, + thread_fn_flink_close, NULL); + assert(r == 0); + } + + sleep(5); + + pls_die = 1; + + for (i = 0; i < num_threads; i++) { + pthread_join(threads[i], &status); + assert(status == 0); + } + + fd = drm_open_any(); + assert(fd >= 0); + + close(fd); + + obj_count = get_object_count() - obj_count; + + printf("leaked %i objects\n", obj_count); + assert(obj_count == 0); +} + +int main(int argc, char **argv) +{ + drmtest_skip_on_simulation(); + + drmtest_subtest_init(argc, argv); + + if (drmtest_run_subtest("flink_name")) + test_flink_name(); + + if (drmtest_run_subtest("flink_close")) + test_flink_close(); return 0; } -- 2.7.4