public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
From: Gary Thomas <gthomas@cygnus.co.uk>
To: Mohammed Illyas Mansoor <mansoor@cdotb.ernet.in>
Cc: jskov@cynus.co.uk.cdotb.ernet.in, ecos-discuss@sourceware.cygnus.com
Subject: RE: [ECOS] probable bug in io/serial/common/serial.c!
Date: Wed, 05 Jan 2000 05:36:00 -0000	[thread overview]
Message-ID: <XFMail.000105063515.gthomas@cygnus.co.uk> (raw)
In-Reply-To: <3872E206.67E7B0E5@cdotb.ernet.in>

I don't think there is a chance for deadlock here since the affected
region [while (size > 0)] is protected by a "DSR lock".  The call to
'cyg_drv_dsr_lock()' effectively says "don't allow DSRs to run while
executing the following code".  Since it is only the DSR that can
signal the condition variable, this should be safe.

On 05-Jan-00 Mohammed Illyas Mansoor wrote:
> Hi,
>     I was going through the common serial io code it seems to me
> that there probably is a bug in it, below is a snap shot of the code
> in question.
> 
> <snap>
> static Cyg_ErrNo
> serial_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len)
> {
>     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
>     serial_channel *chan = (serial_channel *)t->priv;
>     serial_funs *funs = chan->funs;
>     cyg_int32 size = *len;
>     cyg_uint8 *buf = (cyg_uint8 *)_buf;
>     int next;
>     cbuf_t *cbuf = &chan->out_cbuf;
>     Cyg_ErrNo res = ENOERR;
> 
>     cbuf->abort = false;
>     cyg_drv_mutex_lock(&cbuf->lock);
>     if (cbuf->len == 0) {
>         // Non interrupt driven (i.e. polled) operation
>         while (size-- > 0) {
>             while ((funs->putc)(chan, *buf) == false) ;  // Ignore full,
> keep trying
>             buf++;
>         }
>     } else {
>         cyg_drv_dsr_lock();  // Avoid race condition testing pointers
>         while (size > 0) {
>             next = cbuf->put + 1;
>             if (next == cbuf->len) next = 0;
>             if (next == cbuf->get) {
>                 cbuf->waiting = true;
>                 // Buffer full - wait for space
>                 (funs->start_xmit)(chan);  // Make sure xmit is running
>                 cbuf->pending += size;  // Have this much more to send
> eventually]
> ***---->cyg_drv_cond_wait(&cbuf->wait);<-----***
>                 cbuf->pending -= size;
>                 if (cbuf->abort) {
>                     // Give up!
>                     cbuf->abort = false;
>                     cbuf->waiting = false;
>                     res = -EINTR;
>                     break;
>                 }
>             } else {
>                 cbuf->data[cbuf->put++] = *buf++;
>                 cbuf->put = next;
>                 size--;  // Only count if actually sent!
>             }
>         }
>         cyg_drv_dsr_unlock();
>         (funs->start_xmit)(chan);  // Start output as necessary
>     }
>     cyg_drv_mutex_unlock(&cbuf->lock);
>     return res;
> }
> </snap>
> 
>     In the line with ***--->cyg_drv_cond_wait(&cond_wait);<----***,
> will cause a deadlock, because before going for a wait on the condition
> variable
> start_xmt function is called which will trigger the transmitter to send
> the char's, if the call to xmt_char finds out that chan->waiting is true
> 
> and wakes up the writer thread which was supposed to be waiting by now,
> he would also change the chan->waiting to false. Later, when the wait by
> 
> the writer is called there will be no waking up of the writer by the
> driver
> (as it has been already done by the xmt_char() ), causing it to
> deadlock.
> 
> The fix might be as below,
> 
>             if (next == cbuf->get) {
>                 cbuf->waiting = true;
>                 // Buffer full - wait for space
>                 (funs->start_xmit)(chan);  // Make sure xmit is running
>                 cbuf->pending += size;  // Have this much more to send
> [eventually]
>             ++if ( cbuf->waiting == true)
>                 cyg_drv_cond_wait(&cbuf->wait);
> 
> 
> --With Regards,
> 
> M. I. Mansoor.
> 

  reply	other threads:[~2000-01-05  5:36 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-01-04 22:17 Mohammed Illyas Mansoor
2000-01-05  5:36 ` Gary Thomas [this message]
2000-01-05  6:34   ` Mohammed Illyas Mansoor
2000-01-05  6:50     ` Gary Thomas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=XFMail.000105063515.gthomas@cygnus.co.uk \
    --to=gthomas@cygnus.co.uk \
    --cc=ecos-discuss@sourceware.cygnus.com \
    --cc=jskov@cynus.co.uk.cdotb.ernet.in \
    --cc=mansoor@cdotb.ernet.in \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).