mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 15:08:21 +00:00
pipefs: use poll internally rather than keeping the old events
This commit is contained in:
+90
-72
@@ -46,56 +46,86 @@ int pipefs_close(vnode_t *node, int flags, cred_t *cred) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pipenode->readers == 0)
|
if (pipenode->readers == 0)
|
||||||
event_signal(&pipenode->readevent);
|
poll_event(&pipenode->pollheader, POLLERR);
|
||||||
|
|
||||||
if (pipenode->writers == 0)
|
if (pipenode->writers == 0)
|
||||||
event_signal(&pipenode->writeevent);
|
poll_event(&pipenode->pollheader, POLLHUP);
|
||||||
|
|
||||||
VOP_UNLOCK(node);
|
VOP_UNLOCK(node);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int internalpoll(vnode_t *node, polldata_t *data, int events) {
|
||||||
|
pipenode_t *pipenode = (pipenode_t *)node;
|
||||||
|
int revents = 0;
|
||||||
|
|
||||||
|
if (events & POLLIN) {
|
||||||
|
events |= POLLHUP;
|
||||||
|
if (pipenode->writers == 0)
|
||||||
|
revents |= POLLHUP;
|
||||||
|
else if (RINGBUFFER_DATACOUNT(&pipenode->data) > 0)
|
||||||
|
revents |= POLLIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events & POLLOUT) {
|
||||||
|
events |= POLLERR;
|
||||||
|
if (pipenode->readers == 0)
|
||||||
|
revents |= POLLERR;
|
||||||
|
else if (RINGBUFFER_DATACOUNT(&pipenode->data) < BUFFER_SIZE)
|
||||||
|
revents |= POLLOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (revents == 0 && data)
|
||||||
|
poll_add(&pipenode->pollheader, data, events);
|
||||||
|
|
||||||
|
return revents;
|
||||||
|
}
|
||||||
|
|
||||||
int pipefs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) {
|
int pipefs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) {
|
||||||
pipenode_t *pipenode = (pipenode_t *)node;
|
pipenode_t *pipenode = (pipenode_t *)node;
|
||||||
VOP_LOCK(node);
|
VOP_LOCK(node);
|
||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
*readc = 0;
|
*readc = 0;
|
||||||
size_t datacount = 0;
|
|
||||||
|
|
||||||
// wait until there is data to read or return if nonblock
|
// wait until there is data to read or return if nonblock
|
||||||
while (datacount == 0) {
|
while (1) {
|
||||||
datacount = RINGBUFFER_DATACOUNT(&pipenode->data);
|
// check for available data or if the write end has been closed
|
||||||
if (datacount == 0) {
|
int revents = internalpoll(node, NULL, POLLIN);
|
||||||
if (pipenode->writers == 0)
|
if (revents)
|
||||||
goto leave;
|
break;
|
||||||
|
|
||||||
if (flags & V_FFLAGS_NONBLOCKING) {
|
if (flags & V_FFLAGS_NONBLOCKING) {
|
||||||
error = EAGAIN;
|
error = EAGAIN;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
|
||||||
|
|
||||||
// to make it harder for a race condition to happen TODO figure out a way to fix this
|
|
||||||
bool status = interrupt_set(false);
|
|
||||||
VOP_UNLOCK(node);
|
|
||||||
|
|
||||||
error = event_wait(&pipenode->writeevent, true);
|
|
||||||
interrupt_set(status);
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
VOP_LOCK(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do the wait
|
||||||
|
polldesc_t desc = {0};
|
||||||
|
error = poll_initdesc(&desc, 1);
|
||||||
|
if (error)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
revents = internalpoll(node, &desc.data[0], POLLIN);
|
||||||
|
|
||||||
|
VOP_UNLOCK(node);
|
||||||
|
|
||||||
|
error = poll_dowait(&desc, 0);
|
||||||
|
|
||||||
|
poll_leave(&desc);
|
||||||
|
poll_destroydesc(&desc);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
VOP_LOCK(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
*readc = ringbuffer_read(&pipenode->data, buffer, size);
|
*readc = ringbuffer_read(&pipenode->data, buffer, size);
|
||||||
|
|
||||||
if (*readc < datacount) {
|
// signal that there is space to write for any threads blocked on this pipe
|
||||||
|
if (*readc)
|
||||||
poll_event(&pipenode->pollheader, POLLOUT);
|
poll_event(&pipenode->pollheader, POLLOUT);
|
||||||
event_signal(&pipenode->writeevent);
|
|
||||||
}
|
|
||||||
|
|
||||||
event_signal(&pipenode->readevent);
|
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
VOP_UNLOCK(node);
|
VOP_UNLOCK(node);
|
||||||
@@ -109,27 +139,37 @@ int pipefs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
*writec = 0;
|
*writec = 0;
|
||||||
|
|
||||||
// wait until there is space to write data into or return if nonblock
|
// wait until there is space to write data or return if nonblock
|
||||||
size_t datacount = BUFFER_SIZE;
|
while (1) {
|
||||||
while (datacount == BUFFER_SIZE && pipenode->readers) {
|
// check for space or if the read end has been closed
|
||||||
datacount = RINGBUFFER_DATACOUNT(&pipenode->data);
|
int revents = internalpoll(node, NULL, POLLOUT);
|
||||||
if (datacount == BUFFER_SIZE) {
|
if (revents)
|
||||||
if (flags & V_FFLAGS_NONBLOCKING) {
|
break;
|
||||||
error = EAGAIN;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
// to make it harder for a race condition to happen TODO figure out a way to fix this
|
if (flags & V_FFLAGS_NONBLOCKING) {
|
||||||
bool status = interrupt_set(false);
|
error = EAGAIN;
|
||||||
VOP_UNLOCK(node);
|
goto leave;
|
||||||
|
|
||||||
error = event_wait(&pipenode->readevent, true);
|
|
||||||
interrupt_set(status);
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
VOP_LOCK(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do the wait
|
||||||
|
polldesc_t desc = {0};
|
||||||
|
error = poll_initdesc(&desc, 1);
|
||||||
|
if (error)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
revents = internalpoll(node, &desc.data[0], POLLOUT);
|
||||||
|
|
||||||
|
VOP_UNLOCK(node);
|
||||||
|
|
||||||
|
error = poll_dowait(&desc, 0);
|
||||||
|
|
||||||
|
poll_leave(&desc);
|
||||||
|
poll_destroydesc(&desc);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
VOP_LOCK(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipenode->readers == 0) {
|
if (pipenode->readers == 0) {
|
||||||
@@ -140,12 +180,8 @@ int pipefs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int
|
|||||||
|
|
||||||
*writec = ringbuffer_write(&pipenode->data, buffer, size);
|
*writec = ringbuffer_write(&pipenode->data, buffer, size);
|
||||||
|
|
||||||
if (datacount + *writec < BUFFER_SIZE) {
|
__assert(*writec);
|
||||||
poll_event(&pipenode->pollheader, POLLIN);
|
poll_event(&pipenode->pollheader, POLLIN);
|
||||||
event_signal(&pipenode->readevent);
|
|
||||||
}
|
|
||||||
|
|
||||||
event_signal(&pipenode->writeevent);
|
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
VOP_UNLOCK(node);
|
VOP_UNLOCK(node);
|
||||||
@@ -153,26 +189,10 @@ int pipefs_write(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
int pipefs_poll(vnode_t *node, polldata_t *data, int events) {
|
int pipefs_poll(vnode_t *node, polldata_t *data, int events) {
|
||||||
pipenode_t *pipenode = (pipenode_t *)node;
|
|
||||||
int revents = 0;
|
int revents = 0;
|
||||||
VOP_LOCK(node);
|
VOP_LOCK(node);
|
||||||
|
|
||||||
if (events & POLLIN) {
|
revents = internalpoll(node, data, events);
|
||||||
if (pipenode->writers == 0)
|
|
||||||
revents |= POLLHUP;
|
|
||||||
else if (RINGBUFFER_DATACOUNT(&pipenode->data) > 0)
|
|
||||||
revents |= POLLIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events & POLLOUT) {
|
|
||||||
if (pipenode->readers == 0)
|
|
||||||
revents |= POLLERR;
|
|
||||||
else if (RINGBUFFER_DATACOUNT(&pipenode->data) < BUFFER_SIZE)
|
|
||||||
revents |= POLLOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (revents == 0 && data)
|
|
||||||
poll_add(&pipenode->pollheader, data, events);
|
|
||||||
|
|
||||||
VOP_UNLOCK(node);
|
VOP_UNLOCK(node);
|
||||||
return revents;
|
return revents;
|
||||||
@@ -244,8 +264,6 @@ static void ctor(scache_t *cache, void *obj) {
|
|||||||
memset(node, 0, sizeof(pipenode_t));
|
memset(node, 0, sizeof(pipenode_t));
|
||||||
VOP_INIT(&node->vnode, &vnops, 0, V_TYPE_FIFO, NULL);
|
VOP_INIT(&node->vnode, &vnops, 0, V_TYPE_FIFO, NULL);
|
||||||
node->attr.inode = ++currentinode;
|
node->attr.inode = ++currentinode;
|
||||||
EVENT_INIT(&node->writeevent);
|
|
||||||
EVENT_INIT(&node->readevent);
|
|
||||||
POLL_INITHEADER(&node->pollheader);
|
POLL_INITHEADER(&node->pollheader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ typedef struct pipenode_t {
|
|||||||
vattr_t attr;
|
vattr_t attr;
|
||||||
ringbuffer_t data;
|
ringbuffer_t data;
|
||||||
size_t readers, writers;
|
size_t readers, writers;
|
||||||
event_t readevent, writeevent;
|
|
||||||
pollheader_t pollheader;
|
pollheader_t pollheader;
|
||||||
} pipenode_t;
|
} pipenode_t;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user