| Summary: | [patch] Using /usr/share/examples/kld/cdev, testcdev fails when compiled w/ -pthread | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Rob Phillips <rob> |
| Component: | conf | Assignee: | freebsd-bugs (Nobody) <bugs> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 4.3-STABLE | ||
| Hardware: | Any | ||
| OS: | Any | ||
|
Description
Rob Phillips
2001-08-30 20:30:01 UTC
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/
State Changed From-To: open->closed It was mentioned that this was a bug in the kld code itself (from the submitter), no feedback after that so I am assuming this was correct. Please prove me my mistake if needed... |