/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
*/
/*
* Copyright 2016 Joyent, Inc.
*/
/*
* Support for the eventfd facility, a Linux-borne facility for user-generated
* file descriptor-based events.
*/
#include <sys/sysmacros.h>
struct eventfd_state;
struct eventfd_state {
};
/*
* Internal global variables.
*/
/*ARGSUSED*/
static int
{
if (minor != EVENTFDMNRN_EVENTFD)
return (ENXIO);
VM_BESTFIT | VM_SLEEP);
return (NULL);
}
return (0);
}
/*ARGSUSED*/
static int
{
int err;
return (EINVAL);
return (EAGAIN);
}
return (EINTR);
}
}
/*
* We have a non-zero value and we own the lock; our behavior now
* depends on whether or not EFD_SEMAPHORE was set when the eventfd
* was created.
*/
if (state->efd_semaphore) {
val = 1;
} else {
}
/*
* Wake any writers blocked on this eventfd as this read operation may
* have created adequate capacity for their values.
*/
if (state->efd_bwriters != 0) {
}
/*
* It is necessary to emit POLLOUT events only when the eventfd
* transitions from EVENTFD_VALMAX to a lower value. At all other
* times, it is already considered writable by poll.
*/
if (oval == EVENTFD_VALMAX) {
}
return (err);
}
/*ARGSUSED*/
static int
{
int err;
return (EINVAL);
return (err);
if (val > EVENTFD_VALMAX)
return (EINVAL);
return (EAGAIN);
}
state->efd_bwriters++;
state->efd_bwriters--;
return (EINTR);
}
state->efd_bwriters--;
}
/*
* We now know that we can add the value without overflowing.
*/
/*
* If the value was previously "empty", notify blocked readers that
* data is available.
*/
if (oval == 0) {
}
/*
* Notify pollers as well if the eventfd is now readable.
*/
if (oval == 0) {
}
return (0);
}
/*ARGSUSED*/
static int
{
short revents = 0;
return (0);
}
/*ARGSUSED*/
static int
{
switch (cmd) {
case EVENTFDIOC_SEMAPHORE: {
return (0);
}
default:
break;
}
return (ENOTTY);
}
/*ARGSUSED*/
static int
{
}
/*
* Remove our state from our global list.
*/
return (0);
}
static int
{
switch (cmd) {
case DDI_ATTACH:
break;
case DDI_RESUME:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
sizeof (eventfd_state_t), 0) != 0) {
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
eventfd_devi = devi;
return (DDI_SUCCESS);
}
/*ARGSUSED*/
static int
{
switch (cmd) {
case DDI_DETACH:
break;
case DDI_SUSPEND:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
eventfd_devi = NULL;
return (DDI_SUCCESS);
}
/*ARGSUSED*/
static int
{
int error;
switch (infocmd) {
case DDI_INFO_DEVT2DEVINFO:
*result = (void *)eventfd_devi;
error = DDI_SUCCESS;
break;
case DDI_INFO_DEVT2INSTANCE:
*result = (void *)0;
error = DDI_SUCCESS;
break;
default:
error = DDI_FAILURE;
}
return (error);
}
eventfd_open, /* open */
eventfd_close, /* close */
nulldev, /* strategy */
nulldev, /* print */
nodev, /* dump */
eventfd_read, /* read */
eventfd_write, /* write */
eventfd_ioctl, /* ioctl */
nodev, /* devmap */
nodev, /* mmap */
nodev, /* segmap */
eventfd_poll, /* poll */
ddi_prop_op, /* cb_prop_op */
0, /* streamtab */
};
DEVO_REV, /* devo_rev */
0, /* refcnt */
eventfd_info, /* get_dev_info */
nulldev, /* identify */
nulldev, /* probe */
eventfd_attach, /* attach */
eventfd_detach, /* detach */
nodev, /* reset */
&eventfd_cb_ops, /* driver operations */
NULL, /* bus operations */
nodev, /* dev power */
ddi_quiesce_not_needed, /* quiesce */
};
&mod_driverops, /* module type (this is a pseudo driver) */
"eventfd support", /* name of module */
&eventfd_ops, /* driver ops */
};
(void *)&modldrv,
};
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
{
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}