mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Expose some kernel hooks.
- Add Kernel.IsPaused() which indicates whether the kernel is currently paused. - Add TaskSet.ForEachThreadGroup() which allows callers to iterate through all thread groups in the kernel. - Export FDTable.ForEach() which allows other packages to iterate over all FDs. PiperOrigin-RevId: 640760723
This commit is contained in:
@@ -93,7 +93,7 @@ func (f *FDTable) saveDescriptorTable() map[int32]descriptor {
|
||||
m := make(map[int32]descriptor)
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.forEach(context.Background(), func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
|
||||
f.ForEach(context.Background(), func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
|
||||
m[fd] = descriptor{
|
||||
file: file,
|
||||
flags: flags,
|
||||
@@ -172,10 +172,10 @@ func (f *FDTable) forEachUpTo(ctx context.Context, maxFd int32, fn func(fd int32
|
||||
})
|
||||
}
|
||||
|
||||
// forEach iterates over all non-nil files upto maxFd in sorted order.
|
||||
// ForEach iterates over all non-nil files upto maxFd in sorted order.
|
||||
//
|
||||
// It is the caller's responsibility to acquire an appropriate lock.
|
||||
func (f *FDTable) forEach(ctx context.Context, fn func(fd int32, file *vfs.FileDescription, flags FDFlags) bool) {
|
||||
func (f *FDTable) ForEach(ctx context.Context, fn func(fd int32, file *vfs.FileDescription, flags FDFlags) bool) {
|
||||
f.forEachUpTo(ctx, MaxFdLimit, fn)
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ func (f *FDTable) String() string {
|
||||
f.mu.Lock()
|
||||
// Can't release f.mu from defer, because vfsObj.PathnameWithDeleted
|
||||
// should not be called under the fdtable mutex.
|
||||
f.forEach(ctx, func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
|
||||
f.ForEach(ctx, func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
|
||||
if file != nil {
|
||||
file.IncRef()
|
||||
files[fd] = file
|
||||
@@ -424,7 +424,7 @@ func (f *FDTable) GetFDs(ctx context.Context) []int32 {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
fds := make([]int32, 0, int(f.fdBitmap.GetNumOnes()))
|
||||
f.forEach(ctx, func(fd int32, _ *vfs.FileDescription, _ FDFlags) bool {
|
||||
f.ForEach(ctx, func(fd int32, _ *vfs.FileDescription, _ FDFlags) bool {
|
||||
fds = append(fds, fd)
|
||||
return true
|
||||
})
|
||||
@@ -486,7 +486,7 @@ func (f *FDTable) RemoveIf(ctx context.Context, cond func(*vfs.FileDescription,
|
||||
var files []*vfs.FileDescription
|
||||
|
||||
f.mu.Lock()
|
||||
f.forEach(ctx, func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
|
||||
f.ForEach(ctx, func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
|
||||
if cond(file, flags) {
|
||||
// Clear from table.
|
||||
if df := f.set(fd, nil, FDFlags{}); df != nil {
|
||||
|
||||
@@ -1215,7 +1215,7 @@ func (k *Kernel) pauseTimeLocked(ctx context.Context) {
|
||||
// This means we'll iterate FDTables shared by multiple tasks repeatedly,
|
||||
// but ktime.Timer.Pause is idempotent so this is harmless.
|
||||
if t.fdTable != nil {
|
||||
t.fdTable.forEach(ctx, func(_ int32, fd *vfs.FileDescription, _ FDFlags) bool {
|
||||
t.fdTable.ForEach(ctx, func(_ int32, fd *vfs.FileDescription, _ FDFlags) bool {
|
||||
if tfd, ok := fd.Impl().(*timerfd.TimerFileDescription); ok {
|
||||
tfd.PauseTimer()
|
||||
}
|
||||
@@ -1246,7 +1246,7 @@ func (k *Kernel) resumeTimeLocked(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
if t.fdTable != nil {
|
||||
t.fdTable.forEach(ctx, func(_ int32, fd *vfs.FileDescription, _ FDFlags) bool {
|
||||
t.fdTable.ForEach(ctx, func(_ int32, fd *vfs.FileDescription, _ FDFlags) bool {
|
||||
if tfd, ok := fd.Impl().(*timerfd.TimerFileDescription); ok {
|
||||
tfd.ResumeTimer()
|
||||
}
|
||||
@@ -1354,6 +1354,11 @@ func (k *Kernel) Pause() {
|
||||
k.tasks.aioGoroutines.Wait()
|
||||
}
|
||||
|
||||
// IsPaused returns true if the kernel is currently paused.
|
||||
func (k *Kernel) IsPaused() bool {
|
||||
return k.tasks.isExternallyStopped()
|
||||
}
|
||||
|
||||
// ReceiveTaskStates receives full states for all tasks.
|
||||
func (k *Kernel) ReceiveTaskStates() {
|
||||
k.extMu.Lock()
|
||||
|
||||
@@ -241,3 +241,11 @@ func (ts *TaskSet) EndExternalStop() {
|
||||
t.tg.signalHandlers.mu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// isExternallyStopped returns true if BeginExternalStop() has been called on
|
||||
// this TaskSet, without a corresponding call to EndExternalStop().
|
||||
func (ts *TaskSet) isExternallyStopped() bool {
|
||||
ts.mu.Lock()
|
||||
defer ts.mu.Unlock()
|
||||
return ts.stopCount > 0
|
||||
}
|
||||
|
||||
@@ -106,6 +106,13 @@ func newTaskSet(pidns *PIDNamespace) *TaskSet {
|
||||
return ts
|
||||
}
|
||||
|
||||
// ForEachThreadGroup applies f to each thread group in ts.
|
||||
func (ts *TaskSet) ForEachThreadGroup(f func(tg *ThreadGroup)) {
|
||||
ts.mu.RLock()
|
||||
defer ts.mu.RUnlock()
|
||||
ts.forEachThreadGroupLocked(f)
|
||||
}
|
||||
|
||||
// forEachThreadGroupLocked applies f to each thread group in ts.
|
||||
//
|
||||
// Preconditions: ts.mu must be locked (for reading or writing).
|
||||
|
||||
Reference in New Issue
Block a user