Skip to content

Commit

Permalink
drm/amdkfd: fix race condition in kfd_wait_on_events
Browse files Browse the repository at this point in the history
Add the waiters to the wait queue during initialization, while holding the
event spinlock. Otherwise the waiter will not get activated if the event
signals before being added to the wait queue.

Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: Philip Yang<Philip.Yang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Felix Kuehling authored and Alex Deucher committed Apr 14, 2022
1 parent 9e12b59 commit 250e64a
Showing 1 changed file with 5 additions and 21 deletions.
26 changes: 5 additions & 21 deletions drivers/gpu/drm/amd/amdkfd/kfd_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ static struct kfd_event_waiter *alloc_event_waiters(uint32_t num_events)
return event_waiters;
}

static int init_event_waiter_get_status(struct kfd_process *p,
static int init_event_waiter(struct kfd_process *p,
struct kfd_event_waiter *waiter,
uint32_t event_id)
{
Expand All @@ -793,25 +793,13 @@ static int init_event_waiter_get_status(struct kfd_process *p,
waiter->event = ev;
waiter->activated = ev->signaled;
ev->signaled = ev->signaled && !ev->auto_reset;
if (!waiter->activated)
add_wait_queue(&ev->wq, &waiter->wait);
spin_unlock(&ev->lock);

return 0;
}

static void init_event_waiter_add_to_waitlist(struct kfd_event_waiter *waiter)
{
struct kfd_event *ev = waiter->event;

/* Only add to the wait list if we actually need to
* wait on this event.
*/
if (!waiter->activated) {
spin_lock(&ev->lock);
add_wait_queue(&ev->wq, &waiter->wait);
spin_unlock(&ev->lock);
}
}

/* test_event_condition - Test condition of events being waited for
* @all: Return completion only if all events have signaled
* @num_events: Number of events to wait for
Expand Down Expand Up @@ -941,8 +929,8 @@ int kfd_wait_on_events(struct kfd_process *p,
goto out_unlock;
}

ret = init_event_waiter_get_status(p, &event_waiters[i],
event_data.event_id);
ret = init_event_waiter(p, &event_waiters[i],
event_data.event_id);
if (ret)
goto out_unlock;
}
Expand All @@ -960,10 +948,6 @@ int kfd_wait_on_events(struct kfd_process *p,
goto out_unlock;
}

/* Add to wait lists if we need to wait. */
for (i = 0; i < num_events; i++)
init_event_waiter_add_to_waitlist(&event_waiters[i]);

mutex_unlock(&p->event_mutex);

while (true) {
Expand Down

0 comments on commit 250e64a

Please sign in to comment.