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>
