aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/user/ipc.c
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/user/ipc.c
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/user/ipc.c')
-rw-r--r--src/kernel/user/ipc.c55
1 files changed, 41 insertions, 14 deletions
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;