@@ -31,6 +31,7 @@ type object struct {
31
31
client * rootClient // may be == impl
32
32
class nvgpu.ClassID
33
33
handle nvgpu.Handle // in client.resources, and also nvp.clients if impl is rootClient
34
+ parent nvgpu.Handle
34
35
impl objectImpl
35
36
36
37
// The driver tracks parent/child relationships and "arbitrary dependency"
@@ -73,13 +74,15 @@ func (nvp *nvproxy) objsUnlock() {
73
74
74
75
// objAdd records the allocation of a driver object with class c and handle h,
75
76
// in the client with handle clientH, represented by oi. Each non-zero handle
76
- // in deps is a dependency of the created object, such that the freeing of any
77
- // of those objects also results in the freeing of the recorded object.
78
- func (nvp * nvproxy ) objAdd (ctx context.Context , clientH , h nvgpu.Handle , c nvgpu.ClassID , oi objectImpl , deps ... nvgpu.Handle ) {
79
- if h .Val == 0 {
80
- log .Traceback ("nvproxy: new object (class %v) has invalid handle 0" , c )
77
+ // in parentH and deps is a dependency of the created object, such that the
78
+ // freeing of any of those objects also results in the freeing of the recorded
79
+ // object.
80
+ func (nvp * nvproxy ) objAdd (ctx context.Context , clientH , h nvgpu.Handle , c nvgpu.ClassID , oi objectImpl , parentH nvgpu.Handle , deps ... nvgpu.Handle ) {
81
+ if h == nvgpu .NV01_NULL_OBJECT {
82
+ log .Traceback ("nvproxy: new object (class %v) has invalid handle %v" , c , h )
81
83
return
82
84
}
85
+
83
86
var client * rootClient
84
87
// The driver forced NV01_ROOT and NV01_ROOT_NON_PRIV to NV01_ROOT_CLIENT,
85
88
// so we only need to check for the latter.
@@ -98,18 +101,29 @@ func (nvp *nvproxy) objAdd(ctx context.Context, clientH, h nvgpu.Handle, c nvgpu
98
101
return
99
102
}
100
103
}
104
+
101
105
o := oi .Object ()
102
106
o .nvp = nvp
103
107
o .client = client
104
108
o .class = c
105
109
o .handle = h
110
+ o .parent = parentH
106
111
o .impl = oi
107
112
if _ , ok := client .resources [h ]; ok {
108
113
ctx .Warningf ("nvproxy: handle %v:%v already in use" , clientH , h )
109
114
}
110
115
client .resources [h ] = o
116
+
117
+ if parentH != nvgpu .NV01_NULL_OBJECT {
118
+ parent , ok := client .resources [parentH ]
119
+ if ! ok {
120
+ log .Traceback ("nvproxy: new object %v:%v (class %v) has invalid parent handle %v" , clientH , h , c , parentH )
121
+ } else {
122
+ nvp .objDep (o , parent )
123
+ }
124
+ }
111
125
for _ , depH := range deps {
112
- if depH . Val == 0 /* aka NV01_NULL_OBJECT */ {
126
+ if depH == nvgpu . NV01_NULL_OBJECT {
113
127
continue
114
128
}
115
129
dep , ok := client .resources [depH ]
@@ -119,8 +133,9 @@ func (nvp *nvproxy) objAdd(ctx context.Context, clientH, h nvgpu.Handle, c nvgpu
119
133
}
120
134
nvp .objDep (o , dep )
121
135
}
136
+
122
137
if ctx .IsLogging (log .Debug ) {
123
- ctx .Debugf ("nvproxy: added object %v:%v (class %v) with dependencies %v" , clientH , h , c , deps )
138
+ ctx .Debugf ("nvproxy: added object %v:%v (class %v) with parent %v, dependencies %v" , clientH , h , c , parentH , deps )
124
139
}
125
140
}
126
141
@@ -161,6 +176,31 @@ func (nvp *nvproxy) objDep(o1, o2 *object) {
161
176
o2 .rdeps [o1 ] = struct {}{}
162
177
}
163
178
179
+ // objDup records the duplication of the driver object with handle srcH in the
180
+ // client with handle clientSrcH, to handle dstH in the client with handle
181
+ // clientDstH, with new parent parentDstH.
182
+ func (nvp * nvproxy ) objDup (ctx context.Context , clientDstH , dstH , parentDstH , clientSrcH , srcH nvgpu.Handle ) {
183
+ clientSrc , ok := nvp .clients [clientSrcH ]
184
+ if ! ok {
185
+ ctx .Warningf ("nvproxy: duplicating object handle %v with unknown client handle %v" , srcH , clientSrcH )
186
+ return
187
+ }
188
+ oSrc , ok := clientSrc .resources [srcH ]
189
+ if ! ok {
190
+ ctx .Warningf ("nvproxy: duplicating object with unknown handle %v:%v" , clientSrcH , srcH )
191
+ return
192
+ }
193
+ oDst := & miscObject {}
194
+ nvp .objAdd (ctx , clientDstH , dstH , oSrc .class , oDst , parentDstH )
195
+ parentSrc := clientSrc .resources [oSrc .parent ]
196
+ // Copy all non-parent dependencies.
197
+ for dep := range oSrc .deps {
198
+ if dep != parentSrc {
199
+ nvp .objDep (oDst .Object (), dep )
200
+ }
201
+ }
202
+ }
203
+
164
204
// objFree marks an object and its transitive dependents as freed.
165
205
//
166
206
// Compare
@@ -279,6 +319,18 @@ func (o *rmAllocObject) Release(ctx context.Context) {
279
319
// no-op
280
320
}
281
321
322
+ // miscObject is an objectImpl tracking a driver object allocated by something
323
+ // other than an invocation of NV_ESC_RM_ALLOC, whose class is not represented
324
+ // by a more specific type.
325
+ type miscObject struct {
326
+ object
327
+ }
328
+
329
+ // Release implements objectImpl.Release.
330
+ func (o * miscObject ) Release (ctx context.Context ) {
331
+ // no-op
332
+ }
333
+
282
334
// rootClient is an objectImpl tracking a NV01_ROOT_CLIENT.
283
335
//
284
336
// +stateify savable
@@ -323,23 +375,3 @@ func (o *osDescMem) Release(ctx context.Context) {
323
375
}
324
376
})
325
377
}
326
-
327
- // osEvent is an objectImpl tracking a NV01_EVENT_OS_EVENT.
328
- type osEvent struct {
329
- object
330
- }
331
-
332
- // Release implements objectImpl.Release.
333
- func (o * osEvent ) Release (ctx context.Context ) {
334
- // no-op
335
- }
336
-
337
- // virtMem is an objectImpl tracking a NV50_MEMORY_VIRTUAL.
338
- type virtMem struct {
339
- object
340
- }
341
-
342
- // Release implements objectImpl.Release.
343
- func (o * virtMem ) Release (ctx context.Context ) {
344
- // no-op
345
- }
0 commit comments