aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/user
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/user')
-rw-r--r--src/kernel/user/ipc.c107
-rw-r--r--src/kernel/user/nullfs.c26
-rw-r--r--src/kernel/user/vfs.c8
3 files changed, 79 insertions, 62 deletions
diff --git a/src/kernel/user/ipc.c b/src/kernel/user/ipc.c
index b23af56..a518304 100644
--- a/src/kernel/user/ipc.c
+++ b/src/kernel/user/ipc.c
@@ -4,10 +4,10 @@
#include <mutex.h>
#include <thread.h>
-static size_t channel_read(fs_node_ptr c, size_t offset, size_t len, char* buf);
-static size_t channel_write(fs_node_ptr c, size_t offset, size_t len, const char* buf);
+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);
-static void channel_close(fs_node_ptr c);
+static void channel_close(fs_handle_t *c);
static fs_node_ops_t channel_ops = {
.read = channel_read,
@@ -33,7 +33,7 @@ typedef struct channel {
size_t buf_use_begin, buf_used; // circular buffer
} channel_t;
-fs_handle_pair_t make_channel() {
+fs_handle_pair_t make_channel(bool blocking) {
fs_handle_pair_t ret = { .a = 0, .b = 0 };
channel_t *a = 0, *b = 0;
@@ -61,7 +61,7 @@ fs_handle_pair_t make_channel() {
ret.a->data = a;
ret.b->data = b;
ret.a->refs = ret.b->refs = 1;
- ret.a->mode = ret.b->mode = FM_READ | FM_WRITE;
+ ret.a->mode = ret.b->mode = FM_READ | FM_WRITE | (blocking ? FM_BLOCKING : 0);
return ret;
@@ -74,65 +74,82 @@ error:
return ret;
}
-size_t channel_read(fs_node_ptr ch, size_t offset, size_t len, char* buf) {
- channel_t *c = (channel_t*)ch;
+size_t channel_read(fs_handle_t *h, size_t offset, size_t req_len, char* orig_buf) {
+ channel_t *c = (channel_t*)h->data;
+
+ size_t ret = 0;
- mutex_lock(&c->lock);
+ do {
+ size_t len = req_len - ret;
+ char *buf = orig_buf + ret;
+
+ mutex_lock(&c->lock);
- if (c->buf_used < len) len = c->buf_used;
+ if (c->buf_used < len) len = c->buf_used;
- if (len) {
- size_t len0 = len, len1 = 0;
+ if (len) {
+ size_t len0 = len, len1 = 0;
- if (c->buf_use_begin + len > CHANNEL_BUFFER_SIZE) {
- len0 = CHANNEL_BUFFER_SIZE - c->buf_use_begin;
- len1 = len - len0;
+ if (c->buf_use_begin + len > CHANNEL_BUFFER_SIZE) {
+ len0 = CHANNEL_BUFFER_SIZE - c->buf_use_begin;
+ len1 = len - len0;
+ }
+ memcpy(buf, c->buf + c->buf_use_begin, len0);
+ if (len1) memcpy(buf + len0, c->buf, len1);
+
+ c->buf_use_begin = (c->buf_use_begin + len) % CHANNEL_BUFFER_SIZE;
+ c->buf_used -= len;
+
+ if (c->buf_used == 0) c->buf_use_begin = 0;
}
- memcpy(buf, c->buf + c->buf_use_begin, len0);
- if (len1) memcpy(buf + len0, c->buf, len1);
- c->buf_use_begin = (c->buf_use_begin + len) % CHANNEL_BUFFER_SIZE;
- c->buf_used -= len;
-
- if (c->buf_used == 0) c->buf_use_begin = 0;
- }
+ ret += len;
- mutex_unlock(&c->lock);
+ mutex_unlock(&c->lock);
+ } while ((h->mode & FM_BLOCKING) && ret < req_len);
- return len;
+ return ret;
}
-size_t channel_write(fs_node_ptr ch, size_t offset, size_t len, const char* buf) {
- channel_t *tc = (channel_t*)ch;
+size_t channel_write(fs_handle_t *h, size_t offset, size_t req_len, const char* orig_buf) {
+ channel_t *tc = (channel_t*)h->data;
channel_t *c = tc->other_side;
if (c == 0) return 0;
- while (!mutex_try_lock(&c->lock)) {
- yield();
- if (tc->other_side == 0) return 0;
- }
-
- if (c->buf_used + len > CHANNEL_BUFFER_SIZE) len = CHANNEL_BUFFER_SIZE - c->buf_used;
+ size_t ret = 0;
- if (len) {
- size_t len0 = len, len1 = 0;
+ do {
+ size_t len = req_len - ret;
+ const char* buf = orig_buf + ret;
- if (c->buf_use_begin + c->buf_used + len > CHANNEL_BUFFER_SIZE) {
- len0 = CHANNEL_BUFFER_SIZE - c->buf_use_begin - c->buf_used;
- len1 = len - len0;
+ while (!mutex_try_lock(&c->lock)) {
+ yield();
+ if (tc->other_side == 0) break;
}
- memcpy(c->buf + c->buf_use_begin + c->buf_used, buf, len0);
- if (len1) memcpy(c->buf, buf + len0, len1);
- c->buf_used += len;
- }
+ if (c->buf_used + len > CHANNEL_BUFFER_SIZE) len = CHANNEL_BUFFER_SIZE - c->buf_used;
- mutex_unlock(&c->lock);
+ if (len) {
+ size_t len0 = len, len1 = 0;
+
+ if (c->buf_use_begin + c->buf_used + len > CHANNEL_BUFFER_SIZE) {
+ len0 = CHANNEL_BUFFER_SIZE - c->buf_use_begin - c->buf_used;
+ len1 = len - len0;
+ }
+ memcpy(c->buf + c->buf_use_begin + c->buf_used, buf, len0);
+ if (len1) memcpy(c->buf, buf + len0, len1);
+
+ c->buf_used += len;
+ }
- if (len) resume_on(c); // notify processes that may be waiting for data
+ mutex_unlock(&c->lock);
- return len;
+ if (len) resume_on(c); // notify processes that may be waiting for data
+ ret += len;
+ } while ((h->mode & FM_BLOCKING) && ret < req_len);
+
+ return ret;
}
bool channel_stat(fs_node_ptr ch, stat_t *st) {
@@ -149,8 +166,8 @@ bool channel_stat(fs_node_ptr ch, stat_t *st) {
return true;
}
-void channel_close(fs_node_ptr ch) {
- channel_t *c = (channel_t*)ch;
+void channel_close(fs_handle_t *ch) {
+ channel_t *c = (channel_t*)ch->data;
mutex_lock(&c->lock);
diff --git a/src/kernel/user/nullfs.c b/src/kernel/user/nullfs.c
index 77bc3e8..60872ab 100644
--- a/src/kernel/user/nullfs.c
+++ b/src/kernel/user/nullfs.c
@@ -19,16 +19,16 @@ static bool nullfs_d_delete(fs_node_ptr n, const char* file);
static bool nullfs_d_move(fs_node_ptr n, const char* old_name, fs_node_t *new_parent, const char *new_name);
static bool nullfs_d_create(fs_node_ptr n, const char* file, int type);
static void nullfs_d_dispose(fs_node_ptr n);
-static bool nullfs_d_readdir(fs_node_ptr f, size_t ent_no, dirent_t *d);
-static void nullfs_d_close(fs_node_ptr f);
+static bool nullfs_d_readdir(fs_handle_t *f, size_t ent_no, dirent_t *d);
+static void nullfs_d_close(fs_handle_t *f);
// nullfs ram file node
static bool nullfs_f_open(fs_node_ptr n, int mode);
static bool nullfs_f_stat(fs_node_ptr n, stat_t *st);
static void nullfs_f_dispose(fs_node_ptr n);
-static size_t nullfs_f_read(fs_node_ptr f, size_t offset, size_t len, char* buf);
-static size_t nullfs_f_write(fs_node_ptr f, size_t offset, size_t len, const char* buf);
-static void nullfs_f_close(fs_node_ptr f);
+static size_t nullfs_f_read(fs_handle_t *f, size_t offset, size_t len, char* buf);
+static size_t nullfs_f_write(fs_handle_t *f, size_t offset, size_t len, const char* buf);
+static void nullfs_f_close(fs_handle_t *f);
// VTables that go with it
static fs_driver_ops_t nullfs_driver_ops = {
@@ -410,10 +410,10 @@ void nullfs_d_dispose(fs_node_ptr n) {
// nothing to do
}
-bool nullfs_d_readdir(fs_node_ptr f, size_t ent_no, dirent_t *d) {
+bool nullfs_d_readdir(fs_handle_t *f, size_t ent_no, dirent_t *d) {
// Very nonefficient !!
- nullfs_dir_t *h = (nullfs_dir_t*)f;
+ nullfs_dir_t *h = (nullfs_dir_t*)f->data;
mutex_lock(&h->lock);
@@ -442,7 +442,7 @@ bool nullfs_d_readdir(fs_node_ptr f, size_t ent_no, dirent_t *d) {
return ok;
}
-void nullfs_d_close(fs_node_ptr f) {
+void nullfs_d_close(fs_handle_t *f) {
// Nothing to do
}
@@ -486,8 +486,8 @@ void nullfs_f_dispose(fs_node_ptr n) {
// -- File handle --
-static size_t nullfs_f_read(fs_node_ptr h, size_t offset, size_t len, char* buf) {
- nullfs_file_t *f = (nullfs_file_t*)h;
+static size_t nullfs_f_read(fs_handle_t *h, size_t offset, size_t len, char* buf) {
+ nullfs_file_t *f = (nullfs_file_t*)h->data;
mutex_lock(&f->lock);
size_t ret = 0;
@@ -503,8 +503,8 @@ end_read:
return ret;
}
-static size_t nullfs_f_write(fs_node_ptr h, size_t offset, size_t len, const char* buf) {
- nullfs_file_t *f = (nullfs_file_t*)h;
+static size_t nullfs_f_write(fs_handle_t *h, size_t offset, size_t len, const char* buf) {
+ nullfs_file_t *f = (nullfs_file_t*)h->data;
mutex_lock(&f->lock);
size_t ret = 0;
@@ -532,7 +532,7 @@ end_write:
return ret;
}
-static void nullfs_f_close(fs_node_ptr h) {
+static void nullfs_f_close(fs_handle_t *h) {
// nothing to do
}
diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c
index 2af8cf0..4e8cf53 100644
--- a/src/kernel/user/vfs.c
+++ b/src/kernel/user/vfs.c
@@ -449,7 +449,7 @@ void ref_file(fs_handle_t *file) {
void unref_file(fs_handle_t *file) {
file->refs--;
if (file->refs == 0) {
- file->ops->close(file->data);
+ file->ops->close(file);
if (file->node) unref_fs_node(file->node);
if (file->fs) unref_fs(file->fs);
free(file);
@@ -465,7 +465,7 @@ size_t file_read(fs_handle_t *f, size_t offset, size_t len, char* buf) {
if (f->ops->read == 0) return 0;
- return f->ops->read(f->data, offset, len, buf);
+ return f->ops->read(f, offset, len, buf);
}
size_t file_write(fs_handle_t *f, size_t offset, size_t len, const char* buf) {
@@ -473,7 +473,7 @@ size_t file_write(fs_handle_t *f, size_t offset, size_t len, const char* buf) {
if (f->ops->write == 0) return 0;
- return f->ops->write(f->data, offset, len, buf);
+ return f->ops->write(f, offset, len, buf);
}
bool file_stat(fs_handle_t *f, stat_t *st) {
@@ -491,7 +491,7 @@ int file_ioctl(fs_handle_t *f, int command, void* data) {
bool file_readdir(fs_handle_t *f, size_t ent_no, dirent_t *d) {
if (!(f->mode & FM_READDIR)) return 0;
- return f->ops->readdir && f->ops->readdir(f->data, ent_no, d);
+ return f->ops->readdir && f->ops->readdir(f, ent_no, d);
}
/* vim: set ts=4 sw=4 tw=0 noet :*/