bpo-41001: Add os.eventfd() (#20930)
Co-authored-by: Kyle Stanley <aeros167@gmail.com>
This commit is contained in:
parent
bbeb2d266d
commit
cd9fed6afb
|
@ -3276,6 +3276,102 @@ features:
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: eventfd(initval[, flags=os.EFD_CLOEXEC])
|
||||||
|
|
||||||
|
Create and return an event file descriptor. The file descriptors supports
|
||||||
|
raw :func:`read` and :func:`write` with a buffer size of 8,
|
||||||
|
:func:`~select.select`, :func:`~select.poll` and similar. See man page
|
||||||
|
:manpage:`eventfd(2)` for more information. By default, the
|
||||||
|
new file descriptor is :ref:`non-inheritable <fd_inheritance>`.
|
||||||
|
|
||||||
|
*initval* is the initial value of the event counter. The initial value
|
||||||
|
must be an 32 bit unsigned integer. Please note that the initial value is
|
||||||
|
limited to a 32 bit unsigned int although the event counter is an unsigned
|
||||||
|
64 bit integer with a maximum value of 2\ :sup:`64`\ -\ 2.
|
||||||
|
|
||||||
|
*flags* can be constructed from :const:`EFD_CLOEXEC`,
|
||||||
|
:const:`EFD_NONBLOCK`, and :const:`EFD_SEMAPHORE`.
|
||||||
|
|
||||||
|
If :const:`EFD_SEMAPHORE` is specified and the event counter is non-zero,
|
||||||
|
:func:`eventfd_read` returns 1 and decrements the counter by one.
|
||||||
|
|
||||||
|
If :const:`EFD_SEMAPHORE` is not specified and the event counter is
|
||||||
|
non-zero, :func:`eventfd_read` returns the current event counter value and
|
||||||
|
resets the counter to zero.
|
||||||
|
|
||||||
|
If the event counter is zero and :const:`EFD_NONBLOCK` is not
|
||||||
|
specified, :func:`eventfd_read` blocks.
|
||||||
|
|
||||||
|
:func:`eventfd_write` increments the event counter. Write blocks if the
|
||||||
|
write operation would increment the counter to a value larger than
|
||||||
|
2\ :sup:`64`\ -\ 2.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
# semaphore with start value '1'
|
||||||
|
fd = os.eventfd(1, os.EFD_SEMAPHORE | os.EFC_CLOEXEC)
|
||||||
|
try:
|
||||||
|
# acquire semaphore
|
||||||
|
v = os.eventfd_read(fd)
|
||||||
|
try:
|
||||||
|
do_work()
|
||||||
|
finally:
|
||||||
|
# release semaphore
|
||||||
|
os.eventfd_write(fd, v)
|
||||||
|
finally:
|
||||||
|
os.close(fd)
|
||||||
|
|
||||||
|
.. availability:: Linux 2.6.27 or newer with glibc 2.8 or newer.
|
||||||
|
|
||||||
|
.. versionadded:: 3.10
|
||||||
|
|
||||||
|
.. function:: eventfd_read(fd)
|
||||||
|
|
||||||
|
Read value from an :func:`eventfd` file descriptor and return a 64 bit
|
||||||
|
unsigned int. The function does not verify that *fd* is an :func:`eventfd`.
|
||||||
|
|
||||||
|
.. availability:: See :func:`eventfd`
|
||||||
|
|
||||||
|
.. versionadded:: 3.10
|
||||||
|
|
||||||
|
.. function:: eventfd_write(fd, value)
|
||||||
|
|
||||||
|
Add value to an :func:`eventfd` file descriptor. *value* must be a 64 bit
|
||||||
|
unsigned int. The function does not verify that *fd* is an :func:`eventfd`.
|
||||||
|
|
||||||
|
.. availability:: See :func:`eventfd`
|
||||||
|
|
||||||
|
.. versionadded:: 3.10
|
||||||
|
|
||||||
|
.. data:: EFD_CLOEXEC
|
||||||
|
|
||||||
|
Set close-on-exec flag for new :func:`eventfd` file descriptor.
|
||||||
|
|
||||||
|
.. availability:: See :func:`eventfd`
|
||||||
|
|
||||||
|
.. versionadded:: 3.10
|
||||||
|
|
||||||
|
.. data:: EFD_NONBLOCK
|
||||||
|
|
||||||
|
Set :const:`O_NONBLOCK` status flag for new :func:`eventfd` file
|
||||||
|
descriptor.
|
||||||
|
|
||||||
|
.. availability:: See :func:`eventfd`
|
||||||
|
|
||||||
|
.. versionadded:: 3.10
|
||||||
|
|
||||||
|
.. data:: EFD_SEMAPHORE
|
||||||
|
|
||||||
|
Provide semaphore-like semantics for reads from a :func:`eventfd` file
|
||||||
|
descriptor. On read the internal counter is decremented by one.
|
||||||
|
|
||||||
|
.. availability:: Linux 2.6.30 or newer with glibc 2.8 or newer.
|
||||||
|
|
||||||
|
.. versionadded:: 3.10
|
||||||
|
|
||||||
|
|
||||||
Linux extended attributes
|
Linux extended attributes
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -229,6 +229,10 @@ os
|
||||||
Added :func:`os.cpu_count()` support for VxWorks RTOS.
|
Added :func:`os.cpu_count()` support for VxWorks RTOS.
|
||||||
(Contributed by Peixing Xin in :issue:`41440`.)
|
(Contributed by Peixing Xin in :issue:`41440`.)
|
||||||
|
|
||||||
|
Added a new function :func:`os.eventfd` and related helpers to wrap the
|
||||||
|
``eventfd2`` syscall on Linux.
|
||||||
|
(Contributed by Christian Heimes in :issue:`41001`.)
|
||||||
|
|
||||||
py_compile
|
py_compile
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,12 @@ import locale
|
||||||
import mmap
|
import mmap
|
||||||
import os
|
import os
|
||||||
import pickle
|
import pickle
|
||||||
|
import select
|
||||||
import shutil
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
import socket
|
import socket
|
||||||
import stat
|
import stat
|
||||||
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import sysconfig
|
import sysconfig
|
||||||
|
@ -59,6 +61,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
|
INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
|
||||||
|
|
||||||
|
|
||||||
from test.support.script_helper import assert_python_ok
|
from test.support.script_helper import assert_python_ok
|
||||||
from test.support import unix_shell
|
from test.support import unix_shell
|
||||||
from test.support.os_helper import FakePath
|
from test.support.os_helper import FakePath
|
||||||
|
@ -3528,6 +3531,89 @@ class MemfdCreateTests(unittest.TestCase):
|
||||||
self.assertFalse(os.get_inheritable(fd2))
|
self.assertFalse(os.get_inheritable(fd2))
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'eventfd'), 'requires os.eventfd')
|
||||||
|
@support.requires_linux_version(2, 6, 30)
|
||||||
|
class EventfdTests(unittest.TestCase):
|
||||||
|
def test_eventfd_initval(self):
|
||||||
|
def pack(value):
|
||||||
|
"""Pack as native uint64_t
|
||||||
|
"""
|
||||||
|
return struct.pack("@Q", value)
|
||||||
|
size = 8 # read/write 8 bytes
|
||||||
|
initval = 42
|
||||||
|
fd = os.eventfd(initval)
|
||||||
|
self.assertNotEqual(fd, -1)
|
||||||
|
self.addCleanup(os.close, fd)
|
||||||
|
self.assertFalse(os.get_inheritable(fd))
|
||||||
|
|
||||||
|
# test with raw read/write
|
||||||
|
res = os.read(fd, size)
|
||||||
|
self.assertEqual(res, pack(initval))
|
||||||
|
|
||||||
|
os.write(fd, pack(23))
|
||||||
|
res = os.read(fd, size)
|
||||||
|
self.assertEqual(res, pack(23))
|
||||||
|
|
||||||
|
os.write(fd, pack(40))
|
||||||
|
os.write(fd, pack(2))
|
||||||
|
res = os.read(fd, size)
|
||||||
|
self.assertEqual(res, pack(42))
|
||||||
|
|
||||||
|
# test with eventfd_read/eventfd_write
|
||||||
|
os.eventfd_write(fd, 20)
|
||||||
|
os.eventfd_write(fd, 3)
|
||||||
|
res = os.eventfd_read(fd)
|
||||||
|
self.assertEqual(res, 23)
|
||||||
|
|
||||||
|
def test_eventfd_semaphore(self):
|
||||||
|
initval = 2
|
||||||
|
flags = os.EFD_CLOEXEC | os.EFD_SEMAPHORE | os.EFD_NONBLOCK
|
||||||
|
fd = os.eventfd(initval, flags)
|
||||||
|
self.assertNotEqual(fd, -1)
|
||||||
|
self.addCleanup(os.close, fd)
|
||||||
|
|
||||||
|
# semaphore starts has initval 2, two reads return '1'
|
||||||
|
res = os.eventfd_read(fd)
|
||||||
|
self.assertEqual(res, 1)
|
||||||
|
res = os.eventfd_read(fd)
|
||||||
|
self.assertEqual(res, 1)
|
||||||
|
# third read would block
|
||||||
|
with self.assertRaises(BlockingIOError):
|
||||||
|
os.eventfd_read(fd)
|
||||||
|
with self.assertRaises(BlockingIOError):
|
||||||
|
os.read(fd, 8)
|
||||||
|
|
||||||
|
# increase semaphore counter, read one
|
||||||
|
os.eventfd_write(fd, 1)
|
||||||
|
res = os.eventfd_read(fd)
|
||||||
|
self.assertEqual(res, 1)
|
||||||
|
# next read would block, too
|
||||||
|
with self.assertRaises(BlockingIOError):
|
||||||
|
os.eventfd_read(fd)
|
||||||
|
|
||||||
|
def test_eventfd_select(self):
|
||||||
|
flags = os.EFD_CLOEXEC | os.EFD_NONBLOCK
|
||||||
|
fd = os.eventfd(0, flags)
|
||||||
|
self.assertNotEqual(fd, -1)
|
||||||
|
self.addCleanup(os.close, fd)
|
||||||
|
|
||||||
|
# counter is zero, only writeable
|
||||||
|
rfd, wfd, xfd = select.select([fd], [fd], [fd], 0)
|
||||||
|
self.assertEqual((rfd, wfd, xfd), ([], [fd], []))
|
||||||
|
|
||||||
|
# counter is non-zero, read and writeable
|
||||||
|
os.eventfd_write(fd, 23)
|
||||||
|
rfd, wfd, xfd = select.select([fd], [fd], [fd], 0)
|
||||||
|
self.assertEqual((rfd, wfd, xfd), ([fd], [fd], []))
|
||||||
|
self.assertEqual(os.eventfd_read(fd), 23)
|
||||||
|
|
||||||
|
# counter at max, only readable
|
||||||
|
os.eventfd_write(fd, (2**64) - 2)
|
||||||
|
rfd, wfd, xfd = select.select([fd], [fd], [fd], 0)
|
||||||
|
self.assertEqual((rfd, wfd, xfd), ([fd], [], []))
|
||||||
|
os.eventfd_read(fd)
|
||||||
|
|
||||||
|
|
||||||
class OSErrorTests(unittest.TestCase):
|
class OSErrorTests(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
class Str(str):
|
class Str(str):
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Add func:`os.eventfd` to provide a low level interface for Linux's event
|
||||||
|
notification file descriptor.
|
|
@ -7620,6 +7620,134 @@ exit:
|
||||||
|
|
||||||
#endif /* defined(HAVE_MEMFD_CREATE) */
|
#endif /* defined(HAVE_MEMFD_CREATE) */
|
||||||
|
|
||||||
|
#if defined(HAVE_EVENTFD)
|
||||||
|
|
||||||
|
PyDoc_STRVAR(os_eventfd__doc__,
|
||||||
|
"eventfd($module, /, initval, flags=EFD_CLOEXEC)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Creates and returns an event notification file descriptor.");
|
||||||
|
|
||||||
|
#define OS_EVENTFD_METHODDEF \
|
||||||
|
{"eventfd", (PyCFunction)(void(*)(void))os_eventfd, METH_FASTCALL|METH_KEYWORDS, os_eventfd__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_eventfd_impl(PyObject *module, unsigned int initval, int flags);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_eventfd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
static const char * const _keywords[] = {"initval", "flags", NULL};
|
||||||
|
static _PyArg_Parser _parser = {NULL, _keywords, "eventfd", 0};
|
||||||
|
PyObject *argsbuf[2];
|
||||||
|
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
|
||||||
|
unsigned int initval;
|
||||||
|
int flags = EFD_CLOEXEC;
|
||||||
|
|
||||||
|
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
|
||||||
|
if (!args) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!_PyLong_UnsignedInt_Converter(args[0], &initval)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!noptargs) {
|
||||||
|
goto skip_optional_pos;
|
||||||
|
}
|
||||||
|
flags = _PyLong_AsInt(args[1]);
|
||||||
|
if (flags == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
skip_optional_pos:
|
||||||
|
return_value = os_eventfd_impl(module, initval, flags);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined(HAVE_EVENTFD) */
|
||||||
|
|
||||||
|
#if defined(HAVE_EVENTFD)
|
||||||
|
|
||||||
|
PyDoc_STRVAR(os_eventfd_read__doc__,
|
||||||
|
"eventfd_read($module, /, fd)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Read eventfd value");
|
||||||
|
|
||||||
|
#define OS_EVENTFD_READ_METHODDEF \
|
||||||
|
{"eventfd_read", (PyCFunction)(void(*)(void))os_eventfd_read, METH_FASTCALL|METH_KEYWORDS, os_eventfd_read__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_eventfd_read_impl(PyObject *module, int fd);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_eventfd_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
static const char * const _keywords[] = {"fd", NULL};
|
||||||
|
static _PyArg_Parser _parser = {NULL, _keywords, "eventfd_read", 0};
|
||||||
|
PyObject *argsbuf[1];
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
|
||||||
|
if (!args) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
return_value = os_eventfd_read_impl(module, fd);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined(HAVE_EVENTFD) */
|
||||||
|
|
||||||
|
#if defined(HAVE_EVENTFD)
|
||||||
|
|
||||||
|
PyDoc_STRVAR(os_eventfd_write__doc__,
|
||||||
|
"eventfd_write($module, /, fd, value)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Write eventfd value.");
|
||||||
|
|
||||||
|
#define OS_EVENTFD_WRITE_METHODDEF \
|
||||||
|
{"eventfd_write", (PyCFunction)(void(*)(void))os_eventfd_write, METH_FASTCALL|METH_KEYWORDS, os_eventfd_write__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_eventfd_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
static const char * const _keywords[] = {"fd", "value", NULL};
|
||||||
|
static _PyArg_Parser _parser = {NULL, _keywords, "eventfd_write", 0};
|
||||||
|
PyObject *argsbuf[2];
|
||||||
|
int fd;
|
||||||
|
unsigned long long value;
|
||||||
|
|
||||||
|
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
|
||||||
|
if (!args) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!_PyLong_UnsignedLongLong_Converter(args[1], &value)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
return_value = os_eventfd_write_impl(module, fd, value);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined(HAVE_EVENTFD) */
|
||||||
|
|
||||||
#if (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL))
|
#if (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL))
|
||||||
|
|
||||||
PyDoc_STRVAR(os_get_terminal_size__doc__,
|
PyDoc_STRVAR(os_get_terminal_size__doc__,
|
||||||
|
@ -8884,6 +9012,18 @@ exit:
|
||||||
#define OS_MEMFD_CREATE_METHODDEF
|
#define OS_MEMFD_CREATE_METHODDEF
|
||||||
#endif /* !defined(OS_MEMFD_CREATE_METHODDEF) */
|
#endif /* !defined(OS_MEMFD_CREATE_METHODDEF) */
|
||||||
|
|
||||||
|
#ifndef OS_EVENTFD_METHODDEF
|
||||||
|
#define OS_EVENTFD_METHODDEF
|
||||||
|
#endif /* !defined(OS_EVENTFD_METHODDEF) */
|
||||||
|
|
||||||
|
#ifndef OS_EVENTFD_READ_METHODDEF
|
||||||
|
#define OS_EVENTFD_READ_METHODDEF
|
||||||
|
#endif /* !defined(OS_EVENTFD_READ_METHODDEF) */
|
||||||
|
|
||||||
|
#ifndef OS_EVENTFD_WRITE_METHODDEF
|
||||||
|
#define OS_EVENTFD_WRITE_METHODDEF
|
||||||
|
#endif /* !defined(OS_EVENTFD_WRITE_METHODDEF) */
|
||||||
|
|
||||||
#ifndef OS_GET_TERMINAL_SIZE_METHODDEF
|
#ifndef OS_GET_TERMINAL_SIZE_METHODDEF
|
||||||
#define OS_GET_TERMINAL_SIZE_METHODDEF
|
#define OS_GET_TERMINAL_SIZE_METHODDEF
|
||||||
#endif /* !defined(OS_GET_TERMINAL_SIZE_METHODDEF) */
|
#endif /* !defined(OS_GET_TERMINAL_SIZE_METHODDEF) */
|
||||||
|
@ -8919,4 +9059,4 @@ exit:
|
||||||
#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF
|
#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF
|
||||||
#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF
|
#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF
|
||||||
#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */
|
#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */
|
||||||
/*[clinic end generated code: output=936f33448cd66ccb input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=49b7ed768242ef7c input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -518,6 +518,11 @@ extern char *ctermid_r(char *);
|
||||||
# include <linux/memfd.h>
|
# include <linux/memfd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* eventfd() */
|
||||||
|
#ifdef HAVE_SYS_EVENTFD_H
|
||||||
|
# include <sys/eventfd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _Py_MEMORY_SANITIZER
|
#ifdef _Py_MEMORY_SANITIZER
|
||||||
# include <sanitizer/msan_interface.h>
|
# include <sanitizer/msan_interface.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -12859,6 +12864,79 @@ os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
/*[clinic input]
|
||||||
|
os.eventfd
|
||||||
|
|
||||||
|
initval: unsigned_int
|
||||||
|
flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
|
||||||
|
|
||||||
|
Creates and returns an event notification file descriptor.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
|
||||||
|
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
|
||||||
|
|
||||||
|
{
|
||||||
|
/* initval is limited to uint32_t, internal counter is uint64_t */
|
||||||
|
int fd;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
fd = eventfd(initval, flags);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
if (fd == -1) {
|
||||||
|
return PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
}
|
||||||
|
return PyLong_FromLong(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
os.eventfd_read
|
||||||
|
|
||||||
|
fd: fildes
|
||||||
|
|
||||||
|
Read eventfd value
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_eventfd_read_impl(PyObject *module, int fd)
|
||||||
|
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
|
||||||
|
{
|
||||||
|
eventfd_t value;
|
||||||
|
int result;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
result = eventfd_read(fd, &value);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
if (result == -1) {
|
||||||
|
return PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
}
|
||||||
|
return PyLong_FromUnsignedLongLong(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
os.eventfd_write
|
||||||
|
|
||||||
|
fd: fildes
|
||||||
|
value: unsigned_long_long
|
||||||
|
|
||||||
|
Write eventfd value.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
|
||||||
|
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
result = eventfd_write(fd, value);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
if (result == -1) {
|
||||||
|
return PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_EVENTFD */
|
||||||
|
|
||||||
/* Terminal size querying */
|
/* Terminal size querying */
|
||||||
|
|
||||||
PyDoc_STRVAR(TerminalSize_docstring,
|
PyDoc_STRVAR(TerminalSize_docstring,
|
||||||
|
@ -14619,6 +14697,9 @@ static PyMethodDef posix_methods[] = {
|
||||||
OS_FSPATH_METHODDEF
|
OS_FSPATH_METHODDEF
|
||||||
OS_GETRANDOM_METHODDEF
|
OS_GETRANDOM_METHODDEF
|
||||||
OS_MEMFD_CREATE_METHODDEF
|
OS_MEMFD_CREATE_METHODDEF
|
||||||
|
OS_EVENTFD_METHODDEF
|
||||||
|
OS_EVENTFD_READ_METHODDEF
|
||||||
|
OS_EVENTFD_WRITE_METHODDEF
|
||||||
OS__ADD_DLL_DIRECTORY_METHODDEF
|
OS__ADD_DLL_DIRECTORY_METHODDEF
|
||||||
OS__REMOVE_DLL_DIRECTORY_METHODDEF
|
OS__REMOVE_DLL_DIRECTORY_METHODDEF
|
||||||
OS_WAITSTATUS_TO_EXITCODE_METHODDEF
|
OS_WAITSTATUS_TO_EXITCODE_METHODDEF
|
||||||
|
@ -15127,6 +15208,12 @@ all_ins(PyObject *m)
|
||||||
#ifdef MFD_HUGE_16GB
|
#ifdef MFD_HUGE_16GB
|
||||||
if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
|
if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* HAVE_MEMFD_CREATE */
|
||||||
|
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
|
||||||
|
if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
|
||||||
|
if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
@ -15220,6 +15307,10 @@ static const struct have_function {
|
||||||
int (*probe)(void);
|
int (*probe)(void);
|
||||||
} have_functions[] = {
|
} have_functions[] = {
|
||||||
|
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
{"HAVE_EVENTFD", NULL},
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_FACCESSAT
|
#ifdef HAVE_FACCESSAT
|
||||||
{ "HAVE_FACCESSAT", probe_faccessat },
|
{ "HAVE_FACCESSAT", probe_faccessat },
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8032,7 +8032,8 @@ sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
|
||||||
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
|
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
|
||||||
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
|
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
|
||||||
linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
|
linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
|
||||||
sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h sys/mman.h
|
sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \
|
||||||
|
sys/mman.h sys/eventfd.h
|
||||||
do :
|
do :
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||||
|
@ -12098,6 +12099,36 @@ $as_echo "no" >&6; }
|
||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for eventfd" >&5
|
||||||
|
$as_echo_n "checking for eventfd... " >&6; }
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_EVENTFD_H
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
int x = eventfd(0, EFD_CLOEXEC)
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_compile "$LINENO"; then :
|
||||||
|
|
||||||
|
$as_echo "#define HAVE_EVENTFD 1" >>confdefs.h
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
$as_echo "yes" >&6; }
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
|
||||||
# On some systems (eg. FreeBSD 5), we would find a definition of the
|
# On some systems (eg. FreeBSD 5), we would find a definition of the
|
||||||
# functions ctermid_r, setgroups in the library, but no prototype
|
# functions ctermid_r, setgroups in the library, but no prototype
|
||||||
# (e.g. because we use _XOPEN_SOURCE). See whether we can take their
|
# (e.g. because we use _XOPEN_SOURCE). See whether we can take their
|
||||||
|
|
14
configure.ac
14
configure.ac
|
@ -2210,7 +2210,8 @@ sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
|
||||||
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
|
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
|
||||||
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
|
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
|
||||||
linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
|
linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
|
||||||
sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h sys/mman.h)
|
sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \
|
||||||
|
sys/mman.h sys/eventfd.h)
|
||||||
AC_HEADER_DIRENT
|
AC_HEADER_DIRENT
|
||||||
AC_HEADER_MAJOR
|
AC_HEADER_MAJOR
|
||||||
|
|
||||||
|
@ -3803,6 +3804,17 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||||
[AC_MSG_RESULT(no)
|
[AC_MSG_RESULT(no)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(for eventfd)
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||||
|
#ifdef HAVE_SYS_EVENTFD_H
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#endif
|
||||||
|
]], [[int x = eventfd(0, EFD_CLOEXEC)]])],
|
||||||
|
[AC_DEFINE(HAVE_EVENTFD, 1, Define if you have the 'eventfd' function.)
|
||||||
|
AC_MSG_RESULT(yes)],
|
||||||
|
[AC_MSG_RESULT(no)
|
||||||
|
])
|
||||||
|
|
||||||
# On some systems (eg. FreeBSD 5), we would find a definition of the
|
# On some systems (eg. FreeBSD 5), we would find a definition of the
|
||||||
# functions ctermid_r, setgroups in the library, but no prototype
|
# functions ctermid_r, setgroups in the library, but no prototype
|
||||||
# (e.g. because we use _XOPEN_SOURCE). See whether we can take their
|
# (e.g. because we use _XOPEN_SOURCE). See whether we can take their
|
||||||
|
|
|
@ -308,6 +308,9 @@
|
||||||
/* Define to 1 if you have the <errno.h> header file. */
|
/* Define to 1 if you have the <errno.h> header file. */
|
||||||
#undef HAVE_ERRNO_H
|
#undef HAVE_ERRNO_H
|
||||||
|
|
||||||
|
/* Define if you have the 'eventfd' function. */
|
||||||
|
#undef HAVE_EVENTFD
|
||||||
|
|
||||||
/* Define to 1 if you have the `execv' function. */
|
/* Define to 1 if you have the `execv' function. */
|
||||||
#undef HAVE_EXECV
|
#undef HAVE_EXECV
|
||||||
|
|
||||||
|
@ -1119,6 +1122,9 @@
|
||||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
||||||
#undef HAVE_SYS_EPOLL_H
|
#undef HAVE_SYS_EPOLL_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/eventfd.h> header file. */
|
||||||
|
#undef HAVE_SYS_EVENTFD_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||||
#undef HAVE_SYS_EVENT_H
|
#undef HAVE_SYS_EVENT_H
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue