3#define pr_fmt(fmt) "ipc: " fmt
27#define IPC_SERVER_MAGIC MOS_FOURCC('I', 'P', 'C', 'S')
68 return (
void *)
name.c_str();
111 ipc->buffer_size_npages = 0;
159 if (r_fullyclosed || w_fullyclosed)
173 if (r_fullyclosed || w_fullyclosed)
190 pr_dinfo(ipc,
"creating ipc server '%s' with max_pending=%zu",
name.data(), max_pending);
194 if (server->name ==
name)
196 pr_dwarn(ipc,
"ipc server '%s' already exists",
name.data());
213 pr_dinfo2(ipc,
"found waitlist for ipc server '%s'",
name.data());
218 pr_dinfo2(ipc,
"woken up %zu waiters for ipc server '%s'", n,
name.data());
229 if (server->name ==
name)
238 pr_dinfo(ipc,
"accepting connection on ipc server '%s'...", ipc_server->
name.
c_str());
247 pr_dinfo2(ipc,
"ipc server '%s' is closed, aborting accept()", ipc_server->
name.
c_str());
249 return -ECONNABORTED;
255 pr_dinfo2(ipc,
"no pending connections, waiting for a client to connect...");
262 pr_dinfo2(ipc,
"woken up by a signal, aborting accept()");
282 if (readPipe.isErr())
284 pr_dwarn(ipc,
"failed to create read pipe");
286 return readPipe.getErr();
291 if (writePipe.isErr())
293 pr_dwarn(ipc,
"failed to create write pipe");
295 return writePipe.getErr();
307 if (buffer_size == 0)
310 pr_dinfo(ipc,
"connecting to ipc server '%s' with buffer_size=%zu",
name.data(), buffer_size);
319 if (server->name ==
name)
352 pr_dinfo2(ipc,
"created waitlist for ipc server '%s'",
name.data());
355 pr_dinfo2(ipc,
"no ipc server '%s' found, waiting for it to be created...",
name.data());
362 pr_dinfo2(ipc,
"woken up by a signal, aborting connect()");
375 pr_dwarn(ipc,
"ipc server '%s' has reached its max pending connections, rejecting connection", ipc_server->
name.
c_str());
378 return -ECONNREFUSED;
394 if (descriptor->buffer_size_npages == 0)
400 return -ECONNREFUSED;
405 pr_dinfo2(ipc,
"ipc server '%s' has accepted the connection", ipc_server->
name.
c_str());
413 sysfs_printf(f,
"%-20s\t%s\n",
"Server Name",
"Max Pending Connections");
416 sysfs_printf(f,
"%-20s\t%zu\n", ipc->name.c_str(), ipc->pending_max);
438 add_record(state, ipc_server->sysfs_ino->ino, ipc_server->name, ipc_server->sysfs_ino->type);
450 if (ipc->name ==
name)
457 if (ipc_server ==
NULL)
473 if (ipc_server.isErr())
486 const auto guard = waitlist->
lock.
lock();
487 sysfs_printf(f,
"%s\t%s:\n", (
const char *) key, waitlist->
closed ?
"closed" :
"open");
const Char * c_str() const
void dentry_attach(dentry_t *d, inode_t *inode)
Attach an inode to 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.
void ipc_server_close(IPCServer *server)
void ipc_server_close_channel(IPCDescriptor *ipc)
static inode_t * ipc_sysfs_create_ino(IPCServer *ipc_server)
void ipc_client_close_channel(IPCDescriptor *ipc)
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)
size_t ipc_client_write(IPCDescriptor *ipc, const void *buf, size_t size)
PtrResult< IPCDescriptor > ipc_server_accept(IPCServer *ipc_server)
static void ipc_sysfs_list_ipcs(sysfs_item_t *item, dentry_t *d, vfs_listdir_state_t *state, dentry_iterator_op add_record)
PtrResult< IPCDescriptor > ipc_connect_to_server(mos::string_view name, size_t buffer_size)
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_server_write(IPCDescriptor *ipc, const void *buf, size_t size)
static list_head ipc_servers
static bool ipc_sysfs_lookup_ipc(inode_t *parent_dir, dentry_t *dentry)
size_t ipc_server_read(IPCDescriptor *ipc, 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)
size_t ipc_client_read(IPCDescriptor *ipc, void *buf, size_t size)
const file_ops_t ipc_sysfs_file_ops
#define ALIGN_UP_TO_PAGE(addr)
basic_string_view< char > string_view
mos::basic_string< char, mos::default_allocator > string
T * create(Args &&...args)
__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)
#define pr_dinfo(feat, fmt,...)
#define pr_dinfo2(feat, fmt,...)
#define pr_dwarn(feat, fmt,...)
void blocked_reschedule(void)
Mark the current task as blocked and reschedule.
#define spinlock_acquire(lock)
#define spinlock_release(lock)
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
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)
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)
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)