Rodrigo Rosenfeld Rosas wrote: > Hi Alessio, Jan has already provided such example on the list. > > For your easy, I'm re-sending it to you. > Yep, just ignore the patch. Hannes has prepared some demo driver which I promised to review - I still haven't done this :-(. But we already identified one pitfall in my demo: before freeing the shared memory block again, you should call ClearPageReserved analogously to SetPageReserved. ... >> ------------------------------------------------------------------------ >> >> #include >> >> #include >> >> >> #define BUFFER_SIZE 100000 >> >> >> struct demodrv_context { >> void *buf; >> }; >> >> >> static void demo_vm_close(struct vm_area_struct *vma) >> { >> printk("releasing %p, data = %p\n", vma, vma->vm_private_data); >> } >> This hook is useful to detect when the user voluntarily released the last reference to the mapped block. Alternative, you can rip it away via rtdm_munmap (e.g. on device close). Just avoid freeing the memory from kernel space as long as it's mapped and the user has a reference. >> >> static struct vm_operations_struct mmap_ops = { >> .close = demo_vm_close, >> }; >> >> >> int demo_open_rt(struct rtdm_dev_context *context, >> rtdm_user_info_t *user_info, >> int oflags) >> { >> struct demodrv_context *my_context; >> unsigned long vaddr; >> >> >> my_context = (struct demodrv_context *)context->dev_private; >> >> my_context->buf = kmalloc(BUFFER_SIZE, 0); >> /* mark pages reserved so that remap_pfn_range works */ >> for (vaddr = (unsigned long)my_context->buf; >> vaddr < (unsigned long)my_context->buf + BUFFER_SIZE; >> vaddr += PAGE_SIZE) >> SetPageReserved(virt_to_page(vaddr)); >> *(int *)my_context->buf = 1234; >> >> return 0; >> } >> >> >> int demo_close_rt(struct rtdm_dev_context *context, >> rtdm_user_info_t *user_info) >> { >> struct demodrv_context *my_context; >> >> >> my_context = (struct demodrv_context *)context->dev_private; >> >> printk("%d\n", *((int *)my_context->buf + 1000)); >> Here is that ClearPageReserved missing... >> kfree(my_context->buf); >> >> return 0; >> } >> >> >> int demo_ioctl_rt(struct rtdm_dev_context *context, >> rtdm_user_info_t *user_info, >> int request, >> void *arg) >> { >> struct demodrv_context *my_context; >> int err; >> >> >> my_context = (struct demodrv_context *)context->dev_private; >> >> printk("buf = %p:%x\n", my_context->buf, *(int *)my_context->buf); >> >> err = rtdm_mmap_to_user(user_info, my_context->buf, BUFFER_SIZE, >> PROT_READ|PROT_WRITE, (void **)arg, &mmap_ops, >> 0x12345678); >> printk("rtdm_mmap = %p %d\n", *(void **)arg, err); >> >> return 0; >> } >> >> >> static struct rtdm_device demo_device = { >> struct_version: RTDM_DEVICE_STRUCT_VER, >> >> device_flags: RTDM_NAMED_DEVICE, >> context_size: sizeof(struct demodrv_context), >> device_name: "demodev0", >> >> open_rt: NULL, >> open_nrt: demo_open_rt, >> >> ops: { >> close_rt: NULL, >> close_nrt: demo_close_rt, >> >> ioctl_rt: NULL, >> ioctl_nrt: demo_ioctl_rt, >> >> read_rt: NULL, >> read_nrt: NULL, >> >> write_rt: NULL, >> write_nrt: NULL, >> >> recvmsg_rt: NULL, >> recvmsg_nrt: NULL, >> >> sendmsg_rt: NULL, >> sendmsg_nrt: NULL, >> }, >> >> device_class: RTDM_CLASS_EXPERIMENTAL, >> device_sub_class: 222, >> driver_name: "demodrv", >> peripheral_name: "demodev", >> provider_name: "-", >> proc_name: demo_device.device_name, >> }; >> >> int init_module(void) >> { >> int ret; >> >> >> ret = rtdm_dev_register(&demo_device); >> printk("rtdm_dev_register = %d\n", ret); >> >> return ret; >> } >> >> >> void cleanup_module(void) >> { >> rtdm_dev_unregister(&demo_device, 1000); >> } >> >> ------------------------------------------------------------------------ >> >> _______________________________________________ >> Xenomai-help mailing list >> Xenomai-help@domain.hid >> https://mail.gna.org/listinfo/xenomai-help Jan