aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/include/syscallproto.h30
-rw-r--r--src/kernel/include/ipc.h9
-rw-r--r--src/kernel/user/ipc.c114
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 :*/