3#define pr_fmt(fmt) "ipc: " fmt
27#define IPC_SERVER_MAGIC MOS_FOURCC('I', 'P', 'C', 'S')
50typedef struct _ipc_server
96 ipc->buffer_size_npages = 0;
146 if (r_fullyclosed || w_fullyclosed)
161 if (r_fullyclosed || w_fullyclosed)
179 pr_dinfo(ipc,
"creating ipc server '%s' with max_pending=%zu",
name, max_pending);
187 return ERR_PTR(-EEXIST);
213 pr_dinfo2(ipc,
"woken up %zu waiters for ipc server '%s'", n,
name);
238 pr_dinfo(ipc,
"accepting connection on ipc server '%s'...", ipc_server->
name);
247 pr_dinfo2(ipc,
"ipc server '%s' is closed, aborting accept()", ipc_server->
name);
248 kfree(ipc_server->
name);
250 return ERR_PTR(-ECONNABORTED);
256 pr_dinfo2(ipc,
"no pending connections, waiting for a client to connect...");
263 pr_dinfo2(ipc,
"woken up by a signal, aborting accept()");
265 return ERR_PTR(-EINTR);
293 if (buffer_size == 0)
294 return ERR_PTR(-EINVAL);
296 pr_dinfo(ipc,
"connecting to ipc server '%s' with buffer_size=%zu",
name, buffer_size);
341 pr_dinfo2(ipc,
"created waitlist for ipc server '%s'",
name);
344 pr_dinfo2(ipc,
"no ipc server '%s' found, waiting for it to be created...",
name);
351 pr_dinfo2(ipc,
"woken up by a signal, aborting connect()");
353 return ERR_PTR(-EINTR);
364 pr_dwarn(ipc,
"ipc server '%s' has reached its max pending connections, rejecting connection", ipc_server->
name);
367 return ERR_PTR(-ECONNREFUSED);
380 pr_dinfo2(ipc,
"ipc server '%s' woke us up", ipc_server->
name);
386 pr_dwarn(ipc,
"ipc server '%s' has closed", ipc_server->
name);
389 return ERR_PTR(-ECONNREFUSED);
394 pr_dinfo2(ipc,
"ipc server '%s' has accepted the connection", ipc_server->
name);
402 sysfs_printf(f,
"%-20s\t%s\n",
"Server Name",
"Max Pending Connections");
405 sysfs_printf(f,
"%-20s\t%zu\n", ipc->name, ipc->pending_max);
428 add_record(state, ipc_server->sysfs_ino->ino, ipc_server->name,
strlen(ipc_server->name), ipc_server->sysfs_ino->type);
447 if (ipc_server ==
NULL)
463 if (IS_ERR(ipc_server))
477 sysfs_printf(f,
"%s\t%s:\n", (
const char *) key, waitlist->
closed ?
"closed" :
"open");
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 char * strdup(const char *src)
MOSAPI s32 strcmp(const char *str1, const char *str2)
MOSAPI void linked_list_init(list_node_t *head_node)
Initialise a circular double linked list.
#define LIST_HEAD_INIT(container)
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.
ipc_t * ipc_server_accept(ipc_server_t *ipc_server)
void ipc_client_close_channel(ipc_t *ipc)
size_t ipc_client_read(ipc_t *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)
size_t ipc_server_read(ipc_t *ipc, void *buf, size_t size)
static void ipc_sysfs_list_ipcs(sysfs_item_t *item, dentry_t *d, vfs_listdir_state_t *state, dentry_iterator_op add_record)
size_t ipc_client_write(ipc_t *ipc, const void *buf, size_t size)
void ipc_server_close(ipc_server_t *server)
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)
ipc_server_t * ipc_get_server(const char *name)
static spinlock_t ipc_lock
protects ipc_servers and name_waitlist
ipc_server_t * ipc_server_create(const char *name, size_t max_pending)
void ipc_server_close_channel(ipc_t *ipc)
size_t ipc_server_write(ipc_t *ipc, const void *buf, size_t size)
static list_head ipc_servers
static inode_t * ipc_sysfs_create_ino(ipc_server_t *ipc_server)
static bool ipc_sysfs_lookup_ipc(inode_t *parent_dir, dentry_t *dentry)
ipc_t * ipc_connect_to_server(const char *name, size_t buffer_size)
static hashmap_t name_waitlist
waitlist for an IPC server, key = name, value = waitlist_t *
static slab_t * ipc_server_slab
const file_ops_t ipc_sysfs_file_ops
struct _ipc_server ipc_server_t
#define ALIGN_UP_TO_PAGE(addr)
static size_t strlen(const char *s)
__nodiscard bool pipe_close_one_end(pipe_t *pipe)
Close one end of the pipe, so that the other end will get EOF.
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)
pipe_t * pipe_create(size_t bufsize)
#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 SLAB_AUTOINIT(name, var, type)
#define spinlock_acquire(lock)
#define spinlock_release(lock)
const file_ops_t * file_ops
inode_t * sysfs_ino
inode for sysfs
list_head pending
list of ipc_t
waitlist_t server_waitlist
wake up the server here when a client connects
pipe_t * server_read_pipe
as_linked_list
attached to either pending or established list
pipe_t * client_write_pipe
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
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, const char *name, size_t name_len, file_type_t type)
#define waitlist_wake_all(list)
size_t waitlist_wake(waitlist_t *list, size_t max_wakeups)
__BEGIN_DECLS void waitlist_init(waitlist_t *list)
void waitlist_remove_me(waitlist_t *waitlist)
void waitlist_close(waitlist_t *list)
__nodiscard bool waitlist_append(waitlist_t *list)