Import 2.1.118
[davej-history.git] / drivers / sgi / char / usema.c
blob5bf0e4ee7e6a9b8293d8323e6f44773229c4ead6
1 /*
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
25 #include <linux/fs.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>
32 #include <linux/mm.h>
33 #include <linux/slab.h>
34 #include <linux/smp_lock.h>
36 #include <asm/usioctl.h>
37 #include <asm/mman.h>
38 #include <asm/uaccess.h>
40 struct irix_usema {
41 struct file *filp;
42 struct wait_queue *proc_list;
45 static int
46 sgi_usema_attach (usattach_t * attach, struct irix_usema *usema)
48 int newfd;
49 newfd = get_unused_fd();
50 if (newfd < 0)
51 return newfd;
53 current->files->fd [newfd] = usema->filp;
54 usema->filp->f_count++;
55 /* Is that it? */
56 printk("UIOCATTACHSEMA: new usema fd is %d", newfd);
57 return newfd;
60 static int
61 sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
62 unsigned long arg)
64 struct irix_usema *usema = file->private_data;
65 int retval;
67 printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)",
68 current->comm, current->pid, cmd, arg);
70 switch(cmd) {
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));
78 if (retval) {
79 printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): "
80 "verify_area failure",
81 current->comm, current->pid);
82 return retval;
84 if (usema == 0)
85 return -EINVAL;
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);
90 break;
92 case UIOCABLOCK: /* XXX make `async' */
93 case UIOCNOIBLOCK: /* XXX maybe? */
94 case UIOCBLOCK: {
95 /* Block this process on the semaphore */
96 usattach_t *attach = (usattach_t *)arg;
98 retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
99 if (retval) {
100 printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
101 "verify_area failure",
102 current->comm, current->pid);
103 return retval;
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);
109 else
110 sleep_on(&usema->proc_list);
111 return 0;
113 case UIOCAUNBLOCK: /* XXX make `async' */
114 case UIOCUNBLOCK: {
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));
119 if (retval) {
120 printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
121 "verify_area failure",
122 current->comm, current->pid);
123 return retval;
126 printk("[%s:%d] releasing usema %p",
127 current->comm, current->pid, usema);
128 wake_up(&usema->proc_list);
129 return 0;
132 return -ENOSYS;
135 static unsigned int
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);
142 return 0;
145 static int
146 sgi_usemaclone_open(struct inode *inode, struct file *filp)
148 struct irix_usema *usema;
150 usema = kmalloc (sizeof (struct irix_usema), GFP_KERNEL);
151 if (!usema)
152 return -ENOMEM;
154 usema->filp = filp;
155 usema->proc_list = NULL;
156 filp->private_data = usema;
157 return 0;
160 static int
161 sgi_usemaclone_release(struct inode *inode, struct file *filp)
163 return 0;
166 struct file_operations sgi_usemaclone_fops = {
167 NULL, /* llseek */
168 NULL, /* read */
169 NULL, /* write */
170 NULL, /* readdir */
171 sgi_usemaclone_poll, /* poll */
172 sgi_usemaclone_ioctl, /* ioctl */
173 NULL, /* mmap */
174 sgi_usemaclone_open, /* open */
175 NULL, /* flush */
176 sgi_usemaclone_release, /* release */
177 NULL, /* fsync */
178 NULL, /* check_media_change */
179 NULL, /* revalidate */
180 NULL /* lock */
183 static struct miscdevice dev_usemaclone = {
184 SGI_USEMACLONE, "usemaclone", &sgi_usemaclone_fops
187 void
188 usema_init(void)
190 printk("usemaclone misc device registered (minor: %d)\n", SGI_USEMACLONE);
191 misc_register(&dev_usemaclone);