blob: 00b48b657ee08138c97d23d94df5d9dfef019922 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/fifobuf.h>
20#include <pj/log.h>
21#include <pj/assert.h>
22#include <pj/os.h>
23
24#define THIS_FILE "fifobuf"
25
26#define SZ sizeof(unsigned)
27
28PJ_DEF(void)
29pj_fifobuf_init (pj_fifobuf_t *fifobuf, void *buffer, unsigned size)
30{
31 PJ_CHECK_STACK();
32
33 PJ_LOG(6, (THIS_FILE,
34 "fifobuf_init fifobuf=%p buffer=%p, size=%d",
35 fifobuf, buffer, size));
36
37 fifobuf->first = buffer;
38 fifobuf->last = fifobuf->first + size;
39 fifobuf->ubegin = fifobuf->uend = fifobuf->first;
40 fifobuf->full = 0;
41}
42
43PJ_DEF(unsigned)
44pj_fifobuf_max_size (pj_fifobuf_t *fifobuf)
45{
46 unsigned s1, s2;
47
48 PJ_CHECK_STACK();
49
50 if (fifobuf->uend >= fifobuf->ubegin) {
51 s1 = fifobuf->last - fifobuf->uend;
52 s2 = fifobuf->ubegin - fifobuf->first;
53 } else {
54 s1 = s2 = fifobuf->ubegin - fifobuf->uend;
55 }
56
57 return s1<s2 ? s2 : s1;
58}
59
60PJ_DEF(void*)
61pj_fifobuf_alloc (pj_fifobuf_t *fifobuf, unsigned size)
62{
63 unsigned available;
64 char *start;
65
66 PJ_CHECK_STACK();
67
68 if (fifobuf->full) {
69 PJ_LOG(6, (THIS_FILE,
70 "fifobuf_alloc fifobuf=%p, size=%d: full!",
71 fifobuf, size));
72 return NULL;
73 }
74
75 /* try to allocate from the end part of the fifo */
76 if (fifobuf->uend >= fifobuf->ubegin) {
77 available = fifobuf->last - fifobuf->uend;
78 if (available >= size+SZ) {
79 char *ptr = fifobuf->uend;
80 fifobuf->uend += (size+SZ);
81 if (fifobuf->uend == fifobuf->last)
82 fifobuf->uend = fifobuf->first;
83 if (fifobuf->uend == fifobuf->ubegin)
84 fifobuf->full = 1;
85 *(unsigned*)ptr = size+SZ;
86 ptr += SZ;
87
88 PJ_LOG(6, (THIS_FILE,
89 "fifobuf_alloc fifobuf=%p, size=%d: returning %p, p1=%p, p2=%p",
90 fifobuf, size, ptr, fifobuf->ubegin, fifobuf->uend));
91 return ptr;
92 }
93 }
94
95 /* try to allocate from the start part of the fifo */
96 start = (fifobuf->uend <= fifobuf->ubegin) ? fifobuf->uend : fifobuf->first;
97 available = fifobuf->ubegin - start;
98 if (available >= size+SZ) {
99 char *ptr = start;
100 fifobuf->uend = start + size + SZ;
101 if (fifobuf->uend == fifobuf->ubegin)
102 fifobuf->full = 1;
103 *(unsigned*)ptr = size+SZ;
104 ptr += SZ;
105
106 PJ_LOG(6, (THIS_FILE,
107 "fifobuf_alloc fifobuf=%p, size=%d: returning %p, p1=%p, p2=%p",
108 fifobuf, size, ptr, fifobuf->ubegin, fifobuf->uend));
109 return ptr;
110 }
111
112 PJ_LOG(6, (THIS_FILE,
113 "fifobuf_alloc fifobuf=%p, size=%d: no space left! p1=%p, p2=%p",
114 fifobuf, size, fifobuf->ubegin, fifobuf->uend));
115 return NULL;
116}
117
118PJ_DEF(pj_status_t)
119pj_fifobuf_unalloc (pj_fifobuf_t *fifobuf, void *buf)
120{
121 char *ptr = buf;
122 char *endptr;
123 unsigned sz;
124
125 PJ_CHECK_STACK();
126
127 ptr -= SZ;
128 sz = *(unsigned*)ptr;
129
130 endptr = fifobuf->uend;
131 if (endptr == fifobuf->first)
132 endptr = fifobuf->last;
133
134 if (ptr+sz != endptr) {
135 pj_assert(!"Invalid pointer to undo alloc");
136 return -1;
137 }
138
139 fifobuf->uend = ptr;
140 fifobuf->full = 0;
141
142 PJ_LOG(6, (THIS_FILE,
143 "fifobuf_unalloc fifobuf=%p, ptr=%p, size=%d, p1=%p, p2=%p",
144 fifobuf, buf, sz, fifobuf->ubegin, fifobuf->uend));
145
146 return 0;
147}
148
149PJ_DEF(pj_status_t)
150pj_fifobuf_free (pj_fifobuf_t *fifobuf, void *buf)
151{
152 char *ptr = buf;
153 char *end;
154 unsigned sz;
155
156 PJ_CHECK_STACK();
157
158 ptr -= SZ;
159 if (ptr < fifobuf->first || ptr >= fifobuf->last) {
160 pj_assert(!"Invalid pointer to free");
161 return -1;
162 }
163
164 if (ptr != fifobuf->ubegin && ptr != fifobuf->first) {
165 pj_assert(!"Invalid free() sequence!");
166 return -1;
167 }
168
169 end = (fifobuf->uend > fifobuf->ubegin) ? fifobuf->uend : fifobuf->last;
170 sz = *(unsigned*)ptr;
171 if (ptr+sz > end) {
172 pj_assert(!"Invalid size!");
173 return -1;
174 }
175
176 fifobuf->ubegin = ptr + sz;
177
178 /* Rollover */
179 if (fifobuf->ubegin == fifobuf->last)
180 fifobuf->ubegin = fifobuf->first;
181
182 /* Reset if fifobuf is empty */
183 if (fifobuf->ubegin == fifobuf->uend)
184 fifobuf->ubegin = fifobuf->uend = fifobuf->first;
185
186 fifobuf->full = 0;
187
188 PJ_LOG(6, (THIS_FILE,
189 "fifobuf_free fifobuf=%p, ptr=%p, size=%d, p1=%p, p2=%p",
190 fifobuf, buf, sz, fifobuf->ubegin, fifobuf->uend));
191
192 return 0;
193}