diff options
author | Mike Shaver <shaver@ingenia.com> | 1997-08-10 22:24:11 +0000 |
---|---|---|
committer | Mike Shaver <shaver@ingenia.com> | 1997-08-10 22:24:11 +0000 |
commit | 5c10bcd1cd1bc411076fdc3bb414193f2d78f57d (patch) | |
tree | 8d612b6a2ded7ce44a67cc2634003975aa05602c /drivers/sgi | |
parent | 52365146a9da3ea5defe960af8b6d320d4dd7fcc (diff) |
Added skeletal support for /dev/usema and /dev/usemaclone.
Still need to figure out how to do SVR-style clone devices with
fops->open(), and I need a good poll() tutorial. =)
Other than that, I think I know how to do:
/dev/usemaclone open()ing, poll()ing
/dev/usema ioctls:
- UIOCATTACHSEMA
- UIOCBLOCK
- UIOCUNBLOCK
Also, some minor additions to sysirix.c:syssgi().
Diffstat (limited to 'drivers/sgi')
-rw-r--r-- | drivers/sgi/char/usema.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/drivers/sgi/char/usema.c b/drivers/sgi/char/usema.c new file mode 100644 index 000000000..5c92221a2 --- /dev/null +++ b/drivers/sgi/char/usema.c @@ -0,0 +1,195 @@ +/* + * usema.c: software semaphore driver (see IRIX's usema(7M)) + * written 1997 Mike Shaver (shaver@neon.ingenia.ca) + * + * This file contains the implementation of /dev/usema and /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, + * + * 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: + * usema(7m), usinit(3p), usnewsema(3p) + * /usr/include/sys/usioctl.h + * +*/ + +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <linux/sched.h> +#include <linux/file.h> +#include <linux/major.h> + +#include <asm/smp_lock.h> +#include <asm/usioctl.h> +#include <asm/mman.h> + +#define NUM_USEMAS (1 << MINORBITS - 1) + +static struct irix_usema{ + int used; + struct wait_queue *proc_list; +} usema_list[NUM_USEMAS]; + +/* + * Generate and return a descriptor for a new semaphore. + */ + +static int +sgi_usemaclone_open(struct inode *inode, struct file *filp) +{ + int semanum; + 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; + } + /* XXX is this the right way to do it? */ + inode->i_dev = MKDEV(USEMA_MAJOR, semanum); + usema_list[semanum].used = 1; + return 0; +} + +/* + * Generate another descriptor for an existing semaphore. + */ + +static int +sgi_usema_attach(usattach_t * attach, int semanum) { + int newfd; + /* create a new fd for this process with major/minor + correct, I guess. */ + newfd = -ENOSYS; + return newfd; +} + +static int +sgi_usema_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + int retval; + printk("[%s:%d] wants ioctl 0x%xd (arg 0x%xd)", + current->comm, current->pid, cmd, arg); + switch(cmd) { + case UIOCATTACHSEMA: { + /* They pass us information about the semaphore to + which they wish to be attached, and we create&return + 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(UIOATTACHSEMA): " + "verify_area failure", + 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 created for the given descriptor... + in which case there's nothing to which to attach. + */ + return -EINVAL; + } + printk("UIOATTACHSEMA: attaching usema %d to process %d\n", + semanum, current->pid); + return sgi_usema_attach(attach, semanum); + break; + } + case UIOCBLOCK: { + /* Block this process on the semaphore */ + /* I'll probably just pretend they're polling */ + printk("UIOCBLOCK: (not) putting process %d to sleep", + current->pid); + } + case UIOCUNBLOCK: { + /* Wake up all process waiting on this semaphore */ + } + return -ENOSYS; +} + +static int +sgi_usema_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 the poll() semantics. =) + */ + return -ENOSYS; +} + +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 */ +}; + +struct file_operations sgi_usemaclone_fops = { + NULL, /* llseek */ + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + sgi_usemaclone_open, /* open */ + NULL, /* release */ + NULL, /* fsync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ + NULL /* lock */ +}; + + +static struct miscdevice dev_usemaclone = { + SGI_USEMACLONE, "usemaclone", &sgi_usemaclone_fops +}; + +void +usema_init(void) +{ + 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); +} |