Hi -
On 2015-10-28 at 13:41 Kevin Klues <
klu...@gmail.com> wrote:
> I've updated the branch to integrate the fixes mentioned above.
>
> The following changes since commit
> 59d25eaabfc8838e52452dd21fe6f50d4e89dc89:
>
> Adjust
checkpatch.pl for Akaros's style (2015-10-15 12:18:37 -0400)
>
> are available in the git repository at:
>
> g...@github.com:klueska/akaros.git sigpipe-support
>
> for you to fetch changes up to
> 9aaf3a6347dfa824e3334e942c252fe2c8a7a175:
>
> Add support for EPIPE and SIGPIPE (2015-10-28 13:33:06 -0700)
Comments below.
> From 8fea4fabb85d5193bd6ae351d1ee2ea6df5256df Mon Sep 17 00:00:00 2001
> From: Kevin Klues <
klu...@cs.berkeley.edu>
> Date: Tue, 27 Oct 2015 10:19:54 -0700
> Subject: Add support for sigprocmask in SCPs with no 2LS
>
> Previously, we were only able to support signal masks in pthread
> programs. Now we can mask them in SCPs without a 2LS as well.
>
In:
> +static int __sigprocmask(int how, __const sigset_t *__restrict set,
> + sigset_t *__restrict oset)
> {
> + }
> + /* Ensures signals we just unmasked get processed if they are pending */
> + sched_yield();
Does this actually work? In the pthread side, the signals are in the pending
set. On the default 2LS side, I think if they aren't fireably immediately, they
get ignored.
The main thing that caught my eye here was sched_yield(), which although legal,
is a bit dangerous, since it's a full yield to the kernel instead of from a
uthread to a 2LS. I might get rid of it or fix it eventually, due to occasional
bugs from porting other code.
> From 9050d4322914cf99eebe765e526d824c2f83e8c3 Mon Sep 17 00:00:00 2001
> From: Kevin Klues <
klu...@cs.berkeley.edu>
> Date: Tue, 27 Oct 2015 10:22:11 -0700
> Subject: Allow sys_self_notify() to accept (vcoreid == -1)
>
> When vcoreid == -1, treat this as a request to be notified on the
> current physical core. This supercedes the need to set the DONT_MIGRATE
^virtual
> flag for cases when we know we want to notify ourselves on the current
> core. The motivation for this is user-space support of SGIPIPE, as will
> appear in a subsequent commit. It should prove generally useful though
> anytime we want to force ourselves into vcore context to handle an event
> on the current core without setting the DONT_MIGRATE flag (when would we
> unset this if we never return, for example).
If this is so that a notification can be tied to the uthread on a VC,
then it won't work.
Here's the potential race:
- uthread decides to notify its vcore (via sigpipe), say VC 6 on PC 5.
- uthread traps into the kernel, asks for -1 here. kernel determines
it's VC 6
- __preempt occurs. for now, this is a message sitting in PC 5's RKM list.
- the event from sys_self_notify() gets put into VC 6's mbox. the
__notify occurs. for now, this is a message sitting in PC 5's RKM
list.
- the syscall completes and goes to return to the user, handling the
RKMs in order.
- the __preempt saves the uthread's ctx into VCPD for VC 6 (this ctx is
the one that trapped in), and clears owning_proc/owning vcoreid.
- the __notify has no effect, since the owning_proc is now wrong.
- the preemption handler will notice that VC 6 was not in VC context and
could yank the uthread from VCPD and start it on another vcore. A
DONT_MIGRATE would prevent this.
Ultimately, without DONT_MIGRATE, a uthread is not bound to a particular
vcore.
> static int sys_self_notify(struct proc *p, uint32_t vcoreid,
> unsigned int ev_type, struct event_msg *u_msg,
> bool priv)
> {
> struct event_msg local_msg = {0};
> +
> + /* If vcoreid = -1, notify on the current vcore. */
> + if (vcoreid == -1) {
> + vcoreid = p->procinfo->pcoremap[core_id()].vcoreid;
> + }
Use pcpui->owning_vcoreid here. The pcoremap could be changed by a
concurrent preemption (I think).
Also, checkpatch didn't complain about this for some reason, but we
don't need/want the extra {} for one liners.
> From 9aaf3a6347dfa824e3334e942c252fe2c8a7a175 Mon Sep 17 00:00:00 2001
> From: Kevin Klues <
klu...@cs.berkeley.edu>
> Date: Tue, 27 Oct 2015 11:05:23 -0700
> Subject: Add support for EPIPE and SIGPIPE
Don't forget the (XCC) and something like "rebuild glibc".
> With this change, we now support proper handling of SIGPIPE. This
> allows us to now run things such as:
> static long pipewrite(struct chan *c, void *va, long n, int64_t ignored)
> {
> ERRSTACK(2);
> Pipe *p;
> - //Prog *r;
>
> if (waserror()) {
> - /* avoid exceptions when pipe is a mounted queue */
> - if ((c->flag & CMSG) == 0) {
> -/*
> - r = up->iprog;
> - if(r != NULL && r->kill == NULL)
> - r->kill = "write on closed pipe";
> -*/
> - }
Even though that's commented out, we might want to keep it around. It could
also be related to the bug you mentioned in your commit message.
> - nexterror();
> + poperror();
> + error(EPIPE, NULL);
This style is a little weird. A lot of times in Plan 9, they just set_errstr
and call error. Either is okay. The problem here is that errstr is now gone.
If you want to keep errstr, you could set_errno to EPIPE, then call nexterror.
> diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/write.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/write.c
> +ssize_t __libc_write(int fd, const void *buf, size_t nbytes)
> {
> - return ros_syscall(SYS_write, fd, buf, nbytes, 0, 0, 0);
> + int ret = ros_syscall(SYS_write, fd, buf, nbytes, 0, 0, 0);
> +
> + if (unlikely((ret != 0) && (errno == EPIPE))) {
This probably won't compile on recent versions of Akaros, since unlikely() isn't
in the kernel headers anymore.
> + sigset_t mask;
My general take on declaring variables halfway through a function instead of at
the top is that you'd be better off with a helper function. But I didn't write
that in the Contributing guide and neither did Linus.
> +
> + sigprocmask(0, NULL, &mask);
> + if (!__sigismember(&mask, SIGPIPE)) {
> + struct event_msg msg = {0};
> +
> + local_msg.ev_type = EV_POSIX_SIGNAL;
> + local_msg.ev_arg1 = SIGPIPE;
> + ros_syscall(SYS_self_notify, -1, EV_POSIX_SIGNAL, &msg, 0, 0, 0);
I'll think about this over the weekend a bit. Maybe there's another nice way to
get this to work. Hopefully this won't pop up for anything else.
The whole "generate a signal for a syscall" seems nasty, since syscalls are
synchronous vs async, instead of people just checking their return codes and
exiting. I'm sure there was a reason for it.
Barret