26#define IPC_SERVER_MAGIC MOS_FOURCC('I', 'P', 'C', 'S')
67 return (
void *)
name.c_str();
110 ipc->buffer_size_npages = 0;
132 if (dentry->inode ==
nullptr)
169 if (r_fullyclosed || w_fullyclosed)
183 if (r_fullyclosed || w_fullyclosed)
200 dInfo<ipc> <<
"creating ipc server '" <<
name <<
"' with max_pending=" << max_pending;
204 if (server->name ==
name)
228 dInfo<ipc> <<
"woken up " << n <<
" waiters for ipc server '" <<
name <<
"'";
239 if (server->name ==
name)
248 dInfo<ipc> <<
"accepting connection on ipc server '" << ipc_server->
name <<
"'...";
257 dInfo<ipc> <<
"ipc server '" << ipc_server->
name <<
"' is closed, aborting accept()";
259 return -ECONNABORTED;
265 dInfo<ipc> <<
"no pending connections, waiting for a client to connect...";
272 dInfo<ipc> <<
"woken up by a signal, aborting accept()";
292 if (readPipe.isErr())
296 return readPipe.getErr();
301 if (writePipe.isErr())
305 return writePipe.getErr();
317 if (buffer_size == 0)
320 dInfo<ipc> <<
"connecting to ipc server '" <<
name <<
"' with buffer_size=" << buffer_size;
329 if (server->name ==
name)
365 dInfo<ipc> <<
"no ipc server '" <<
name <<
"' found, waiting for it to be created...";
372 dInfo<ipc> <<
"woken up by a signal, aborting connect()";
385 dWarn<ipc> <<
"ipc server '" << ipc_server->
name <<
"' has reached its max pending connections, rejecting connection";
388 return -ECONNREFUSED;
401 dInfo<ipc> <<
"ipc server '" << ipc_server->
name <<
"' woke us up";
404 if (descriptor->buffer_size_npages == 0)
407 dWarn<ipc> <<
"ipc server '" << ipc_server->
name <<
"' has closed";
410 return -ECONNREFUSED;
415 dInfo<ipc> <<
"ipc server '" << ipc_server->
name <<
"' has accepted the connection";
423 sysfs_printf(
f,
"%-40s\t%s\n",
"Server Name",
"Max Pending Connections");
426 sysfs_printf(
f,
"%-40s\t%zu\n", ipc->name.c_str(), ipc->pending_max);
448 add_record(state, ipc_server->sysfs_ino->ino, ipc_server->name, ipc_server->sysfs_ino->type);
460 if (ipc->name ==
name)
467 if (ipc_server ==
NULL)
483 if (ipc_server.isErr())
496 const auto guard = waitlist->
lock.
lock();
524 return __sysfs_ipc._dentry;
void dentry_attach(dentry_t *d, inode_t *inode)
Attach an inode to a dentry.
void dentry_detach(dentry_t *d)
Detach the inode from a dentry.
void dentry_try_release(dentry_t *dentry)
void dentry_unref(dentry_t *dentry)
Decrement the reference count of a dentry.
bool signal_has_pending(void)
Return true if there's a pending signal.
MOSAPI hash_t __pure hashmap_hash_string(uintn key)
MOSAPI int __pure hashmap_compare_string(uintn key1, uintn key2)
MOSAPI void * hashmap_get(hashmap_t *map, uintn key)
MOSAPI void * hashmap_put(hashmap_t *map, uintn key, void *value)
MOSAPI void hashmap_init(hashmap_t *map, size_t capacity, hashmap_hash_t hash_func, hashmap_key_compare_t compare_func)
MOSAPI void hashmap_foreach(hashmap_t *map, hashmap_foreach_func_t func, void *data)
MOSAPI void linked_list_init(list_node_t *head_node)
Initialise a circular double linked list.
MOSAPI void list_node_append(list_node_t *head, list_node_t *item)
#define list_foreach(t, v, h)
Iterate over a list.
#define list_node(element)
Get the ‘list_node’ of a list element. This is exactly the reverse of ‘list_entry’ above.
list_node_t list_head
A linked list head.
MOSAPI bool list_is_empty(const list_node_t *head)
#define list_remove(element)
#define list_node_next_entry(node, type)
Get the next list node.
bool inode_unlink(inode_t *dir, dentry_t *dentry)
Unlink a dentry from its parent inode.
void ipc_server_close(IPCServer *server)
void ipc_server_close_channel(IpcDescriptor *ipc)
dentry_t * ipc_get_sysfs_dir()
static inode_t * ipc_sysfs_create_ino(IPCServer *ipc_server)
size_t ipc_server_read(IpcDescriptor *ipc, void *buf, size_t size)
static bool ipc_sysfs_create_server(inode_t *dir, dentry_t *dentry, file_type_t type, file_perm_t perm)
static bool ipc_sysfs_dump_name_waitlist(sysfs_file_t *f)
PtrResult< IPCServer > ipc_get_server(mos::string_view name)
PtrResult< IpcDescriptor > ipc_connect_to_server(mos::string_view name, size_t buffer_size)
static void ipc_sysfs_list_ipcs(sysfs_item_t *item, dentry_t *d, vfs_listdir_state_t *state, dentry_iterator_op add_record)
static bool ipc_dump_name_waitlist(uintn key, void *value, void *data)
static sysfs_item_t ipc_sysfs_items[]
static bool ipc_sysfs_servers(sysfs_file_t *f)
static spinlock_t ipc_lock
protects ipc_servers and name_waitlist
size_t ipc_client_read(IpcDescriptor *ipc, void *buf, size_t size)
void ipc_client_close_channel(IpcDescriptor *ipc)
PtrResult< IpcDescriptor > ipc_server_accept(IPCServer *ipc_server)
static list_head ipc_servers
size_t ipc_server_write(IpcDescriptor *ipc, const void *buf, size_t size)
static bool ipc_sysfs_lookup_ipc(inode_t *parent_dir, dentry_t *dentry)
size_t ipc_client_write(IpcDescriptor *ipc, const void *buf, size_t size)
static hashmap_t name_waitlist
waitlist for an IPC server, key = name, value = waitlist_t *
PtrResult< IPCServer > ipc_server_create(mos::string_view name, size_t max_pending)
const file_ops_t ipc_sysfs_file_ops
#define ALIGN_UP_TO_PAGE(addr)
basic_string_view< char > string_view
T * create(Args &&...args)
mos::basic_string< char > string
__nodiscard bool pipe_close_one_end(pipe_t *pipe)
Close one end of the pipe, so that the other end will get EOF.
PtrResult< pipe_t > pipe_create(size_t bufsize)
size_t pipe_write(pipe_t *pipe, const void *buf, size_t size)
size_t pipe_read(pipe_t *pipe, void *buf, size_t size)
void blocked_reschedule(void)
Mark the current task as blocked and reschedule.
#define spinlock_acquire(lock)
#define spinlock_release(lock)
inode_t * sysfs_ino
inode for sysfs
list_head pending
list of IPCDescriptor
waitlist_t server_waitlist
wake up the server here when a client connects
IPCServer(mos::string_view name, size_t pending_max)
pipe_t * server_read_pipe
IpcDescriptor(mos::string_view name, size_t buffer_size)
as_linked_list
attached to either pending or established list
pipe_t * client_write_pipe
const mos::string server_name
waitlist_t client_waitlist
client waits here for the server to accept the connection
size_t buffer_size_npages
pipe_t * server_write_pipe
pipe_t * client_read_pipe
superblock_t * superblock
const file_ops_t * file_ops
ssize_t sysfs_printf(sysfs_file_t *file, const char *fmt,...)
inode_t * sysfs_create_inode(file_type_t type, void *data)
#define SYSFS_RO_ITEM(_name, _show_fn)
#define SYSFS_DYN_DIR(_name, _iterate_fn, _lookup_fn, _create_fn)
#define SYSFS_AUTOREGISTER(sysfs_name, sysfs_items)
void dentry_iterator_op(vfs_listdir_state_t *state, u64 ino, mos::string_view name, file_type_t type)
dentry_t * dentry_get_from_parent(superblock_t *sb, dentry_t *parent, mos::string_view name)
Create a new dentry with the given name and parent.
void waitlist_init(waitlist_t *list)
#define waitlist_wake_all(list)
size_t waitlist_wake(waitlist_t *list, size_t max_wakeups)
void waitlist_remove_me(waitlist_t *waitlist)
void waitlist_close(waitlist_t *list)
__nodiscard bool waitlist_append(waitlist_t *list)