diff options
author | Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 2005-08-09 23:08:09 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:41:49 -0400 |
commit | f3f05f7046e7c85b04af390d95a82a27160dd5d0 (patch) | |
tree | 9a4a552c030ea8b2428ceee75311d73a6b339255 /net/ipv4/inet_hashtables.c | |
parent | 6e04e02165a7209a71db553b7bc48d68421e5ebf (diff) |
[INET]: Generalise the tcp_listen_ lock routines
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/inet_hashtables.c')
-rw-r--r-- | net/ipv4/inet_hashtables.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 33d6cbe32cdc..06cbc6f689c5 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -15,7 +15,9 @@ | |||
15 | 15 | ||
16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/sched.h> | ||
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/wait.h> | ||
19 | 21 | ||
20 | #include <net/inet_hashtables.h> | 22 | #include <net/inet_hashtables.h> |
21 | 23 | ||
@@ -89,3 +91,33 @@ void inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk) | |||
89 | } | 91 | } |
90 | 92 | ||
91 | EXPORT_SYMBOL(inet_put_port); | 93 | EXPORT_SYMBOL(inet_put_port); |
94 | |||
95 | /* | ||
96 | * This lock without WQ_FLAG_EXCLUSIVE is good on UP and it can be very bad on SMP. | ||
97 | * Look, when several writers sleep and reader wakes them up, all but one | ||
98 | * immediately hit write lock and grab all the cpus. Exclusive sleep solves | ||
99 | * this, _but_ remember, it adds useless work on UP machines (wake up each | ||
100 | * exclusive lock release). It should be ifdefed really. | ||
101 | */ | ||
102 | void inet_listen_wlock(struct inet_hashinfo *hashinfo) | ||
103 | { | ||
104 | write_lock(&hashinfo->lhash_lock); | ||
105 | |||
106 | if (atomic_read(&hashinfo->lhash_users)) { | ||
107 | DEFINE_WAIT(wait); | ||
108 | |||
109 | for (;;) { | ||
110 | prepare_to_wait_exclusive(&hashinfo->lhash_wait, | ||
111 | &wait, TASK_UNINTERRUPTIBLE); | ||
112 | if (!atomic_read(&hashinfo->lhash_users)) | ||
113 | break; | ||
114 | write_unlock_bh(&hashinfo->lhash_lock); | ||
115 | schedule(); | ||
116 | write_lock_bh(&hashinfo->lhash_lock); | ||
117 | } | ||
118 | |||
119 | finish_wait(&hashinfo->lhash_wait, &wait); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | EXPORT_SYMBOL(inet_listen_wlock); | ||