From b9f4ee7e13cc59f6c69f8ff4751a99a5f1e5f390 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Mon, 20 Sep 2010 20:34:44 +0000 Subject: dahdi: Channels can have their own file_operations structure. If we know that an open file is associated with a channel (pseudo or real) we can just update the file->f_ops pointer so that we can short circuit some of the checks in read/write/poll. Trades sizeof(file_operations) bytes for less function call overhead in the "hot" path. On a 2.4 GHz Xeon, saves around 150 ns on each read / write. Review: https://reviewboard.asterisk.org/r/905/ Signed-off-by: Shaun Ruffell git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9386 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- drivers/dahdi/dahdi-base.c | 121 ++++++++++++--------------------------------- 1 file changed, 31 insertions(+), 90 deletions(-) (limited to 'drivers/dahdi/dahdi-base.c') diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index 72a01ae..4fe9303 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -233,7 +233,6 @@ static sumtype *conf_sums; static sumtype *conf_sums_prev; static struct dahdi_span *master; -static struct file_operations dahdi_fops; struct file_operations *dahdi_transcode_fops = NULL; static struct { @@ -2122,7 +2121,7 @@ static void dahdi_chan_unreg(struct dahdi_chan *chan) } static ssize_t dahdi_chan_read(struct file *file, char __user *usrbuf, - size_t count) + size_t count, loff_t *ppos) { struct dahdi_chan *chan = file->private_data; int amnt; @@ -2241,7 +2240,7 @@ static int num_filled_bufs(struct dahdi_chan *chan) } static ssize_t dahdi_chan_write(struct file *file, const char __user *usrbuf, - size_t count) + size_t count, loff_t *ppos) { unsigned long flags; struct dahdi_chan *chan = file->private_data; @@ -2805,6 +2804,8 @@ static int dahdi_timer_release(struct file *file) return 0; } +static const struct file_operations dahdi_chan_fops; + static int dahdi_specchan_open(struct file *file) { int res = 0; @@ -2838,6 +2839,10 @@ static int dahdi_specchan_open(struct file *file) if (!res) { chan->file = file; file->private_data = chan; + /* Since we know we're a channel now, we can + * update the f_op pointer and bypass a few of + * the checks on the minor number. */ + file->f_op = &dahdi_chan_fops; spin_unlock_irqrestore(&chan->lock, flags); } else { spin_unlock_irqrestore(&chan->lock, flags); @@ -3003,69 +3008,6 @@ static int dahdi_open(struct file *file) } #endif -static ssize_t dahdi_read(struct file *file, char __user *usrbuf, size_t count, loff_t *ppos) -{ - int unit = UNIT(file); - struct dahdi_chan *chan; - - /* Can't read from control */ - if (!unit) { - return -EINVAL; - } - - if (unit == 253) - return -EINVAL; - - if (unit == 254) { - chan = file->private_data; - if (!chan) - return -EINVAL; - return dahdi_chan_read(file, usrbuf, count); - } - - if (unit == 255) { - chan = file->private_data; - if (!chan) { - module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n"); - return -EINVAL; - } - return dahdi_chan_read(file, usrbuf, count); - } - if (count < 0) - return -EINVAL; - - return dahdi_chan_read(file, usrbuf, count); -} - -static ssize_t dahdi_write(struct file *file, const char __user *usrbuf, size_t count, loff_t *ppos) -{ - int unit = UNIT(file); - struct dahdi_chan *chan; - /* Can't read from control */ - if (!unit) - return -EINVAL; - if (count < 0) - return -EINVAL; - if (unit == 253) - return -EINVAL; - if (unit == 254) { - chan = file->private_data; - if (!chan) - return -EINVAL; - return dahdi_chan_write(file, usrbuf, count); - } - if (unit == 255) { - chan = file->private_data; - if (!chan) { - module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n"); - return -EINVAL; - } - return dahdi_chan_write(file, usrbuf, count); - } - return dahdi_chan_write(file, usrbuf, count); - -} - static int dahdi_set_default_zone(int defzone) { if ((defzone < 0) || (defzone >= DAHDI_TONE_ZONE_MAX)) @@ -8325,30 +8267,14 @@ dahdi_chan_poll(struct file *file, struct poll_table_struct *wait_table) static unsigned int dahdi_poll(struct file *file, struct poll_table_struct *wait_table) { - int unit = UNIT(file); - - if (!unit) - return -EINVAL; - - if (unit == 250) - return dahdi_transcode_fops->poll(file, wait_table); + const int unit = UNIT(file); - if (unit == 253) + if (likely(unit == 253)) return dahdi_timer_poll(file, wait_table); - if (unit == 254) { - if (!file->private_data) - return -EINVAL; - return dahdi_chan_poll(file, wait_table); - } - if (unit == 255) { - if (!file->private_data) { - module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n"); - return -EINVAL; - } - return dahdi_chan_poll(file, wait_table); - } - return dahdi_chan_poll(file, wait_table); + /* transcoders and channels should have updated their file_operations + * before poll is ever called. */ + return -EINVAL; } static void __dahdi_transmit_chunk(struct dahdi_chan *chan, unsigned char *buf) @@ -8868,7 +8794,7 @@ MODULE_VERSION(DAHDI_VERSION); module_param(debug, int, 0644); module_param(deftaps, int, 0644); -static struct file_operations dahdi_fops = { +static const struct file_operations dahdi_fops = { .owner = THIS_MODULE, .open = dahdi_open, .release = dahdi_release, @@ -8880,11 +8806,26 @@ static struct file_operations dahdi_fops = { #else .ioctl = dahdi_ioctl, #endif - .read = dahdi_read, - .write = dahdi_write, .poll = dahdi_poll, }; +static const struct file_operations dahdi_chan_fops = { + .owner = THIS_MODULE, + .open = dahdi_open, + .release = dahdi_release, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = dahdi_ioctl, +#ifdef HAVE_COMPAT_IOCTL + .compat_ioctl = dahdi_ioctl_compat, +#endif +#else + .ioctl = dahdi_ioctl, +#endif + .read = dahdi_chan_read, + .write = dahdi_chan_write, + .poll = dahdi_chan_poll, +}; + #ifdef CONFIG_DAHDI_WATCHDOG static struct timer_list watchdogtimer; -- cgit v1.2.3