From owner-freebsd-bugs Sun Jan 6 20:30:14 2002 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 16D5737B417 for ; Sun, 6 Jan 2002 20:30:03 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id g074U3f16390; Sun, 6 Jan 2002 20:30:03 -0800 (PST) (envelope-from gnats) Date: Sun, 6 Jan 2002 20:30:03 -0800 (PST) Message-Id: <200201070430.g074U3f16390@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: k Macy Subject: Re: kern/30223: Using /usr/share/examples/kld/cdev, testcdev fails when compiled w/ -pthread Reply-To: k Macy Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org The following reply was made to PR kern/30223; it has been noted by GNATS. From: k Macy 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