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