The following issue has been SUBMITTED. 
====================================================================== 
http://austingroupbugs.net/view.php?id=1263 
====================================================================== 
Reported By:                eblake
Assigned To:                
====================================================================== 
Project:                    1003.1(2016)/Issue7+TC2
Issue ID:                   1263
Category:                   System Interfaces
Type:                       Omission
Severity:                   Objection
Priority:                   normal
Status:                     New
Name:                       Eric Blake 
Organization:               Red Hat 
User Reference:             ebb.ppoll 
Section:                    poll 
Page Number:                1433 
Line Number:                47551 
Interp Status:              --- 
Final Accepted Text:         
====================================================================== 
Date Submitted:             2019-06-18 12:04 UTC
Last Modified:              2019-06-18 12:04 UTC
====================================================================== 
Summary:                    Add ppoll( )
Description: 
The [p]select() interfaces do NOT scale well at handling large numbers of
file descriptors.  To begin with, the select() interface requires a lot of
boilerplate and is destructive (you must rebuild the list of fds prior to
each call) when compared to poll() (the separation of events and revents
means you don't have to rebuild the list).  What's more, the larger the fd,
the more bits that have to be scanned even if there are the same number of
file descriptors being acted on, and the list is inherently capped at
FD_SETSIZE even if you can obtain a larger file descriptor. 
https://beesbuzz.biz/code/5739-The-problem-with-select-vs-poll is a good
summary of arguments why poll() is better than select().

However, there is one thing that pselect() can do that poll() cannot - and
that is atomic safety of handling blocked signals.  Several operating
systems provide ppoll() as a counterpart to poll() to match how pselect()
improves select(), and it is high time that we standardize this interface. 
This proposal uses FreeBSD and Linux for guidance:
https://www.freebsd.org/cgi/man.cgi?query=ppoll&apropos=0&sektion=2&manpath=FreeBSD+12.0-RELEASE+and+Ports&arch=default&format=html
https://linux.die.net/man/2/ppoll

Desired Action: 
On page 313 after line 10605 (XBD <poll.h>), insert:<blockquote>The
<poll.h> header shall define the sigset_t type as described in <signal.h>.
The <poll.h> header shall define the timespec structure as described in
<time.h>.</blockquote>

On page 313 line 10621 (XBD <poll.h>), change:<blockquote>The following
shall be declared as a function and may also be defined as a macro. A
function prototype shall be provided.
int  poll(struct pollfd [], nfds_t, int);</blockquote>to:<blockquote>
The following shall be declared as functions and may also be defined as
macros. Function prototypes shall be provided.
int  poll(struct pollfd [], nfds_t, int);
int ppoll(struct pollfd [], nfds_t, const struct timespec *restrict, const
sigset_t *restrict);
Inclusion of the <poll.h> header may make visible all symbols from the
headers
<signal.h> and <time.h>.</blockquote>

Add "<i>ppoll</i>( )" with correct sorting to the following lists:
page 494 line 17130 (XBD 2.4.3 Signal Actions list of async-safe
functions)
page 501 line 17418 (XBD 2.6.1 Accessing STREAMS)
page 518 line 18123 (XBD 2.9.5.2 Cancellation Points)
page 626 line 21649 (XSH bind DESCRIPTION)
page 702 line 24051 (XSH connect DESCRIPTION)
page 3790 line 130053 (XRAT E.1 Subprofiling Option Groups
POSIX_DEVICE_IO)


At page 1433 line 47552 (XSH poll NAME),
change:<blockquote>poll</blockquote>to:<blockquote>poll,
ppoll</blockquote>

After page 1433 line 47555 (XSH poll SYNOPSIS), insert:<blockquote>int
ppoll(struct pollfd <i>fds</i>[], nfds_t <i>nfds</i>, const struct timespec
*restrict <i>timeout</i>, const sigset_t *restrict
<i>sigmask</i>);</blockquote>

At page 1433 lines 47557-47561 (XSH poll DESCRIPTION),
change:<blockquote>The <i>poll</i>( ) function provides applications with a
mechanism for multiplexing input/output over a set of file descriptors. For
each member of the array pointed to by <i>fds</i>, <i>poll</i>( ) shall
examine the given file descriptor for the event(s) specified in
<i>events</i>. The number of <b>pollfd</b> structures in the <i>fds</i>
array is specified by <i>nfds</i>. The <i>poll</i>( ) function shall
identify those file descriptors on which an application can read or write
data, or on which certain events have
occurred.</blockquote>to:<blockquote>The <i>ppoll</i>( ) function provides
applications with a mechanism for multiplexing input/output over a set of
file descriptors. For each member of the array pointed to by <i>fds</i>,
<i>ppoll</i>( ) shall examine the given file descriptor for the event(s)
specified in <i>events</i>. The number of <b>pollfd</b> structures in the
<i>fds</i> array is specified by <i>nfds</i>. The <i>ppoll</i>( ) function
shall identify those file descriptors on which an application can read or
write data, or on which certain events have occurred.

The <i>poll</i>( ) function shall be equivalent to the <i>ppoll</i>( )
function, except as follows:
• For the <i>poll</i>( ) function, the timeout period is given in
milliseconds in an argument of type <b>int</b>, whereas for the
<i>ppoll</i>( ) function the timeout period is given in seconds and
nanoseconds in an argument of type <b>struct timespec</b>. A <i>timeout</i>
of -1 for <i>poll</i>( ) is equivalent to passing a null pointer for the
<i>timeout</i> for <i>ppoll</i>( ).
• The <i>poll</i>( ) function has no <i>sigmask</i> argument; it shall
behave as <i>ppoll</i>( ) does when <i>sigmask</i> is a null
pointer.</blockquote>

On page 1434 (XSH poll APPLICATION USAGE, RETURN VALUE, ERRORS), change the
following instances of "<i>poll</i>( )" to "<i>poll</i>( ) or <i>ppoll</i>(
)":
line 47600
line 47601
line 47602
line 47603
line 47613
line 47614
line 47615
line 47623
line 47625
line 47628
line 47630
line 47633

