From 4417141216d224c48f9bb7287e9b80aa6ddd6da8 Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Wed, 29 Oct 2025 21:21:35 +0100 Subject: [PATCH] Implement ipc_netsockdelete() syscall and automatic dangling socket cleanup --- kernel/ipc/netsock/netsock.c | 60 +++++++++++++++++++++++++++++++++++- kernel/ipc/netsock/netsock.h | 5 ++- kernel/proc/proc.c | 2 ++ kernel/syscall/ipcnetsock.c | 22 ++++++++++++- kernel/syscall/ipcnetsock.h | 1 + kernel/syscall/syscall.c | 1 + share/sysdefs/syscall.h | 1 + ulib/system/system.c | 4 +++ ulib/system/system.h | 1 + user/diagdummy/diagdummy.c | 6 ++-- user/diagdummy/tcptest.c | 8 ++++- user/diagdummy/tcptest.h | 3 +- 12 files changed, 107 insertions(+), 7 deletions(-) diff --git a/kernel/ipc/netsock/netsock.c b/kernel/ipc/netsock/netsock.c index 3eda4c8..8024840 100644 --- a/kernel/ipc/netsock/netsock.c +++ b/kernel/ipc/netsock/netsock.c @@ -9,6 +9,7 @@ #include "util/util.h" #include "sysdefs/ipcnetsock.h" #include "kprintf.h" +#include "proc/proc.h" IpcNetSocks IPC_NETSOCKS; @@ -71,7 +72,7 @@ void ipc_netsock_event(uint16_t ev, struct pico_socket *sock1) { spinlock_release(&netsock->spinlock); } -IpcNetSock *ipc_netsockmake(uint16_t net, uint16_t proto, uint16_t port) { +IpcNetSock *ipc_netsockmake(uint16_t net, uint16_t proto, uint16_t port, uint64_t pid) { IpcNetSock *netsock = dlmalloc(sizeof(*netsock)); if (netsock == NULL) { return NULL; @@ -89,6 +90,8 @@ IpcNetSock *ipc_netsockmake(uint16_t net, uint16_t proto, uint16_t port) { uint8_t *eventbuffer = dlmalloc(sizeof(IpcNetSockEventBuffer) * IPC_NETSOCK_EVENTBUFFER_MAX); rbuft_init(&netsock->eventbuffer, eventbuffer, sizeof(IpcNetSockEventBuffer), IPC_NETSOCK_EVENTBUFFER_MAX); + netsock->ownerpid = pid; + uint16_t port_be = short_be(port); struct pico_ip4 inaddr_any = {0}; pico_socket_bind(netsock->picosock, &inaddr_any, &port_be); @@ -110,3 +113,58 @@ int32_t ipc_netsocklisten(IpcNetSock *netsock, size_t maxlisteners) { spinlock_release(&netsock->spinlock); return r == 0 ? E_OK : E_NETSOCKLISTEN; } + +int32_t ipc_netsockdelete_nolock(IpcNetSock *netsock) { + LL_REMOVE(IPC_NETSOCKS.netsocks, netsock); + + spinlock_acquire(&netsock->spinlock); + pico_socket_del(netsock->picosock); + ipc_pipefree(netsock->datapipe); + dlfree(netsock->datapipe); + dlfree(netsock->eventbuffer.buffer); + spinlock_release(&netsock->spinlock); + + dlfree(netsock); + return E_OK; +} + +int32_t ipc_netsockdelete(IpcNetSock *netsock) { + spinlock_acquire(&IPC_NETSOCKS.spinlock); + LL_REMOVE(IPC_NETSOCKS.netsocks, netsock); + spinlock_release(&IPC_NETSOCKS.spinlock); + + spinlock_acquire(&netsock->spinlock); + pico_socket_del(netsock->picosock); + ipc_pipefree(netsock->datapipe); + dlfree(netsock->datapipe); + dlfree(netsock->eventbuffer.buffer); + spinlock_release(&netsock->spinlock); + + dlfree(netsock); + return E_OK; +} + +void ipc_netsock_cleanup_dangling(void) { + IpcNetSock *ns, *nstmp; + + spinlock_acquire(&IPC_NETSOCKS.spinlock); + spinlock_acquire(&PROCS.spinlock); + + LL_FOREACH_SAFE(IPC_NETSOCKS.netsocks, ns, nstmp) { + bool foundowner = false; + Proc *proc, *proctmp; + LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) { + if (ns->ownerpid == proc->pid) { + foundowner = true; + break; + } + } + + if (!foundowner) { + ipc_netsockdelete_nolock(ns); + } + } + + spinlock_release(&PROCS.spinlock); + spinlock_release(&IPC_NETSOCKS.spinlock); +} diff --git a/kernel/ipc/netsock/netsock.h b/kernel/ipc/netsock/netsock.h index 721260b..efb701e 100644 --- a/kernel/ipc/netsock/netsock.h +++ b/kernel/ipc/netsock/netsock.h @@ -16,6 +16,7 @@ typedef struct IpcNetSock { IpcPipe *datapipe; RBufT eventbuffer; SpinLock spinlock; + uint64_t ownerpid; } IpcNetSock; typedef struct { @@ -26,7 +27,9 @@ typedef struct { extern IpcNetSocks IPC_NETSOCKS; void ipc_netsockinit(void); -IpcNetSock *ipc_netsockmake(uint16_t net, uint16_t proto, uint16_t port); +IpcNetSock *ipc_netsockmake(uint16_t net, uint16_t proto, uint16_t port, uint64_t pid); int32_t ipc_netsocklisten(IpcNetSock *netsock, size_t maxlisteners); +int32_t ipc_netsockdelete(IpcNetSock *netsock); +void ipc_netsock_cleanup_dangling(void); #endif // NETSOCK_NETSOCK_H_ diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index d8539b4..e83799b 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -13,6 +13,7 @@ #include "vfs/vfs.h" #include "bootinfo/bootinfo.h" #include "ipc/pipe/pipe.h" +#include "ipc/netsock/netsock.h" #include "sysdefs/proc.h" #include "sysdefs/fs.h" #include "time/time.h" @@ -246,6 +247,7 @@ void proc_reaper(void) { void proc_sched(void *cpustate) { hal_intr_disable(); sched_ticks++; + ipc_netsock_cleanup_dangling(); update_time(); pico_stack_tick(); diff --git a/kernel/syscall/ipcnetsock.c b/kernel/syscall/ipcnetsock.c index f43ab54..e1d6850 100644 --- a/kernel/syscall/ipcnetsock.c +++ b/kernel/syscall/ipcnetsock.c @@ -11,7 +11,7 @@ int32_t SYSCALL3(sys_ipc_netsockmake, net1, proto1, port1) { uint16_t proto = proto1; uint16_t port = port1; - IpcNetSock *netsock = ipc_netsockmake(net, proto, port); + IpcNetSock *netsock = ipc_netsockmake(net, proto, port, _caller_pid); if (netsock == NULL) { return E_NOMEMORY; @@ -82,3 +82,23 @@ int32_t SYSCALL1(sys_ipc_netsockpollev, socknum1) { return (int32_t)ev; } + +int32_t SYSCALL1(sys_ipc_netsockdelete, socknum1) { + size_t socknum = socknum1; + + spinlock_acquire(&IPC_NETSOCKS.spinlock); + size_t idx = 0; + IpcNetSock *ns, *nstmp; + LL_FOREACH_SAFE_IDX(IPC_NETSOCKS.netsocks, ns, nstmp, idx) { + if (idx == socknum) { + break; + } + } + spinlock_release(&IPC_NETSOCKS.spinlock); + + if (ns == NULL) { + return E_NOENTRY; + } + + return ipc_netsockdelete(ns); +} diff --git a/kernel/syscall/ipcnetsock.h b/kernel/syscall/ipcnetsock.h index 399b1cf..ed8239b 100644 --- a/kernel/syscall/ipcnetsock.h +++ b/kernel/syscall/ipcnetsock.h @@ -8,5 +8,6 @@ int32_t SYSCALL3(sys_ipc_netsockmake, net1, proto1, port1); int32_t SYSCALL2(sys_ipc_netsocklisten, socknum1, maxlisteners1); int32_t SYSCALL1(sys_ipc_netsockpollev, socknum1); +int32_t SYSCALL1(sys_ipc_netsockdelete, socknum1); #endif // SYSCALL_IPC_NETSOCK_H_ diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 09b085b..269ede4 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -68,4 +68,5 @@ SyscallFn SYSCALL_TABLE[SYSCALLS_MAX] = { [SYS_IPC_NETSOCKMAKE] = &sys_ipc_netsockmake, [SYS_IPC_NETSOCKLISTEN] = &sys_ipc_netsocklisten, [SYS_IPC_NETSOCKPOLLEV] = &sys_ipc_netsockpollev, + [SYS_IPC_NETSOCKDELETE] = &sys_ipc_netsockdelete, }; diff --git a/share/sysdefs/syscall.h b/share/sysdefs/syscall.h index 5c1e45b..169f341 100644 --- a/share/sysdefs/syscall.h +++ b/share/sysdefs/syscall.h @@ -38,5 +38,6 @@ #define SYS_IPC_NETSOCKMAKE 39 #define SYS_IPC_NETSOCKLISTEN 40 #define SYS_IPC_NETSOCKPOLLEV 41 +#define SYS_IPC_NETSOCKDELETE 42 #endif // SHARE_HDRS_SYSCALL_H_ diff --git a/ulib/system/system.c b/ulib/system/system.c index fc7a579..f680c88 100644 --- a/ulib/system/system.c +++ b/ulib/system/system.c @@ -154,3 +154,7 @@ int32_t ipc_netsocklisten(uint64_t netsock, size_t maxlisteners) { int32_t ipc_netsockpollev(uint64_t netsock) { return syscall(SYS_IPC_NETSOCKPOLLEV, (uint64_t)netsock, 0, 0, 0, 0, 0); } + +int32_t ipc_netsockdelete(uint64_t netsock) { + return syscall(SYS_IPC_NETSOCKDELETE, (uint64_t)netsock, 0, 0, 0, 0, 0); +} diff --git a/ulib/system/system.h b/ulib/system/system.h index e712e36..0664dde 100644 --- a/ulib/system/system.h +++ b/ulib/system/system.h @@ -47,5 +47,6 @@ int32_t time(Time *time); int32_t ipc_netsockmake(uint16_t net, uint16_t proto, uint16_t port); int32_t ipc_netsocklisten(uint64_t netsock, size_t maxlisteners); int32_t ipc_netsockpollev(uint64_t netsock); +int32_t ipc_netsockdelete(uint64_t netsock); #endif // ULIB_SYSTEM_SYSTEM_H_ diff --git a/user/diagdummy/diagdummy.c b/user/diagdummy/diagdummy.c index d9227bb..d6cffdb 100644 --- a/user/diagdummy/diagdummy.c +++ b/user/diagdummy/diagdummy.c @@ -12,8 +12,10 @@ void main(void) { if (string_strcmp(cmd, "block") == 0) { diagdummy_block(); - } else if (string_strcmp(cmd, "tcp-test") == 0) { - diagdummy_tcptest(); + } else if (string_strcmp(cmd, "tcp-test-server") == 0) { + diagdummy_tcptestserver(); + } else if (string_strcmp(cmd, "tcp-test-client") == 0) { + diagdummy_tcptestclient(); } else { uprintf("diagdummy: unknown cmd %s\n", cmd); } diff --git a/user/diagdummy/tcptest.c b/user/diagdummy/tcptest.c index fc2ee91..e2674b7 100644 --- a/user/diagdummy/tcptest.c +++ b/user/diagdummy/tcptest.c @@ -4,7 +4,7 @@ #define MAX_CONNS 10 -void diagdummy_tcptest(void) { +void diagdummy_tcptestserver(void) { netsock_t netsock = ipc_netsockmake(NETSOCK_IPV4, NETSOCK_TCP, 1); ipc_netsocklisten(netsock, MAX_CONNS); @@ -16,4 +16,10 @@ void diagdummy_tcptest(void) { } else { } } + + ipc_netsockdelete(netsock); +} + +void diagdummy_tcptestclient(void) { + } diff --git a/user/diagdummy/tcptest.h b/user/diagdummy/tcptest.h index 4945eea..0c1f94a 100644 --- a/user/diagdummy/tcptest.h +++ b/user/diagdummy/tcptest.h @@ -1,6 +1,7 @@ #ifndef DIAGDUMMY_TCPTEST_H_ #define DIAGDUMMY_TCPTEST_H_ -void diagdummy_tcptest(void); +void diagdummy_tcptestserver(void); +void diagdummy_tcptestclient(void); #endif // DIAGDUMMY_TCPTEST_H_