<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>