diff options
author | Miguel de Icaza <miguel@nuclecu.unam.mx> | 1997-11-01 03:26:09 +0000 |
---|---|---|
committer | Miguel de Icaza <miguel@nuclecu.unam.mx> | 1997-11-01 03:26:09 +0000 |
commit | a01cb3bdf448bff477c7434fb6e061a916511356 (patch) | |
tree | e333c7c9dbf6428051ba9a2fd1017807277ad122 /drivers/sgi | |
parent | 9471eb08a5d012f044e06f97ca38a3b179081a72 (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')
-rw-r--r-- | drivers/sgi/char/usema.c | 207 |
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); } |