2 * usema.c: software semaphore driver (see IRIX's usema(7M))
3 * written 1997 Mike Shaver (shaver@neon.ingenia.ca)
4 * 1997 Miguel de Icaza (miguel@kernel.org)
6 * This file contains the implementation of /dev/usemaclone,
7 * the devices used by IRIX's us* semaphore routines.
9 * /dev/usemaclone is used to create a new semaphore device, and then
10 * the semaphore is manipulated via ioctls.
12 * At least for the zero-contention case, lock set and unset as well
13 * as semaphore P and V are done in userland, which makes things a
14 * little bit better. I suspect that the ioctls are used to register
15 * the process as blocking, etc.
17 * Much inspiration and structure stolen from Miguel's shmiq work.
19 * For more information:
20 * usema(7m), usinit(3p), usnewsema(3p)
21 * /usr/include/sys/usioctl.h
26 #include <linux/miscdevice.h>
27 #include <linux/sched.h>
28 #include <linux/file.h>
29 #include <linux/major.h>
30 #include <linux/string.h>
31 #include <linux/dcache.h>
33 #include <linux/slab.h>
34 #include <linux/smp_lock.h>
36 #include <asm/usioctl.h>
38 #include <asm/uaccess.h>
42 struct wait_queue
*proc_list
;
46 sgi_usema_attach (usattach_t
* attach
, struct irix_usema
*usema
)
49 newfd
= get_unused_fd();
53 current
->files
->fd
[newfd
] = usema
->filp
;
54 usema
->filp
->f_count
++;
56 printk("UIOCATTACHSEMA: new usema fd is %d", newfd
);
61 sgi_usemaclone_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
,
64 struct irix_usema
*usema
= file
->private_data
;
67 printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)",
68 current
->comm
, current
->pid
, cmd
, arg
);
71 case UIOCATTACHSEMA
: {
72 /* They pass us information about the semaphore to
73 which they wish to be attached, and we create&return
74 a new fd corresponding to the appropriate semaphore.
76 usattach_t
*attach
= (usattach_t
*)arg
;
77 retval
= verify_area(VERIFY_READ
, attach
, sizeof(usattach_t
));
79 printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): "
80 "verify_area failure",
81 current
->comm
, current
->pid
);
87 printk("UIOCATTACHSEMA: attaching usema %p to process %d\n", usema
, current
->pid
);
88 /* XXX what is attach->us_handle for? */
89 return sgi_usema_attach(attach
, usema
);
92 case UIOCABLOCK
: /* XXX make `async' */
93 case UIOCNOIBLOCK
: /* XXX maybe? */
95 /* Block this process on the semaphore */
96 usattach_t
*attach
= (usattach_t
*)arg
;
98 retval
= verify_area(VERIFY_READ
, attach
, sizeof(usattach_t
));
100 printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
101 "verify_area failure",
102 current
->comm
, current
->pid
);
105 printk("UIOC*BLOCK: putting process %d to sleep on usema %p",
106 current
->pid
, usema
);
107 if (cmd
== UIOCNOIBLOCK
)
108 interruptible_sleep_on(&usema
->proc_list
);
110 sleep_on(&usema
->proc_list
);
113 case UIOCAUNBLOCK
: /* XXX make `async' */
115 /* Wake up all process waiting on this semaphore */
116 usattach_t
*attach
= (usattach_t
*)arg
;
118 retval
= verify_area(VERIFY_READ
, attach
, sizeof(usattach_t
));
120 printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
121 "verify_area failure",
122 current
->comm
, current
->pid
);
126 printk("[%s:%d] releasing usema %p",
127 current
->comm
, current
->pid
, usema
);
128 wake_up(&usema
->proc_list
);
136 sgi_usemaclone_poll(struct file
*filp
, poll_table
*wait
)
138 struct irix_usema
*usema
= filp
->private_data
;
140 printk("[%s:%d] wants to poll usema %p", current
->comm
, current
->pid
, usema
);
146 sgi_usemaclone_open(struct inode
*inode
, struct file
*filp
)
148 struct irix_usema
*usema
;
150 usema
= kmalloc (sizeof (struct irix_usema
), GFP_KERNEL
);
155 usema
->proc_list
= NULL
;
156 filp
->private_data
= usema
;
161 sgi_usemaclone_release(struct inode
*inode
, struct file
*filp
)
166 struct file_operations sgi_usemaclone_fops
= {
171 sgi_usemaclone_poll
, /* poll */
172 sgi_usemaclone_ioctl
, /* ioctl */
174 sgi_usemaclone_open
, /* open */
176 sgi_usemaclone_release
, /* release */
178 NULL
, /* check_media_change */
179 NULL
, /* revalidate */
183 static struct miscdevice dev_usemaclone
= {
184 SGI_USEMACLONE
, "usemaclone", &sgi_usemaclone_fops
190 printk("usemaclone misc device registered (minor: %d)\n", SGI_USEMACLONE
);
191 misc_register(&dev_usemaclone
);