I noticed that after a call to interruptible_sleep_on() in an ioctl I can't pass back data to the user mode.
I am verifying that the data can be written (using verify_area()) and I also verified that I am writing to the same physical address that I am using in the user mode, still I don't get the value I sent.
A few checks that I did:
1) current->pid stays the after interruptible_sleep_on().
2) the problem also sometimes happens after down_interruptible() used to wait on a semaphore. This leads me to assume that this can happen after the scheduler is invoked.
3) I translated the user-mode virtual address to physical address (using uvirt_to_phys() from bttv.c driver in the kernel). The physical address did not change.
4) using the physical address from #3, I read directly from the physical address to make sure the data was actually written to the physical memory. It was.
It seems like after interruptible_sleep_on() there are two physical copies of the page, and when it returns to user mode, it copies back the page from before interruptible_sleep_on().
ANY IDEAS???
Lee Nichols
leenicholes at my-deja dot com
The following code shows my problem:
extern wait_queue ** interrupt_event; /* this event is signaled from the interrupt handler */
int mydrv_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
int data;
if (cmd==IOCTL_TEST)
{
/* check received the correct data from user-mode */
verify_area(VERIFY_READ, arg, sizeof(data));
copy_from_user(&data, arg, sizeof (data));
printk ("data from user mode %d\n", data); /* prints 1 */
/* write data 2 to user-mode */
verify_area(VERIFY_WRITE, arg, sizeof(data));
data = 2;
copy_to_user(arg, &data, sizeof (data));
/* this causes the problem. removing this - everything is fine */
interruptible_sleep_on(interrupt_event);
/* check that data 2 is still where we expect it to be */
verify_area(VERIFY_READ, arg, sizeof(data));
data = 0;
copy_from_user(&data, arg, sizeof(data));
printk("data after interruptible_sleep_on %d\n",data); /* prints 2 */
/* write data 3 to user-mode */
verify_area(VERIFY_WRITE, arg, sizeof(data));
data = 3;
copy_to_user(arg, &data, sizeof (data));
/* check that data 3 is still where we expect it to be */
verify_area(VERIFY_READ, arg, sizeof(data));
data = 0;
copy_from_user(&data, arg, sizeof(data));
printk("data after interruptible_sleep_on %d\n",data); /* prints 3 */
return 0;
}
return -1;
}
from user mode:
int main(int argc, char *argv[])
{
int fd;
int data;
fd = open("/dev/mydrvr", O_RDWR);
data = 1;
ioctl(fd, IOCTL_TEST, &data);
printf ("data from kernel mode %d\n", data); /* ERROR!!! prints 2, not 3 */
close(fd);
}
--== Sent via Deja.com http://www.deja.com/ ==--
Share what you know. Learn what you don't.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/