On Thu, Aug 10, 2017 at 2:40 AM, Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> wrote:
Quoting Jason Ekstrand (2017-08-10 06:35:43)
> This adds both trivial error-checking tests as well as more complex
> tests which actually test whether or not waits do what they're supposed
> to do. They only currently work on i915 but it should be simple to hook
> them up for other drivers by simply implementing the little function
> pointer hook provided at the top for triggering a syncobj.
>
> v2:
> - Actually add the reset tests.
> v3:
> - Only do one execbuf for trigger
> - Use do_ioctl and do_ioctl_err
> - Better check for syncobj support
> - Add local_/LOCAL_ defines of things
> - Use a timer instead of a pthread
> v4:
> - Use ioctl wrappers
> - Use VGEM instead of i915
> - Combine a bunch of the simple tests into one function
> v5:
> - Combinatorially generate basic tests
> - Use sw_sync instead of using vgem directly
Aye, sw_sync looks to be quite useful here - a completely driver
agnostic method for signaling syncobj. Nice.
static void
> +static int
> +syncobj_attach_sw_sync(int fd, uint32_t handle)
> +{
> + struct drm_syncobj_handle;
> + int timeline, fence;
> +
> + timeline = sw_sync_timeline_create();
> + fence = sw_sync_timeline_create_fence(timeline, 1);
> + syncobj_import_sync_file(fd, handle, fence);
> + close(fence);
> +
> + return timeline;
> +}
> +
> +static void
> +syncobj_trigger(int fd, uint32_t handle)
> +{
> + int timeline = syncobj_attach_sw_sync(fd, handle);
> + sw_sync_timeline_inc(timeline, 1);
> +}
> +
> +struct delayed_trigger {
> + int fd;
> + uint32_t *syncobjs;
> + int count;
> + uint64_t nsec;
> +};
> +
> +static void
> +trigger_syncobj_delayed_func(union sigval sigval)
> +{
> + struct delayed_trigger *trigger = sigval.sival_ptr;
> + int i;
> +
> + for (i = 0; i < trigger->count; i++)
> + syncobj_trigger(trigger->fd, trigger->syncobjs[i]);
> + free(trigger);
> +}
> +
> +static timer_t
> +trigger_syncobj_delayed(int fd, uint32_t *syncobjs, int count, uint64_t nsec)
> +{
> + struct delayed_trigger *trigger;
> + timer_t timer;
> + struct sigevent sev;
> + struct itimerspec its;
> +
> + trigger = malloc(sizeof(*trigger));
> + trigger->fd = fd;
> + trigger->syncobjs = syncobjs;
> + trigger->count = count;
> + trigger->nsec = nsec;
> +
> + memset(&sev, 0, sizeof(sev));
> + sev.sigev_notify = SIGEV_THREAD;
> + sev.sigev_value.sival_ptr = trigger;
> + sev.sigev_notify_function = trigger_syncobj_delayed_func;
> + igt_assert(timer_create(CLOCK_MONOTONIC, &sev, &timer) == 0);
> +
> + memset(&its, 0, sizeof(its));
> + its.it_value.tv_sec = nsec / NSEC_PER_SEC;
> + its.it_value.tv_nsec = nsec % NSEC_PER_SEC;
> + igt_assert(timer_settime(timer, 0, &its, NULL) == 0);
> +
> + return timer;
> +}
trigger_syncobj_delayed_func(union sigval sigval)
{
int timeline = (intptr_t)sigval.sival_ptr;
sw_sync_timeline_inc(timeline, 1);
close(timeline);
}
static timer_t
trigger_syncobj_delayed(int fd, uint32_t *syncobjs, int count, uint64_t nsec)
{
struct itimerspec its;
struct sigevent sev;
int timeline, fence;
timer_t timer;
timeline = sw_sync_timeline_create();
fence = sw_sync_timeline_create_fence(timeline, 1);
for (int i = 0; i < count; i++)
syncobj_import_sync_file(fd, syncobjs[i], fence);
close(fence);
memset(&sev, 0, sizeof(sev));
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_value.sival_ptr = (intptr_t)timeline;
sev.sigev_notify_function = trigger_syncobj_delayed_func;
igt_assert(timer_create(CLOCK_MONOTONIC, &sev, &timer) == 0); memset(&its, 0, sizeof(its));
its.it_value.tv_sec = nsec / NSEC_PER_SEC;
its.it_value.tv_nsec = nsec % NSEC_PER_SEC;
igt_assert(timer_settime(timer, 0, &its, NULL) == 0); return timer;
}
As i continue improving things, it's morphing to look more like that. Actually my current test do it both ways. The original way for WAIT_FOR_SUBMIT and the way described above for normal waits. There will be a v6...
_______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx