diff options
author | dzwdz | 2022-07-06 19:46:35 +0200 |
---|---|---|
committer | dzwdz | 2022-07-06 19:46:35 +0200 |
commit | caec20e9886fd6d0437b59a9de48a7b686a2cc09 (patch) | |
tree | 2b2e06d90876168a81fdcda15029cd1a2eaffd0a /src/kernel/pipe.c | |
parent | a89984d7200381d7b8035c48124d93105d59cf24 (diff) |
kernel/pipes: read & write support
Diffstat (limited to 'src/kernel/pipe.c')
-rw-r--r-- | src/kernel/pipe.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/src/kernel/pipe.c b/src/kernel/pipe.c new file mode 100644 index 0000000..8afd359 --- /dev/null +++ b/src/kernel/pipe.c @@ -0,0 +1,43 @@ +#include <kernel/mem/virt.h> +#include <kernel/panic.h> +#include <kernel/pipe.h> +#include <kernel/util.h> + +void pipe_joinqueue(struct handle *h, bool wants_write, + struct process *proc, void __user *pbuf, size_t pbuflen) +{ + struct process **slot = wants_write ? &h->pipe.reader : &h->pipe.writer; + if (*slot) { + assert((*slot)->state == PS_WAITS4PIPE); + panic_unimplemented(); + } + + process_transition(proc, PS_WAITS4PIPE); + *slot = proc; + proc->waits4pipe.pipe = h; + proc->waits4pipe.buf = pbuf; + proc->waits4pipe.len = pbuflen; +} + +void pipe_trytransfer(struct handle *h) { + struct process *rdr = h->pipe.reader, *wtr = h->pipe.writer; + int len; + if (!(rdr && wtr)) return; + assert(rdr->state == PS_WAITS4PIPE); + assert(wtr->state == PS_WAITS4PIPE); + + len = min(rdr->waits4pipe.len, wtr->waits4pipe.len); + + if (!virt_cpy( + rdr->pages, rdr->waits4pipe.buf, + wtr->pages, wtr->waits4pipe.buf, len)) + { + panic_unimplemented(); + } + process_transition(rdr, PS_RUNNING); + process_transition(wtr, PS_RUNNING); + h->pipe.reader = NULL; + h->pipe.writer = NULL; + regs_savereturn(&rdr->regs, len); + regs_savereturn(&wtr->regs, len); +} |