summaryrefslogtreecommitdiff
path: root/tests/gem_flink_race.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2013-07-24 09:46:57 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-07-24 12:52:01 +0200
commit24bbca9237cbb6bd5e85db839dc517db65e693e8 (patch)
treed00e9d90e1f08db8630b05e3d61a995b62c5a6b8 /tests/gem_flink_race.c
parentdfe942edec1a713568a19e15ce75e1ed01b9fb08 (diff)
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 <daniel.vetter@ffwll.ch>
Diffstat (limited to 'tests/gem_flink_race.c')
-rw-r--r--tests/gem_flink_race.c118
1 files changed, 109 insertions, 9 deletions
diff --git a/tests/gem_flink_race.c b/tests/gem_flink_race.c
index a8bbfd35..522c92d8 100644
--- a/tests/gem_flink_race.c
+++ b/tests/gem_flink_race.c
@@ -24,6 +24,7 @@
* Daniel Vetter <daniel.vetter@ffwll.ch>
*/
+#define _GNU_SOURCE
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
@@ -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;
}