Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 6 Jan 2002 20:30:03 -0800 (PST)
From:      k Macy <kip_macy@yahoo.com>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/30223: Using /usr/share/examples/kld/cdev, testcdev fails when compiled w/ -pthread
Message-ID:  <200201070430.g074U3f16390@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/30223; it has been noted by GNATS.

From: k Macy <kip_macy@yahoo.com>
To: freebsd-gnats-submit@FreeBSD.org, rob@netrake.com
Cc:  
Subject: Re: kern/30223: Using /usr/share/examples/kld/cdev, testcdev fails when compiled w/ -pthread
Date: Sun, 6 Jan 2002 20:26:23 -0800 (PST)

 This isn't a bug in the threads library, it is a bug
 in the driver :
 
 /*
  * mydev_write takes in a character string and saves
 it
  * to buf for later accessing.
  */
 int
 mydev_write(dev_t dev, struct uio *uio, int ioflag)
 {
     int err = 0;
 
     printf("mydev_write: dev_t=%d, uio=%p,
 ioflag=%d\n",
         dev2udev(dev), uio, ioflag);
 
     err = copyinstr(uio->uio_iov->iov_base, &buf, 512,
 &len);
     if (err != 0) {
         printf("Write to \"cdev\" failed.\n");
     }
     return(err);
 }
 
 if err is 0 it mydev_write should be returning len,
 the 
 number of bytes copied.
 
 It isn't returning because the thread library does a 
 non-blocking write and simulates a blocking write by 
 doing writes piecemeal:
 
                   /*
                    * Loop while no error occurs and
 until the expected number
                    * of bytes are written if
 performing a blocking write:
                    */
                   while (ret == 0) {
                           /* Perform a non-blocking
 write syscall: */
                           n = __sys_write(fd, buf +
 num, nbytes - num);
 
 sys_write is returning 0 so it keeps on writing the
 string over and over again.
 write(5,0x804988c,14)                            = 0
 (0x0)
 poll(0x8059000,0x1,0x0)                          = 1
 (0x1)
 write(5,0x804988c,14)                            = 0
 (0x0)
 poll(0x8059000,0x1,0x0)                          = 1
 (0x1)
 
 The following patch will make the driver work:
 > diff -Naur cdev.c.bak cdev.c
 --- cdev.c.bak  Sun Jan  6 18:54:54 2002
 +++ cdev.c      Sun Jan  6 20:03:51 2002
 @@ -149,16 +149,14 @@
  int
  mydev_write(dev_t dev, struct uio *uio, int ioflag)
  {
 -    int err = 0;
 +    int towrite = 0;
  
      printf("mydev_write: dev_t=%d, uio=%p,
 ioflag=%d\n",
         dev2udev(dev), uio, ioflag);
  
 -    err = copyinstr(uio->uio_iov->iov_base, &buf,
 512, &len);
 -    if (err != 0) {
 -       printf("Write to \"cdev\" failed.\n");
 -    }
 -    return(err);
 +    towrite = (min(uio->uio_resid, sizeof(buf)));
 +    len = towrite;
 +    return(uiomove(buf, towrite, uio));
  }
  
  /*
 
 Although the ioctl is still getting called incorrectly
 twice when compiled with pthread:
 once after open:
 open("/dev/cdev",0x2,00)                         = 5
 (0x5)
 fcntl(0x5,0x3,0x0)                               = 2
 (0x2)
 fcntl(0x5,0x4,0x6)                              
 ERR#22 'Invalid argument'
 
 and once before exit:
 fcntl(0x5,0x4,0x2)                              
 ERR#22 'Invalid argument'
 exit(0x0)                                      
 process exit, rval = 0
 
 What is doing is setting the nonblocking flag on open,
 and unsetting on exit and this trivial driver doesn't
 support having flags set on it:
         /*
          * Enter a loop to set all file descriptors to
 blocking
          * if they were not created as non-blocking:
          */
         for (i = 0; i < _thread_dtablesize; i++) {
                 /* Check if this file descriptor is in
 use: */
                 if (_thread_fd_table[i] != NULL &&
                         !(_thread_fd_table[i]->flags &
 O_NONBLOCK)) {
                         /* Get the current flags: */
                         flags = _thread_sys_fcntl(i,
 F_GETFL, NULL);
                         /* Clear the nonblocking file
 descriptor flag: */
                         _thread_sys_fcntl(i, F_SETFL,
 flags & ~O_NONBLOCK);
                 }
         }
 
         /* Call the _exit syscall: */
         _thread_sys__exit(status);
 
 
 
 
 __________________________________________________
 Do You Yahoo!?
 Send FREE video emails in Yahoo! Mail!
 http://promo.yahoo.com/videomail/

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200201070430.g074U3f16390>