Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.15-rc3 139 lines 2.7 kB view raw
1/* 2 * net/dccp/ccid.c 3 * 4 * An implementation of the DCCP protocol 5 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 6 * 7 * CCID infrastructure 8 * 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. 12 */ 13 14#include "ccid.h" 15 16static struct ccid *ccids[CCID_MAX]; 17#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) 18static atomic_t ccids_lockct = ATOMIC_INIT(0); 19static DEFINE_SPINLOCK(ccids_lock); 20 21/* 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. 24 */ 25static void ccids_write_lock(void) 26{ 27 spin_lock(&ccids_lock); 28 while (atomic_read(&ccids_lockct) != 0) { 29 spin_unlock(&ccids_lock); 30 yield(); 31 spin_lock(&ccids_lock); 32 } 33} 34 35static inline void ccids_write_unlock(void) 36{ 37 spin_unlock(&ccids_lock); 38} 39 40static inline void ccids_read_lock(void) 41{ 42 atomic_inc(&ccids_lockct); 43 spin_unlock_wait(&ccids_lock); 44} 45 46static inline void ccids_read_unlock(void) 47{ 48 atomic_dec(&ccids_lockct); 49} 50 51#else 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) 56#endif 57 58int ccid_register(struct ccid *ccid) 59{ 60 int err; 61 62 if (ccid->ccid_init == NULL) 63 return -1; 64 65 ccids_write_lock(); 66 err = -EEXIST; 67 if (ccids[ccid->ccid_id] == NULL) { 68 ccids[ccid->ccid_id] = ccid; 69 err = 0; 70 } 71 ccids_write_unlock(); 72 if (err == 0) 73 pr_info("CCID: Registered CCID %d (%s)\n", 74 ccid->ccid_id, ccid->ccid_name); 75 return err; 76} 77 78EXPORT_SYMBOL_GPL(ccid_register); 79 80int ccid_unregister(struct ccid *ccid) 81{ 82 ccids_write_lock(); 83 ccids[ccid->ccid_id] = NULL; 84 ccids_write_unlock(); 85 pr_info("CCID: Unregistered CCID %d (%s)\n", 86 ccid->ccid_id, ccid->ccid_name); 87 return 0; 88} 89 90EXPORT_SYMBOL_GPL(ccid_unregister); 91 92struct ccid *ccid_init(unsigned char id, struct sock *sk) 93{ 94 struct ccid *ccid; 95 96#ifdef CONFIG_KMOD 97 if (ccids[id] == NULL) 98 request_module("net-dccp-ccid-%d", id); 99#endif 100 ccids_read_lock(); 101 102 ccid = ccids[id]; 103 if (ccid == NULL) 104 goto out; 105 106 if (!try_module_get(ccid->ccid_owner)) 107 goto out_err; 108 109 if (ccid->ccid_init(sk) != 0) 110 goto out_module_put; 111out: 112 ccids_read_unlock(); 113 return ccid; 114out_module_put: 115 module_put(ccid->ccid_owner); 116out_err: 117 ccid = NULL; 118 goto out; 119} 120 121EXPORT_SYMBOL_GPL(ccid_init); 122 123void ccid_exit(struct ccid *ccid, struct sock *sk) 124{ 125 if (ccid == NULL) 126 return; 127 128 ccids_read_lock(); 129 130 if (ccids[ccid->ccid_id] != NULL) { 131 if (ccid->ccid_exit != NULL) 132 ccid->ccid_exit(sk); 133 module_put(ccid->ccid_owner); 134 } 135 136 ccids_read_unlock(); 137} 138 139EXPORT_SYMBOL_GPL(ccid_exit);