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
NextIndex(sb_queue_t sq,index_type i)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
PrevIndex(sb_queue_t sq,index_type i)49 PrevIndex(sb_queue_t sq, index_type i)
50 {
51 	return (i != 0 ? i - 1: sq->_capacity);
52 }
53 /*---------------------------------------------------------------------------*/
54 static inline void
SBMemoryBarrier(struct tcp_send_buffer * volatile buf,volatile index_type index)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
CreateSBQueue(int capacity)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
DestroySBQueue(sb_queue_t sq)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
SBEnqueue(sb_queue_t sq,struct tcp_send_buffer * buf)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 *
SBDequeue(sb_queue_t sq)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