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,
|
||||
};
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
@ -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_
|
||||
|
||||
Reference in New Issue
Block a user