summaryrefslogtreecommitdiffstats
path: root/drivers/sgi/char
diff options
context:
space:
mode:
authorMiguel de Icaza <miguel@nuclecu.unam.mx>1997-11-01 03:26:09 +0000
committerMiguel de Icaza <miguel@nuclecu.unam.mx>1997-11-01 03:26:09 +0000
commita01cb3bdf448bff477c7434fb6e061a916511356 (patch)
treee333c7c9dbf6428051ba9a2fd1017807277ad122 /drivers/sgi/char
parent9471eb08a5d012f044e06f97ca38a3b179081a72 (diff)
Fixed the userland semaphores. No need for the dentry hacks
as I found that struct file has a private_data pointer. WOOO!
Diffstat (limited to 'drivers/sgi/char')
-rw-r--r--drivers/sgi/char/usema.c207
1 files changed, 57 insertions, 150 deletions
diff --git a/drivers/sgi/char/usema.c b/drivers/sgi/char/usema.c
index 602db0a9e..ec8ce3a48 100644
--- a/drivers/sgi/char/usema.c
+++ b/drivers/sgi/char/usema.c
@@ -1,24 +1,19 @@
/*
* usema.c: software semaphore driver (see IRIX's usema(7M))
* written 1997 Mike Shaver (shaver@neon.ingenia.ca)
+ * 1997 Miguel de Icaza (miguel@kernel.org)
*
- * This file contains the implementation of /dev/usema and /dev/usemaclone,
+ * This file contains the implementation of /dev/usemaclone,
* the devices used by IRIX's us* semaphore routines.
*
* /dev/usemaclone is used to create a new semaphore device, and then
- * the semaphore is manipulated via ioctls on /dev/usema. I'm sure
- * it'll make more sense when I get it working. =) The devices are
- * only accessed by the libc routines, apparently,
+ * the semaphore is manipulated via ioctls.
*
* At least for the zero-contention case, lock set and unset as well
* as semaphore P and V are done in userland, which makes things a
* little bit better. I suspect that the ioctls are used to register
* the process as blocking, etc.
*
- * The minor number for the usema descriptor used to poll and block
- * such determines which semaphore you're manipulating, so I think you're
- * limited to (1 << MINORBITS - 1) semaphores active at a given time.
- *
* Much inspiration and structure stolen from Miguel's shmiq work.
*
* For more information:
@@ -34,114 +29,44 @@
#include <linux/major.h>
#include <linux/string.h>
#include <linux/dcache.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
#include <asm/smp_lock.h>
#include <asm/usioctl.h>
#include <asm/mman.h>
#include <asm/uaccess.h>
-#define NUM_USEMAS (1 << MINORBITS - 1)
-#define USEMA_FORMAT "/dev/usema%d"
-
-static struct irix_usema{
- int used;
+struct irix_usema {
struct file *filp;
struct wait_queue *proc_list;
-} usema_list[NUM_USEMAS];
-
-/*
- * Generate and return a descriptor for a new semaphore.
- *
- * We want to find a usema that's not in use, and then allocate it to
- * this descriptor. The minor number in the returned fd's st_rdev is used
- * to identify the usema, and should correspond to the index in usema_list.
- *
- * What I do right now is pretty ugly, and likely dangerous.
- * Maybe we need generic clone-device support in Linux?
- */
-
-static int
-sgi_usemaclone_open(struct inode *inode, struct file *filp)
-{
-#ifdef USEMA_FOR_REAL
- int semanum;
- char semaname[14];
- struct dentry * semadentry;
- printk("[%s:%d] wants a new usema",
- current->comm, current->pid);
- for (semanum = 0;
- semanum < NUM_USEMAS && !usema_list[semanum].used;
- semanum++)
- /* nothing */;
- if (usema_list[semanum].used) {
- printk("usemaclone: no more usemas left for process %d",
- current->pid);
- return -EBUSY;
- }
- /* We find a dentry for the clone device that we're
- * allocating and pull a switcheroo on filp->d_entry.
- */
- sprintf(semaname, USEMA_FORMAT, semanum);
- semadentry = namei(semaname);
- if (!semadentry) {
- /* This Shouldn't Happen(tm) */
- printk("[%s:%d] usemaclone_open: can't find dentry for %s",
- current->comm, current->pid, semaname);
- return -EINVAL; /* ??? */
- }
- dput(filp->f_dentry);
- filp->f_dentry = semadentry;
- usema_list[semanum].used = 1;
- usema_list[semanum].filp = filp;
- printk("[%s:%d] got usema %d",
- current->comm, current->pid, semanum);
-#endif
- return 0;
-}
+};
static int
-sgi_usemaclone_release(struct inode *inode, struct file *filp)
+sgi_usema_attach (usattach_t * attach, struct irix_usema *usema)
{
- int semanum = MINOR(filp->f_dentry->d_inode->i_rdev);
- printk("[%s:%d] released usema %d",
- current->comm, current->pid, semanum);
- /* There shouldn't be anything waiting on proc_list, right? */
- usema_list[semanum].used = 0;
- return 0;
-}
-
-/*
- * Generate another descriptor for an existing semaphore.
- *
- * The minor number is used to identify usemas, so we have to create
- * a new descriptor in the current process with the appropriate minor number.
- *
- * Can I share the same fd between all the processes, a la clone()? I can't
- * see how that'd cause any problems, and it'd mean I don't have to do my
- * own reference counting.
- */
-
-static int
-sgi_usema_attach(usattach_t * attach, int semanum) {
int newfd;
newfd = get_unused_fd();
if (newfd < 0)
return newfd;
- current->files->fd[newfd] = usema_list[semanum].filp;
- usema_list[semanum].filp->f_count++;
+
+ current->files->fd [newfd] = usema->filp;
+ usema->filp->f_count++;
/* Is that it? */
printk("UIOCATTACHSEMA: new usema fd is %d", newfd);
return newfd;
}
static int
-sgi_usema_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
+ struct irix_usema *usema = file->private_data;
int retval;
+
printk("[%s:%d] wants ioctl 0x%xd (arg 0x%xd)",
current->comm, current->pid, cmd, arg);
-#ifdef USEMA_FOR_REAL
+
switch(cmd) {
case UIOCATTACHSEMA: {
/* They pass us information about the semaphore to
@@ -149,8 +74,6 @@ sgi_usema_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
a new fd corresponding to the appropriate semaphore.
*/
usattach_t *attach = (usattach_t *)arg;
- int newfd;
- int semanum;
retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
if (retval) {
printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): "
@@ -158,19 +81,12 @@ sgi_usema_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
current->comm, current->pid);
return retval;
}
- semanum = MINOR(attach->us_dev);
- if (semanum == 0) {
- /* This shouldn't happen (tm).
- A minor of zero indicates that there's no
- semaphore allocated for the given descriptor...
- in which case there's nothing to which to attach.
- */
+ if (usema == 0)
return -EINVAL;
- }
- printk("UIOCATTACHSEMA: attaching usema %d to process %d\n",
- semanum, current->pid);
+
+ printk("UIOCATTACHSEMA: attaching usema %p to process %d\n", usema, current->pid);
/* XXX what is attach->us_handle for? */
- return sgi_usema_attach(attach, semanum);
+ return sgi_usema_attach(attach, usema);
break;
}
case UIOCABLOCK: /* XXX make `async' */
@@ -178,7 +94,7 @@ sgi_usema_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case UIOCBLOCK: {
/* Block this process on the semaphore */
usattach_t *attach = (usattach_t *)arg;
- int semanum;
+
retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
if (retval) {
printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
@@ -186,20 +102,19 @@ sgi_usema_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
current->comm, current->pid);
return retval;
}
- semanum = MINOR(attach->us_dev);
- printk("UIOC*BLOCK: putting process %d to sleep on usema %d",
- current->pid, semanum);
+ printk("UIOC*BLOCK: putting process %d to sleep on usema %p",
+ current->pid, usema);
if (cmd == UIOCNOIBLOCK)
- sleep_on_interruptible(&usema_list[semanum].proc_list);
+ interruptible_sleep_on(usema->proc_list);
else
- sleep_on(&usema_list[semanum].proc_list);
+ sleep_on(usema->proc_list);
return 0;
}
case UIOCAUNBLOCK: /* XXX make `async' */
case UIOCUNBLOCK: {
/* Wake up all process waiting on this semaphore */
usattach_t *attach = (usattach_t *)arg;
- int semanum;
+
retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
if (retval) {
printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
@@ -207,56 +122,54 @@ sgi_usema_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
current->comm, current->pid);
return retval;
}
- semanum = MINOR(attach->us_dev);
- printk("[%s:%d] releasing usema %d",
- current->comm, current->pid, semanum);
- wake_up(&usema_list[semanum].proc_list);
+
+ printk("[%s:%d] releasing usema %p",
+ current->comm, current->pid, usema);
+ wake_up(usema->proc_list);
return 0;
}
}
return -ENOSYS;
-#else
- return 0;
-#endif
}
static unsigned int
-sgi_usema_poll(struct file *filp, poll_table *wait)
+sgi_usemaclone_poll(struct file *filp, poll_table *wait)
{
- int semanum = MINOR(filp->f_dentry->d_inode->i_rdev);
- printk("[%s:%d] wants to poll usema %d",
- current->comm, current->pid, semanum);
- /* I have to figure out what the behaviour is when:
- - polling and the lock is free
- - the lock becomes free and there's a process polling it
- And I have to figure out poll()'s semantics. =)
- */
+ struct irix_usema *usema = filp->private_data;
+
+ printk("[%s:%d] wants to poll usema %p", current->comm, current->pid, usema);
+
return 0;
}
-struct file_operations sgi_usema_fops = {
- NULL, /* llseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- sgi_usema_poll, /* poll */
- sgi_usema_ioctl, /* ioctl */
- NULL, /* mmap */
- NULL, /* open */
- NULL, /* release */
- NULL, /* fsync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
- NULL /* lock */
-};
+static int
+sgi_usemaclone_open(struct inode *inode, struct file *filp)
+{
+ struct irix_usema *usema;
+
+ usema = kmalloc (sizeof (struct irix_usema), GFP_KERNEL);
+ if (!usema)
+ return -ENOMEM;
+
+ usema->filp = filp;
+ usema->proc_list = NULL;
+ filp->private_data = usema;
+ return 0;
+}
+
+static int
+sgi_usemaclone_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
struct file_operations sgi_usemaclone_fops = {
NULL, /* llseek */
NULL, /* read */
NULL, /* write */
NULL, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
+ sgi_usemaclone_poll, /* poll */
+ sgi_usemaclone_ioctl, /* ioctl */
NULL, /* mmap */
sgi_usemaclone_open, /* open */
sgi_usemaclone_release, /* release */
@@ -266,7 +179,6 @@ struct file_operations sgi_usemaclone_fops = {
NULL /* lock */
};
-
static struct miscdevice dev_usemaclone = {
SGI_USEMACLONE, "usemaclone", &sgi_usemaclone_fops
};
@@ -274,11 +186,6 @@ static struct miscdevice dev_usemaclone = {
void
usema_init(void)
{
- printk("usemaclone misc device registered (minor: %d)\n",
- SGI_USEMACLONE);
+ printk("usemaclone misc device registered (minor: %d)\n", SGI_USEMACLONE);
misc_register(&dev_usemaclone);
- register_chrdev(USEMA_MAJOR, "usema", &sgi_usema_fops);
- printk("usema device registered (major %d)\n",
- USEMA_MAJOR);
- memset((void *)usema_list, 0, sizeof(struct irix_usema) * NUM_USEMAS);
}