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>


   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  22 /*        All Rights Reserved   */
  23 
  24 
  25 /*
  26  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  27  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  28  */
  29 
  30 #include <sys/types.h>
  31 #include <sys/sysmacros.h>
  32 #include <sys/param.h>
  33 #include <sys/errno.h>
  34 #include <sys/signal.h>
  35 #include <sys/stat.h>
  36 #include <sys/proc.h>
  37 #include <sys/cred.h>
  38 #include <sys/user.h>
  39 #include <sys/vnode.h>
  40 #include <sys/file.h>
  41 #include <sys/stream.h>
  42 #include <sys/strsubr.h>
  43 #include <sys/stropts.h>
  44 #include <sys/tihdr.h>
  45 #include <sys/var.h>
  46 #include <sys/poll.h>
  47 #include <sys/termio.h>


8157 
8158 /*
8159  * Determines whether the necessary conditions are set on a stream
8160  * for it to be readable, writeable, or have exceptions.
8161  *
8162  * strpoll handles the consolidation private events:
8163  *      POLLNOERR       Do not return POLLERR even if there are stream
8164  *                      head errors.
8165  *                      Used by sockfs.
8166  *      POLLRDDATA      Do not return POLLIN unless at least one message on
8167  *                      the queue contains one or more M_DATA mblks. Thus
8168  *                      when this flag is set a queue with only
8169  *                      M_PROTO/M_PCPROTO mblks does not return POLLIN.
8170  *                      Used by sockfs to ignore T_EXDATA_IND messages.
8171  *
8172  * Note: POLLRDDATA assumes that synch streams only return messages with
8173  * an M_DATA attached (i.e. not messages consisting of only
8174  * an M_PROTO/M_PCPROTO part).
8175  */
8176 int
8177 strpoll(
8178         struct stdata *stp,
8179         short events_arg,
8180         int anyyet,
8181         short *reventsp,
8182         struct pollhead **phpp)
8183 {
8184         int events = (ushort_t)events_arg;
8185         int retevents = 0;
8186         mblk_t *mp;
8187         qband_t *qbp;
8188         long sd_flags = stp->sd_flag;
8189         int headlocked = 0;
8190 
8191         /*
8192          * For performance, a single 'if' tests for most possible edge
8193          * conditions in one shot
8194          */
8195         if (sd_flags & (STPLEX | STRDERR | STWRERR)) {
8196                 if (sd_flags & STPLEX) {
8197                         *reventsp = POLLNVAL;
8198                         return (EINVAL);
8199                 }
8200                 if (((events & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) &&
8201                     (sd_flags & STRDERR)) ||


8299                          * find an M_DATA.
8300                          */
8301                         if ((events & POLLRDDATA) &&
8302                             mp->b_datap->db_type != M_DATA) {
8303                                 mblk_t *nmp = mp->b_cont;
8304 
8305                                 while (nmp != NULL &&
8306                                     nmp->b_datap->db_type != M_DATA)
8307                                         nmp = nmp->b_cont;
8308                                 if (nmp == NULL) {
8309                                         mp = mp->b_next;
8310                                         continue;
8311                                 }
8312                         }
8313                         if (mp->b_band == 0)
8314                                 retevents |= normevents;
8315                         else
8316                                 retevents |= (events & (POLLIN | POLLRDBAND));
8317                         break;
8318                 }
8319                 if (! (retevents & normevents) &&
8320                     (stp->sd_wakeq & RSLEEP)) {
8321                         /*
8322                          * Sync stream barrier read queue has data.
8323                          */
8324                         retevents |= normevents;
8325                 }
8326                 /* Treat eof as normal data */
8327                 if (sd_flags & STREOF)
8328                         retevents |= normevents;
8329         }
8330 
8331         *reventsp = (short)retevents;
8332         if (retevents && !(events & POLLET)) {
8333                 if (headlocked)
8334                         mutex_exit(&stp->sd_lock);
8335                 return (0);
8336         }
8337 
8338         /*
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.
8342          */
8343         if (!anyyet) {
8344                 *phpp = &stp->sd_pollist;
8345                 if (headlocked == 0) {
8346                         if (polllock(&stp->sd_pollist, &stp->sd_lock) != 0) {
8347                                 *reventsp = POLLNVAL;
8348                                 return (0);
8349                         }
8350                         headlocked = 1;
8351                 }
8352                 stp->sd_rput_opt |= SR_POLLIN;
8353         }


8354         if (headlocked)
8355                 mutex_exit(&stp->sd_lock);
8356         return (0);
8357 }
8358 
8359 /*
8360  * The purpose of putback() is to assure sleeping polls/reads
8361  * are awakened when there are no new messages arriving at the,
8362  * stream head, and a message is placed back on the read queue.
8363  *
8364  * sd_lock must be held when messages are placed back on stream
8365  * head.  (getq() holds sd_lock when it removes messages from
8366  * the queue)
8367  */
8368 
8369 static void
8370 putback(struct stdata *stp, queue_t *q, mblk_t *bp, int band)
8371 {
8372         mblk_t  *qfirst;
8373         ASSERT(MUTEX_HELD(&stp->sd_lock));




   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  22 /*        All Rights Reserved   */
  23 
  24 
  25 /*
  26  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  27  * Copyright 2017 Joyent, Inc.
  28  */
  29 
  30 #include <sys/types.h>
  31 #include <sys/sysmacros.h>
  32 #include <sys/param.h>
  33 #include <sys/errno.h>
  34 #include <sys/signal.h>
  35 #include <sys/stat.h>
  36 #include <sys/proc.h>
  37 #include <sys/cred.h>
  38 #include <sys/user.h>
  39 #include <sys/vnode.h>
  40 #include <sys/file.h>
  41 #include <sys/stream.h>
  42 #include <sys/strsubr.h>
  43 #include <sys/stropts.h>
  44 #include <sys/tihdr.h>
  45 #include <sys/var.h>
  46 #include <sys/poll.h>
  47 #include <sys/termio.h>


8157 
8158 /*
8159  * Determines whether the necessary conditions are set on a stream
8160  * for it to be readable, writeable, or have exceptions.
8161  *
8162  * strpoll handles the consolidation private events:
8163  *      POLLNOERR       Do not return POLLERR even if there are stream
8164  *                      head errors.
8165  *                      Used by sockfs.
8166  *      POLLRDDATA      Do not return POLLIN unless at least one message on
8167  *                      the queue contains one or more M_DATA mblks. Thus
8168  *                      when this flag is set a queue with only
8169  *                      M_PROTO/M_PCPROTO mblks does not return POLLIN.
8170  *                      Used by sockfs to ignore T_EXDATA_IND messages.
8171  *
8172  * Note: POLLRDDATA assumes that synch streams only return messages with
8173  * an M_DATA attached (i.e. not messages consisting of only
8174  * an M_PROTO/M_PCPROTO part).
8175  */
8176 int
8177 strpoll(struct stdata *stp, short events_arg, int anyyet, short *reventsp,




8178     struct pollhead **phpp)
8179 {
8180         int events = (ushort_t)events_arg;
8181         int retevents = 0;
8182         mblk_t *mp;
8183         qband_t *qbp;
8184         long sd_flags = stp->sd_flag;
8185         int headlocked = 0;
8186 
8187         /*
8188          * For performance, a single 'if' tests for most possible edge
8189          * conditions in one shot
8190          */
8191         if (sd_flags & (STPLEX | STRDERR | STWRERR)) {
8192                 if (sd_flags & STPLEX) {
8193                         *reventsp = POLLNVAL;
8194                         return (EINVAL);
8195                 }
8196                 if (((events & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) &&
8197                     (sd_flags & STRDERR)) ||


8295                          * find an M_DATA.
8296                          */
8297                         if ((events & POLLRDDATA) &&
8298                             mp->b_datap->db_type != M_DATA) {
8299                                 mblk_t *nmp = mp->b_cont;
8300 
8301                                 while (nmp != NULL &&
8302                                     nmp->b_datap->db_type != M_DATA)
8303                                         nmp = nmp->b_cont;
8304                                 if (nmp == NULL) {
8305                                         mp = mp->b_next;
8306                                         continue;
8307                                 }
8308                         }
8309                         if (mp->b_band == 0)
8310                                 retevents |= normevents;
8311                         else
8312                                 retevents |= (events & (POLLIN | POLLRDBAND));
8313                         break;
8314                 }
8315                 if (!(retevents & normevents) && (stp->sd_wakeq & RSLEEP)) {

8316                         /*
8317                          * Sync stream barrier read queue has data.
8318                          */
8319                         retevents |= normevents;
8320                 }
8321                 /* Treat eof as normal data */
8322                 if (sd_flags & STREOF)
8323                         retevents |= normevents;
8324         }
8325 







8326         /*
8327          * Pass back a pollhead if no events are pending or if edge-triggering
8328          * has been configured on this resource.

8329          */
8330         if ((retevents == 0 && !anyyet) || (events & POLLET)) {
8331                 *phpp = &stp->sd_pollist;
8332                 if (headlocked == 0) {
8333                         if (polllock(&stp->sd_pollist, &stp->sd_lock) != 0) {
8334                                 *reventsp = POLLNVAL;
8335                                 return (0);
8336                         }
8337                         headlocked = 1;
8338                 }
8339                 stp->sd_rput_opt |= SR_POLLIN;
8340         }
8341 
8342         *reventsp = (short)retevents;
8343         if (headlocked)
8344                 mutex_exit(&stp->sd_lock);
8345         return (0);
8346 }
8347 
8348 /*
8349  * The purpose of putback() is to assure sleeping polls/reads
8350  * are awakened when there are no new messages arriving at the,
8351  * stream head, and a message is placed back on the read queue.
8352  *
8353  * sd_lock must be held when messages are placed back on stream
8354  * head.  (getq() holds sd_lock when it removes messages from
8355  * the queue)
8356  */
8357 
8358 static void
8359 putback(struct stdata *stp, queue_t *q, mblk_t *bp, int band)
8360 {
8361         mblk_t  *qfirst;
8362         ASSERT(MUTEX_HELD(&stp->sd_lock));