<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Aug 10, 2017 at 2:40 AM, Chris Wilson <span dir="ltr"><<a href="mailto:chris@chris-wilson.co.uk" target="_blank">chris@chris-wilson.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">Quoting Jason Ekstrand (2017-08-10 06:35:43)<br>
</span><span class="">> This adds both trivial error-checking tests as well as more complex<br>
> tests which actually test whether or not waits do what they're supposed<br>
> to do. They only currently work on i915 but it should be simple to hook<br>
> them up for other drivers by simply implementing the little function<br>
> pointer hook provided at the top for triggering a syncobj.<br>
><br>
> v2:<br>
> - Actually add the reset tests.<br>
> v3:<br>
> - Only do one execbuf for trigger<br>
> - Use do_ioctl and do_ioctl_err<br>
> - Better check for syncobj support<br>
> - Add local_/LOCAL_ defines of things<br>
> - Use a timer instead of a pthread<br>
> v4:<br>
> - Use ioctl wrappers<br>
> - Use VGEM instead of i915<br>
> - Combine a bunch of the simple tests into one function<br>
> v5:<br>
> - Combinatorially generate basic tests<br>
> - Use sw_sync instead of using vgem directly<br>
<br>
</span>Aye, sw_sync looks to be quite useful here - a completely driver<br>
agnostic method for signaling syncobj. Nice.<br>
<div><div class="h5"><br>
> +static int<br>
> +syncobj_attach_sw_sync(int fd, uint32_t handle)<br>
> +{<br>
> + struct drm_syncobj_handle;<br>
> + int timeline, fence;<br>
> +<br>
> + timeline = sw_sync_timeline_create();<br>
> + fence = sw_sync_timeline_create_fence(<wbr>timeline, 1);<br>
> + syncobj_import_sync_file(fd, handle, fence);<br>
> + close(fence);<br>
> +<br>
> + return timeline;<br>
> +}<br>
> +<br>
> +static void<br>
> +syncobj_trigger(int fd, uint32_t handle)<br>
> +{<br>
> + int timeline = syncobj_attach_sw_sync(fd, handle);<br>
> + sw_sync_timeline_inc(timeline, 1);<br>
> +}<br>
> +<br>
> +struct delayed_trigger {<br>
> + int fd;<br>
> + uint32_t *syncobjs;<br>
> + int count;<br>
> + uint64_t nsec;<br>
> +};<br>
> +<br>
> +static void<br>
> +trigger_syncobj_delayed_func(<wbr>union sigval sigval)<br>
> +{<br>
> + struct delayed_trigger *trigger = sigval.sival_ptr;<br>
> + int i;<br>
> +<br>
> + for (i = 0; i < trigger->count; i++)<br>
> + syncobj_trigger(trigger->fd, trigger->syncobjs[i]);<br>
> + free(trigger);<br>
> +}<br>
> +<br>
> +static timer_t<br>
> +trigger_syncobj_delayed(int fd, uint32_t *syncobjs, int count, uint64_t nsec)<br>
> +{<br>
> + struct delayed_trigger *trigger;<br>
> + timer_t timer;<br>
> + struct sigevent sev;<br>
> + struct itimerspec its;<br>
> +<br>
> + trigger = malloc(sizeof(*trigger));<br>
> + trigger->fd = fd;<br>
> + trigger->syncobjs = syncobjs;<br>
> + trigger->count = count;<br>
> + trigger->nsec = nsec;<br>
> +<br>
> + memset(&sev, 0, sizeof(sev));<br>
> + sev.sigev_notify = SIGEV_THREAD;<br>
> + sev.sigev_value.sival_ptr = trigger;<br>
> + sev.sigev_notify_function = trigger_syncobj_delayed_func;<br>
> + igt_assert(timer_create(CLOCK_<wbr>MONOTONIC, &sev, &timer) == 0);<br>
> +<br>
> + memset(&its, 0, sizeof(its));<br>
> + its.it_value.tv_sec = nsec / NSEC_PER_SEC;<br>
> + its.it_value.tv_nsec = nsec % NSEC_PER_SEC;<br>
> + igt_assert(timer_settime(<wbr>timer, 0, &its, NULL) == 0);<br>
> +<br>
> + return timer;<br>
> +}<br>
<br>
</div></div>static void<br>
trigger_syncobj_delayed_func(<wbr>union sigval sigval)<br>
{<br>
int timeline = (intptr_t)sigval.sival_ptr;<br>
sw_sync_timeline_inc(timeline, 1);<br>
close(timeline);<br>
}<br>
<br>
static timer_t<br>
<span class="">trigger_syncobj_delayed(int fd, uint32_t *syncobjs, int count, uint64_t nsec)<br>
</span>{<br>
struct itimerspec its;<br>
struct sigevent sev;<br>
int timeline, fence;<br>
timer_t timer;<br>
<br>
timeline = sw_sync_timeline_create();<br>
fence = sw_sync_timeline_create_fence(<wbr>timeline, 1);<br>
<br>
for (int i = 0; i < count; i++)<br>
syncobj_import_sync_file(fd, syncobjs[i], fence);<br>
close(fence);<br>
<br>
memset(&sev, 0, sizeof(sev));<br>
sev.sigev_notify = SIGEV_THREAD;<br>
sev.sigev_value.sival_ptr = (intptr_t)timeline;<br>
sev.sigev_notify_function = trigger_syncobj_delayed_func;<br>
<span class=""> igt_assert(timer_create(CLOCK_<wbr>MONOTONIC, &sev, &timer) == 0);<br>
<br>
</span> memset(&its, 0, sizeof(its));<br>
<span class=""> its.it_value.tv_sec = nsec / NSEC_PER_SEC;<br>
</span><span class=""> its.it_value.tv_nsec = nsec % NSEC_PER_SEC;<br>
</span><span class=""> igt_assert(timer_settime(<wbr>timer, 0, &its, NULL) == 0);<br>
<br>
</span> return timer;<br>
}<br>
</blockquote></div><br></div><div class="gmail_extra">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...<br></div></div>