On Thu, Nov 24, 2016 at 12:16:11PM +0200, Abdiel Janulgue wrote: > A lot of igt testcases need some GPU workload to make sure a race > window is big enough. Unfortunately having a fixed amount of > workload leads to spurious test failures or overly long runtimes > on some fast/slow platforms. This library contains functionality > to submit GPU workloads that should consume exactly a specific > amount of time. > > v2 : Add recursive batch feature from Chris > v3 : Drop auto-tuned stuff. Add bo dependecy to recursive batch > by adding a dummy reloc to the bo as suggested by Ville. > v4: Fix dependency reloc as write instead of read (Ville). > Fix wrong handling of batchbuffer start on ILK causing > test failure > v5: Convert kms_busy to use this api > v6: Add this library to docs > v7: Document global use of batch, reuse defines > Minor code cleanups. > Rename igt_spin_batch and igt_post_spin_batch to > igt_spin_batch_new and igt_spin_batch_free > respectively (Tomeu Vizoso). > Fix error in dependency relocation handling in HSW causing > tests to fail. > v8: Restore correct order of objects in the execbuffer. Batch > object should always be last. > v9 : Add helper to terminate batch manually > v10: Split timeout function. Clarify function names (Chris) > v11: From Chris: > * Add gem_quiescent_gpu exit handler > * Use gem_bo_busy > * Skip spin->handle > 0 checks > * Ensure terminate batch on free > * Remove igt_spin_batch_wait > * Remove single-ring limitation > v12: Hook into gem_quiescent_gpu exit handler to idle the GPU if > the user terminates tests with ^C > > Cc: Daniel Vetter <daniel.vetter@xxxxxxxx> > Cc: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> > Cc: tomeu@xxxxxxxxxxxxxxx > Reviewed-by: Tomeu Vizoso <tomeu.vizoso@xxxxxxxxxxxxx> > Signed-off-by: Abdiel Janulgue <abdiel.janulgue@xxxxxxxxxxxxxxx> > --- > +/** > + * igt_spin_batch_set_timeout: > + * @spin: spin batch state from igt_spin_batch_new() > + * @ns: amount of time in nanoseconds the batch continues to execute > + * before finishing. > + * > + * Specify a timeout. This ends the recursive batch associated with @spin after > + * the timeout has elapsed. > + */ > +void igt_spin_batch_set_timeout(igt_spin_t *spin, int64_t ns) > +{ > + timer_t timer; > + struct sigevent sev; > + struct sigaction act; > + struct itimerspec its; > + > + igt_assert(ns > 0); > + if (!spin) > + return; > + > + memset(&sev, 0, sizeof(sev)); > + sev.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID; > + sev.sigev_notify_thread_id = gettid(); > + sev.sigev_signo = SIGRTMIN + 1; > + igt_assert(timer_create(CLOCK_MONOTONIC, &sev, &timer) == 0); > + igt_assert(timer > 0); > + > + memset(&act, 0, sizeof(act)); > + act.sa_sigaction = exit_batch_handler; > + act.sa_flags = SA_SIGINFO; > + igt_assert(sigaction(SIGRTMIN + 1, &act, NULL) == 0); Note that we can use multiple signals here and so have multiple spinners with timeout in parallel now that we save the spinners in a global list. We should probably check the returned oldact to confirm that the signal was not in use previously. > + memset(&its, 0, sizeof(its)); > + its.it_value.tv_sec = ns / NSEC_PER_SEC; > + its.it_value.tv_nsec = ns % NSEC_PER_SEC; > + igt_assert(timer_settime(timer, 0, &its, NULL) == 0); > + > + spin->timer = timer; > +} > + > +/** > + * igt_spin_batch_end: > + * @spin: spin batch state from igt_spin_batch_new() > + * > + * End the recursive batch associated with @spin manually. > + */ > +void igt_spin_batch_end(igt_spin_t *spin) > +{ > + if (!spin) > + return; > + > + *spin->batch = MI_BATCH_BUFFER_END; > + __sync_synchronize(); > +} > + > +/** > + * igt_spin_batch_free: > + * @fd: open i915 drm file descriptor > + * @spin: spin batch state from igt_spin_batch_new() > + * > + * This function does the necessary post-processing after starting a recursive > + * batch with igt_spin_batch_new(). > + */ > +void igt_spin_batch_free(int fd, igt_spin_t *spin) > +{ > + if (!spin) > + return; > + > + if (spin->timer > 0) > + timer_delete(spin->timer); > + > + igt_spin_batch_end(spin); > + munmap(spin->batch, bo_size); > + gem_close(fd, spin->handle); > + free(spin); > + > + num_spin_objects--; This doesn't handle multiple spin objects correctly. If only we had a nice circular list struct. We should also contemplate whether we want this to support threading. -Chris -- Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx