diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-11 17:23:45 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-11 17:23:45 -0400 |
| commit | 12732c5894c893344422da4fd8d075c4c43c8e8a (patch) | |
| tree | 6df0f33b1d519e9bd37737dd44bc758a97ad718e /kernel/gsp_sema_service.c | |
| parent | 35ca086b20f04f6be5bd935fd53d08e43f67e869 (diff) | |
| download | open-iov-12732c5894c893344422da4fd8d075c4c43c8e8a.tar.gz open-iov-12732c5894c893344422da4fd8d075c4c43c8e8a.zip | |
vgsp-sema: session boundary is a client change, not the last channel closing (ISSUE-0002)
r79 regression from keeping the CeUtils scrubber channel registered
(client-scoped deletion): the session flush trigger required EVERY
channel to close, and the scrubber never closes, so the per-session
discovery reset never ran and the next client inherited the previous
session's map/pins (the r9 class; the first client of r79 wedged the
guest on an rwsem with no output).
The session is now keyed by owning client: channel_add records
svc_sess_client and requests the flush when a channel of a DIFFERENT
client registers while the previous session is live (then waits for it,
exactly like a pending flush); channel_del's flush trigger counts only
channels of the current session client, so persistent kernel/GPU-global
channels (the scrubber) no longer keep a dead session open.
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 638a866..9f967a5 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -451,6 +451,11 @@ static u32 svc_ring_n; */ static u8 svc_sess_flush; static u8 svc_sess_active; /* a channel of a session has registered (until flush) */ +static u32 svc_sess_client; /* owning client of the current session's channels. + * The kernel/GPU-global channels (the CeUtils + * scrubber) persist across clients; the session + * boundary is a change of owning client, not the + * last channel closing (ISSUE-0002 r79). */ static struct completion svc_sess_flush_done; /* a pending flush has executed */ static unsigned long svc_ring_done; /* CE ranks whose ring is pinned (session state) */ static u8 svc_pb_passes; @@ -950,6 +955,20 @@ void gsp_sema_service_channel_add(const struct sema_channel_desc *desc) WRITE_ONCE(svc_gr_content_rearm, true); /* + * ISSUE-0002 (r79): the kernel/GPU-global channels (the CeUtils + * scrubber, entries=4096) persist across client sessions, so the + * "last channel closed" trigger never fires once they are kept + * registered. The real session boundary is a change of owning + * client: when a channel of a new client registers while the + * previous session's state is still live, request the same flush a + * session end would (the wait below then lets svc_thread execute it + * before this session's state exists). + */ + if (desc->h_client && svc_sess_client && + desc->h_client != svc_sess_client && svc_sess_active) + WRITE_ONCE(svc_sess_flush, 1); + + /* * ISSUE-0002: a session-end flush may still be pending on svc_thread. * It must not execute after this session's state exists (r9: the * deferred flush ran between the first and second channel @@ -1050,6 +1069,8 @@ void gsp_sema_service_channel_add(const struct sema_channel_desc *desc) } ch->valid = true; svc_sess_active = 1; + if (desc->h_client) + svc_sess_client = desc->h_client; ch->h_object = desc->h_object; ch->h_client = desc->h_client; ch->engine_type = desc->engine_type; @@ -1136,19 +1157,28 @@ void gsp_sema_service_channel_del(u32 h_object, u32 h_client) break; } /* - * ISSUE-0002: when the last channel closes, the next client is a new - * session in a new UVM VA space; its discovery state must not inherit - * this session's map/pins/page-directory latch. Request the flush - * here; it executes at the next rebuild (the only writer of that - * state) just like a fresh boot would start empty. Only the transition - * from "a session existed" to "empty" may request it: redundant - * deletes for handles that never registered would otherwise re-flush - * (and wipe) a session that started after the real one ended. + * ISSUE-0002: when the last channel of the current session's client + * closes, the next client is a new session in a new UVM VA space; its + * discovery state must not inherit this session's map/pins/page- + * directory latch. Request the flush here; it executes at the next + * rebuild (the only writer of that state) just like a fresh boot + * would start empty. Only the transition from "a session existed" to + * "empty" may request it: redundant deletes for handles that never + * registered would otherwise re-flush (and wipe) a session that + * started after the real one ended. Persistent kernel/GPU-global + * channels (a different owning client, e.g. the CeUtils scrubber) do + * not keep the session open (ISSUE-0002 r79: with the scrubber kept + * registered the old all-channels check never fired and the next + * client inherited stale state). */ if (svc_sess_active) { for (i = 0; i < SVC_MAX_CHANNELS; i++) { - if (svc.chan[i].valid) - break; + if (!svc.chan[i].valid) + continue; + if (svc_sess_client && svc.chan[i].h_client && + svc.chan[i].h_client != svc_sess_client) + continue; + break; } if (i == SVC_MAX_CHANNELS) { svc_sess_active = 0; |
