On Wed, Apr 05, 2023 at 05:43:01PM +0200, Daniel Vetter wrote:
On Tue, Mar 07, 2023 at 11:25:37PM +0900, Asahi Lina wrote:
+/// An armed DRM scheduler job (not yet submitted) +pub struct ArmedJob<'a, T: JobImpl>(Box<Job<T>>, PhantomData<&'a T>);
+impl<'a, T: JobImpl> ArmedJob<'a, T> {
- /// Returns the job fences
- pub fn fences(&self) -> JobFences<'_> {
JobFences(unsafe { &mut *self.0.job.s_fence })
- }
- /// Push the job for execution into the scheduler
- pub fn push(self) {
// After this point, the job is submitted and owned by the scheduler
let ptr = match self {
ArmedJob(job, _) => Box::<Job<T>>::into_raw(job),
};
If I get this all right then this all makes sure that drivers can't use the job after push and they don't forgot to call arm.
What I'm not seeing is how we force drivers to call push once they've called arm? I haven't check what the code does, but from the docs it sounds like if you don't call push then drop will get called. Which wreaks the book-keeping on an armed job. Or is there someting that prevents ArmedJob<T> from having the Drop trait and so the only way to not go boom is by pushing it?
Googling for "rust undroppable" seems to indicate that this isn't a thing rust can do?
Another thing that I just realized: The driver must ensure that the arm->push sequence on a given drm_sched_entity isn't interrupte by another thread doing the same, i.e. you need to wrap it all in a lock, and it always needs to be the same lock for a given entity.
I have no idea how to guarantee that, but I guess somehow we should? -Daniel