source: mainline/uspace/srv/net/structures/packet/packet.c@ aadf01e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since aadf01e was aadf01e, checked in by Lukas Mejdrech <lukasmejdrech@…>, 15 years ago

Coding style (no functional change)

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup packet
30 * @{
31 */
32
33/** @file
34 * Packet map and queue implementation.
35 * This file has to be compiled with both the packet server and the client.
36 */
37
38#include <errno.h>
39#include <malloc.h>
40#include <mem.h>
41#include <fibril_synch.h>
42//#include <stdio.h>
43#include <unistd.h>
44
45#include <sys/mman.h>
46
47#include "../../err.h"
48
49#include "../generic_field.h"
50
51#include "packet.h"
52#include "packet_header.h"
53
54/** Packet map page size.
55 */
56#define PACKET_MAP_SIZE 100
57
58/** Returns the packet map page index.
59 * @param[in] packet_id The packet identifier.
60 */
61#define PACKET_MAP_PAGE(packet_id) (((packet_id) - 1) / PACKET_MAP_SIZE)
62
63/** Returns the packet index in the corresponding packet map page.
64 * @param[in] packet_id The packet identifier.
65 */
66#define PACKET_MAP_INDEX(packet_id) (((packet_id) - 1) % PACKET_MAP_SIZE)
67
68/** Type definition of the packet map page.
69 */
70typedef packet_t packet_map_t[PACKET_MAP_SIZE];
71/** Type definition of the packet map page pointer.
72 */
73typedef packet_map_t * packet_map_ref;
74
75/** Packet map.
76 * Maps packet identifiers to the packet references.
77 * @see generic_field.h
78 */
79GENERIC_FIELD_DECLARE(gpm, packet_map_t);
80
81/** Releases the packet.
82 * @param[in] packet The packet to be released.
83 * @returns EOK on success.
84 * @returns EINVAL if the packet is not valid.
85 */
86int packet_destroy(packet_t packet);
87
88/** Packet map global data.
89 */
90static struct{
91 /** Safety lock.
92 */
93 fibril_rwlock_t lock;
94 /** Packet map.
95 */
96 gpm_t packet_map;
97} pm_globals;
98
99GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t);
100
101int packet_destroy(packet_t packet){
102 if(! packet_is_valid(packet)){
103 return EINVAL;
104 }
105 return munmap(packet, packet->length);
106}
107
108int pm_init(void){
109 ERROR_DECLARE;
110
111 fibril_rwlock_initialize(&pm_globals.lock);
112 fibril_rwlock_write_lock(&pm_globals.lock);
113 ERROR_PROPAGATE(gpm_initialize(&pm_globals.packet_map));
114 fibril_rwlock_write_unlock(&pm_globals.lock);
115 return EOK;
116}
117
118packet_t pm_find(packet_id_t packet_id){
119 packet_map_ref map;
120 packet_t packet;
121
122 if(! packet_id){
123 return NULL;
124 }
125 fibril_rwlock_read_lock(&pm_globals.lock);
126 if(packet_id > PACKET_MAP_SIZE * gpm_count(&pm_globals.packet_map)){
127 fibril_rwlock_read_unlock(&pm_globals.lock);
128 return NULL;
129 }
130 map = gpm_get_index(&pm_globals.packet_map, PACKET_MAP_PAGE(packet_id));
131 if(! map){
132 fibril_rwlock_read_unlock(&pm_globals.lock);
133 return NULL;
134 }
135 packet = (*map)[PACKET_MAP_INDEX(packet_id)];
136 fibril_rwlock_read_unlock(&pm_globals.lock);
137 return packet;
138}
139
140int pm_add(packet_t packet){
141 ERROR_DECLARE;
142
143 packet_map_ref map;
144
145 if(! packet_is_valid(packet)){
146 return EINVAL;
147 }
148 fibril_rwlock_write_lock(&pm_globals.lock);
149 if(PACKET_MAP_PAGE(packet->packet_id) < gpm_count(&pm_globals.packet_map)){
150 map = gpm_get_index(&pm_globals.packet_map, PACKET_MAP_PAGE(packet->packet_id));
151 }else{
152 do{
153 map = (packet_map_ref) malloc(sizeof(packet_map_t));
154 if(! map){
155 fibril_rwlock_write_unlock(&pm_globals.lock);
156 return ENOMEM;
157 }
158 bzero(map, sizeof(packet_map_t));
159 if((ERROR_CODE = gpm_add(&pm_globals.packet_map, map)) < 0){
160 fibril_rwlock_write_unlock(&pm_globals.lock);
161 free(map);
162 return ERROR_CODE;
163 }
164 }while(PACKET_MAP_PAGE(packet->packet_id) >= gpm_count(&pm_globals.packet_map));
165 }
166 (*map)[PACKET_MAP_INDEX(packet->packet_id)] = packet;
167 fibril_rwlock_write_unlock(&pm_globals.lock);
168 return EOK;
169}
170
171void pm_destroy(void){
172 int count;
173 int index;
174 packet_map_ref map;
175 packet_t packet;
176
177 fibril_rwlock_write_lock(&pm_globals.lock);
178 count = gpm_count(&pm_globals.packet_map);
179 while(count > 0){
180 map = gpm_get_index(&pm_globals.packet_map, count - 1);
181 for(index = PACKET_MAP_SIZE - 1; index >= 0; -- index){
182 packet = (*map)[index];
183 if(packet_is_valid(packet)){
184 munmap(packet, packet->length);
185 }
186 }
187 }
188 gpm_destroy(&pm_globals.packet_map);
189 // leave locked
190}
191
192int pq_add(packet_t * first, packet_t packet, size_t order, size_t metric){
193 packet_t item;
194
195 if((! first) || (! packet_is_valid(packet))){
196 return EINVAL;
197 }
198 pq_set_order(packet, order, metric);
199 if(packet_is_valid(*first)){
200 item = * first;
201 do{
202 if(item->order < order){
203 if(item->next){
204 item = pm_find(item->next);
205 }else{
206 item->next = packet->packet_id;
207 packet->previous = item->packet_id;
208 return EOK;
209 }
210 }else{
211 packet->previous = item->previous;
212 packet->next = item->packet_id;
213 item->previous = packet->packet_id;
214 item = pm_find(packet->previous);
215 if(item){
216 item->next = packet->packet_id;
217 }else{
218 *first = packet;
219 }
220 return EOK;
221 }
222 }while(packet_is_valid(item));
223 }
224 *first = packet;
225 return EOK;
226}
227
228packet_t pq_find(packet_t packet, size_t order){
229 packet_t item;
230
231 if(! packet_is_valid(packet)){
232 return NULL;
233 }
234 if(packet->order == order){
235 return packet;
236 }
237 item = pm_find(packet->next);
238 while(item && (item != packet)){
239 item = pm_find(item->next);
240 if(item->order == order){
241 return item;
242 }
243 }
244 return NULL;
245}
246
247int pq_insert_after(packet_t packet, packet_t new_packet){
248 packet_t item;
249
250 if(!(packet_is_valid(packet) && packet_is_valid(new_packet))){
251 return EINVAL;
252 }
253 new_packet->previous = packet->packet_id;
254 new_packet->next = packet->next;
255 item = pm_find(packet->next);
256 if(item){
257 item->previous = new_packet->packet_id;
258 }
259 packet->next = new_packet->packet_id;
260 return EOK;
261}
262
263packet_t pq_detach(packet_t packet){
264 packet_t next;
265 packet_t previous;
266
267 if(! packet_is_valid(packet)){
268 return NULL;
269 }
270 next = pm_find(packet->next);
271 if(next){
272 next->previous = packet->previous;
273 previous = pm_find(next->previous);
274 if(previous){
275 previous->next = next->packet_id;
276 }
277 }
278 packet->previous = 0;
279 packet->next = 0;
280 return next;
281}
282
283int pq_set_order(packet_t packet, size_t order, size_t metric){
284 if(! packet_is_valid(packet)){
285 return EINVAL;
286 }
287 packet->order = order;
288 packet->metric = metric;
289 return EOK;
290}
291
292int pq_get_order(packet_t packet, size_t * order, size_t * metric){
293 if(! packet_is_valid(packet)){
294 return EINVAL;
295 }
296 if(order){
297 *order = packet->order;
298 }
299 if(metric){
300 *metric = packet->metric;
301 }
302 return EOK;
303}
304
305void pq_destroy(packet_t first, void (*packet_release)(packet_t packet)){
306 packet_t actual;
307 packet_t next;
308
309 actual = first;
310 while(packet_is_valid(actual)){
311 next = pm_find(actual->next);
312 actual->next = 0;
313 actual->previous = 0;
314 if(packet_release){
315 packet_release(actual);
316 }
317 actual = next;
318 }
319}
320
321packet_t pq_next(packet_t packet){
322 if(! packet_is_valid(packet)){
323 return NULL;
324 }
325 return pm_find(packet->next);
326}
327
328packet_t pq_previous(packet_t packet){
329 if(! packet_is_valid(packet)){
330 return NULL;
331 }
332 return pm_find(packet->previous);
333}
334
335/** @}
336 */
Note: See TracBrowser for help on using the repository browser.