diff options
-rw-r--r-- | src/common/include/syscallproto.h | 30 | ||||
-rw-r--r-- | src/kernel/include/ipc.h | 9 | ||||
-rw-r--r-- | src/kernel/user/ipc.c | 114 |
3 files changed, 138 insertions, 15 deletions
diff --git a/src/common/include/syscallproto.h b/src/common/include/syscallproto.h index 4cfd9ae..9673cde 100644 --- a/src/common/include/syscallproto.h +++ b/src/common/include/syscallproto.h @@ -28,21 +28,25 @@ #define SC_IOCTL 36 // args: fd, command, out void* data #define SC_GET_MODE 37 // args: fd -- get mode for open file handle -#define SC_MAKE_FS 40 // args: sc_make_fs_args_t -#define SC_FS_ADD_SRC 41 // args: fs_name, fs_name_strlen, fd, opts, opts_strlen -#define SC_SUBFS 42 // args: sc_subfs_args_t -#define SC_RM_FS 43 // args: fs_name, fs_name_strlen +#define SC_MK_CHANNEL 40 // args: blocking?, (int, int)* +#define SC_GEN_TOKEN 41 // args: fd, token_t* +#define SC_USE_TOKEN 42 // args: token_t* + +#define SC_MAKE_FS 50 // args: sc_make_fs_args_t +#define SC_FS_ADD_SRC 51 // args: fs_name, fs_name_strlen, fd, opts, opts_strlen +#define SC_SUBFS 52 // args: sc_subfs_args_t +#define SC_RM_FS 53 // args: fs_name, fs_name_strlen // TODO : how do we enumerate filesystems ? -#define SC_NEW_PROC 50 // args: nothing ? -#define SC_BIND_FS 51 // args: pid, new_name, new_name_strlen, fs_name, fs_name_strlen -- bind FS to child process -#define SC_BIND_SUBFS 52 // args: sc_subfs_args_t -- subfs & bind to child process -#define SC_BIND_MAKE_FS 53 // args: sc_make_fs_args_t -#define SC_BIND_FD 54 // args: pid, new_fd, local_fd -- copy a file descriptor to child process -#define SC_PROC_EXEC 55 // args: pid, exec_name, exec_name_strlen -- execute binary in process -#define SC_PROC_STATUS 56 // args: pid, proc_status_t* -#define SC_PROC_KILL 57 // args: pid, proc_status_t* -- inconditionnally kill child process -#define SC_PROC_WAIT 58 // args: pid?, block?, proc_status_t* +#define SC_NEW_PROC 60 // args: nothing ? +#define SC_BIND_FS 61 // args: pid, new_name, new_name_strlen, fs_name, fs_name_strlen -- bind FS to child process +#define SC_BIND_SUBFS 62 // args: sc_subfs_args_t -- subfs & bind to child process +#define SC_BIND_MAKE_FS 63 // args: sc_make_fs_args_t +#define SC_BIND_FD 64 // args: pid, new_fd, local_fd -- copy a file descriptor to child process +#define SC_PROC_EXEC 65 // args: pid, exec_name, exec_name_strlen -- execute binary in process +#define SC_PROC_STATUS 66 // args: pid, proc_status_t* +#define SC_PROC_KILL 67 // args: pid, proc_status_t* -- inconditionnally kill child process +#define SC_PROC_WAIT 68 // args: pid?, block?, proc_status_t* #define INVALID_PID 0 // do a wait with this PID to wayt for any child diff --git a/src/kernel/include/ipc.h b/src/kernel/include/ipc.h index c61ec93..0feddf2 100644 --- a/src/kernel/include/ipc.h +++ b/src/kernel/include/ipc.h @@ -15,7 +15,12 @@ fs_handle_pair_t make_channel(bool blocking); // ---- Tokens for sharing file descriptors between processes -token_t gen_token_for(fs_handle_t *h); -fs_handle_t *use_token(token_t tok); +#define TOKEN_LIFETIME 1500000 // in usecs + +bool gen_token_for(fs_handle_t *h, token_t *tok); +fs_handle_t *use_token(token_t *tok); + +bool token_eq_fun(const void* a, const void* b); +hash_t token_hash_fun(const void* t); /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/user/ipc.c b/src/kernel/user/ipc.c index a518304..648fdf2 100644 --- a/src/kernel/user/ipc.c +++ b/src/kernel/user/ipc.c @@ -4,6 +4,11 @@ #include <mutex.h> #include <thread.h> +#include <prng.h> +#include <worker.h> + +#include <hashtbl.h> + static size_t channel_read(fs_handle_t *c, size_t offset, size_t len, char* buf); static size_t channel_write(fs_handle_t *c, size_t offset, size_t len, const char* buf); static bool channel_stat(fs_node_ptr c, stat_t *st); @@ -175,5 +180,114 @@ void channel_close(fs_handle_t *ch) { free(c); } +// ---- ------ +// ---- Tokens +// ---- ------ + +static hashtbl_t *token_table = 0; +STATIC_MUTEX(token_table_mutex); + +typedef struct { + token_t tok; + fs_handle_t *h; + uint64_t time; +} token_table_entry_t; + +static token_table_entry_t *expired_token = 0; + +static void token_expiration_check(void* x) { + mutex_lock(&token_table_mutex); + + do { + expired_token = 0; + + void find_expired_token(void* k, void* x) { + token_table_entry_t *e = (token_table_entry_t*)x; + if (e->time + TOKEN_LIFETIME < get_kernel_time()) { + expired_token = e; + } + } + hashtbl_iter(token_table, find_expired_token); + + if (expired_token) { + hashtbl_remove(token_table, &expired_token->tok); + unref_file(expired_token->h); + free(expired_token); + } + } while (expired_token != 0); + + mutex_unlock(&token_table_mutex); + + while (!worker_push_in(1000000, token_expiration_check, 0)) yield(); +} + +bool gen_token_for(fs_handle_t *h, token_t *tok) { + bool ok = false; + + token_table_entry_t *e = 0; + + mutex_lock(&token_table_mutex); + + if (token_table == 0) { + token_table = create_hashtbl(token_eq_fun, token_hash_fun, 0); + if (token_table == 0) goto end; + + while (!worker_push_in(1000000, token_expiration_check, 0)) yield(); + } + + e = (token_table_entry_t*)malloc(sizeof(token_t)); + if (!e) goto end; + + prng_bytes((uint8_t*)e->tok.bytes, TOKEN_LENGTH); + memcpy(tok->bytes, e->tok.bytes, TOKEN_LENGTH); + e->h = h; + e->time = get_kernel_time(); + + ok = hashtbl_add(token_table, &e->tok, e); + if (!ok) goto end; + + ref_file(h); + ok = true; + +end: + if (!ok && e) free(e); + mutex_unlock(&token_table_mutex); + return ok; +} + +fs_handle_t* use_token(token_t* tok) { + fs_handle_t *ret = 0; + + mutex_lock(&token_table_mutex); + + token_table_entry_t *e = hashtbl_find(token_table, tok); + if (e != 0) { + ret = e->h; + + hashtbl_remove(token_table, tok); + free(e); + } + + mutex_unlock(&token_table_mutex); + return ret; + +} + +hash_t token_hash_fun(const void* v) { + token_t *t = (token_t*)v; + hash_t h = 707; + for (int i = 0; i < TOKEN_LENGTH; i++) { + h = h * 101 + t->bytes[i]; + } + return h; +} + +bool token_eq_fun(const void* a, const void* b) { + token_t *ta = (token_t*)a, *tb = (token_t*)b; + for (int i = 0; i < TOKEN_LENGTH; i++) { + if (ta->bytes[i] != tb->bytes[i]) return false; + } + return true; +} /* vim: set ts=4 sw=4 tw=0 noet :*/ |