github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/waiter/waiter.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 waiter provides the implementation of a wait queue, where waiters can
    16  // be enqueued to be notified when an event of interest happens.
    17  //
    18  // Becoming readable and/or writable are examples of events. Waiters are
    19  // expected to use a pattern similar to this to make a blocking function out of
    20  // a non-blocking one:
    21  //
    22  //	func (o *object) blockingRead(...) error {
    23  //		err := o.nonBlockingRead(...)
    24  //		if err != ErrAgain {
    25  //			// Completed with no need to wait!
    26  //			return err
    27  //		}
    28  //
    29  //		e := createOrGetWaiterEntry(...)
    30  //		o.EventRegister(&e, waiter.EventIn)
    31  //		defer o.EventUnregister(&e)
    32  //
    33  //		// We need to try to read again after registration because the
    34  //		// object may have become readable between the last attempt to
    35  //		// read and read registration.
    36  //		err = o.nonBlockingRead(...)
    37  //		for err == ErrAgain {
    38  //			wait()
    39  //			err = o.nonBlockingRead(...)
    40  //		}
    41  //
    42  //		return err
    43  //	}
    44  //
    45  // Another goroutine needs to notify waiters when events happen. For example:
    46  //
    47  //	func (o *object) Write(...) ... {
    48  //		// Do write work.
    49  //		[...]
    50  //
    51  //		if oldDataAvailableSize == 0 && dataAvailableSize > 0 {
    52  //			// If no data was available and now some data is
    53  //			// available, the object became readable, so notify
    54  //			// potential waiters about this.
    55  //			o.Notify(waiter.EventIn)
    56  //		}
    57  //	}
    58  package waiter
    59  
    60  import (
    61  	"github.com/SagerNet/gvisor/pkg/sync"
    62  )
    63  
    64  // EventMask represents io events as used in the poll() syscall.
    65  type EventMask uint64
    66  
    67  // Events that waiters can wait on. The meaning is the same as those in the
    68  // poll() syscall.
    69  const (
    70  	EventIn     EventMask = 0x01   // POLLIN
    71  	EventPri    EventMask = 0x02   // POLLPRI
    72  	EventOut    EventMask = 0x04   // POLLOUT
    73  	EventErr    EventMask = 0x08   // POLLERR
    74  	EventHUp    EventMask = 0x10   // POLLHUP
    75  	EventRdNorm EventMask = 0x0040 // POLLRDNORM
    76  	EventWrNorm EventMask = 0x0100 // POLLWRNORM
    77  
    78  	allEvents      EventMask = 0x1f | EventRdNorm | EventWrNorm
    79  	ReadableEvents EventMask = EventIn | EventRdNorm
    80  	WritableEvents EventMask = EventOut | EventWrNorm
    81  )
    82  
    83  // EventMaskFromLinux returns an EventMask representing the supported events
    84  // from the Linux events e, which is in the format used by poll(2).
    85  func EventMaskFromLinux(e uint32) EventMask {
    86  	// Our flag definitions are currently identical to Linux.
    87  	return EventMask(e) & allEvents
    88  }
    89  
    90  // ToLinux returns e in the format used by Linux poll(2).
    91  func (e EventMask) ToLinux() uint32 {
    92  	// Our flag definitions are currently identical to Linux.
    93  	return uint32(e)
    94  }
    95  
    96  // Waitable contains the methods that need to be implemented by waitable
    97  // objects.
    98  type Waitable interface {
    99  	// Readiness returns what the object is currently ready for. If it's
   100  	// not ready for a desired purpose, the caller may use EventRegister and
   101  	// EventUnregister to get notifications once the object becomes ready.
   102  	//
   103  	// Implementations should allow for events like EventHUp and EventErr
   104  	// to be returned regardless of whether they are in the input EventMask.
   105  	Readiness(mask EventMask) EventMask
   106  
   107  	// EventRegister registers the given waiter entry to receive
   108  	// notifications when an event occurs that makes the object ready for
   109  	// at least one of the events in mask.
   110  	EventRegister(e *Entry, mask EventMask)
   111  
   112  	// EventUnregister unregisters a waiter entry previously registered with
   113  	// EventRegister().
   114  	EventUnregister(e *Entry)
   115  }
   116  
   117  // EntryCallback provides a notify callback.
   118  type EntryCallback interface {
   119  	// Callback is the function to be called when the waiter entry is
   120  	// notified. It is responsible for doing whatever is needed to wake up
   121  	// the waiter.
   122  	//
   123  	// The callback is supposed to perform minimal work, and cannot call
   124  	// any method on the queue itself because it will be locked while the
   125  	// callback is running.
   126  	//
   127  	// The mask indicates the events that occurred and that the entry is
   128  	// interested in.
   129  	Callback(e *Entry, mask EventMask)
   130  }
   131  
   132  // Entry represents a waiter that can be add to the a wait queue. It can
   133  // only be in one queue at a time, and is added "intrusively" to the queue with
   134  // no extra memory allocations.
   135  //
   136  // +stateify savable
   137  type Entry struct {
   138  	Callback EntryCallback
   139  
   140  	// The following fields are protected by the queue lock.
   141  	mask EventMask
   142  	waiterEntry
   143  }
   144  
   145  type channelCallback struct {
   146  	ch chan struct{}
   147  }
   148  
   149  // Callback implements EntryCallback.Callback.
   150  func (c *channelCallback) Callback(*Entry, EventMask) {
   151  	select {
   152  	case c.ch <- struct{}{}:
   153  	default:
   154  	}
   155  }
   156  
   157  // NewChannelEntry initializes a new Entry that does a non-blocking write to a
   158  // struct{} channel when the callback is called. It returns the new Entry
   159  // instance and the channel being used.
   160  //
   161  // If a channel isn't specified (i.e., if "c" is nil), then NewChannelEntry
   162  // allocates a new channel.
   163  func NewChannelEntry(c chan struct{}) (Entry, chan struct{}) {
   164  	if c == nil {
   165  		c = make(chan struct{}, 1)
   166  	}
   167  
   168  	return Entry{Callback: &channelCallback{ch: c}}, c
   169  }
   170  
   171  // Queue represents the wait queue where waiters can be added and
   172  // notifiers can notify them when events happen.
   173  //
   174  // The zero value for waiter.Queue is an empty queue ready for use.
   175  //
   176  // +stateify savable
   177  type Queue struct {
   178  	list waiterList
   179  	mu   sync.RWMutex `state:"nosave"`
   180  }
   181  
   182  // EventRegister adds a waiter to the wait queue; the waiter will be notified
   183  // when at least one of the events specified in mask happens.
   184  func (q *Queue) EventRegister(e *Entry, mask EventMask) {
   185  	q.mu.Lock()
   186  	e.mask = mask
   187  	q.list.PushBack(e)
   188  	q.mu.Unlock()
   189  }
   190  
   191  // EventUnregister removes the given waiter entry from the wait queue.
   192  func (q *Queue) EventUnregister(e *Entry) {
   193  	q.mu.Lock()
   194  	q.list.Remove(e)
   195  	q.mu.Unlock()
   196  }
   197  
   198  // Notify notifies all waiters in the queue whose masks have at least one bit
   199  // in common with the notification mask.
   200  func (q *Queue) Notify(mask EventMask) {
   201  	q.mu.RLock()
   202  	for e := q.list.Front(); e != nil; e = e.Next() {
   203  		if m := mask & e.mask; m != 0 {
   204  			e.Callback.Callback(e, m)
   205  		}
   206  	}
   207  	q.mu.RUnlock()
   208  }
   209  
   210  // Events returns the set of events being waited on. It is the union of the
   211  // masks of all registered entries.
   212  func (q *Queue) Events() EventMask {
   213  	ret := EventMask(0)
   214  
   215  	q.mu.RLock()
   216  	for e := q.list.Front(); e != nil; e = e.Next() {
   217  		ret |= e.mask
   218  	}
   219  	q.mu.RUnlock()
   220  
   221  	return ret
   222  }
   223  
   224  // IsEmpty returns if the wait queue is empty or not.
   225  func (q *Queue) IsEmpty() bool {
   226  	q.mu.Lock()
   227  	defer q.mu.Unlock()
   228  
   229  	return q.list.Front() == nil
   230  }
   231  
   232  // AlwaysReady implements the Waitable interface but is always ready. Embedding
   233  // this struct into another struct makes it implement the boilerplate empty
   234  // functions automatically.
   235  type AlwaysReady struct {
   236  }
   237  
   238  // Readiness always returns the input mask because this object is always ready.
   239  func (*AlwaysReady) Readiness(mask EventMask) EventMask {
   240  	return mask
   241  }
   242  
   243  // EventRegister doesn't do anything because this object doesn't need to issue
   244  // notifications because its readiness never changes.
   245  func (*AlwaysReady) EventRegister(*Entry, EventMask) {
   246  }
   247  
   248  // EventUnregister doesn't do anything because this object doesn't need to issue
   249  // notifications because its readiness never changes.
   250  func (*AlwaysReady) EventUnregister(e *Entry) {
   251  }