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