mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
kernel: do preparation work for copyless read/write
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#include <arch/io.h>
|
#include <arch/io.h>
|
||||||
#include <kernel/devfs.h>
|
#include <kernel/devfs.h>
|
||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
|
#include <kernel/usercopy.h>
|
||||||
|
|
||||||
void arch_e9_putc(char c) {
|
void arch_e9_putc(char c) {
|
||||||
#ifdef X86_64_ENABLE_E9
|
#ifdef X86_64_ENABLE_E9
|
||||||
@@ -16,11 +17,18 @@ void arch_e9_puts(char *c) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef X86_64_ENABLE_E9
|
||||||
static int devwrite(int minor, void *bufferp, size_t count, uintmax_t offset, int flags, size_t *wcount) {
|
static int devwrite(int minor, void *bufferp, size_t count, uintmax_t offset, int flags, size_t *wcount) {
|
||||||
uint8_t *buffer = bufferp;
|
uint8_t *buffer = bufferp;
|
||||||
|
|
||||||
for (uintmax_t i = 0; i < count; ++i)
|
for (uintmax_t i = 0; i < count; ++i) {
|
||||||
outb(0xe9, buffer[i]);
|
char c;
|
||||||
|
int error = USERCOPY_POSSIBLY_FROM_USER(&c, &buffer[i], 1);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
outb(0xe9, c);
|
||||||
|
}
|
||||||
|
|
||||||
*wcount = count;
|
*wcount = count;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -29,6 +37,7 @@ static int devwrite(int minor, void *bufferp, size_t count, uintmax_t offset, in
|
|||||||
static devops_t devops = {
|
static devops_t devops = {
|
||||||
.write = devwrite
|
.write = devwrite
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
void arch_e9_initdev() {
|
void arch_e9_initdev() {
|
||||||
#ifdef X86_64_ENABLE_E9
|
#ifdef X86_64_ENABLE_E9
|
||||||
|
|||||||
@@ -1317,6 +1317,8 @@ static int ext2_readlink(vnode_t *vnode, char **link, cred_t *cred) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this *should*, by the rules of the vnode ops, accept a user buffer. however, this will never be the case. all I/O will
|
||||||
|
// go through the page cache
|
||||||
static int ext2_read(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) {
|
static int ext2_read(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc, cred_t *cred) {
|
||||||
if (vnode->type == V_TYPE_DIR)
|
if (vnode->type == V_TYPE_DIR)
|
||||||
return EISDIR;
|
return EISDIR;
|
||||||
@@ -1356,6 +1358,8 @@ static int ext2_read(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this *should*, by the rules of the vnode ops, accept a user buffer. however, this will never be the case. all I/O will
|
||||||
|
// go through the page cache
|
||||||
int ext2_write(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) {
|
int ext2_write(vnode_t *vnode, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec, cred_t *cred) {
|
||||||
if (vnode->type == V_TYPE_DIR)
|
if (vnode->type == V_TYPE_DIR)
|
||||||
return EISDIR;
|
return EISDIR;
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ static int internalpoll(vnode_t *node, polldata_t *data, int events) {
|
|||||||
return revents;
|
return revents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buffer can possibly be a user address
|
||||||
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;
|
||||||
INTERNAL_LOCK(node);
|
INTERNAL_LOCK(node);
|
||||||
@@ -171,6 +172,8 @@ int pipefs_read(vnode_t *node, void *buffer, size_t size, uintmax_t offset, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
*readc = ringbuffer_read(&pipenode->data, buffer, size);
|
*readc = ringbuffer_read(&pipenode->data, buffer, size);
|
||||||
|
if (*readc == RINGBUFFER_USER_COPY_FAILED)
|
||||||
|
error = EFAULT;
|
||||||
|
|
||||||
// signal that there is space to write for any threads blocked on this pipe
|
// signal that there is space to write for any threads blocked on this pipe
|
||||||
if (RINGBUFFER_DATACOUNT(&pipenode->data) < BUFFER_SIZE - PIPE_ATOMIC_SIZE)
|
if (RINGBUFFER_DATACOUNT(&pipenode->data) < BUFFER_SIZE - PIPE_ATOMIC_SIZE)
|
||||||
@@ -190,6 +193,8 @@ static int writetopipe(pipenode_t *pipenode, void *buffer, size_t size, size_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
*writec = ringbuffer_write(&pipenode->data, buffer, size);
|
*writec = ringbuffer_write(&pipenode->data, buffer, size);
|
||||||
|
if (*writec == RINGBUFFER_USER_COPY_FAILED)
|
||||||
|
return EFAULT;
|
||||||
|
|
||||||
__assert(*writec);
|
__assert(*writec);
|
||||||
poll_event(&pipenode->pollheader, POLLIN);
|
poll_event(&pipenode->pollheader, POLLIN);
|
||||||
|
|||||||
+10
-17
@@ -7,15 +7,11 @@
|
|||||||
|
|
||||||
static ringbuffer_t ringbuffer;
|
static ringbuffer_t ringbuffer;
|
||||||
static pollheader_t pollheader;
|
static pollheader_t pollheader;
|
||||||
static spinlock_t lock;
|
static mutex_t mutex;
|
||||||
|
|
||||||
void acpi_signaldevice(char c) {
|
void acpi_signaldevice(char c) {
|
||||||
long ipl = spinlock_acquireraiseipl(&lock, IPL_DPC);
|
|
||||||
|
|
||||||
if (ringbuffer_write(&ringbuffer, &c, 1))
|
if (ringbuffer_write(&ringbuffer, &c, 1))
|
||||||
poll_event(&pollheader, POLLIN);
|
poll_event(&pollheader, POLLIN);
|
||||||
|
|
||||||
spinlock_releaseloweripl(&lock, ipl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int internalpoll(polldata_t *data, int events) {
|
static int internalpoll(polldata_t *data, int events) {
|
||||||
@@ -43,13 +39,11 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
MUTEX_ACQUIRE(&mutex, false);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
long ipl = spinlock_acquireraiseipl(&lock, IPL_DPC);
|
|
||||||
|
|
||||||
int revents = internalpoll(&desc.data[0], POLLIN);
|
int revents = internalpoll(&desc.data[0], POLLIN);
|
||||||
|
|
||||||
spinlock_releaseloweripl(&lock, ipl);
|
|
||||||
|
|
||||||
if (revents)
|
if (revents)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -66,13 +60,14 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
poll_leave(&desc);
|
poll_leave(&desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
long ipl = spinlock_acquireraiseipl(&lock, IPL_DPC);
|
// this abuses a behavior of how the ringbuffer works to not need a lock for reading
|
||||||
|
// (as it would need interrupts to be off)
|
||||||
*readc = ringbuffer_read(&ringbuffer, buffer, size);
|
*readc = ringbuffer_read(&ringbuffer, buffer, size);
|
||||||
|
if (*readc == RINGBUFFER_USER_COPY_FAILED)
|
||||||
spinlock_releaseloweripl(&lock, ipl);
|
error = EFAULT;
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
MUTEX_RELEASE(&mutex);
|
||||||
poll_leave(&desc);
|
poll_leave(&desc);
|
||||||
poll_destroydesc(&desc);
|
poll_destroydesc(&desc);
|
||||||
return error;
|
return error;
|
||||||
@@ -98,11 +93,9 @@ static int write(int minor, void *buffer, size_t size, uintmax_t offset, int fla
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int poll(int minor, polldata_t *data, int events) {
|
static int poll(int minor, polldata_t *data, int events) {
|
||||||
long ipl = spinlock_acquireraiseipl(&lock, IPL_DPC);
|
MUTEX_ACQUIRE(&mutex, false);
|
||||||
|
|
||||||
int revents = internalpoll(data, events);
|
int revents = internalpoll(data, events);
|
||||||
|
MUTEX_RELEASE(&mutex);
|
||||||
spinlock_releaseloweripl(&lock, ipl);
|
|
||||||
return revents;
|
return revents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-2
@@ -99,7 +99,10 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
if(size + offset > end)
|
if(size + offset > end)
|
||||||
size = end - offset;
|
size = end - offset;
|
||||||
|
|
||||||
memcpy(buffer, (void *)((uintptr_t)fbs[minor]->address + offset), size);
|
int error = USERCOPY_POSSIBLY_TO_USER(buffer, (void *)((uintptr_t)fbs[minor]->address + offset), size);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
*readc = size;
|
*readc = size;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -118,7 +121,10 @@ static int write(int minor, void *buffer, size_t size, uintmax_t offset, int fla
|
|||||||
if(size + offset > end)
|
if(size + offset > end)
|
||||||
size = end - offset;
|
size = end - offset;
|
||||||
|
|
||||||
memcpy((void *)((uintptr_t)fbs[minor]->address + offset), buffer, size);
|
int error = USERCOPY_POSSIBLY_FROM_USER((void *)((uintptr_t)fbs[minor]->address + offset), buffer, size);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
*writec = size;
|
*writec = size;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <kernel/devfs.h>
|
#include <kernel/devfs.h>
|
||||||
#include <hashtable.h>
|
#include <hashtable.h>
|
||||||
#include <kernel/poll.h>
|
#include <kernel/poll.h>
|
||||||
|
#include <kernel/usercopy.h>
|
||||||
|
|
||||||
#define BUFFER_PACKET_CAPACITY 100
|
#define BUFFER_PACKET_CAPACITY 100
|
||||||
#define BUFFER_SIZE (BUFFER_PACKET_CAPACITY * sizeof(kbpacket_t))
|
#define BUFFER_SIZE (BUFFER_PACKET_CAPACITY * sizeof(kbpacket_t))
|
||||||
@@ -165,25 +166,34 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
|
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
kbpacket_t *buff = (kbpacket_t *)((uintptr_t)buffer + i * sizeof(kbpacket_t));
|
kbpacket_t *buff = (kbpacket_t *)((uintptr_t)buffer + i * sizeof(kbpacket_t));
|
||||||
bool ok = keyboard_get(kb, buff);
|
kbpacket_t packet;
|
||||||
|
|
||||||
|
bool ok = keyboard_get(kb, &packet);
|
||||||
if (ok == false) {
|
if (ok == false) {
|
||||||
if (i == 0 && (flags & V_FFLAGS_NONBLOCKING) == 0) {
|
if (i == 0 && (flags & V_FFLAGS_NONBLOCKING) == 0) {
|
||||||
int err = keyboard_wait(kb, buff);
|
int error = keyboard_wait(kb, &packet);
|
||||||
*readc += err ? 0 : sizeof(kbpacket_t);
|
if (error)
|
||||||
return err;
|
return error;
|
||||||
|
|
||||||
|
error = USERCOPY_POSSIBLY_TO_USER(buff, &packet, sizeof(kbpacket_t));
|
||||||
|
|
||||||
|
*readc += error ? 0 : sizeof(kbpacket_t);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int error = USERCOPY_POSSIBLY_TO_USER(buff, &packet, sizeof(kbpacket_t));
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
*readc += sizeof(kbpacket_t);
|
*readc += sizeof(kbpacket_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int poll(int minor, polldata_t *data, int events) {
|
static int poll(int minor, polldata_t *data, int events) {
|
||||||
int revents = 0;
|
int revents = 0;
|
||||||
keyboard_t *kb = getkb(minor);
|
keyboard_t *kb = getkb(minor);
|
||||||
|
|||||||
@@ -122,6 +122,11 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
}
|
}
|
||||||
|
|
||||||
*readc = ringbuffer_read(&mouse->packetbuffer, buffer, sizeof(mousepacket_t) * packetcount);
|
*readc = ringbuffer_read(&mouse->packetbuffer, buffer, sizeof(mousepacket_t) * packetcount);
|
||||||
|
if (*readc == RINGBUFFER_USER_COPY_FAILED) {
|
||||||
|
error = EFAULT;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
__assert(*readc);
|
__assert(*readc);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
|||||||
@@ -365,6 +365,11 @@ static int localsock_send(socket_t *socket, sockdesc_t *sockdesc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sockdesc->donecount = ringbuffer_write(&peer->ringbuffer, sockdesc->buffer, sockdesc->count);
|
sockdesc->donecount = ringbuffer_write(&peer->ringbuffer, sockdesc->buffer, sockdesc->count);
|
||||||
|
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||||
|
error = EFAULT;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
__assert(sockdesc->donecount > 0);
|
__assert(sockdesc->donecount > 0);
|
||||||
|
|
||||||
error = sendctrl(socket, sockdesc->ctrl, sockdesc->ctrllen, sockdesc->donecount);
|
error = sendctrl(socket, sockdesc->ctrl, sockdesc->ctrllen, sockdesc->donecount);
|
||||||
@@ -465,8 +470,17 @@ static int localsock_recv(socket_t *socket, sockdesc_t *sockdesc) {
|
|||||||
|
|
||||||
if (flags & SOCKET_RECV_FLAGS_PEEK) {
|
if (flags & SOCKET_RECV_FLAGS_PEEK) {
|
||||||
sockdesc->donecount = ringbuffer_peek(&localsocket->ringbuffer, sockdesc->buffer, 0, recvcount);
|
sockdesc->donecount = ringbuffer_peek(&localsocket->ringbuffer, sockdesc->buffer, 0, recvcount);
|
||||||
|
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||||
|
error = EFAULT;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sockdesc->donecount = ringbuffer_read(&localsocket->ringbuffer, sockdesc->buffer, recvcount);
|
sockdesc->donecount = ringbuffer_read(&localsocket->ringbuffer, sockdesc->buffer, recvcount);
|
||||||
|
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||||
|
error = EPIPE;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
localsocket_t *peer = pair->client == localsocket ? pair->server : pair->client;
|
localsocket_t *peer = pair->client == localsocket ? pair->server : pair->client;
|
||||||
// signal that there is space to write for any threads blocked on this socket
|
// signal that there is space to write for any threads blocked on this socket
|
||||||
if (peer && sockdesc->donecount)
|
if (peer && sockdesc->donecount)
|
||||||
|
|||||||
+20
-5
@@ -1305,8 +1305,13 @@ static int tcp_send(socket_t *socket, sockdesc_t *sockdesc) {
|
|||||||
size_t writesize = min(TCB_RINGBUFFER_SIZE - RINGBUFFER_DATACOUNT(&tcb->transmitbuffer), sockdesc->count);
|
size_t writesize = min(TCB_RINGBUFFER_SIZE - RINGBUFFER_DATACOUNT(&tcb->transmitbuffer), sockdesc->count);
|
||||||
__assert(writesize);
|
__assert(writesize);
|
||||||
|
|
||||||
__assert(ringbuffer_write(&tcb->transmitbuffer, sockdesc->buffer, writesize) == writesize);
|
sockdesc->donecount = ringbuffer_write(&tcb->transmitbuffer, sockdesc->buffer, writesize);
|
||||||
sockdesc->donecount = writesize;
|
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||||
|
error = EFAULT;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
__assert(sockdesc->donecount == writesize);
|
||||||
|
|
||||||
if (tcb->sndnext == tcb->sndunack)
|
if (tcb->sndnext == tcb->sndunack)
|
||||||
error = tcp_transmitnextsegment(tcb);
|
error = tcp_transmitnextsegment(tcb);
|
||||||
@@ -1381,14 +1386,24 @@ static int tcp_recv(socket_t *socket, sockdesc_t *sockdesc) {
|
|||||||
|
|
||||||
size_t copycount = min(RINGBUFFER_DATACOUNT(&tcb->receivebuffer), sockdesc->count);
|
size_t copycount = min(RINGBUFFER_DATACOUNT(&tcb->receivebuffer), sockdesc->count);
|
||||||
if (flags & SOCKET_RECV_FLAGS_PEEK) {
|
if (flags & SOCKET_RECV_FLAGS_PEEK) {
|
||||||
__assert(ringbuffer_peek(&tcb->receivebuffer, sockdesc->buffer, 0, copycount) == copycount);
|
sockdesc->donecount = ringbuffer_peek(&tcb->receivebuffer, sockdesc->buffer, 0, copycount);
|
||||||
|
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||||
|
error = EFAULT;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
__assert(ringbuffer_read(&tcb->receivebuffer, sockdesc->buffer, copycount) == copycount);
|
sockdesc->donecount = ringbuffer_read(&tcb->receivebuffer, sockdesc->buffer, copycount);
|
||||||
|
if (sockdesc->donecount == RINGBUFFER_USER_COPY_FAILED) {
|
||||||
|
error = EFAULT;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
tcb->rcvwindow += copycount;
|
tcb->rcvwindow += copycount;
|
||||||
// notify about the window increase
|
// notify about the window increase
|
||||||
tcp_ack(tcb);
|
tcp_ack(tcb);
|
||||||
}
|
}
|
||||||
sockdesc->donecount = copycount;
|
|
||||||
|
__assert(sockdesc->donecount == copycount);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
MUTEX_RELEASE(&tcb->mutex);
|
MUTEX_RELEASE(&tcb->mutex);
|
||||||
|
|||||||
@@ -262,6 +262,7 @@ static int udp_recv(socket_t *socket, sockdesc_t *sockdesc) {
|
|||||||
bool intstate = interrupt_set(false);
|
bool intstate = interrupt_set(false);
|
||||||
spinlock_acquire(&udpsocket->ringbufferlock);
|
spinlock_acquire(&udpsocket->ringbufferlock);
|
||||||
|
|
||||||
|
// TODO rewrite this to handle a possible sleep in the ringbuffer
|
||||||
size_t copycount;
|
size_t copycount;
|
||||||
dataheader_t header;
|
dataheader_t header;
|
||||||
if (flags & SOCKET_RECV_FLAGS_PEEK) {
|
if (flags & SOCKET_RECV_FLAGS_PEEK) {
|
||||||
|
|||||||
+14
-5
@@ -132,10 +132,10 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
if (pty == NULL)
|
if (pty == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
|
int e = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
polldesc_t desc = {0};
|
polldesc_t desc = {0};
|
||||||
int e = poll_initdesc(&desc, 1);
|
e = poll_initdesc(&desc, 1);
|
||||||
if (e)
|
if (e)
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
@@ -146,6 +146,8 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
|
|
||||||
if (revents) {
|
if (revents) {
|
||||||
*readc = ringbuffer_read(&pty->ringbuffer, buffer, size);
|
*readc = ringbuffer_read(&pty->ringbuffer, buffer, size);
|
||||||
|
if (*readc == RINGBUFFER_USER_COPY_FAILED)
|
||||||
|
e = EFAULT;
|
||||||
|
|
||||||
spinlock_release(&pty->lock);
|
spinlock_release(&pty->lock);
|
||||||
interrupt_set(intstatus);
|
interrupt_set(intstatus);
|
||||||
@@ -173,7 +175,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int poll(int minor, polldata_t *data, int events) {
|
static int poll(int minor, polldata_t *data, int events) {
|
||||||
@@ -215,8 +217,15 @@ static int write(int minor, void *buffer, size_t size, uintmax_t offset, int fla
|
|||||||
|
|
||||||
char *str = buffer;
|
char *str = buffer;
|
||||||
|
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i) {
|
||||||
tty_process(pty->tty, str[i]);
|
// bruh
|
||||||
|
char c;
|
||||||
|
int error = USERCOPY_POSSIBLY_FROM_USER(&c, &str[i], sizeof(char));
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
tty_process(pty->tty, c);
|
||||||
|
}
|
||||||
|
|
||||||
*writec = size;
|
*writec = size;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+26
-10
@@ -195,8 +195,13 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
if (min == 0 && time == 0) {
|
if (min == 0 && time == 0) {
|
||||||
MUTEX_ACQUIRE(&tty->readmutex, false);
|
MUTEX_ACQUIRE(&tty->readmutex, false);
|
||||||
*readc = ringbuffer_read(&tty->readbuffer, buffer, size);
|
*readc = ringbuffer_read(&tty->readbuffer, buffer, size);
|
||||||
|
|
||||||
|
int error = 0;
|
||||||
|
if (*readc == RINGBUFFER_USER_COPY_FAILED)
|
||||||
|
error = EFAULT;
|
||||||
|
|
||||||
MUTEX_RELEASE(&tty->readmutex);
|
MUTEX_RELEASE(&tty->readmutex);
|
||||||
return 0;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// time is in 1/10 of a second
|
// time is in 1/10 of a second
|
||||||
@@ -207,8 +212,6 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
size_t readcount = 0;
|
size_t readcount = 0;
|
||||||
size_t spaceleft = size;
|
size_t spaceleft = size;
|
||||||
|
|
||||||
// TODO hangup stuff
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// for VMIN > 0 and VTIME > 0, the timeout is inter byte only.
|
// for VMIN > 0 and VTIME > 0, the timeout is inter byte only.
|
||||||
size_t effectivetimeout = (min > 0 && time > 0 && spins == 0) ? 0 : timeoutus;
|
size_t effectivetimeout = (min > 0 && time > 0 && spins == 0) ? 0 : timeoutus;
|
||||||
@@ -225,13 +228,19 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag
|
|||||||
MUTEX_ACQUIRE(&tty->readmutex, false);
|
MUTEX_ACQUIRE(&tty->readmutex, false);
|
||||||
|
|
||||||
size_t actuallyread = ringbuffer_read(&tty->readbuffer, (void *)((uintptr_t)buffer + readcount), spaceleft);
|
size_t actuallyread = ringbuffer_read(&tty->readbuffer, (void *)((uintptr_t)buffer + readcount), spaceleft);
|
||||||
readcount += actuallyread;
|
|
||||||
spaceleft -= actuallyread;
|
|
||||||
MUTEX_RELEASE(&tty->readmutex);
|
MUTEX_RELEASE(&tty->readmutex);
|
||||||
|
|
||||||
// XXX is this valid?
|
if (actuallyread == RINGBUFFER_USER_COPY_FAILED) {
|
||||||
if (spaceleft > 0 && readcount < min)
|
error = EFAULT;
|
||||||
continue;
|
} else {
|
||||||
|
readcount += actuallyread;
|
||||||
|
spaceleft -= actuallyread;
|
||||||
|
|
||||||
|
// XXX is this valid?
|
||||||
|
if (spaceleft > 0 && readcount < min && (revents & POLLHUP) == 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
poll_leave(&desc);
|
poll_leave(&desc);
|
||||||
poll_destroydesc(&desc);
|
poll_destroydesc(&desc);
|
||||||
@@ -276,11 +285,18 @@ static int write(int minor, void *_buffer, size_t size, uintmax_t offset, int fl
|
|||||||
|
|
||||||
*writec = size;
|
*writec = size;
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
if (buffer[i] == '\n' && (tty->termios.c_oflag & ONLCR)) {
|
// bruh
|
||||||
|
char c;
|
||||||
|
int error = USERCOPY_POSSIBLY_FROM_USER(&c, &buffer[i], sizeof(char));
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (c == '\n' && (tty->termios.c_oflag & ONLCR)) {
|
||||||
char cr = '\r';
|
char cr = '\r';
|
||||||
tty->writetodevice(tty->deviceinternal, &cr, 1);
|
tty->writetodevice(tty->deviceinternal, &cr, 1);
|
||||||
}
|
}
|
||||||
tty->writetodevice(tty->deviceinternal, &buffer[i], 1);
|
|
||||||
|
tty->writetodevice(tty->deviceinternal, &c, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user