From d10de37498f5b09f98fef135da4927456f9e11e3 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sat, 20 Apr 2024 15:46:17 -0300 Subject: [PATCH] mouse: fix deadlock --- kernel-src/include/kernel/abi.h | 1 + kernel-src/include/kernel/mouse.h | 2 ++ kernel-src/include/kernel/sock.h | 1 + kernel-src/include/kernel/vfs.h | 4 ++-- kernel-src/io/mouse.c | 27 +++++++++++++++++++-------- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/kernel-src/include/kernel/abi.h b/kernel-src/include/kernel/abi.h index cf18e0f6..d877e6ea 100644 --- a/kernel-src/include/kernel/abi.h +++ b/kernel-src/include/kernel/abi.h @@ -137,6 +137,7 @@ typedef struct { #define SIOCGIFHWADDR 0x8927 #define SIOCADDRT 0x890b #define SIOCSIFADDR 0x8916 +#define FIONREAD 0x541B typedef struct { char name[IFNAMSIZ]; diff --git a/kernel-src/include/kernel/mouse.h b/kernel-src/include/kernel/mouse.h index 834abaa0..3a4bbcb6 100644 --- a/kernel-src/include/kernel/mouse.h +++ b/kernel-src/include/kernel/mouse.h @@ -3,6 +3,7 @@ #include #include +#include #define MOUSE_FLAG_RB 1 #define MOUSE_FLAG_MB 2 @@ -20,6 +21,7 @@ typedef struct { spinlock_t lock; pollheader_t pollheader; int flags; + mutex_t readmutex; } mouse_t; void mouse_init(); diff --git a/kernel-src/include/kernel/sock.h b/kernel-src/include/kernel/sock.h index a93bf458..a1cb4880 100644 --- a/kernel-src/include/kernel/sock.h +++ b/kernel-src/include/kernel/sock.h @@ -36,6 +36,7 @@ typedef struct socketops_t { int (*connect)(socket_t *socket, sockaddr_t *addr, uintmax_t data); int (*listen)(socket_t *socket, int backlog); int (*accept)(socket_t *server, socket_t *client, sockaddr_t *addr, uintmax_t flags); + size_t (*datacount)(socket_t *socket); void (*destroy)(socket_t *socket); } socketops_t; diff --git a/kernel-src/include/kernel/vfs.h b/kernel-src/include/kernel/vfs.h index fab974ad..b3fee378 100644 --- a/kernel-src/include/kernel/vfs.h +++ b/kernel-src/include/kernel/vfs.h @@ -172,8 +172,8 @@ int vfs_unlink(vnode_t *ref, char *path); int vfs_pollstub(vnode_t *node, struct polldata *, int events); void vfs_inactive(vnode_t *node); -#define VFS_LOOKUP_PARENT 1 -#define VFS_LOOKUP_NOLINK 2 +#define VFS_LOOKUP_PARENT 0x20000000 +#define VFS_LOOKUP_NOLINK 0x40000000 #define VFS_LOOKUP_INTERNAL 0x80000000 int vfs_lookup(vnode_t **result, vnode_t *start, char *path, char *lastcomp, int flags); diff --git a/kernel-src/io/mouse.c b/kernel-src/io/mouse.c index ed5b0d1d..d846daa5 100644 --- a/kernel-src/io/mouse.c +++ b/kernel-src/io/mouse.c @@ -23,6 +23,7 @@ static mouse_t *newmouse() { POLL_INITHEADER(&mouse->pollheader); SPINLOCK_INIT(mouse->lock); + MUTEX_INIT(&mouse->readmutex); return mouse; } @@ -77,11 +78,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag if (packetcount == 0) return error; - // disable interrupts here as to not lose any interrupts - // and because we cannot sleep with a raised ipl - bool oldintstatus = interrupt_set(false); - spinlock_acquire(&mouse->lock); - + MUTEX_ACQUIRE(&mouse->readmutex, false); // wait until there is data to read or return if nonblock for (;;) { polldesc_t desc = {0}; @@ -89,22 +86,33 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag if (error) goto leave; + // disable interrupts here as to not lose any interrupts + // and because we cannot sleep with a raised ipl + bool oldintstatus = interrupt_set(false); + spinlock_acquire(&mouse->lock); + int revents = internalpoll(mouse, &desc.data[0], POLLIN); if (revents) { + spinlock_release(&mouse->lock); + interrupt_set(oldintstatus); poll_leave(&desc); poll_destroydesc(&desc); break; } if (revents == 0 && flags & V_FFLAGS_NONBLOCKING) { + spinlock_release(&mouse->lock); + interrupt_set(oldintstatus); + poll_leave(&desc); + poll_destroydesc(&desc); error = EAGAIN; goto leave; } spinlock_release(&mouse->lock); error = poll_dowait(&desc, 0); - spinlock_acquire(&mouse->lock); + interrupt_set(oldintstatus); poll_leave(&desc); poll_destroydesc(&desc); @@ -117,8 +125,7 @@ static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flag __assert(*readc); leave: - spinlock_release(&mouse->lock); - interrupt_set(oldintstatus); + MUTEX_RELEASE(&mouse->readmutex); return error; } @@ -128,12 +135,16 @@ static int poll(int minor, polldata_t *data, int events) { if (mouse == NULL) return POLLERR; + MUTEX_ACQUIRE(&mouse->readmutex, false); + long ipl = interrupt_raiseipl(IPL_MOUSE); spinlock_acquire(&mouse->lock); int revents = internalpoll(mouse, data, events); spinlock_release(&mouse->lock); interrupt_loweripl(ipl); + MUTEX_RELEASE(&mouse->readmutex); + return revents; }