@@ -27,6 +27,7 @@
*/
#include "igt.h"
+#include <pthread.h>
#define EXEC_OBJECT_PINNED (1<<4)
#define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3)
@@ -471,6 +472,74 @@ static void test_noreloc(int fd, enum sleep sleep)
gem_close(fd, object[i].handle);
}
+#define SOFTPIN_STRESS_LOOPS 100000
+
+struct evict_close_thread_data {
+ int fd;
+ int pipefd[2];
+ bool stop;
+ pthread_mutex_t mutex;
+};
+
+static void *evict_close_thread(void *data)
+{
+ struct evict_close_thread_data *t = (struct evict_close_thread_data*)data;
+ uint32_t handle;
+
+ pthread_mutex_lock(&t->mutex);
+ while (!t->stop) {
+ pthread_mutex_unlock(&t->mutex);
+ read(t->pipefd[0], &handle, sizeof(handle));
+ gem_close(t->fd, handle);
+ pthread_mutex_lock(&t->mutex);
+ }
+ pthread_mutex_unlock(&t->mutex);
+
+ return NULL;
+}
+
+static void test_evict_close_race(int fd)
+{
+ pthread_t t;
+ struct evict_close_thread_data t_data;
+ unsigned int loops = SOFTPIN_STRESS_LOOPS;
+ const uint32_t bbe = MI_BATCH_BUFFER_END;
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 object;
+
+ memset(&execbuf, 0, sizeof(execbuf));
+ memset(&object, 0, sizeof(object));
+
+ execbuf.buffers_ptr = (uintptr_t)&object;
+ execbuf.buffer_count = 1;
+ object.flags = EXEC_OBJECT_PINNED;
+ object.offset = 0;
+
+ memset(&t_data, 0, sizeof(t_data));
+ t_data.fd = fd;
+ igt_assert(pthread_mutex_init(&t_data.mutex, NULL) == 0);
+ igt_assert(pipe(t_data.pipefd) == 0);
+
+ igt_assert(pthread_create(&t, NULL, evict_close_thread, &t_data) == 0);
+
+ while (loops--) {
+ object.handle = gem_create(fd, 4096);
+ gem_write(fd, object.handle, 0, &bbe, sizeof(bbe));
+ gem_execbuf(fd, &execbuf);
+ write(t_data.pipefd[1], &object.handle, sizeof(object.handle));
+ }
+
+ pthread_mutex_lock(&t_data.mutex);
+ t_data.stop = 1;
+ pthread_mutex_unlock(&t_data.mutex);
+
+ pthread_join(t, NULL);
+
+ close(t_data.pipefd[0]);
+ close(t_data.pipefd[1]);
+ pthread_mutex_destroy(&t_data.mutex);
+}
+
igt_main
{
int fd = -1;
@@ -507,6 +576,9 @@ igt_main
igt_subtest("evict-hang")
test_evict_hang(fd);
+ igt_subtest("stress-evict-close")
+ test_evict_close_race(fd);
+
igt_fixture
close(fd);
}