Implement ipc_netsockdelete() syscall and automatic dangling socket cleanup
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user