1 /* 2 * TCP free send buffer queue - tcp_sb_queue.c/h 3 * 4 * EunYoung Jeong 5 * 6 * Part of this code borrows Click's simple queue implementation 7 * 8 * ============================== Click License ============================= 9 * 10 * Copyright (c) 1999-2000 Massachusetts Institute of Technology 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a 13 * copy of this software and associated documentation files (the "Software"), 14 * to deal in the Software without restriction, subject to the conditions 15 * listed in the Click LICENSE file. These conditions include: you must 16 * preserve this copyright notice, and you cannot mention the copyright 17 * holders in advertising related to the Software without their permission. 18 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 19 * notice is a summary of the Click LICENSE file; the license in that file is 20 * legally binding. 21 */ 22 23 #include "tcp_sb_queue.h" 24 #include "debug.h" 25 26 /*----------------------------------------------------------------------------*/ 27 #ifndef _INDEX_TYPE_ 28 #define _INDEX_TYPE_ 29 typedef uint32_t index_type; 30 typedef int32_t signed_index_type; 31 #endif 32 /*---------------------------------------------------------------------------*/ 33 struct sb_queue 34 { 35 index_type _capacity; 36 volatile index_type _head; 37 volatile index_type _tail; 38 39 struct tcp_send_buffer * volatile * _q; 40 }; 41 /*----------------------------------------------------------------------------*/ 42 static inline index_type 43 NextIndex(sb_queue_t sq, index_type i) 44 { 45 return (i != sq->_capacity ? i + 1: 0); 46 } 47 /*---------------------------------------------------------------------------*/ 48 static inline index_type 49 PrevIndex(sb_queue_t sq, index_type i) 50 { 51 return (i != 0 ? i - 1: sq->_capacity); 52 } 53 /*---------------------------------------------------------------------------*/ 54 static inline void 55 SBMemoryBarrier(struct tcp_send_buffer * volatile buf, volatile index_type index) 56 { 57 __asm__ volatile("" : : "m" (buf), "m" (index)); 58 } 59 /*---------------------------------------------------------------------------*/ 60 sb_queue_t 61 CreateSBQueue(int capacity) 62 { 63 sb_queue_t sq; 64 65 sq = (sb_queue_t)calloc(1, sizeof(struct sb_queue)); 66 if (!sq) 67 return NULL; 68 69 sq->_q = (struct tcp_send_buffer **) 70 calloc(capacity + 1, sizeof(struct tcp_send_buffer *)); 71 if (!sq->_q) { 72 free(sq); 73 return NULL; 74 } 75 76 sq->_capacity = capacity; 77 sq->_head = sq->_tail = 0; 78 79 return sq; 80 } 81 /*---------------------------------------------------------------------------*/ 82 void 83 DestroySBQueue(sb_queue_t sq) 84 { 85 if (!sq) 86 return; 87 88 if (sq->_q) { 89 free((void *)sq->_q); 90 sq->_q = NULL; 91 } 92 93 free(sq); 94 } 95 /*---------------------------------------------------------------------------*/ 96 int 97 SBEnqueue(sb_queue_t sq, struct tcp_send_buffer *buf) 98 { 99 index_type h = sq->_head; 100 index_type t = sq->_tail; 101 index_type nt = NextIndex(sq, t); 102 103 if (nt != h) { 104 sq->_q[t] = buf; 105 SBMemoryBarrier(sq->_q[t], sq->_tail); 106 sq->_tail = nt; 107 return 0; 108 } 109 110 TRACE_ERROR("Exceed capacity of buf queue!\n"); 111 return -1; 112 } 113 /*---------------------------------------------------------------------------*/ 114 struct tcp_send_buffer * 115 SBDequeue(sb_queue_t sq) 116 { 117 index_type h = sq->_head; 118 index_type t = sq->_tail; 119 120 if (h != t) { 121 struct tcp_send_buffer *buf = sq->_q[h]; 122 SBMemoryBarrier(sq->_q[h], sq->_head); 123 sq->_head = NextIndex(sq, h); 124 assert(buf); 125 126 return buf; 127 } 128 129 return NULL; 130 } 131 /*---------------------------------------------------------------------------*/ 132