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 }