@@ -163,13 +163,53 @@ type setnsProcess struct {
163
163
initProcessPid int
164
164
}
165
165
166
+ // Starts setns process with specified initial CPU affinity.
167
+ func (p * setnsProcess ) startWithCPUAffinity () error {
168
+ aff := p .config .CPUAffinity
169
+ if aff == nil || aff .Initial == nil {
170
+ return p .cmd .Start ()
171
+ }
172
+ errCh := make (chan error )
173
+ defer close (errCh )
174
+
175
+ // Use a goroutine to dedicate an OS thread.
176
+ go func () {
177
+ runtime .LockOSThread ()
178
+ // Command inherits the CPU affinity.
179
+ if err := unix .SchedSetaffinity (unix .Gettid (), aff .Initial ); err != nil {
180
+ runtime .UnlockOSThread ()
181
+ errCh <- fmt .Errorf ("error setting initial CPU affinity: %w" , err )
182
+ return
183
+ }
184
+
185
+ errCh <- p .cmd .Start ()
186
+ // Deliberately omit runtime.UnlockOSThread here.
187
+ // https://pkg.go.dev/runtime#LockOSThread says:
188
+ // "If the calling goroutine exits without unlocking the
189
+ // thread, the thread will be terminated".
190
+ }()
191
+
192
+ return <- errCh
193
+ }
194
+
195
+ func (p * setnsProcess ) setFinalCPUAffinity () error {
196
+ aff := p .config .CPUAffinity
197
+ if aff == nil || aff .Final == nil {
198
+ return nil
199
+ }
200
+ if err := unix .SchedSetaffinity (p .pid (), aff .Final ); err != nil {
201
+ return fmt .Errorf ("error setting final CPU affinity: %w" , err )
202
+ }
203
+ return nil
204
+ }
205
+
166
206
func (p * setnsProcess ) start () (retErr error ) {
167
207
defer p .comm .closeParent ()
168
208
169
- // get the "before" value of oom kill count
209
+ // Get the "before" value of oom kill count.
170
210
oom , _ := p .manager .OOMKillCount ()
171
- err := p .cmd . Start ()
172
- // close the child-side of the pipes (controlled by child)
211
+ err := p .startWithCPUAffinity ()
212
+ // Close the child-side of the pipes (controlled by child).
173
213
p .comm .closeChild ()
174
214
if err != nil {
175
215
return fmt .Errorf ("error starting setns process: %w" , err )
@@ -219,6 +259,10 @@ func (p *setnsProcess) start() (retErr error) {
219
259
}
220
260
}
221
261
}
262
+ // Set final CPU affinity right after the process is moved into container's cgroup.
263
+ if err := p .setFinalCPUAffinity (); err != nil {
264
+ return err
265
+ }
222
266
if p .intelRdtPath != "" {
223
267
// if Intel RDT "resource control" filesystem path exists
224
268
_ , err := os .Stat (p .intelRdtPath )
@@ -228,7 +272,6 @@ func (p *setnsProcess) start() (retErr error) {
228
272
}
229
273
}
230
274
}
231
-
232
275
if err := utils .WriteJSON (p .comm .initSockParent , p .config ); err != nil {
233
276
return fmt .Errorf ("error writing config to pipe: %w" , err )
234
277
}
0 commit comments