I noticed that the tasks queues still rely on the global tqueue_lock
spinlock, instead of a per-taskqueue lock.
The patch is virtually transparent for task queue users: all users
except ieee1394 use DECLARE_TASK_QUEUE.
I admit that the tqueue_lock isn't that often used (numbers from sgi's
lockstat)
* 10000 users/min during 'find / -xdev -uid 4711' (1.2% of all spinlock
calls)
* 60000 users/min during 'dd if=/dev/hda of=/dev/null' (~1.1% of all
spinlock calls).
--
Manfred
// $Header$
// Kernel Version:
// VERSION = 2
// PATCHLEVEL = 4
// SUBLEVEL = 1
// EXTRAVERSION =-pre11
--- 2.4/drivers/char/n_r3964.c Mon Dec 11 21:57:28 2000
+++ build-2.4/drivers/char/n_r3964.c Mon Jan 29 14:54:29 2001
@@ -1185,13 +1185,15 @@
/*
* Make sure that our task queue isn't activated. If it
* is, take it out of the linked list.
+ * FIXME: buggy, another cpu might be in the middle of
+ * __run_task_queue().
*/
- spin_lock_irqsave(&tqueue_lock, flags);
+ spin_lock_irqsave(&tq_timer.lock, flags);
if (pInfo->bh_1.sync)
list_del(&pInfo->bh_1.list);
if (pInfo->bh_2.sync)
list_del(&pInfo->bh_2.list);
- spin_unlock_irqrestore(&tqueue_lock, flags);
+ spin_unlock_irqrestore(&tq_timer.lock, flags);
/* Remove client-structs and message queues: */
pClient=pInfo->firstClient;
--- 2.4/include/linux/tqueue.h Thu Jan 4 23:50:46 2001
+++ build-2.4/include/linux/tqueue.h Mon Jan 29 14:54:29 2001
@@ -42,10 +42,21 @@
void *data; /* argument to function */
};
-typedef struct list_head task_queue;
+typedef struct {
+ struct list_head list;
+ spinlock_t lock;
+} task_queue;
-#define DECLARE_TASK_QUEUE(q) LIST_HEAD(q)
-#define TQ_ACTIVE(q) (!list_empty(&q))
+#define TASK_QUEUE_INIT(name) { LIST_HEAD_INIT(name.list), SPIN_LOCK_UNLOCKED }
+
+#define INIT_TASK_QUEUE(ptr) do { \
+ INIT_LIST_HEAD(&(ptr)->list); \
+ spin_lock_init(&(ptr)->lock); \
+} while (0)
+
+
+#define DECLARE_TASK_QUEUE(q) task_queue q = TASK_QUEUE_INIT(q)
+#define TQ_ACTIVE(q) (!list_empty(&(q).list))
extern task_queue tq_timer, tq_immediate, tq_disk;
@@ -72,20 +83,18 @@
* interrupt.
*/
-extern spinlock_t tqueue_lock;
-
/*
* Queue a task on a tq. Return non-zero if it was successfully
* added.
*/
-static inline int queue_task(struct tq_struct *bh_pointer, task_queue *bh_list)
+static inline int queue_task(struct tq_struct *bh_pointer, task_queue *tq)
{
int ret = 0;
if (!test_and_set_bit(0,&bh_pointer->sync)) {
unsigned long flags;
- spin_lock_irqsave(&tqueue_lock, flags);
- list_add_tail(&bh_pointer->list, bh_list);
- spin_unlock_irqrestore(&tqueue_lock, flags);
+ spin_lock_irqsave(&tq->lock, flags);
+ list_add_tail(&bh_pointer->list, &tq->list);
+ spin_unlock_irqrestore(&tq->lock, flags);
ret = 1;
}
return ret;
@@ -97,10 +106,10 @@
extern void __run_task_queue(task_queue *list);
-static inline void run_task_queue(task_queue *list)
+static inline void run_task_queue(task_queue *tq)
{
- if (TQ_ACTIVE(*list))
- __run_task_queue(list);
+ if (TQ_ACTIVE(*tq))
+ __run_task_queue(tq);
}
#endif /* _LINUX_TQUEUE_H */
--- 2.4/kernel/timer.c Sun Dec 10 18:53:19 2000
+++ build-2.4/kernel/timer.c Mon Jan 29 14:54:29 2001
@@ -323,8 +323,6 @@
spin_unlock_irq(&timerlist_lock);
}
-spinlock_t tqueue_lock = SPIN_LOCK_UNLOCKED;
-
void tqueue_bh(void)
{
run_task_queue(&tq_timer);
--- 2.4/kernel/ksyms.c Mon Jan 29 14:53:44 2001
+++ build-2.4/kernel/ksyms.c Mon Jan 29 14:54:29 2001
@@ -372,7 +372,6 @@
#ifdef CONFIG_SMP
/* Various random spinlocks we want to export */
-EXPORT_SYMBOL(tqueue_lock);
/* Big-Reader lock implementation */
EXPORT_SYMBOL(__brlock_array);
--- 2.4/kernel/softirq.c Fri Dec 29 23:07:24 2000
+++ build-2.4/kernel/softirq.c Mon Jan 29 14:54:29 2001
@@ -289,15 +289,15 @@
open_softirq(HI_SOFTIRQ, tasklet_hi_action, NULL);
}
-void __run_task_queue(task_queue *list)
+void __run_task_queue(task_queue *tq)
{
struct list_head head, *next;
unsigned long flags;
- spin_lock_irqsave(&tqueue_lock, flags);
- list_add(&head, list);
- list_del_init(list);
- spin_unlock_irqrestore(&tqueue_lock, flags);
+ spin_lock_irqsave(&tq->lock, flags);
+ list_add(&head, &tq->list);
+ list_del_init(&tq->list);
+ spin_unlock_irqrestore(&tq->lock, flags);
next = head.next;
while (next != &head) {
--- 2.4/drivers/ieee1394/ieee1394_core.c Mon Oct 2 04:53:07 2000
+++ build-2.4/drivers/ieee1394/ieee1394_core.c Mon Jan 29 14:54:29 2001
@@ -100,6 +100,7 @@
INIT_LIST_HEAD(&packet->list);
sema_init(&packet->state_change, 0);
+ INIT_TASK_QUEUE(&packet->complete_tq);
packet->state = unused;
packet->generation = get_hpsb_generation();
packet->data_be = 1;