4 * An implementation of the DCCP protocol
5 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
16 static struct ccid *ccids[CCID_MAX];
17 #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
18 static atomic_t ccids_lockct = ATOMIC_INIT(0);
19 static DEFINE_SPINLOCK(ccids_lock);
22 * The strategy is: modifications ccids vector are short, do not sleep and
23 * veeery rare, but read access should be free of any exclusive locks.
25 static void ccids_write_lock(void)
27 spin_lock(&ccids_lock);
28 while (atomic_read(&ccids_lockct) != 0) {
29 spin_unlock(&ccids_lock);
31 spin_lock(&ccids_lock);
35 static inline void ccids_write_unlock(void)
37 spin_unlock(&ccids_lock);
40 static inline void ccids_read_lock(void)
42 atomic_inc(&ccids_lockct);
43 spin_unlock_wait(&ccids_lock);
46 static inline void ccids_read_unlock(void)
48 atomic_dec(&ccids_lockct);
52 #define ccids_write_lock() do { } while(0)
53 #define ccids_write_unlock() do { } while(0)
54 #define ccids_read_lock() do { } while(0)
55 #define ccids_read_unlock() do { } while(0)
58 int ccid_register(struct ccid *ccid)
62 if (ccid->ccid_init == NULL)
67 if (ccids[ccid->ccid_id] == NULL) {
68 ccids[ccid->ccid_id] = ccid;
73 pr_info("CCID: Registered CCID %d (%s)\n",
74 ccid->ccid_id, ccid->ccid_name);
78 EXPORT_SYMBOL_GPL(ccid_register);
80 int ccid_unregister(struct ccid *ccid)
83 ccids[ccid->ccid_id] = NULL;
85 pr_info("CCID: Unregistered CCID %d (%s)\n",
86 ccid->ccid_id, ccid->ccid_name);
90 EXPORT_SYMBOL_GPL(ccid_unregister);
92 struct ccid *ccid_init(unsigned char id, struct sock *sk)
97 if (ccids[id] == NULL)
98 request_module("net-dccp-ccid-%d", id);
106 if (!try_module_get(ccid->ccid_owner))
109 if (ccid->ccid_init(sk) != 0)
115 module_put(ccid->ccid_owner);
121 EXPORT_SYMBOL_GPL(ccid_init);
123 void ccid_exit(struct ccid *ccid, struct sock *sk)
130 if (ccids[ccid->ccid_id] != NULL) {
131 if (ccid->ccid_exit != NULL)
133 module_put(ccid->ccid_owner);
139 EXPORT_SYMBOL_GPL(ccid_exit);