1 /*
2 * TCP free fragment queue for ring buffer - tcp_rb_frag_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_rb_frag_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 rb_frag_queue
34 {
35 index_type _capacity;
36 volatile index_type _head;
37 volatile index_type _tail;
38
39 struct fragment_ctx * volatile * _q;
40 };
41 /*----------------------------------------------------------------------------*/
42 static inline index_type
NextIndex(rb_frag_queue_t rb_fragq,index_type i)43 NextIndex(rb_frag_queue_t rb_fragq, index_type i)
44 {
45 return (i != rb_fragq->_capacity ? i + 1: 0);
46 }
47 /*---------------------------------------------------------------------------*/
48 static inline index_type
PrevIndex(rb_frag_queue_t rb_fragq,index_type i)49 PrevIndex(rb_frag_queue_t rb_fragq, index_type i)
50 {
51 return (i != 0 ? i - 1: rb_fragq->_capacity);
52 }
53 /*---------------------------------------------------------------------------*/
54 static inline void
RBFragMemoryBarrier(struct fragment_ctx * volatile frag,volatile index_type index)55 RBFragMemoryBarrier(struct fragment_ctx * volatile frag, volatile index_type index)
56 {
57 __asm__ volatile("" : : "m" (frag), "m" (index));
58 }
59 /*---------------------------------------------------------------------------*/
60 rb_frag_queue_t
CreateRBFragQueue(int capacity)61 CreateRBFragQueue(int capacity)
62 {
63 rb_frag_queue_t rb_fragq;
64
65 rb_fragq = (rb_frag_queue_t)calloc(1, sizeof(struct rb_frag_queue));
66 if (!rb_fragq)
67 return NULL;
68
69 rb_fragq->_q = (struct fragment_ctx **)
70 calloc(capacity + 1, sizeof(struct fragment_ctx *));
71 if (!rb_fragq->_q) {
72 free(rb_fragq);
73 return NULL;
74 }
75
76 rb_fragq->_capacity = capacity;
77 rb_fragq->_head = rb_fragq->_tail = 0;
78
79 return rb_fragq;
80 }
81 /*---------------------------------------------------------------------------*/
82 void
DestroyRBFragQueue(rb_frag_queue_t rb_fragq)83 DestroyRBFragQueue(rb_frag_queue_t rb_fragq)
84 {
85 if (!rb_fragq)
86 return;
87
88 if (rb_fragq->_q) {
89 free((void *)rb_fragq->_q);
90 rb_fragq->_q = NULL;
91 }
92
93 free(rb_fragq);
94 }
95 /*---------------------------------------------------------------------------*/
96 int
RBFragEnqueue(rb_frag_queue_t rb_fragq,struct fragment_ctx * frag)97 RBFragEnqueue(rb_frag_queue_t rb_fragq, struct fragment_ctx *frag)
98 {
99 index_type h = rb_fragq->_head;
100 index_type t = rb_fragq->_tail;
101 index_type nt = NextIndex(rb_fragq, t);
102
103 if (nt != h) {
104 rb_fragq->_q[t] = frag;
105 RBFragMemoryBarrier(rb_fragq->_q[t], rb_fragq->_tail);
106 rb_fragq->_tail = nt;
107 return 0;
108 }
109
110 TRACE_ERROR("Exceed capacity of frag queue!\n");
111 return -1;
112 }
113 /*---------------------------------------------------------------------------*/
114 struct fragment_ctx *
RBFragDequeue(rb_frag_queue_t rb_fragq)115 RBFragDequeue(rb_frag_queue_t rb_fragq)
116 {
117 index_type h = rb_fragq->_head;
118 index_type t = rb_fragq->_tail;
119
120 if (h != t) {
121 struct fragment_ctx *frag = rb_fragq->_q[h];
122 RBFragMemoryBarrier(rb_fragq->_q[h], rb_fragq->_head);
123 rb_fragq->_head = NextIndex(rb_fragq, h);
124 assert(frag);
125
126 return frag;
127 }
128
129 return NULL;
130 }
131 /*---------------------------------------------------------------------------*/
132