inet.af/netstack@v0.0.0-20220214151720-7585b01ddccf/context/context.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package context defines an internal context type.
    16  //
    17  // The given Context conforms to the standard Go context, but mandates
    18  // additional methods that are specific to the kernel internals. Note however,
    19  // that the Context described by this package carries additional constraints
    20  // regarding concurrent access and retaining beyond the scope of a call.
    21  //
    22  // See the Context type for complete details.
    23  package context
    24  
    25  import (
    26  	"context"
    27  	"time"
    28  
    29  	"inet.af/netstack/log"
    30  )
    31  
    32  // A Context represents a thread of execution (hereafter "goroutine" to reflect
    33  // Go idiosyncrasy). It carries state associated with the goroutine across API
    34  // boundaries.
    35  //
    36  // While Context exists for essentially the same reasons as Go's standard
    37  // context.Context, the standard type represents the state of an operation
    38  // rather than that of a goroutine. This is a critical distinction:
    39  //
    40  // - Unlike context.Context, which "may be passed to functions running in
    41  // different goroutines", it is *not safe* to use the same Context in multiple
    42  // concurrent goroutines.
    43  //
    44  // - It is *not safe* to retain a Context passed to a function beyond the scope
    45  // of that function call.
    46  //
    47  // In both cases, values extracted from the Context should be used instead.
    48  type Context interface {
    49  	log.Logger
    50  	context.Context
    51  
    52  	ChannelSleeper
    53  
    54  	// UninterruptibleSleepStart indicates the beginning of an uninterruptible
    55  	// sleep state (equivalent to Linux's TASK_UNINTERRUPTIBLE). If deactivate
    56  	// is true and the Context represents a Task, the Task's AddressSpace is
    57  	// deactivated.
    58  	UninterruptibleSleepStart(deactivate bool)
    59  
    60  	// UninterruptibleSleepFinish indicates the end of an uninterruptible sleep
    61  	// state that was begun by a previous call to UninterruptibleSleepStart. If
    62  	// activate is true and the Context represents a Task, the Task's
    63  	// AddressSpace is activated. Normally activate is the same value as the
    64  	// deactivate parameter passed to UninterruptibleSleepStart.
    65  	UninterruptibleSleepFinish(activate bool)
    66  }
    67  
    68  // A ChannelSleeper represents a goroutine that may sleep interruptibly, where
    69  // interruption is indicated by a channel becoming readable.
    70  type ChannelSleeper interface {
    71  	// SleepStart is called before going to sleep interruptibly. If SleepStart
    72  	// returns a non-nil channel and that channel becomes ready for receiving
    73  	// while the goroutine is sleeping, the goroutine should be woken, and
    74  	// SleepFinish(false) should be called. Otherwise, SleepFinish(true) should
    75  	// be called after the goroutine stops sleeping.
    76  	SleepStart() <-chan struct{}
    77  
    78  	// SleepFinish is called after an interruptibly-sleeping goroutine stops
    79  	// sleeping, as documented by SleepStart.
    80  	SleepFinish(success bool)
    81  
    82  	// Interrupted returns true if the channel returned by SleepStart is
    83  	// ready for receiving.
    84  	Interrupted() bool
    85  }
    86  
    87  // NoopSleeper is a noop implementation of ChannelSleeper and
    88  // Context.UninterruptibleSleep* methods for anonymous embedding in other types
    89  // that do not implement special behavior around sleeps.
    90  type NoopSleeper struct{}
    91  
    92  // SleepStart implements ChannelSleeper.SleepStart.
    93  func (NoopSleeper) SleepStart() <-chan struct{} {
    94  	return nil
    95  }
    96  
    97  // SleepFinish implements ChannelSleeper.SleepFinish.
    98  func (NoopSleeper) SleepFinish(success bool) {}
    99  
   100  // Interrupted implements ChannelSleeper.Interrupted.
   101  func (NoopSleeper) Interrupted() bool {
   102  	return false
   103  }
   104  
   105  // UninterruptibleSleepStart implements Context.UninterruptibleSleepStart.
   106  func (NoopSleeper) UninterruptibleSleepStart(deactivate bool) {}
   107  
   108  // UninterruptibleSleepFinish implements Context.UninterruptibleSleepFinish.
   109  func (NoopSleeper) UninterruptibleSleepFinish(activate bool) {}
   110  
   111  // Deadline implements context.Context.Deadline.
   112  func (NoopSleeper) Deadline() (time.Time, bool) {
   113  	return time.Time{}, false
   114  }
   115  
   116  // Done implements context.Context.Done.
   117  func (NoopSleeper) Done() <-chan struct{} {
   118  	return nil
   119  }
   120  
   121  // Err returns context.Context.Err.
   122  func (NoopSleeper) Err() error {
   123  	return nil
   124  }
   125  
   126  // logContext implements basic logging.
   127  type logContext struct {
   128  	log.Logger
   129  	NoopSleeper
   130  }
   131  
   132  // Value implements Context.Value.
   133  func (logContext) Value(key interface{}) interface{} {
   134  	return nil
   135  }
   136  
   137  // bgContext is the context returned by context.Background.
   138  var bgContext = &logContext{Logger: log.Log()}
   139  
   140  // Background returns an empty context using the default logger.
   141  // Generally, one should use the Task as their context when available, or avoid
   142  // having to use a context in places where a Task is unavailable.
   143  //
   144  // Using a Background context for tests is fine, as long as no values are
   145  // needed from the context in the tested code paths.
   146  func Background() Context {
   147  	return bgContext
   148  }
   149  
   150  // WithValue returns a copy of parent in which the value associated with key is
   151  // val.
   152  func WithValue(parent Context, key, val interface{}) Context {
   153  	return &withValue{
   154  		Context: parent,
   155  		key:     key,
   156  		val:     val,
   157  	}
   158  }
   159  
   160  type withValue struct {
   161  	Context
   162  	key interface{}
   163  	val interface{}
   164  }
   165  
   166  // Value implements Context.Value.
   167  func (ctx *withValue) Value(key interface{}) interface{} {
   168  	if key == ctx.key {
   169  		return ctx.val
   170  	}
   171  	return ctx.Context.Value(key)
   172  }