inet.af/netstack@v0.0.0-20220214151720-7585b01ddccf/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  	"inet.af/netstack/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)
   111  
   112  	// EventUnregister unregisters a waiter entry previously registered with
   113  	// EventRegister().
   114  	EventUnregister(e *Entry)
   115  }
   116  
   117  // EventListener provides a notify callback.
   118  type EventListener interface {
   119  	// NotifyEvent 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  	NotifyEvent(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  	waiterEntry
   139  
   140  	// eventListener receives the notification.
   141  	eventListener EventListener
   142  
   143  	// mask should be immutable once queued.
   144  	mask EventMask
   145  }
   146  
   147  // Init initializes the Entry.
   148  //
   149  // This must only be called when unregistered.
   150  func (e *Entry) Init(eventListener EventListener, mask EventMask) {
   151  	e.eventListener = eventListener
   152  	e.mask = mask
   153  }
   154  
   155  // Mask returns the entry mask.
   156  func (e *Entry) Mask() EventMask {
   157  	return e.mask
   158  }
   159  
   160  // NotifyEvent notifies the event listener.
   161  //
   162  // Mask should be the full set of active events.
   163  func (e *Entry) NotifyEvent(mask EventMask) {
   164  	if m := mask & e.mask; m != 0 {
   165  		e.eventListener.NotifyEvent(m)
   166  	}
   167  }
   168  
   169  // ChannelNotifier is a simple channel-based notification.
   170  type ChannelNotifier chan struct{}
   171  
   172  // NotifyEvent implements waiter.EventListener.NotifyEvent.
   173  func (c ChannelNotifier) NotifyEvent(EventMask) {
   174  	select {
   175  	case c <- struct{}{}:
   176  	default:
   177  	}
   178  }
   179  
   180  // NewChannelEntry initializes a new Entry that does a non-blocking write to a
   181  // struct{} channel when the callback is called. It returns the new Entry
   182  // instance and the channel being used.
   183  func NewChannelEntry(mask EventMask) (e Entry, ch chan struct{}) {
   184  	ch = make(chan struct{}, 1)
   185  	e.Init(ChannelNotifier(ch), mask)
   186  	return e, ch
   187  }
   188  
   189  type functionNotifier func(EventMask)
   190  
   191  // NotifyEvent implements waiter.EventListener.NotifyEvent.
   192  func (f functionNotifier) NotifyEvent(mask EventMask) {
   193  	f(mask)
   194  }
   195  
   196  // NewFunctionEntry initializes a new Entry that calls the given function.
   197  func NewFunctionEntry(mask EventMask, fn func(EventMask)) (e Entry) {
   198  	e.Init(functionNotifier(fn), mask)
   199  	return e
   200  }
   201  
   202  // Queue represents the wait queue where waiters can be added and
   203  // notifiers can notify them when events happen.
   204  //
   205  // The zero value for waiter.Queue is an empty queue ready for use.
   206  //
   207  // +stateify savable
   208  type Queue struct {
   209  	list waiterList
   210  	mu   sync.RWMutex `state:"nosave"`
   211  }
   212  
   213  // EventRegister adds a waiter to the wait queue.
   214  func (q *Queue) EventRegister(e *Entry) {
   215  	q.mu.Lock()
   216  	q.list.PushBack(e)
   217  	q.mu.Unlock()
   218  }
   219  
   220  // EventUnregister removes the given waiter entry from the wait queue.
   221  func (q *Queue) EventUnregister(e *Entry) {
   222  	q.mu.Lock()
   223  	q.list.Remove(e)
   224  	q.mu.Unlock()
   225  }
   226  
   227  // Notify notifies all waiters in the queue whose masks have at least one bit
   228  // in common with the notification mask.
   229  func (q *Queue) Notify(mask EventMask) {
   230  	q.mu.RLock()
   231  	for e := q.list.Front(); e != nil; e = e.Next() {
   232  		m := mask & e.mask
   233  		if m == 0 {
   234  			continue
   235  		}
   236  		e.eventListener.NotifyEvent(m) // Skip intermediate call.
   237  	}
   238  	q.mu.RUnlock()
   239  }
   240  
   241  // Events returns the set of events being waited on. It is the union of the
   242  // masks of all registered entries.
   243  func (q *Queue) Events() EventMask {
   244  	ret := EventMask(0)
   245  
   246  	q.mu.RLock()
   247  	for e := q.list.Front(); e != nil; e = e.Next() {
   248  		ret |= e.mask
   249  	}
   250  	q.mu.RUnlock()
   251  
   252  	return ret
   253  }
   254  
   255  // IsEmpty returns if the wait queue is empty or not.
   256  func (q *Queue) IsEmpty() bool {
   257  	q.mu.Lock()
   258  	defer q.mu.Unlock()
   259  
   260  	return q.list.Front() == nil
   261  }
   262  
   263  // AlwaysReady implements the Waitable interface but is always ready. Embedding
   264  // this struct into another struct makes it implement the boilerplate empty
   265  // functions automatically.
   266  type AlwaysReady struct {
   267  }
   268  
   269  // Readiness always returns the input mask because this object is always ready.
   270  func (*AlwaysReady) Readiness(mask EventMask) EventMask {
   271  	return mask
   272  }
   273  
   274  // EventRegister doesn't do anything because this object doesn't need to issue
   275  // notifications because its readiness never changes.
   276  func (*AlwaysReady) EventRegister(e *Entry) {
   277  }
   278  
   279  // EventUnregister doesn't do anything because this object doesn't need to issue
   280  // notifications because its readiness never changes.
   281  func (*AlwaysReady) EventUnregister(e *Entry) {
   282  }