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)
64 if (ccids[ccid->ccid_id] == NULL) {
65 ccids[ccid->ccid_id] = ccid;
70 pr_info("CCID: Registered CCID %d (%s)\n",
71 ccid->ccid_id, ccid->ccid_name);
75 EXPORT_SYMBOL_GPL(ccid_register);
77 int ccid_unregister(struct ccid *ccid)
80 ccids[ccid->ccid_id] = NULL;
82 pr_info("CCID: Unregistered CCID %d (%s)\n",
83 ccid->ccid_id, ccid->ccid_name);
87 EXPORT_SYMBOL_GPL(ccid_unregister);
89 struct ccid *ccid_init(unsigned char id, struct sock *sk)
94 if (ccids[id] == NULL)
95 request_module("net-dccp-ccid-%d", id);
103 if (!try_module_get(ccid->ccid_owner))
106 if (ccid->ccid_init != NULL && ccid->ccid_init(sk) != 0)
112 module_put(ccid->ccid_owner);
118 EXPORT_SYMBOL_GPL(ccid_init);
120 void ccid_exit(struct ccid *ccid, struct sock *sk)
127 if (ccids[ccid->ccid_id] != NULL) {
128 if (ccid->ccid_exit != NULL)
130 module_put(ccid->ccid_owner);
136 EXPORT_SYMBOL_GPL(ccid_exit);