Print this page
8634 epoll fails to wake on certain edge-triggered conditions
8635 epoll should not emit POLLNVAL
8636 recursive epoll should emit EPOLLRDNORM
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <igor@dilos.org>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/streamio.c
          +++ new/usr/src/uts/common/os/streamio.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  22   22  /*        All Rights Reserved   */
  23   23  
  24   24  
  25   25  /*
  26   26   * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  27      - * Copyright (c) 2014, Joyent, Inc. All rights reserved.
       27 + * Copyright 2017 Joyent, Inc.
  28   28   */
  29   29  
  30   30  #include <sys/types.h>
  31   31  #include <sys/sysmacros.h>
  32   32  #include <sys/param.h>
  33   33  #include <sys/errno.h>
  34   34  #include <sys/signal.h>
  35   35  #include <sys/stat.h>
  36   36  #include <sys/proc.h>
  37   37  #include <sys/cred.h>
↓ open down ↓ 8129 lines elided ↑ open up ↑
8167 8167   *                      the queue contains one or more M_DATA mblks. Thus
8168 8168   *                      when this flag is set a queue with only
8169 8169   *                      M_PROTO/M_PCPROTO mblks does not return POLLIN.
8170 8170   *                      Used by sockfs to ignore T_EXDATA_IND messages.
8171 8171   *
8172 8172   * Note: POLLRDDATA assumes that synch streams only return messages with
8173 8173   * an M_DATA attached (i.e. not messages consisting of only
8174 8174   * an M_PROTO/M_PCPROTO part).
8175 8175   */
8176 8176  int
8177      -strpoll(
8178      -        struct stdata *stp,
8179      -        short events_arg,
8180      -        int anyyet,
8181      -        short *reventsp,
8182      -        struct pollhead **phpp)
     8177 +strpoll(struct stdata *stp, short events_arg, int anyyet, short *reventsp,
     8178 +    struct pollhead **phpp)
8183 8179  {
8184 8180          int events = (ushort_t)events_arg;
8185 8181          int retevents = 0;
8186 8182          mblk_t *mp;
8187 8183          qband_t *qbp;
8188 8184          long sd_flags = stp->sd_flag;
8189 8185          int headlocked = 0;
8190 8186  
8191 8187          /*
8192 8188           * For performance, a single 'if' tests for most possible edge
↓ open down ↓ 116 lines elided ↑ open up ↑
8309 8305                                          mp = mp->b_next;
8310 8306                                          continue;
8311 8307                                  }
8312 8308                          }
8313 8309                          if (mp->b_band == 0)
8314 8310                                  retevents |= normevents;
8315 8311                          else
8316 8312                                  retevents |= (events & (POLLIN | POLLRDBAND));
8317 8313                          break;
8318 8314                  }
8319      -                if (! (retevents & normevents) &&
8320      -                    (stp->sd_wakeq & RSLEEP)) {
     8315 +                if (!(retevents & normevents) && (stp->sd_wakeq & RSLEEP)) {
8321 8316                          /*
8322 8317                           * Sync stream barrier read queue has data.
8323 8318                           */
8324 8319                          retevents |= normevents;
8325 8320                  }
8326 8321                  /* Treat eof as normal data */
8327 8322                  if (sd_flags & STREOF)
8328 8323                          retevents |= normevents;
8329 8324          }
8330 8325  
8331      -        *reventsp = (short)retevents;
8332      -        if (retevents && !(events & POLLET)) {
8333      -                if (headlocked)
8334      -                        mutex_exit(&stp->sd_lock);
8335      -                return (0);
8336      -        }
8337      -
8338 8326          /*
8339      -         * If poll() has not found any events yet, set up event cell
8340      -         * to wake up the poll if a requested event occurs on this
8341      -         * stream.  Check for collisions with outstanding poll requests.
     8327 +         * Pass back a pollhead if no events are pending or if edge-triggering
     8328 +         * has been configured on this resource.
8342 8329           */
8343      -        if (!anyyet) {
     8330 +        if ((retevents == 0 && !anyyet) || (events & POLLET)) {
8344 8331                  *phpp = &stp->sd_pollist;
8345 8332                  if (headlocked == 0) {
8346 8333                          if (polllock(&stp->sd_pollist, &stp->sd_lock) != 0) {
8347 8334                                  *reventsp = POLLNVAL;
8348 8335                                  return (0);
8349 8336                          }
8350 8337                          headlocked = 1;
8351 8338                  }
8352 8339                  stp->sd_rput_opt |= SR_POLLIN;
8353 8340          }
     8341 +
     8342 +        *reventsp = (short)retevents;
8354 8343          if (headlocked)
8355 8344                  mutex_exit(&stp->sd_lock);
8356 8345          return (0);
8357 8346  }
8358 8347  
8359 8348  /*
8360 8349   * The purpose of putback() is to assure sleeping polls/reads
8361 8350   * are awakened when there are no new messages arriving at the,
8362 8351   * stream head, and a message is placed back on the read queue.
8363 8352   *
↓ open down ↓ 274 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX