I run into an interesting problem with linuxemu.

The problem *seems* to be that traps can be
enqueued in the process note array *after* some
other note causing notify() to kill us.

Please correct me if i miss(understand) something
here. It just hit my mind after hours of late night
debugging.

The case:

If some other process sends a note with postnote(). The
kernel will enqueue the note in the target process.
(The note is marked as Nuser)

notestate of the target process:

note[0] = {Nuser, "usernote"}
nnote = 1
notified = 0

This note will be "delivered" when notify() is called.
notify is called on:

- after a syscall
- after interrupt/trap handling (timer interrupt?)

Now, in our case, the receiving process causes a trap.
It enters the kernel from the vector table
and /sys/src/9/pc/trap.c:trap() is called.

trap() decodes the error and enqueues a note
with the Ndebug flag.

the target process note state now looks like
this:

note[0] = {Nuser, "usernote"}
note[1] = {Ndebug, "sys: trap: some trap"}
nnote = 2
notified = 0

trap() now calls notify() because nnote != 0.

notify() delivers the "usernote" and sets
notified = 1;

we return to userspace with kexit() and we
pop out in the note handler to process the
"usernote".

the note state looks now like this:

note[0] = {Ndebug, "sys: trap: some trap"}
nnote = 1
notified = 1

now strange things happen. if we enter
the kernel for some reason (syscall, timer
interrupt?)

notify() will kill us:

   /* n is the address of the 0th entry from the note array */

   if(n->flag!=NUser && (up->notified || up->notify==0)){
       if(n->flag == NDebug)
           pprint("suicide: %s\n", n->msg);
       qunlock(&up->debug);
       pexit(n->msg, n->flag!=NDebug);
   }

if we are lucky, we could do a noted() inside
the notehandler and it will set up->notified to
zero before some the timer interrupt arrives.

What i need is that i get the Ndebug-note in the
notehandler *first*. it doesnt make sense to me to
queue traps.

Something similar i found in postnote():

   if(flag != NUser && (p->notify == 0 || p->notified))
       p->nnote = 0;

but obviously this only works if it has already notified
the process. why?

--
cinap


Reply via email to