* [RFC PATCH 2.6.17-mm1 1/3] ieee1394: reduce size of hpsb_host by 252 bytes [not found] ` <tkrat.df6845846c72176e@s5r6.in-berlin.de> @ 2006-06-24 9:32 ` Stefan Richter 2006-06-24 9:33 ` [RFC PATCH 2.6.17-mm1 2/3] ieee1394: coarser locking for tlabel allocation Stefan Richter 0 siblings, 1 reply; 11+ messages in thread From: Stefan Richter @ 2006-06-24 9:32 UTC (permalink / raw) To: linux1394-devel; +Cc: linux-kernel Struct hpsb_host contains struct hpsb_tlabel_pool 63 times, therefore each word that can be shaved off of hpsb_tlabel_pool is a win. Since hpsb_tlabel_pool.next is accessed twice as often as .allocations, .next is put into the lower part of the word. The value of .allocations rolls over after about 67 million now but we don't care. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> --- drivers/ieee1394/ieee1394_transactions.c | 22 ++++++++++++---------- drivers/ieee1394/ieee1394_types.h | 9 +++++++-- 2 files changed, 19 insertions(+), 12 deletions(-) Index: linux/drivers/ieee1394/ieee1394_types.h =================================================================== --- linux.orig/drivers/ieee1394/ieee1394_types.h 2006-04-24 22:20:24.000000000 +0200 +++ linux/drivers/ieee1394/ieee1394_types.h 2006-06-24 09:52:37.000000000 +0200 @@ -17,8 +17,13 @@ struct hpsb_tlabel_pool { DECLARE_BITMAP(pool, 64); spinlock_t lock; - u8 next; - u32 allocations; +#ifdef __BIG_ENDIAN_BITFIELD + u32 allocations :26 __attribute__((packed)); + u32 next :6 __attribute__((packed)); +#else + u32 next :6 __attribute__((packed)); + u32 allocations :26 __attribute__((packed)); +#endif struct semaphore count; }; Index: linux/drivers/ieee1394/ieee1394_transactions.c =================================================================== --- linux.orig/drivers/ieee1394/ieee1394_transactions.c 2006-06-23 19:10:30.000000000 +0200 +++ linux/drivers/ieee1394/ieee1394_transactions.c 2006-06-24 09:24:00.000000000 +0200 @@ -136,7 +136,7 @@ int hpsb_get_tlabel(struct hpsb_packet * { unsigned long flags; struct hpsb_tlabel_pool *tp; - int n = NODEID_TO_NODE(packet->node_id); + int tlabel, n = NODEID_TO_NODE(packet->node_id); if (unlikely(n == ALL_NODES)) return 0; @@ -151,15 +151,17 @@ int hpsb_get_tlabel(struct hpsb_packet * spin_lock_irqsave(&tp->lock, flags); - packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next); - if (packet->tlabel > 63) - packet->tlabel = find_first_zero_bit(tp->pool, 64); - tp->next = (packet->tlabel + 1) % 64; + tlabel = find_next_zero_bit(tp->pool, 64, tp->next); + if (tlabel > 63) + tlabel = find_first_zero_bit(tp->pool, 64); + /* tp->next is 6 bits wide, thus rolls over from 63 to 0 */ + tp->next = (tlabel + 1); /* Should _never_ happen */ - BUG_ON(test_and_set_bit(packet->tlabel, tp->pool)); + BUG_ON(test_and_set_bit(tlabel, tp->pool)); tp->allocations++; - spin_unlock_irqrestore(&tp->lock, flags); + spin_unlock_irqrestore(&tp->lock, flags); + packet->tlabel = tlabel; return 0; } @@ -178,16 +180,16 @@ void hpsb_free_tlabel(struct hpsb_packet { unsigned long flags; struct hpsb_tlabel_pool *tp; - int n = NODEID_TO_NODE(packet->node_id); + int tlabel = packet->tlabel, n = NODEID_TO_NODE(packet->node_id); if (unlikely(n == ALL_NODES)) return; tp = &packet->host->tpool[n]; - BUG_ON(packet->tlabel > 63 || packet->tlabel < 0); + BUG_ON(tlabel > 63 || tlabel < 0); spin_lock_irqsave(&tp->lock, flags); - BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool)); + BUG_ON(!test_and_clear_bit(tlabel, tp->pool)); spin_unlock_irqrestore(&tp->lock, flags); up(&tp->count); ^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 2.6.17-mm1 2/3] ieee1394: coarser locking for tlabel allocation 2006-06-24 9:32 ` [RFC PATCH 2.6.17-mm1 1/3] ieee1394: reduce size of hpsb_host by 252 bytes Stefan Richter @ 2006-06-24 9:33 ` Stefan Richter 2006-06-24 9:35 ` [RFC PATCH 2.6.17-mm1 3/3] ieee1394: nodemgr: read tlabel attributes atomically Stefan Richter 0 siblings, 1 reply; 11+ messages in thread From: Stefan Richter @ 2006-06-24 9:33 UTC (permalink / raw) To: linux1394-devel; +Cc: linux-kernel Full parallelism in getting and freeing transaction labels of different nodes is not really required. Therefore reduce the number of locks for access to tlabel pools from 63 locks per host to 1 global lock. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> --- drivers/ieee1394/ieee1394_transactions.c | 10 ++++++---- drivers/ieee1394/ieee1394_types.h | 2 -- 2 files changed, 6 insertions(+), 6 deletions(-) Index: linux/drivers/ieee1394/ieee1394_types.h =================================================================== --- linux.orig/drivers/ieee1394/ieee1394_types.h 2006-06-24 09:53:24.000000000 +0200 +++ linux/drivers/ieee1394/ieee1394_types.h 2006-06-24 10:02:15.000000000 +0200 @@ -16,7 +16,6 @@ /* Transaction Label handling */ struct hpsb_tlabel_pool { DECLARE_BITMAP(pool, 64); - spinlock_t lock; #ifdef __BIG_ENDIAN_BITFIELD u32 allocations :26 __attribute__((packed)); u32 next :6 __attribute__((packed)); @@ -30,7 +29,6 @@ struct hpsb_tlabel_pool { #define HPSB_TPOOL_INIT(_tp) \ do { \ bitmap_zero((_tp)->pool, 64); \ - spin_lock_init(&(_tp)->lock); \ (_tp)->next = 0; \ (_tp)->allocations = 0; \ sema_init(&(_tp)->count, 63); \ Index: linux/drivers/ieee1394/ieee1394_transactions.c =================================================================== --- linux.orig/drivers/ieee1394/ieee1394_transactions.c 2006-06-24 09:24:00.000000000 +0200 +++ linux/drivers/ieee1394/ieee1394_transactions.c 2006-06-24 10:08:35.000000000 +0200 @@ -31,6 +31,8 @@ packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \ packet->header[2] = addr & 0xffffffff +static spinlock_t hpsb_tlabel_lock = SPIN_LOCK_UNLOCKED; + static void fill_async_readquad(struct hpsb_packet *packet, u64 addr) { PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ); @@ -149,7 +151,7 @@ int hpsb_get_tlabel(struct hpsb_packet * down(&tp->count); } - spin_lock_irqsave(&tp->lock, flags); + spin_lock_irqsave(&hpsb_tlabel_lock, flags); tlabel = find_next_zero_bit(tp->pool, 64, tp->next); if (tlabel > 63) @@ -160,7 +162,7 @@ int hpsb_get_tlabel(struct hpsb_packet * BUG_ON(test_and_set_bit(tlabel, tp->pool)); tp->allocations++; - spin_unlock_irqrestore(&tp->lock, flags); + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); packet->tlabel = tlabel; return 0; } @@ -188,9 +190,9 @@ void hpsb_free_tlabel(struct hpsb_packet BUG_ON(tlabel > 63 || tlabel < 0); - spin_lock_irqsave(&tp->lock, flags); + spin_lock_irqsave(&hpsb_tlabel_lock, flags); BUG_ON(!test_and_clear_bit(tlabel, tp->pool)); - spin_unlock_irqrestore(&tp->lock, flags); + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); up(&tp->count); } ^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 2.6.17-mm1 3/3] ieee1394: nodemgr: read tlabel attributes atomically 2006-06-24 9:33 ` [RFC PATCH 2.6.17-mm1 2/3] ieee1394: coarser locking for tlabel allocation Stefan Richter @ 2006-06-24 9:35 ` Stefan Richter 2006-06-24 17:32 ` [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue Stefan Richter 0 siblings, 1 reply; 11+ messages in thread From: Stefan Richter @ 2006-06-24 9:35 UTC (permalink / raw) To: linux1394-devel; +Cc: linux-kernel A node_entry's sysfs attributes tlabels_free, tlabels_allocations, and tlabels_mask may theoretically be sometimes wrong if they were read without taking the respective lock. Although this is not very serious since these attributes are rarely accessed and not interesting outside of driver or application development, why not do it properly. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> --- applies after patch "ieee1394: nodemgr: do not peek into struct semaphore" http://marc.theaimsgroup.com/?l=linux-mm-commits&m=115113030025655 drivers/ieee1394/ieee1394_transactions.c | 2 - drivers/ieee1394/ieee1394_transactions.h | 5 +++ drivers/ieee1394/nodemgr.c | 31 ++++++++++++++++++----- 3 files changed, 31 insertions(+), 7 deletions(-) Index: linux/drivers/ieee1394/ieee1394_transactions.h =================================================================== --- linux.orig/drivers/ieee1394/ieee1394_transactions.h 2006-04-24 22:20:24.000000000 +0200 +++ linux/drivers/ieee1394/ieee1394_transactions.h 2006-06-24 11:00:23.000000000 +0200 @@ -1,6 +1,11 @@ #ifndef _IEEE1394_TRANSACTIONS_H #define _IEEE1394_TRANSACTIONS_H +#include <linux/spinlock_types.h> + +/* internal to ieee1394 core */ +extern spinlock_t hpsb_tlabel_lock; + #include "ieee1394_core.h" Index: linux/drivers/ieee1394/ieee1394_transactions.c =================================================================== --- linux.orig/drivers/ieee1394/ieee1394_transactions.c 2006-06-24 10:08:35.000000000 +0200 +++ linux/drivers/ieee1394/ieee1394_transactions.c 2006-06-24 10:30:00.000000000 +0200 @@ -31,7 +31,7 @@ packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \ packet->header[2] = addr & 0xffffffff -static spinlock_t hpsb_tlabel_lock = SPIN_LOCK_UNLOCKED; +spinlock_t hpsb_tlabel_lock = SPIN_LOCK_UNLOCKED; static void fill_async_readquad(struct hpsb_packet *packet, u64 addr) { Index: linux/drivers/ieee1394/nodemgr.c =================================================================== --- linux.orig/drivers/ieee1394/nodemgr.c 2006-06-23 19:10:32.000000000 +0200 +++ linux/drivers/ieee1394/nodemgr.c 2006-06-24 10:43:18.000000000 +0200 @@ -327,12 +327,17 @@ static ssize_t fw_show_ne_bus_options(st static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL); -/* tlabels_free, tlabels_allocations, tlabels_mask are read non-atomically - * here, therefore displayed values may be occasionally wrong. */ static ssize_t fw_show_ne_tlabels_free(struct device *dev, struct device_attribute *attr, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); - return sprintf(buf, "%d\n", 64 - bitmap_weight(ne->tpool->pool, 64)); + unsigned long flags; + int tf; + + spin_lock_irqsave(&hpsb_tlabel_lock, flags); + tf = 64 - bitmap_weight(ne->tpool->pool, 64); + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); + + return sprintf(buf, "%d\n", tf); } static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL); @@ -340,7 +345,14 @@ static DEVICE_ATTR(tlabels_free,S_IRUGO, static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, struct device_attribute *attr, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); - return sprintf(buf, "%u\n", ne->tpool->allocations); + unsigned long flags; + int ta; + + spin_lock_irqsave(&hpsb_tlabel_lock, flags); + ta = ne->tpool->allocations; + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); + + return sprintf(buf, "%u\n", ta); } static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_show_ne_tlabels_allocations,NULL); @@ -348,11 +360,18 @@ static DEVICE_ATTR(tlabels_allocations,S static ssize_t fw_show_ne_tlabels_mask(struct device *dev, struct device_attribute *attr, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); + unsigned long flags; + u64 tm; + + spin_lock_irqsave(&hpsb_tlabel_lock, flags); #if (BITS_PER_LONG <= 32) - return sprintf(buf, "0x%08lx%08lx\n", ne->tpool->pool[0], ne->tpool->pool[1]); + tm = ((u64)ne->tpool->pool[0] << 32) + ne->tpool->pool[1]; #else - return sprintf(buf, "0x%016lx\n", ne->tpool->pool[0]); + tm = ne->tpool->pool[0]; #endif + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); + + return sprintf(buf, "0x%016llx\n", tm); } static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL); ^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue 2006-06-24 9:35 ` [RFC PATCH 2.6.17-mm1 3/3] ieee1394: nodemgr: read tlabel attributes atomically Stefan Richter @ 2006-06-24 17:32 ` Stefan Richter 2006-06-24 17:45 ` Stefan Richter 2006-06-25 17:27 ` [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue Stefan Richter 0 siblings, 2 replies; 11+ messages in thread From: Stefan Richter @ 2006-06-24 17:32 UTC (permalink / raw) To: linux1394-devel; +Cc: linux-kernel There were 63 instances of counting semaphores used for each hpsb_host. All of them are now replaced by a single wait_queue. Note, it is rather unlikely that a process has to wait for a transaction label to become free. This condition occurs only if more than 64 transactions are initiated before the receiving node is able to complete any of them. A slight change in behaviour is introduced: Allocation of a tlabel will fail if a signal was received while the process had to sleep until a tlabel becomes available. Previously, the process slept uninterruptibly on the semaphore until availability of a tlabel. Furthermore, error return values of hpsb_get_tlabel() are now -ERESTARTSYS or -EAGAIN instead of 1. However an error return value has always been defined as "non-zero" in the API and all in-tree callers respect that. The macro HPSB_TPOOL_INIT is no longer necessary since struct hpsb_host is kzalloc'd. The spinlock-protected code which accesses tlabel pools can use the non-atomic variants of bitmap manipulation functions. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> --- drivers/ieee1394/hosts.c | 3 drivers/ieee1394/ieee1394_transactions.c | 82 ++++++++++++----------- drivers/ieee1394/ieee1394_types.h | 10 -- 3 files changed, 46 insertions(+), 49 deletions(-) Index: linux-2.6.17-mm1/drivers/ieee1394/ieee1394_types.h =================================================================== --- linux-2.6.17-mm1.orig/drivers/ieee1394/ieee1394_types.h 2006-06-24 11:11:55.000000000 +0200 +++ linux-2.6.17-mm1/drivers/ieee1394/ieee1394_types.h 2006-06-24 18:03:24.000000000 +0200 @@ -23,18 +23,8 @@ struct hpsb_tlabel_pool { u32 next :6 __attribute__((packed)); u32 allocations :26 __attribute__((packed)); #endif - struct semaphore count; }; -#define HPSB_TPOOL_INIT(_tp) \ -do { \ - bitmap_zero((_tp)->pool, 64); \ - (_tp)->next = 0; \ - (_tp)->allocations = 0; \ - sema_init(&(_tp)->count, 63); \ -} while (0) - - typedef u32 quadlet_t; typedef u64 octlet_t; typedef u16 nodeid_t; Index: linux-2.6.17-mm1/drivers/ieee1394/hosts.c =================================================================== --- linux-2.6.17-mm1.orig/drivers/ieee1394/hosts.c 2006-06-23 17:58:03.000000000 +0200 +++ linux-2.6.17-mm1/drivers/ieee1394/hosts.c 2006-06-24 18:03:24.000000000 +0200 @@ -143,9 +143,6 @@ struct hpsb_host *hpsb_alloc_host(struct for (i = 2; i < 16; i++) h->csr.gen_timestamp[i] = jiffies - 60 * HZ; - for (i = 0; i < ARRAY_SIZE(h->tpool); i++) - HPSB_TPOOL_INIT(&h->tpool[i]); - atomic_set(&h->generation, 0); INIT_WORK(&h->delayed_reset, delayed_reset_bus, h); Index: linux-2.6.17-mm1/drivers/ieee1394/ieee1394_transactions.c =================================================================== --- linux-2.6.17-mm1.orig/drivers/ieee1394/ieee1394_transactions.c 2006-06-24 11:12:01.000000000 +0200 +++ linux-2.6.17-mm1/drivers/ieee1394/ieee1394_transactions.c 2006-06-24 18:03:24.000000000 +0200 @@ -9,10 +9,9 @@ * directory of the kernel sources for details. */ -#include <linux/sched.h> #include <linux/bitops.h> -#include <linux/smp_lock.h> -#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/wait.h> #include <asm/errno.h> @@ -20,8 +19,6 @@ #include "ieee1394_types.h" #include "hosts.h" #include "ieee1394_core.h" -#include "highlevel.h" -#include "nodemgr.h" #include "ieee1394_transactions.h" #define PREP_ASYNC_HEAD_ADDRESS(tc) \ @@ -32,6 +29,7 @@ packet->header[2] = addr & 0xffffffff spinlock_t hpsb_tlabel_lock = SPIN_LOCK_UNLOCKED; +static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq); static void fill_async_readquad(struct hpsb_packet *packet, u64 addr) { @@ -116,50 +114,35 @@ static void fill_async_stream_packet(str packet->tcode = TCODE_ISO_DATA; } -/** - * hpsb_get_tlabel - allocate a transaction label - * @packet: the packet who's tlabel/tpool we set - * - * Every asynchronous transaction on the 1394 bus needs a transaction - * label to match the response to the request. This label has to be - * different from any other transaction label in an outstanding request to - * the same node to make matching possible without ambiguity. - * - * There are 64 different tlabels, so an allocated tlabel has to be freed - * with hpsb_free_tlabel() after the transaction is complete (unless it's - * reused again for the same target node). - * - * Return value: Zero on success, otherwise non-zero. A non-zero return - * generally means there are no available tlabels. If this is called out - * of interrupt or atomic context, then it will sleep until can return a - * tlabel. - */ -int hpsb_get_tlabel(struct hpsb_packet *packet) +/* same as hpsb_get_tlabel, except that it returns immediately */ +static int hpsb_get_tlabel_atomic(struct hpsb_packet *packet) { unsigned long flags; struct hpsb_tlabel_pool *tp; int tlabel, n = NODEID_TO_NODE(packet->node_id); - if (unlikely(n == ALL_NODES)) + /* Broadcast transactions are complete once the request has been sent. + * Use the same transaction label for all broadcast transactions. */ + if (unlikely(n == ALL_NODES)) { + packet->tlabel = 0; return 0; - tp = &packet->host->tpool[n]; - - if (irqs_disabled() || in_atomic()) { - if (down_trylock(&tp->count)) - return 1; - } else { - down(&tp->count); } + BUG_ON(n > ARRAY_SIZE(packet->host->tpool)); + tp = &packet->host->tpool[n]; spin_lock_irqsave(&hpsb_tlabel_lock, flags); tlabel = find_next_zero_bit(tp->pool, 64, tp->next); if (tlabel > 63) tlabel = find_first_zero_bit(tp->pool, 64); + if (tlabel > 63) { + spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); + return -EAGAIN; + } + __set_bit(tlabel, tp->pool); + /* tp->next is 6 bits wide, thus rolls over from 63 to 0 */ tp->next = (tlabel + 1); - /* Should _never_ happen */ - BUG_ON(test_and_set_bit(tlabel, tp->pool)); tp->allocations++; spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); @@ -168,6 +151,33 @@ int hpsb_get_tlabel(struct hpsb_packet * } /** + * hpsb_get_tlabel - allocate a transaction label + * @packet: the packet who's tlabel/tpool we set + * + * Every asynchronous transaction on the 1394 bus needs a transaction + * label to match the response to the request. This label has to be + * different from any other transaction label in an outstanding request to + * the same node to make matching possible without ambiguity. + * + * There are 64 different tlabels, so an allocated tlabel has to be freed + * with hpsb_free_tlabel() after the transaction is complete (unless it's + * reused again for the same target node). + * + * Return value: Zero on success, otherwise non-zero. A non-zero return + * generally means there are no available tlabels. If this is called out + * of interrupt or atomic context, then it will sleep until can return a + * tlabel or a signal is received. + */ +int hpsb_get_tlabel(struct hpsb_packet *packet) +{ + if (irqs_disabled() || in_atomic()) + return hpsb_get_tlabel_atomic(packet); + + return wait_event_interruptible(tlabel_wq, + !hpsb_get_tlabel_atomic(packet)); +} + +/** * hpsb_free_tlabel - free an allocated transaction label * @packet: packet whos tlabel/tpool needs to be cleared * @@ -191,10 +201,10 @@ void hpsb_free_tlabel(struct hpsb_packet BUG_ON(tlabel > 63 || tlabel < 0); spin_lock_irqsave(&hpsb_tlabel_lock, flags); - BUG_ON(!test_and_clear_bit(tlabel, tp->pool)); + BUG_ON(!__test_and_clear_bit(tlabel, tp->pool)); spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); - up(&tp->count); + wake_up_interruptible(&tlabel_wq); } int hpsb_packet_success(struct hpsb_packet *packet) ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue 2006-06-24 17:32 ` [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue Stefan Richter @ 2006-06-24 17:45 ` Stefan Richter 2006-06-24 18:12 ` Arjan van de Ven 2006-06-25 17:27 ` [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue Stefan Richter 1 sibling, 1 reply; 11+ messages in thread From: Stefan Richter @ 2006-06-24 17:45 UTC (permalink / raw) To: linux1394-devel; +Cc: linux-kernel I wrote: > There were 63 instances of counting semaphores used for each hpsb_host. > All of them are now replaced by a single wait_queue. After this and patch "ieee1394: dv1394: sem2mutex conversion", the following semaphores remain in the ieee1394 subsystem: highlevel.c: hl_drivers_sem (RW semaphore) nodemgr.c: subsys.rwsem (driver core's RW semaphores) raw1394.c: fi->complete_sem (completion semaphore) -- Stefan Richter -=====-=-==- -==- ==--- http://arcgraph.de/sr/ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue 2006-06-24 17:45 ` Stefan Richter @ 2006-06-24 18:12 ` Arjan van de Ven 2006-06-24 20:28 ` Stefan Richter 2006-06-25 19:37 ` [RFC PATCH 2.6.17-mm1 5/3] ieee1394: raw1394: remove redundant counting semaphore Stefan Richter 0 siblings, 2 replies; 11+ messages in thread From: Arjan van de Ven @ 2006-06-24 18:12 UTC (permalink / raw) To: Stefan Richter; +Cc: linux1394-devel, linux-kernel On Sat, 2006-06-24 at 19:45 +0200, Stefan Richter wrote: > I wrote: > > There were 63 instances of counting semaphores used for each hpsb_host. > > All of them are now replaced by a single wait_queue. > > After this and patch "ieee1394: dv1394: sem2mutex conversion", the > following semaphores remain in the ieee1394 subsystem: > > highlevel.c: hl_drivers_sem (RW semaphore) > nodemgr.c: subsys.rwsem (driver core's RW semaphores) > raw1394.c: fi->complete_sem (completion semaphore) Hi, can this last one move to an actual completion? That would get rid of it nicely ;) Greetings, Arjan van de Ven ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue 2006-06-24 18:12 ` Arjan van de Ven @ 2006-06-24 20:28 ` Stefan Richter 2006-06-24 20:56 ` Stefan Richter 2006-06-25 19:37 ` [RFC PATCH 2.6.17-mm1 5/3] ieee1394: raw1394: remove redundant counting semaphore Stefan Richter 1 sibling, 1 reply; 11+ messages in thread From: Stefan Richter @ 2006-06-24 20:28 UTC (permalink / raw) To: Arjan van de Ven; +Cc: linux1394-devel, linux-kernel Arjan van de Ven wrote: > On Sat, 2006-06-24 at 19:45 +0200, Stefan Richter wrote: >>following semaphores remain in the ieee1394 subsystem: >> >>highlevel.c: hl_drivers_sem (RW semaphore) >>nodemgr.c: subsys.rwsem (driver core's RW semaphores) >>raw1394.c: fi->complete_sem (completion semaphore) > can this last one move to an actual completion? That would get rid of it > nicely ;) Hmm. There are dozens of points in raw1394 which call __queue_complete_req() which up()s the semaphore. ("fi" is the private_data of a struct file. Multiple outstanding requests may be associated with a file.) Then there are two places which wait on the semaphore: raw1394_read(), called when somebody reads /dev/raw1394: if (file->f_flags & O_NONBLOCK) { if (down_trylock(&fi->complete_sem)) return -EAGAIN; } else { if (down_interruptible(&fi->complete_sem)) return -ERESTARTSYS; } raw1394_release(), called when somebody closes (releases) /dev/raw1394: done = 0; while (!done) { /* free all complete requests */ /* set "done" if there are no more pending requests */ if (!done) down_interruptible(&fi->complete_sem); } /* cleanup, free fi */ It looks like fi->complete_sem is a actually a counting semaphore. It could perhaps be replaced by a wait queue plus an atomic counter. There is even already a wait queue in "fi" for use with poll_wait() via raw1394_poll(). -- Stefan Richter -=====-=-==- -==- ==--- http://arcgraph.de/sr/ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue 2006-06-24 20:28 ` Stefan Richter @ 2006-06-24 20:56 ` Stefan Richter 0 siblings, 0 replies; 11+ messages in thread From: Stefan Richter @ 2006-06-24 20:56 UTC (permalink / raw) To: Arjan van de Ven; +Cc: linux1394-devel, linux-kernel I wrote: > It looks like fi->complete_sem is a actually a counting semaphore. It > could perhaps be replaced by a wait queue plus an atomic counter. ...which would be a semaphore. %-| -- Stefan Richter -=====-=-==- -==- ==--- http://arcgraph.de/sr/ ^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 2.6.17-mm1 5/3] ieee1394: raw1394: remove redundant counting semaphore 2006-06-24 18:12 ` Arjan van de Ven 2006-06-24 20:28 ` Stefan Richter @ 2006-06-25 19:37 ` Stefan Richter 2006-06-25 19:54 ` Stefan Richter 1 sibling, 1 reply; 11+ messages in thread From: Stefan Richter @ 2006-06-25 19:37 UTC (permalink / raw) To: linux1394-devel; +Cc: linux-kernel An already existing wait queue replaces raw1394's complete_sem which was maintained in parallel to the wait queue. The role of the semaphore's counter is taken over by a direct check of what was really counted: The presence of items in the list of completed requests. Notes: - raw1394_release() sleeps uninterruptibly until all requests were completed. This is the same behaviour as before the patch. - The macros wait_event and wait_event_interruptible are called with a condition argument which has a side effect, i.e. manipulation of the requests list. This side effect happens only if the condition is true. The patch relies on the fact that wait_event[_interruptible] does not evaluate the condition again after it became true. - The diffstat looks unfavorable with respect to added lines of code. However 6 of them are comments, and some are due to separation of existing code blocks into two small helper functions. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> --- drivers/ieee1394/raw1394-private.h | 3 - drivers/ieee1394/raw1394.c | 79 ++++++++++++++++------------- 2 files changed, 46 insertions(+), 36 deletions(-) This patch won't apply without the -mm patch because of the list_move patch in -mm. Variants of this and other 1394 patches for older kernels can be found at http://me.in-berlin.de/~s5r6/linux1394/updates/. I tested the patch on 2.6.16.x SMP PREEMPT x86 K7 uniprocessor with the libraw1394 apps 1394commander and gscanbus, issuing asynchronous transactions, bus resets, and PHY packets, which trigger raw1394_open, raw1394_write, raw1394_read, raw1394_poll, raw1394_release. Index: linux-2.6.17-mm2/drivers/ieee1394/raw1394-private.h =================================================================== --- linux-2.6.17-mm2.orig/drivers/ieee1394/raw1394-private.h 2006-06-25 21:10:39.000000000 +0200 +++ linux-2.6.17-mm2/drivers/ieee1394/raw1394-private.h 2006-06-25 21:11:07.000000000 +0200 @@ -29,9 +29,8 @@ struct file_info { struct list_head req_pending; struct list_head req_complete; - struct semaphore complete_sem; spinlock_t reqlists_lock; - wait_queue_head_t poll_wait_complete; + wait_queue_head_t wait_complete; struct list_head addr_list; Index: linux-2.6.17-mm2/drivers/ieee1394/raw1394.c =================================================================== --- linux-2.6.17-mm2.orig/drivers/ieee1394/raw1394.c 2006-06-25 21:10:39.000000000 +0200 +++ linux-2.6.17-mm2/drivers/ieee1394/raw1394.c 2006-06-25 21:11:41.000000000 +0200 @@ -132,10 +132,9 @@ static void free_pending_request(struct static void __queue_complete_req(struct pending_request *req) { struct file_info *fi = req->file_info; - list_move_tail(&req->list, &fi->req_complete); - up(&fi->complete_sem); - wake_up_interruptible(&fi->poll_wait_complete); + list_move_tail(&req->list, &fi->req_complete); + wake_up(&fi->wait_complete); } static void queue_complete_req(struct pending_request *req) @@ -463,13 +462,36 @@ raw1394_compat_read(const char __user *b #endif +/* get next completed request (caller must hold fi->reqlists_lock) */ +static inline struct pending_request *__next_complete_req(struct file_info *fi) +{ + struct list_head *lh; + struct pending_request *req = NULL; + + if (!list_empty(&fi->req_complete)) { + lh = fi->req_complete.next; + list_del(lh); + req = list_entry(lh, struct pending_request, list); + } + return req; +} + +/* atomically get next completed request */ +static struct pending_request *next_complete_req(struct file_info *fi) +{ + unsigned long flags; + struct pending_request *req; + + spin_lock_irqsave(&fi->reqlists_lock, flags); + req = __next_complete_req(fi); + spin_unlock_irqrestore(&fi->reqlists_lock, flags); + return req; +} static ssize_t raw1394_read(struct file *file, char __user * buffer, size_t count, loff_t * offset_is_ignored) { - unsigned long flags; struct file_info *fi = (struct file_info *)file->private_data; - struct list_head *lh; struct pending_request *req; ssize_t ret; @@ -487,22 +509,14 @@ static ssize_t raw1394_read(struct file } if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&fi->complete_sem)) { + if (!(req = next_complete_req(fi))) return -EAGAIN; - } } else { - if (down_interruptible(&fi->complete_sem)) { + if (wait_event_interruptible(fi->wait_complete, + (req = next_complete_req(fi)))) return -ERESTARTSYS; - } } - spin_lock_irqsave(&fi->reqlists_lock, flags); - lh = fi->req_complete.next; - list_del(lh); - spin_unlock_irqrestore(&fi->reqlists_lock, flags); - - req = list_entry(lh, struct pending_request, list); - if (req->req.length) { if (copy_to_user(int2ptr(req->req.recvb), req->data, req->req.length)) { @@ -2744,7 +2758,7 @@ static unsigned int raw1394_poll(struct unsigned int mask = POLLOUT | POLLWRNORM; unsigned long flags; - poll_wait(file, &fi->poll_wait_complete, pt); + poll_wait(file, &fi->wait_complete, pt); spin_lock_irqsave(&fi->reqlists_lock, flags); if (!list_empty(&fi->req_complete)) { @@ -2769,9 +2783,8 @@ static int raw1394_open(struct inode *in fi->state = opened; INIT_LIST_HEAD(&fi->req_pending); INIT_LIST_HEAD(&fi->req_complete); - sema_init(&fi->complete_sem, 0); spin_lock_init(&fi->reqlists_lock); - init_waitqueue_head(&fi->poll_wait_complete); + init_waitqueue_head(&fi->wait_complete); INIT_LIST_HEAD(&fi->addr_list); file->private_data = fi; @@ -2784,7 +2797,7 @@ static int raw1394_release(struct inode struct file_info *fi = file->private_data; struct list_head *lh; struct pending_request *req; - int done = 0, i, fail = 0; + int i, fail; int retval = 0; struct list_head *entry; struct arm_addr *addr = NULL; @@ -2864,25 +2877,23 @@ static int raw1394_release(struct inode "error(s) occurred \n"); } - while (!done) { + for (;;) { + /* This locked section guarantees that neither + * complete nor pending requests exist once i!=0 */ spin_lock_irqsave(&fi->reqlists_lock, flags); - - while (!list_empty(&fi->req_complete)) { - lh = fi->req_complete.next; - list_del(lh); - - req = list_entry(lh, struct pending_request, list); - + while ((req = __next_complete_req(fi))) free_pending_request(req); - } - - if (list_empty(&fi->req_pending)) - done = 1; + i = list_empty(&fi->req_pending); spin_unlock_irqrestore(&fi->reqlists_lock, flags); - if (!done) - down_interruptible(&fi->complete_sem); + if (i) + break; + + /* Sleep until more requests can be freed. + * FIXME? This sleeps uninterruptibly. */ + wait_event(fi->wait_complete, (req = next_complete_req(fi))); + free_pending_request(req); } /* Remove any sub-trees left by user space programs */ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 2.6.17-mm1 5/3] ieee1394: raw1394: remove redundant counting semaphore 2006-06-25 19:37 ` [RFC PATCH 2.6.17-mm1 5/3] ieee1394: raw1394: remove redundant counting semaphore Stefan Richter @ 2006-06-25 19:54 ` Stefan Richter 0 siblings, 0 replies; 11+ messages in thread From: Stefan Richter @ 2006-06-25 19:54 UTC (permalink / raw) To: linux1394-devel; +Cc: linux-kernel I wrote: ... > @@ -2864,25 +2877,23 @@ static int raw1394_release(struct inode ... > + /* Sleep until more requests can be freed. > + * FIXME? This sleeps uninterruptibly. */ > + wait_event(fi->wait_complete, (req = next_complete_req(fi))); > + free_pending_request(req); We certainly cannot allow anybody to close the file with pending or orphaned complete requests, so maybe I should white-out that FIXME. -- Stefan Richter -=====-=-==- -==- ==--= http://arcgraph.de/sr/ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue 2006-06-24 17:32 ` [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue Stefan Richter 2006-06-24 17:45 ` Stefan Richter @ 2006-06-25 17:27 ` Stefan Richter 1 sibling, 0 replies; 11+ messages in thread From: Stefan Richter @ 2006-06-25 17:27 UTC (permalink / raw) To: linux1394-devel; +Cc: linux-kernel I wrote on 2006-06-24: > + return wait_event_interruptible(tlabel_wq, > + !hpsb_get_tlabel_atomic(packet)); Hmm. "Linux Device Drivers" says about wait_event_interruptible(wq, condition): ''Note that @condition may be evaluated an arbitrary number of times, so it should not have any side effects.'' Alas the hpsb_get_tlabel_atomic() _does_ have a side effect, but only when !hpsb_get_tlabel_atomic(packet) is true. The current implementation of wait_event_interruptible() seems to evaluate @condition multiple times if it is false but only _once_ while it is true. May I rely on this fact or do I have to rewrite the condition to be completely free of side effects? I don't believe there would be ever a sensible implementation of wait_event_interruptible() which would evaluate @condition again after it became true. Thanks, -- Stefan Richter -=====-=-==- -==- ==--= http://arcgraph.de/sr/ ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2006-06-25 19:56 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <449BEBFB.60302@s5r6.in-berlin.de>
[not found] ` <200606230904.k5N94Al3005245@shell0.pdx.osdl.net>
[not found] ` <30866.1151072338@warthog.cambridge.redhat.com>
[not found] ` <tkrat.df6845846c72176e@s5r6.in-berlin.de>
2006-06-24 9:32 ` [RFC PATCH 2.6.17-mm1 1/3] ieee1394: reduce size of hpsb_host by 252 bytes Stefan Richter
2006-06-24 9:33 ` [RFC PATCH 2.6.17-mm1 2/3] ieee1394: coarser locking for tlabel allocation Stefan Richter
2006-06-24 9:35 ` [RFC PATCH 2.6.17-mm1 3/3] ieee1394: nodemgr: read tlabel attributes atomically Stefan Richter
2006-06-24 17:32 ` [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue Stefan Richter
2006-06-24 17:45 ` Stefan Richter
2006-06-24 18:12 ` Arjan van de Ven
2006-06-24 20:28 ` Stefan Richter
2006-06-24 20:56 ` Stefan Richter
2006-06-25 19:37 ` [RFC PATCH 2.6.17-mm1 5/3] ieee1394: raw1394: remove redundant counting semaphore Stefan Richter
2006-06-25 19:54 ` Stefan Richter
2006-06-25 17:27 ` [RFC PATCH 2.6.17-mm1 4/3] ieee1394: convert ieee1394_transactions from semaphores to waitqueue Stefan Richter
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®