aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2015-03-14 15:01:46 +0100
committerAlex Auvolat <alex@adnab.me>2015-03-14 15:01:46 +0100
commit51def2fc45d98b59be0413fcb9c25cbb0bbca211 (patch)
tree8b57930186622a8fad2aeb6fa6aac1025f9db224 /src/kernel
parent4672f514591f0f7110103c4cd898909aef95b635 (diff)
downloadkogata-51def2fc45d98b59be0413fcb9c25cbb0bbca211.tar.gz
kogata-51def2fc45d98b59be0413fcb9c25cbb0bbca211.zip
Fix blocking channel && channel write on circular-overflow. (see ipc.c)
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/core/thread.c2
-rw-r--r--src/kernel/include/ipc.h2
-rw-r--r--src/kernel/user/ipc.c55
3 files changed, 43 insertions, 16 deletions
diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c
index 4a3722d..fab4eef 100644
--- a/src/kernel/core/thread.c
+++ b/src/kernel/core/thread.c
@@ -421,7 +421,7 @@ void kill_thread(thread_t *thread) {
enqueue_thread(thread, false);
}
yield();
- if (i++ > 100) dbg_printf("Thread 0x%p must be killed but will not exit.\n", thread);
+ if (i++ == 100) dbg_printf("Thread 0x%p must be killed but will not exit.\n", thread);
}
exit_critical(st);
diff --git a/src/kernel/include/ipc.h b/src/kernel/include/ipc.h
index 4f8573c..5be6d48 100644
--- a/src/kernel/include/ipc.h
+++ b/src/kernel/include/ipc.h
@@ -6,7 +6,7 @@
// ---- Communication channels
-#define CHANNEL_BUFFER_SIZE 1000 // 1000 + other channel_t fields = 1024 - epsilon
+#define CHANNEL_BUFFER_SIZE 200 // 1000 + other channel_t fields = 1024 - epsilon
typedef struct {
fs_handle_t *a, *b;
diff --git a/src/kernel/user/ipc.c b/src/kernel/user/ipc.c
index 0287793..3643eb2 100644
--- a/src/kernel/user/ipc.c
+++ b/src/kernel/user/ipc.c
@@ -128,11 +128,23 @@ size_t channel_read(fs_handle_t *h, size_t offset, size_t req_len, char* orig_bu
c->buf_used -= len;
if (c->buf_used == 0) c->buf_use_begin = 0;
- }
- ret += len;
+ resume_on(c);
+
+ mutex_unlock(&c->lock);
+
+ ret += len;
+ } else if (h->mode & FM_BLOCKING) {
+ int st = enter_critical(CL_NOINT);
+
+ mutex_unlock(&c->lock);
- mutex_unlock(&c->lock);
+ wait_on(c);
+
+ exit_critical(st);
+ } else {
+ mutex_unlock(&c->lock);
+ }
} while ((h->mode & FM_BLOCKING) && ret < req_len);
return ret;
@@ -158,22 +170,37 @@ size_t channel_write(fs_handle_t *h, size_t offset, size_t req_len, const char*
if (c->buf_used + len > CHANNEL_BUFFER_SIZE) len = CHANNEL_BUFFER_SIZE - c->buf_used;
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;
+ if (c->buf_use_begin + c->buf_used >= CHANNEL_BUFFER_SIZE) {
+ memcpy(c->buf + c->buf_use_begin + c->buf_used - CHANNEL_BUFFER_SIZE, buf, len);
+ } else {
+ 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);
}
- memcpy(c->buf + c->buf_use_begin + c->buf_used, buf, len0);
- if (len1) memcpy(c->buf, buf + len0, len1);
c->buf_used += len;
- }
- mutex_unlock(&c->lock);
+ resume_on(c); // notify other side
+
+ mutex_unlock(&c->lock);
+
+ ret += len;
+ } else if (h->mode & FM_BLOCKING) {
+ int st = enter_critical(CL_NOINT);
- if (len) resume_on(c); // notify processes that may be waiting for data
- ret += len;
+ mutex_unlock(&c->lock);
+
+ wait_on(c);
+
+ exit_critical(st);
+ } else {
+ mutex_unlock(&c->lock);
+ }
} while ((h->mode & FM_BLOCKING) && ret < req_len);
return ret;