summaryrefslogtreecommitdiff
path: root/src/kernel/syscalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/syscalls.c')
-rw-r--r--src/kernel/syscalls.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index c916e81..421b5ce 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -194,8 +194,10 @@ int _syscall_read(handle_t handle_num, void __user *buf, size_t len, int offset)
});
break;
case HANDLE_PIPE:
- pipe_joinqueue(h, true, process_current, buf, len);
- pipe_trytransfer(h);
+ if (pipe_joinqueue(h, true, process_current, buf, len))
+ pipe_trytransfer(h);
+ else
+ SYSCALL_RETURN(-1);
break;
default:
SYSCALL_RETURN(-1);
@@ -221,8 +223,10 @@ int _syscall_write(handle_t handle_num, const void __user *buf, size_t len, int
});
break;
case HANDLE_PIPE:
- pipe_joinqueue(h, false, process_current, (void __user *)buf, len);
- pipe_trytransfer(h);
+ if (pipe_joinqueue(h, false, process_current, (void __user *)buf, len))
+ pipe_trytransfer(h);
+ else
+ SYSCALL_RETURN(-1);
break;
default:
SYSCALL_RETURN(-1);
@@ -310,15 +314,24 @@ void __user *_syscall_memflag(void __user *addr, size_t len, int flags) {
SYSCALL_RETURN((uintptr_t)addr);
}
-handle_t _syscall_pipe(int flags) {
- if (flags) return -1;
+int _syscall_pipe(handle_t __user user_ends[2], int flags) {
+ if (flags) SYSCALL_RETURN(-1);
+ handle_t ends[2];
+ struct handle *rend, *wend;
- handle_t h = process_find_free_handle(process_current, 0);
- if (h < 0) return -1;
- process_current->handles[h] = handle_init(HANDLE_PIPE);
- assert(process_current->handles[h]->pipe.reader == NULL);
- assert(process_current->handles[h]->pipe.writer == NULL);
- SYSCALL_RETURN(h);
+ ends[0] = process_find_free_handle(process_current, 0);
+ if (ends[0] < 0) SYSCALL_RETURN(-1);
+ ends[1] = process_find_free_handle(process_current, ends[0]+1);
+ if (ends[1] < 0) SYSCALL_RETURN(-1);
+
+ rend = process_current->handles[ends[0]] = handle_init(HANDLE_PIPE);
+ wend = process_current->handles[ends[1]] = handle_init(HANDLE_PIPE);
+ wend->pipe.write_end = true;
+ wend->pipe.sister = rend;
+ rend->pipe.sister = wend;
+
+ virt_cpy_to(process_current->pages, user_ends, ends, sizeof ends);
+ SYSCALL_RETURN(0);
}
void _syscall_debug_klog(const void __user *buf, size_t len) {
@@ -366,7 +379,7 @@ int _syscall(int num, int a, int b, int c, int d) {
_syscall_memflag((userptr_t)a, b, c);
break;
case _SYSCALL_PIPE:
- _syscall_pipe(a);
+ _syscall_pipe((userptr_t)a, b);
break;
case _SYSCALL_DEBUG_KLOG:
_syscall_debug_klog((userptr_t)a, b);