At page 1434 lines 47606-47609 (XSH poll DESCRIPTION),
change:<blockquote>If none of the defined events have occurred on any
selected file descriptor, <i>poll</i>( ) shall wait at least <i>timeout</i>
milliseconds for an event to occur on any of the selected file descriptors.
If the value of <i>timeout</i> is 0, <i>poll</i>( ) shall return
immediately. If the value of <i>timeout</i> is −1, <i>poll</i>( ) shall
block until a requested event occurs or until the call is interrupted.
Implementations may place limitations on the
granularity</blockquote>to:<blockquote>The <i>timeout</i> parameter
controls how long the <i>poll</i>( ) or <i>ppoll</i>( ) function shall take
before timing out. If the <i>timeout</i> parameter is positive for
<i>poll</i>( ) or not a null pointer for <i>ppoll</i>( ), it specifies a
maximum interval to wait for the poll to complete. If the specified time
interval expires without any requested operation becoming ready, the
function shall return.  If the <i>timeout</i> parameter is -1 for
<i>poll</i>( ) or a null pointer for <i>ppoll</i>( ), then the call shall
block indefinitely until at least one descriptor meets the specified
criteria. To effect a poll, the <i>timeout</i> parameter should be 0 for
<i>poll</i>( ), or for <i>ppoll</i>( ) should not be a null pointer, and
should point to a zero-valued <b>timespec</b> structure.
Implementations may place limitations on the maximum timeout interval
supported. All implementations shall support a maximum timeout interval of
at least 31 days for <i>ppoll</i>( ). If the <i>timeout</i> argument
specifies a timeout interval greater than the implementation-defined
maximum value, the maximum value shall be used as the actual timeout value.
Implementations may also place limitations on the granularity</blockquote>

