ng_base.c (149881) | ng_base.c (151238) |
---|---|
1/* 2 * ng_base.c 3 */ 4 5/*- 6 * Copyright (c) 1996-1999 Whistle Communications, Inc. 7 * All rights reserved. 8 * --- 24 unchanged lines hidden (view full) --- 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 36 * OF SUCH DAMAGE. 37 * 38 * Authors: Julian Elischer <julian@freebsd.org> 39 * Archie Cobbs <archie@freebsd.org> 40 * | 1/* 2 * ng_base.c 3 */ 4 5/*- 6 * Copyright (c) 1996-1999 Whistle Communications, Inc. 7 * All rights reserved. 8 * --- 24 unchanged lines hidden (view full) --- 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 36 * OF SUCH DAMAGE. 37 * 38 * Authors: Julian Elischer <julian@freebsd.org> 39 * Archie Cobbs <archie@freebsd.org> 40 * |
41 * $FreeBSD: head/sys/netgraph/ng_base.c 149881 2005-09-08 14:32:19Z glebius $ | 41 * $FreeBSD: head/sys/netgraph/ng_base.c 151238 2005-10-11 13:48:38Z glebius $ |
42 * $Whistle: ng_base.c,v 1.39 1999/01/28 23:54:53 julian Exp $ 43 */ 44 45/* 46 * This file implements the base netgraph code. 47 */ 48 49#include <sys/param.h> --- 133 unchanged lines hidden (view full) --- 183 184/* Internal functions */ 185static int ng_add_hook(node_p node, const char *name, hook_p * hookp); 186static int ng_generic_msg(node_p here, item_p item, hook_p lasthook); 187static ng_ID_t ng_decodeidname(const char *name); 188static int ngb_mod_event(module_t mod, int event, void *data); 189static void ng_worklist_remove(node_p node); 190static void ngintr(void); | 42 * $Whistle: ng_base.c,v 1.39 1999/01/28 23:54:53 julian Exp $ 43 */ 44 45/* 46 * This file implements the base netgraph code. 47 */ 48 49#include <sys/param.h> --- 133 unchanged lines hidden (view full) --- 183 184/* Internal functions */ 185static int ng_add_hook(node_p node, const char *name, hook_p * hookp); 186static int ng_generic_msg(node_p here, item_p item, hook_p lasthook); 187static ng_ID_t ng_decodeidname(const char *name); 188static int ngb_mod_event(module_t mod, int event, void *data); 189static void ng_worklist_remove(node_p node); 190static void ngintr(void); |
191static int ng_apply_item(node_p node, item_p item); | 191static int ng_apply_item(node_p node, item_p item, int rw); |
192static void ng_flush_input_queue(struct ng_queue * ngq); 193static void ng_setisr(node_p node); 194static node_p ng_ID2noderef(ng_ID_t ID); 195static int ng_con_nodes(node_p node, const char *name, node_p node2, 196 const char *name2); 197static void ng_con_part2(node_p node, hook_p hook, void *arg1, int arg2); 198static void ng_con_part3(node_p node, hook_p hook, void *arg1, int arg2); 199static int ng_mkpeer(node_p node, const char *name, --- 1498 unchanged lines hidden (view full) --- 1698* Input queue handling. 1699* All activities are submitted to the node via the input queue 1700* which implements a multiple-reader/single-writer gate. 1701* Items which cannot be handled immeditly are queued. 1702* 1703* read-write queue locking inline functions * 1704\***************************************************************/ 1705 | 192static void ng_flush_input_queue(struct ng_queue * ngq); 193static void ng_setisr(node_p node); 194static node_p ng_ID2noderef(ng_ID_t ID); 195static int ng_con_nodes(node_p node, const char *name, node_p node2, 196 const char *name2); 197static void ng_con_part2(node_p node, hook_p hook, void *arg1, int arg2); 198static void ng_con_part3(node_p node, hook_p hook, void *arg1, int arg2); 199static int ng_mkpeer(node_p node, const char *name, --- 1498 unchanged lines hidden (view full) --- 1698* Input queue handling. 1699* All activities are submitted to the node via the input queue 1700* which implements a multiple-reader/single-writer gate. 1701* Items which cannot be handled immeditly are queued. 1702* 1703* read-write queue locking inline functions * 1704\***************************************************************/ 1705 |
1706static __inline item_p ng_dequeue(struct ng_queue * ngq); | 1706static __inline item_p ng_dequeue(struct ng_queue * ngq, int *rw); |
1707static __inline item_p ng_acquire_read(struct ng_queue * ngq, 1708 item_p item); 1709static __inline item_p ng_acquire_write(struct ng_queue * ngq, 1710 item_p item); 1711static __inline void ng_leave_read(struct ng_queue * ngq); 1712static __inline void ng_leave_write(struct ng_queue * ngq); 1713static __inline void ng_queue_rw(struct ng_queue * ngq, 1714 item_p item, int rw); --- 42 unchanged lines hidden (view full) --- 1757 1758/* tests to decide if we could get a read or write off the queue */ 1759#define CAN_GET_READ(flag) ((flag & NGQ_RMASK) == READ_PENDING) 1760#define CAN_GET_WRITE(flag) ((flag & NGQ_WMASK) == WRITE_PENDING) 1761 1762/* Is there a chance of getting ANY work off the queue? */ 1763#define CAN_GET_WORK(flag) (CAN_GET_READ(flag) || CAN_GET_WRITE(flag)) 1764 | 1707static __inline item_p ng_acquire_read(struct ng_queue * ngq, 1708 item_p item); 1709static __inline item_p ng_acquire_write(struct ng_queue * ngq, 1710 item_p item); 1711static __inline void ng_leave_read(struct ng_queue * ngq); 1712static __inline void ng_leave_write(struct ng_queue * ngq); 1713static __inline void ng_queue_rw(struct ng_queue * ngq, 1714 item_p item, int rw); --- 42 unchanged lines hidden (view full) --- 1757 1758/* tests to decide if we could get a read or write off the queue */ 1759#define CAN_GET_READ(flag) ((flag & NGQ_RMASK) == READ_PENDING) 1760#define CAN_GET_WRITE(flag) ((flag & NGQ_WMASK) == WRITE_PENDING) 1761 1762/* Is there a chance of getting ANY work off the queue? */ 1763#define CAN_GET_WORK(flag) (CAN_GET_READ(flag) || CAN_GET_WRITE(flag)) 1764 |
1765#define NGQRW_R 0 1766#define NGQRW_W 1 1767 |
|
1765/* 1766 * Taking into account the current state of the queue and node, possibly take 1767 * the next entry off the queue and return it. Return NULL if there was 1768 * nothing we could return, either because there really was nothing there, or 1769 * because the node was in a state where it cannot yet process the next item 1770 * on the queue. 1771 * 1772 * This MUST MUST MUST be called with the mutex held. 1773 */ 1774static __inline item_p | 1768/* 1769 * Taking into account the current state of the queue and node, possibly take 1770 * the next entry off the queue and return it. Return NULL if there was 1771 * nothing we could return, either because there really was nothing there, or 1772 * because the node was in a state where it cannot yet process the next item 1773 * on the queue. 1774 * 1775 * This MUST MUST MUST be called with the mutex held. 1776 */ 1777static __inline item_p |
1775ng_dequeue(struct ng_queue *ngq) | 1778ng_dequeue(struct ng_queue *ngq, int *rw) |
1776{ 1777 item_p item; 1778 u_int add_arg; 1779 1780 mtx_assert(&ngq->q_mtx, MA_OWNED); 1781 1782 if (CAN_GET_READ(ngq->q_flags)) { 1783 /* 1784 * Head of queue is a reader and we have no write active. 1785 * We don't care how many readers are already active. 1786 * Adjust the flags for the item we are about to dequeue. 1787 * Add the correct increment for the reader count as well. 1788 */ 1789 add_arg = (READER_INCREMENT - READ_PENDING); | 1779{ 1780 item_p item; 1781 u_int add_arg; 1782 1783 mtx_assert(&ngq->q_mtx, MA_OWNED); 1784 1785 if (CAN_GET_READ(ngq->q_flags)) { 1786 /* 1787 * Head of queue is a reader and we have no write active. 1788 * We don't care how many readers are already active. 1789 * Adjust the flags for the item we are about to dequeue. 1790 * Add the correct increment for the reader count as well. 1791 */ 1792 add_arg = (READER_INCREMENT - READ_PENDING); |
1793 *rw = NGQRW_R; |
|
1790 } else if (CAN_GET_WRITE(ngq->q_flags)) { 1791 /* 1792 * There is a pending write, no readers and no active writer. 1793 * This means we can go ahead with the pending writer. Note 1794 * the fact that we now have a writer, ready for when we take 1795 * it off the queue. 1796 * 1797 * We don't need to worry about a possible collision with the --- 22 unchanged lines hidden (view full) --- 1820 * would arrive at this function. Usually it will have to 1821 * leave empty handed because the ACTIVE WRITER bit will be 1822 * set. 1823 * 1824 * Adjust the flags for the item we are about to dequeue 1825 * and for the new active writer. 1826 */ 1827 add_arg = (WRITER_ACTIVE - WRITE_PENDING); | 1794 } else if (CAN_GET_WRITE(ngq->q_flags)) { 1795 /* 1796 * There is a pending write, no readers and no active writer. 1797 * This means we can go ahead with the pending writer. Note 1798 * the fact that we now have a writer, ready for when we take 1799 * it off the queue. 1800 * 1801 * We don't need to worry about a possible collision with the --- 22 unchanged lines hidden (view full) --- 1824 * would arrive at this function. Usually it will have to 1825 * leave empty handed because the ACTIVE WRITER bit will be 1826 * set. 1827 * 1828 * Adjust the flags for the item we are about to dequeue 1829 * and for the new active writer. 1830 */ 1831 add_arg = (WRITER_ACTIVE - WRITE_PENDING); |
1832 *rw = NGQRW_W; |
|
1828 /* 1829 * We want to write "active writer, no readers " Now go make 1830 * it true. In fact there may be a number in the readers 1831 * count but we know it is not true and will be fixed soon. 1832 * We will fix the flags for the next pending entry in a 1833 * moment. 1834 */ 1835 } else { --- 27 unchanged lines hidden (view full) --- 1863 * Whatever flag was set will be cleared and 1864 * the new acive field will be set by the add as well, 1865 * so we don't need to change add_arg. 1866 * But we know we don't need to be on the work list. 1867 */ 1868 atomic_add_long(&ngq->q_flags, add_arg); 1869 ng_worklist_remove(ngq->q_node); 1870 } else { | 1833 /* 1834 * We want to write "active writer, no readers " Now go make 1835 * it true. In fact there may be a number in the readers 1836 * count but we know it is not true and will be fixed soon. 1837 * We will fix the flags for the next pending entry in a 1838 * moment. 1839 */ 1840 } else { --- 27 unchanged lines hidden (view full) --- 1868 * Whatever flag was set will be cleared and 1869 * the new acive field will be set by the add as well, 1870 * so we don't need to change add_arg. 1871 * But we know we don't need to be on the work list. 1872 */ 1873 atomic_add_long(&ngq->q_flags, add_arg); 1874 ng_worklist_remove(ngq->q_node); 1875 } else { |
1876 item_p item = ngq->queue; 1877 hook_p hook = NGI_HOOK(item); 1878 node_p node = NGI_NODE(item); 1879 |
|
1871 /* 1872 * Since there is something on the queue, note what it is | 1880 /* 1881 * Since there is something on the queue, note what it is |
1873 * in the flags word. | 1882 * in the flags word. Don't forget about overrides, too. |
1874 */ | 1883 */ |
1875 if ((ngq->queue->el_flags & NGQF_RW) == NGQF_READER) { | 1884 if ((node->nd_flags & NGF_FORCE_WRITER) 1885 || (hook && (hook->hk_flags & HK_FORCE_WRITER))) 1886 add_arg += WRITE_PENDING; 1887 else if ((item->el_flags & NGQF_RW) == NGQF_READER) |
1876 add_arg += READ_PENDING; | 1888 add_arg += READ_PENDING; |
1877 } else { | 1889 else |
1878 add_arg += WRITE_PENDING; | 1890 add_arg += WRITE_PENDING; |
1879 } | 1891 |
1880 atomic_add_long(&ngq->q_flags, add_arg); 1881 /* 1882 * If we see more doable work, make sure we are 1883 * on the work queue. 1884 */ 1885 if (CAN_GET_WORK(ngq->q_flags)) { 1886 ng_setisr(ngq->q_node); 1887 } --- 5 unchanged lines hidden (view full) --- 1893 */ 1894 return (item); 1895} 1896 1897/* 1898 * Queue a packet to be picked up by someone else. 1899 * We really don't care who, but we can't or don't want to hang around 1900 * to process it ourselves. We are probably an interrupt routine.. | 1892 atomic_add_long(&ngq->q_flags, add_arg); 1893 /* 1894 * If we see more doable work, make sure we are 1895 * on the work queue. 1896 */ 1897 if (CAN_GET_WORK(ngq->q_flags)) { 1898 ng_setisr(ngq->q_node); 1899 } --- 5 unchanged lines hidden (view full) --- 1905 */ 1906 return (item); 1907} 1908 1909/* 1910 * Queue a packet to be picked up by someone else. 1911 * We really don't care who, but we can't or don't want to hang around 1912 * to process it ourselves. We are probably an interrupt routine.. |
1901 * 1 = writer, 0 = reader | |
1902 */ | 1913 */ |
1903#define NGQRW_R 0 1904#define NGQRW_W 1 | |
1905static __inline void 1906ng_queue_rw(struct ng_queue * ngq, item_p item, int rw) 1907{ 1908 mtx_assert(&ngq->q_mtx, MA_OWNED); 1909 1910 item->el_next = NULL; /* maybe not needed */ 1911 *ngq->last = item; 1912 /* --- 262 unchanged lines hidden (view full) --- 2175 break; 2176 default: 2177 panic("%s: invalid item flags %lx", __func__, item->el_flags); 2178 } 2179 2180 /* 2181 * If the node specifies single threading, force writer semantics. 2182 * Similarly, the node may say one hook always produces writers. | 1914static __inline void 1915ng_queue_rw(struct ng_queue * ngq, item_p item, int rw) 1916{ 1917 mtx_assert(&ngq->q_mtx, MA_OWNED); 1918 1919 item->el_next = NULL; /* maybe not needed */ 1920 *ngq->last = item; 1921 /* --- 262 unchanged lines hidden (view full) --- 2184 break; 2185 default: 2186 panic("%s: invalid item flags %lx", __func__, item->el_flags); 2187 } 2188 2189 /* 2190 * If the node specifies single threading, force writer semantics. 2191 * Similarly, the node may say one hook always produces writers. |
2183 * These are overrides. Modify the item itself, so that if it 2184 * is queued now, it would be dequeued later with corrected 2185 * read/write flags. | 2192 * These are overrides. |
2186 */ 2187 if ((node->nd_flags & NGF_FORCE_WRITER) | 2193 */ 2194 if ((node->nd_flags & NGF_FORCE_WRITER) |
2188 || (hook && (hook->hk_flags & HK_FORCE_WRITER))) { | 2195 || (hook && (hook->hk_flags & HK_FORCE_WRITER))) |
2189 rw = NGQRW_W; | 2196 rw = NGQRW_W; |
2190 item->el_flags &= ~NGQF_READER; 2191 } | |
2192 2193 if (queue) { 2194 /* Put it on the queue for that node*/ 2195#ifdef NETGRAPH_DEBUG 2196 _ngi_check(item, __FILE__, __LINE__); 2197#endif 2198 mtx_lock_spin(&(ngq->q_mtx)); 2199 ng_queue_rw(ngq, item, rw); --- 49 unchanged lines hidden (view full) --- 2249 _ngi_check(item, __FILE__, __LINE__); 2250#endif 2251 /* 2252 * Take over the reference frm the item. 2253 * Hold it until the called function returns. 2254 */ 2255 NGI_GET_NODE(item, node); /* zaps stored node */ 2256 | 2197 2198 if (queue) { 2199 /* Put it on the queue for that node*/ 2200#ifdef NETGRAPH_DEBUG 2201 _ngi_check(item, __FILE__, __LINE__); 2202#endif 2203 mtx_lock_spin(&(ngq->q_mtx)); 2204 ng_queue_rw(ngq, item, rw); --- 49 unchanged lines hidden (view full) --- 2254 _ngi_check(item, __FILE__, __LINE__); 2255#endif 2256 /* 2257 * Take over the reference frm the item. 2258 * Hold it until the called function returns. 2259 */ 2260 NGI_GET_NODE(item, node); /* zaps stored node */ 2261 |
2257 ierror = ng_apply_item(node, item); /* drops r/w lock when done */ | 2262 ierror = ng_apply_item(node, item, rw); /* drops r/w lock when done */ |
2258 2259 /* only return an error if it was our initial item.. (compat hack) */ 2260 if (oitem == item) { 2261 error = ierror; 2262 } 2263 2264 /* 2265 * If the node goes away when we remove the reference, --- 13 unchanged lines hidden (view full) --- 2279} 2280 2281/* 2282 * We have an item that was possibly queued somewhere. 2283 * It should contain all the information needed 2284 * to run it on the appropriate node/hook. 2285 */ 2286static int | 2263 2264 /* only return an error if it was our initial item.. (compat hack) */ 2265 if (oitem == item) { 2266 error = ierror; 2267 } 2268 2269 /* 2270 * If the node goes away when we remove the reference, --- 13 unchanged lines hidden (view full) --- 2284} 2285 2286/* 2287 * We have an item that was possibly queued somewhere. 2288 * It should contain all the information needed 2289 * to run it on the appropriate node/hook. 2290 */ 2291static int |
2287ng_apply_item(node_p node, item_p item) | 2292ng_apply_item(node_p node, item_p item, int rw) |
2288{ 2289 hook_p hook; | 2293{ 2294 hook_p hook; |
2290 int was_reader = ((item->el_flags & NGQF_RW)); | |
2291 int error = 0; 2292 ng_rcvdata_t *rcvdata; 2293 ng_rcvmsg_t *rcvmsg; 2294 ng_apply_t *apply = NULL; 2295 void *context = NULL; 2296 2297 NGI_GET_HOOK(item, hook); /* clears stored hook */ 2298#ifdef NETGRAPH_DEBUG --- 116 unchanged lines hidden (view full) --- 2415 * We held references on some of the resources 2416 * that we took from the item. Now that we have 2417 * finished doing everything, drop those references. 2418 */ 2419 if (hook) { 2420 NG_HOOK_UNREF(hook); 2421 } 2422 | 2295 int error = 0; 2296 ng_rcvdata_t *rcvdata; 2297 ng_rcvmsg_t *rcvmsg; 2298 ng_apply_t *apply = NULL; 2299 void *context = NULL; 2300 2301 NGI_GET_HOOK(item, hook); /* clears stored hook */ 2302#ifdef NETGRAPH_DEBUG --- 116 unchanged lines hidden (view full) --- 2419 * We held references on some of the resources 2420 * that we took from the item. Now that we have 2421 * finished doing everything, drop those references. 2422 */ 2423 if (hook) { 2424 NG_HOOK_UNREF(hook); 2425 } 2426 |
2423 if (was_reader) { | 2427 if (rw == NGQRW_R) { |
2424 ng_leave_read(&node->nd_input_queue); 2425 } else { 2426 ng_leave_write(&node->nd_input_queue); 2427 } 2428 2429 /* Apply callback. */ 2430 if (apply != NULL) 2431 (*apply)(context, error); --- 787 unchanged lines hidden (view full) --- 3219 * that lets us be sure that the node still exists. 3220 * Let the reference go at the last minute. 3221 * ng_dequeue will put us back on the worklist 3222 * if there is more too do. This may be of use if there 3223 * are Multiple Processors and multiple Net threads in the 3224 * future. 3225 */ 3226 for (;;) { | 2428 ng_leave_read(&node->nd_input_queue); 2429 } else { 2430 ng_leave_write(&node->nd_input_queue); 2431 } 2432 2433 /* Apply callback. */ 2434 if (apply != NULL) 2435 (*apply)(context, error); --- 787 unchanged lines hidden (view full) --- 3223 * that lets us be sure that the node still exists. 3224 * Let the reference go at the last minute. 3225 * ng_dequeue will put us back on the worklist 3226 * if there is more too do. This may be of use if there 3227 * are Multiple Processors and multiple Net threads in the 3228 * future. 3229 */ 3230 for (;;) { |
3231 int rw; 3232 |
|
3227 mtx_lock_spin(&node->nd_input_queue.q_mtx); | 3233 mtx_lock_spin(&node->nd_input_queue.q_mtx); |
3228 item = ng_dequeue(&node->nd_input_queue); | 3234 item = ng_dequeue(&node->nd_input_queue, &rw); |
3229 if (item == NULL) { 3230 mtx_unlock_spin(&node->nd_input_queue.q_mtx); 3231 break; /* go look for another node */ 3232 } else { 3233 mtx_unlock_spin(&node->nd_input_queue.q_mtx); 3234 NGI_GET_NODE(item, node); /* zaps stored node */ | 3235 if (item == NULL) { 3236 mtx_unlock_spin(&node->nd_input_queue.q_mtx); 3237 break; /* go look for another node */ 3238 } else { 3239 mtx_unlock_spin(&node->nd_input_queue.q_mtx); 3240 NGI_GET_NODE(item, node); /* zaps stored node */ |
3235 ng_apply_item(node, item); | 3241 ng_apply_item(node, item, rw); |
3236 NG_NODE_UNREF(node); 3237 } 3238 } 3239 NG_NODE_UNREF(node); 3240 } 3241} 3242 3243static void --- 392 unchanged lines hidden --- | 3242 NG_NODE_UNREF(node); 3243 } 3244 } 3245 NG_NODE_UNREF(node); 3246 } 3247} 3248 3249static void --- 392 unchanged lines hidden --- |