aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/include/ipc.h9
-rw-r--r--src/kernel/user/ipc.c114
2 files changed, 121 insertions, 2 deletions
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 :*/