Implement ipc_netsockdelete() syscall and automatic dangling socket cleanup
This commit is contained in:
@ -9,6 +9,7 @@
|
|||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "sysdefs/ipcnetsock.h"
|
#include "sysdefs/ipcnetsock.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
|
#include "proc/proc.h"
|
||||||
|
|
||||||
IpcNetSocks IPC_NETSOCKS;
|
IpcNetSocks IPC_NETSOCKS;
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ void ipc_netsock_event(uint16_t ev, struct pico_socket *sock1) {
|
|||||||
spinlock_release(&netsock->spinlock);
|
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));
|
IpcNetSock *netsock = dlmalloc(sizeof(*netsock));
|
||||||
if (netsock == NULL) {
|
if (netsock == NULL) {
|
||||||
return 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);
|
uint8_t *eventbuffer = dlmalloc(sizeof(IpcNetSockEventBuffer) * IPC_NETSOCK_EVENTBUFFER_MAX);
|
||||||
rbuft_init(&netsock->eventbuffer, eventbuffer, 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);
|
uint16_t port_be = short_be(port);
|
||||||
struct pico_ip4 inaddr_any = {0};
|
struct pico_ip4 inaddr_any = {0};
|
||||||
pico_socket_bind(netsock->picosock, &inaddr_any, &port_be);
|
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);
|
spinlock_release(&netsock->spinlock);
|
||||||
return r == 0 ? E_OK : E_NETSOCKLISTEN;
|
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;
|
IpcPipe *datapipe;
|
||||||
RBufT eventbuffer;
|
RBufT eventbuffer;
|
||||||
SpinLock spinlock;
|
SpinLock spinlock;
|
||||||
|
uint64_t ownerpid;
|
||||||
} IpcNetSock;
|
} IpcNetSock;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -26,7 +27,9 @@ typedef struct {
|
|||||||
extern IpcNetSocks IPC_NETSOCKS;
|
extern IpcNetSocks IPC_NETSOCKS;
|
||||||
|
|
||||||
void ipc_netsockinit(void);
|
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_netsocklisten(IpcNetSock *netsock, size_t maxlisteners);
|
||||||
|
int32_t ipc_netsockdelete(IpcNetSock *netsock);
|
||||||
|
void ipc_netsock_cleanup_dangling(void);
|
||||||
|
|
||||||
#endif // NETSOCK_NETSOCK_H_
|
#endif // NETSOCK_NETSOCK_H_
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include "vfs/vfs.h"
|
#include "vfs/vfs.h"
|
||||||
#include "bootinfo/bootinfo.h"
|
#include "bootinfo/bootinfo.h"
|
||||||
#include "ipc/pipe/pipe.h"
|
#include "ipc/pipe/pipe.h"
|
||||||
|
#include "ipc/netsock/netsock.h"
|
||||||
#include "sysdefs/proc.h"
|
#include "sysdefs/proc.h"
|
||||||
#include "sysdefs/fs.h"
|
#include "sysdefs/fs.h"
|
||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
@ -246,6 +247,7 @@ void proc_reaper(void) {
|
|||||||
void proc_sched(void *cpustate) {
|
void proc_sched(void *cpustate) {
|
||||||
hal_intr_disable();
|
hal_intr_disable();
|
||||||
sched_ticks++;
|
sched_ticks++;
|
||||||
|
ipc_netsock_cleanup_dangling();
|
||||||
update_time();
|
update_time();
|
||||||
pico_stack_tick();
|
pico_stack_tick();
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ int32_t SYSCALL3(sys_ipc_netsockmake, net1, proto1, port1) {
|
|||||||
uint16_t proto = proto1;
|
uint16_t proto = proto1;
|
||||||
uint16_t port = port1;
|
uint16_t port = port1;
|
||||||
|
|
||||||
IpcNetSock *netsock = ipc_netsockmake(net, proto, port);
|
IpcNetSock *netsock = ipc_netsockmake(net, proto, port, _caller_pid);
|
||||||
|
|
||||||
if (netsock == NULL) {
|
if (netsock == NULL) {
|
||||||
return E_NOMEMORY;
|
return E_NOMEMORY;
|
||||||
@ -82,3 +82,23 @@ int32_t SYSCALL1(sys_ipc_netsockpollev, socknum1) {
|
|||||||
|
|
||||||
return (int32_t)ev;
|
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 SYSCALL3(sys_ipc_netsockmake, net1, proto1, port1);
|
||||||
int32_t SYSCALL2(sys_ipc_netsocklisten, socknum1, maxlisteners1);
|
int32_t SYSCALL2(sys_ipc_netsocklisten, socknum1, maxlisteners1);
|
||||||
int32_t SYSCALL1(sys_ipc_netsockpollev, socknum1);
|
int32_t SYSCALL1(sys_ipc_netsockpollev, socknum1);
|
||||||
|
int32_t SYSCALL1(sys_ipc_netsockdelete, socknum1);
|
||||||
|
|
||||||
#endif // SYSCALL_IPC_NETSOCK_H_
|
#endif // SYSCALL_IPC_NETSOCK_H_
|
||||||
|
|||||||
@ -68,4 +68,5 @@ SyscallFn SYSCALL_TABLE[SYSCALLS_MAX] = {
|
|||||||
[SYS_IPC_NETSOCKMAKE] = &sys_ipc_netsockmake,
|
[SYS_IPC_NETSOCKMAKE] = &sys_ipc_netsockmake,
|
||||||
[SYS_IPC_NETSOCKLISTEN] = &sys_ipc_netsocklisten,
|
[SYS_IPC_NETSOCKLISTEN] = &sys_ipc_netsocklisten,
|
||||||
[SYS_IPC_NETSOCKPOLLEV] = &sys_ipc_netsockpollev,
|
[SYS_IPC_NETSOCKPOLLEV] = &sys_ipc_netsockpollev,
|
||||||
|
[SYS_IPC_NETSOCKDELETE] = &sys_ipc_netsockdelete,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -38,5 +38,6 @@
|
|||||||
#define SYS_IPC_NETSOCKMAKE 39
|
#define SYS_IPC_NETSOCKMAKE 39
|
||||||
#define SYS_IPC_NETSOCKLISTEN 40
|
#define SYS_IPC_NETSOCKLISTEN 40
|
||||||
#define SYS_IPC_NETSOCKPOLLEV 41
|
#define SYS_IPC_NETSOCKPOLLEV 41
|
||||||
|
#define SYS_IPC_NETSOCKDELETE 42
|
||||||
|
|
||||||
#endif // SHARE_HDRS_SYSCALL_H_
|
#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) {
|
int32_t ipc_netsockpollev(uint64_t netsock) {
|
||||||
return syscall(SYS_IPC_NETSOCKPOLLEV, (uint64_t)netsock, 0, 0, 0, 0, 0);
|
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_netsockmake(uint16_t net, uint16_t proto, uint16_t port);
|
||||||
int32_t ipc_netsocklisten(uint64_t netsock, size_t maxlisteners);
|
int32_t ipc_netsocklisten(uint64_t netsock, size_t maxlisteners);
|
||||||
int32_t ipc_netsockpollev(uint64_t netsock);
|
int32_t ipc_netsockpollev(uint64_t netsock);
|
||||||
|
int32_t ipc_netsockdelete(uint64_t netsock);
|
||||||
|
|
||||||
#endif // ULIB_SYSTEM_SYSTEM_H_
|
#endif // ULIB_SYSTEM_SYSTEM_H_
|
||||||
|
|||||||
@ -12,8 +12,10 @@ void main(void) {
|
|||||||
|
|
||||||
if (string_strcmp(cmd, "block") == 0) {
|
if (string_strcmp(cmd, "block") == 0) {
|
||||||
diagdummy_block();
|
diagdummy_block();
|
||||||
} else if (string_strcmp(cmd, "tcp-test") == 0) {
|
} else if (string_strcmp(cmd, "tcp-test-server") == 0) {
|
||||||
diagdummy_tcptest();
|
diagdummy_tcptestserver();
|
||||||
|
} else if (string_strcmp(cmd, "tcp-test-client") == 0) {
|
||||||
|
diagdummy_tcptestclient();
|
||||||
} else {
|
} else {
|
||||||
uprintf("diagdummy: unknown cmd %s\n", cmd);
|
uprintf("diagdummy: unknown cmd %s\n", cmd);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#define MAX_CONNS 10
|
#define MAX_CONNS 10
|
||||||
|
|
||||||
void diagdummy_tcptest(void) {
|
void diagdummy_tcptestserver(void) {
|
||||||
netsock_t netsock = ipc_netsockmake(NETSOCK_IPV4, NETSOCK_TCP, 1);
|
netsock_t netsock = ipc_netsockmake(NETSOCK_IPV4, NETSOCK_TCP, 1);
|
||||||
ipc_netsocklisten(netsock, MAX_CONNS);
|
ipc_netsocklisten(netsock, MAX_CONNS);
|
||||||
|
|
||||||
@ -16,4 +16,10 @@ void diagdummy_tcptest(void) {
|
|||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipc_netsockdelete(netsock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diagdummy_tcptestclient(void) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#ifndef DIAGDUMMY_TCPTEST_H_
|
#ifndef DIAGDUMMY_TCPTEST_H_
|
||||||
#define DIAGDUMMY_TCPTEST_H_
|
#define DIAGDUMMY_TCPTEST_H_
|
||||||
|
|
||||||
void diagdummy_tcptest(void);
|
void diagdummy_tcptestserver(void);
|
||||||
|
void diagdummy_tcptestclient(void);
|
||||||
|
|
||||||
#endif // DIAGDUMMY_TCPTEST_H_
|
#endif // DIAGDUMMY_TCPTEST_H_
|
||||||
|
|||||||
Reference in New Issue
Block a user