[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: deferred cancellation of ipc

From: Marcus Brinkmann
Subject: Re: deferred cancellation of ipc
Date: Tue, 14 Oct 2003 16:25:04 +0200
User-agent: Mutt/1.5.4i

On Tue, Oct 14, 2003 at 02:24:27PM +0200, Niels M?ller wrote:
> I think it may be possible to distinguish between these two cases, but
> to do it one gets one's hands dirty in the architecture-specific
> details of the L4-spec. Assume the l4_ipc system call puts its return
> value into machine register X when returning, and that after a
> cancelled ipc, X will contain a value L4_CANCEL iff the L4 ipc operation
> was cancelled.

Maybe you want to consider the following solution, which might be
acceptable.  Plus it is simple.  Well, it started out to be simple, and the
final version below is already a bit complex, but there is no dirty magic in

The ipc thread does something like this:

thread_var_in_ipc = 1;
if (thread_var_ipc_cancel)
    thread_var_in_ipc = 0;
    thread_var_ipc_cancel = 0;
    return ECANCEL;  /* Or fake canceled Ipc() by setting ErrorCode
                        and msg_tag.  */
l4_ipc ();
thread_var_in_ipc = 0;

The cancelling thread does something like this:

other_thread_status = stop_other_thread ();
if (!other_thread_var_in_ipc)
  other_thread_var_ipc_cancel = 1;
    if (is_currently_doing_ipc (other_thread_status))
      ipc_cancel_other_thread ();
        unsigned int tries = 0;
        /* The other thread declared it is going to do an Ipc(), but is
           not in it right now.  Give it a chance to make progress.  */
        other_thread_var_ipc_cancel = 1;

            start_other_thread ();
            if (tries <= 2)
                l4_yield (other_thread);
                /* We are not making any progress.  This might be because we
                   are running on a different processor, and on this
                   processor we are the only highest priority thread
                   that is runnable, so we are spinning.  */
                /* 2^14 * 625 is the L4 default time slice length (10ms).  */
                l4_sleep (l4_time_period ((1 << 14) * 625) / 2);
            other_thread_status = stop_other_thread ();
        while (other_thread_var_ipc_cancel && other_thread_var_in_ipc &&
               !is_currently_doing_ipc (other_thread_status);
        if (other_thread_var_ipc_cancel && other_thread_var_in_ipc)
            /* This means it is now in the IPC system call.  */
            ipc_cancel_other_thread ();
            other_thread_var_ipc_cancel = 0;
        start_other_thread ();

The basic idea is to force the other thread into the blocking IPC.  The
thread variable in_ipc is set to 1 if you are within a cancellable IPC.
The thread variable ipc_cancel is the flag that is used to indicate that
cancellation is requested.  Note that whoever puts the cancellation into
effect clears this flag: If we reap it in the cancelled thread, the canceled
flag clears it.  If the cancelling thread canceles the ipc, it clears the
flag instead.  I think this avoids spurious cancellation.

After setting in_ipc to 0, before clearing the cancel flag, the cancelled
thread could try to do the ipc (if it has only one phase, ie only send or
receive) with zero timeouts (and xfer timeouts) to check if it works without
blocking.  That way, it would try harder to avoid cancellation at this
point.  Is this an improvement?  Maybe, maybe not.  I am not sure.

Another thing: If two threads try to cancel another thread at the same time,
I don't think it will work out too well.  Mutual exclusion is required, for
the stop/start of the thread alone, if not for any other reasons.


`Rhubarb is no Egyptian god.' GNU      http://www.gnu.org    address@hidden
Marcus Brinkmann              The Hurd http://www.gnu.org/software/hurd/

reply via email to

[Prev in Thread] Current Thread [Next in Thread]