After page 1434 line 47623 (XSH poll DESCRIPTION), insert:<blockquote>If
<i>sigmask</i> is not a null pointer, then the <i>ppoll</i>( ) function
shall replace the signal mask of the caller by the set of signals pointed
to by <i>sigmask</i> before examining the descriptors, and shall restore
the signal mask of the calling thread before returning.

If a thread gets canceled during a <i>ppoll( ) call, the signal mask in
effect when executing the registered cleanup functions is either the
original signal mask or the signal mask installed as part of the
<i>ppoll</i>( ) call.</blockquote>

After page 1434 line 47636 (XSH poll ERRORS), insert:<blockquote>The
<i>ppoll</i>( ) function shall fail if:
[EINVAL] An invalid timeout interval was specified.</blockquote>

At page 1436 line 47691 (XSH poll APPLICATION USAGE),
change:<blockquote>None.</blockquote>to:<blockquote>Other than the
difference in the precision of the timeout argument, the following
<i>ppoll</i>( ) call:
<code>ready = ppoll(&fds, nfds, tmo_p, &sigmask);</code>
is equivalent to atomically executing the following calls:
<code>sigset_t origmask;
int timeout;

timeout = (tmo_p == NULL) ? -1 :
  (tmo_p->tv_sec * 1000 + tmo_p->tv_nsec / 1000000);
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
ready = poll(&fds, nfds, timeout);
pthread_sigmask(SIG_SETMASK, &origmask, NULL);</code></blockquote>

After page 1436 line 47695 (XSH poll RATIONALE), insert:<blockquote>Code
which wants to avoid the ambiguity of the signal mask for thread
cancellation handlers can install an additional cancellation handler which
resets the signal mask to the expected value.
<code>void cleanup(void *arg)
{
  sigset_t *ss = (sigset_t *) arg;
  pthread_sigmask(SIG_SETMASK, ss, NULL);
}
int call_ppoll(struct pollfd fds[], nfds_t nfds, const struct timespec
*restrict timeout, const sigset_t *restrict sigmask)
{
  sigset_t oldmask;
  int result;
  pthread_sigmask(SIG_SETMASK, NULL, &oldmask);
  pthread_cleanup_push(cleanup, &oldmask);
  result = ppoll(fds, nfds, timeout, sigmask);
  pthread_cleanup_pop(0);
  return result;
}</code></blockquote>

At page 1556 line 50968 (XSH pselect APPLICATION USAGE),
change:<blockquote>None.</blockquote>to:<blockquote>The use of select( )
and pselect( ) requires that the application construct the set of fds to
work on each time through a polling loop, and is inherently limited from
operating on file descriptors larger than FD_SETSIZE.  Also, the amount of
work to perform scales as <i>nfds</i> increases, even if the number of file
descriptors selected within the larger set remains the same.  Thus,
applications may wish to consider using poll( ) and ppoll( ) instead, for
better scaling.</blockquote>

After page 1550 (between XSH pow and pread), insert a new
page:<blockquote>NAME
ppoll select — input/output multiplexing
SYNOPSIS
#include <poll.h>
int ppoll(struct pollfd [], nfds_t, const struct timespec *restrict, const
sigset_t *restrict);
DESCRIPTION
Refer to poll( ).</blockquote>

Include ppoll if XRAT B.1.1 Change History lists new interfaces for issue
8,  (compare page 3563 line 120849 listing poll for issue 7).

====================================================================== 

Issue History 
Date Modified    Username       Field                    Change               
====================================================================== 
2019-06-18 12:04 eblake         New Issue                                    
2019-06-18 12:04 eblake         Name                      => Eric Blake      
2019-06-18 12:04 eblake         Organization              => Red Hat         
2019-06-18 12:04 eblake         User Reference            => ebb.ppoll       
2019-06-18 12:04 eblake         Section                   => poll            
2019-06-18 12:04 eblake         Page Number               => 1433            
2019-06-18 12:04 eblake         Line Number               => 47551           
2019-06-18 12:04 eblake         Interp Status             => ---             
======================================================================


Reply via email to