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
RevLine 
[21580dd]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 */
[aadf01e]61#define PACKET_MAP_PAGE(packet_id) (((packet_id) - 1) / PACKET_MAP_SIZE)
[21580dd]62
63/** Returns the packet index in the corresponding packet map page.
64 * @param[in] packet_id The packet identifier.
65 */
[aadf01e]66#define PACKET_MAP_INDEX(packet_id) (((packet_id) - 1) % PACKET_MAP_SIZE)
[21580dd]67
68/** Type definition of the packet map page.
69 */
[aadf01e]70typedef packet_t packet_map_t[PACKET_MAP_SIZE];
[21580dd]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 */
[aadf01e]79GENERIC_FIELD_DECLARE(gpm, packet_map_t);
[21580dd]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 */
[aadf01e]86int packet_destroy(packet_t packet);
[21580dd]87
88/** Packet map global data.
89 */
90static struct{
91 /** Safety lock.
92 */
[aadf01e]93 fibril_rwlock_t lock;
[21580dd]94 /** Packet map.
95 */
[aadf01e]96 gpm_t packet_map;
[21580dd]97} pm_globals;
98
[aadf01e]99GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t);
[21580dd]100
[aadf01e]101int packet_destroy(packet_t packet){
102 if(! packet_is_valid(packet)){
103 return EINVAL;
104 }
105 return munmap(packet, packet->length);
[21580dd]106}
107
[aadf01e]108int pm_init(void){
[21580dd]109 ERROR_DECLARE;
110
[aadf01e]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);
[21580dd]115 return EOK;
116}
117
[aadf01e]118packet_t pm_find(packet_id_t packet_id){
[21580dd]119 packet_map_ref map;
120 packet_t packet;
121
[aadf01e]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);
[21580dd]128 return NULL;
129 }
[aadf01e]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);
[21580dd]133 return NULL;
134 }
[aadf01e]135 packet = (*map)[PACKET_MAP_INDEX(packet_id)];
136 fibril_rwlock_read_unlock(&pm_globals.lock);
[21580dd]137 return packet;
138}
139
[aadf01e]140int pm_add(packet_t packet){
[21580dd]141 ERROR_DECLARE;
142
143 packet_map_ref map;
144
[aadf01e]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));
[21580dd]151 }else{
152 do{
[aadf01e]153 map = (packet_map_ref) malloc(sizeof(packet_map_t));
154 if(! map){
155 fibril_rwlock_write_unlock(&pm_globals.lock);
[21580dd]156 return ENOMEM;
157 }
[aadf01e]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);
[21580dd]162 return ERROR_CODE;
163 }
[aadf01e]164 }while(PACKET_MAP_PAGE(packet->packet_id) >= gpm_count(&pm_globals.packet_map));
[21580dd]165 }
[aadf01e]166 (*map)[PACKET_MAP_INDEX(packet->packet_id)] = packet;
167 fibril_rwlock_write_unlock(&pm_globals.lock);
[21580dd]168 return EOK;
169}
170
[aadf01e]171void pm_destroy(void){
[21580dd]172 int count;
173 int index;
174 packet_map_ref map;
175 packet_t packet;
176
[aadf01e]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);
[21580dd]185 }
186 }
187 }
[aadf01e]188 gpm_destroy(&pm_globals.packet_map);
[21580dd]189 // leave locked
190}
191
[aadf01e]192int pq_add(packet_t * first, packet_t packet, size_t order, size_t metric){
193 packet_t item;
[21580dd]194
[aadf01e]195 if((! first) || (! packet_is_valid(packet))){
196 return EINVAL;
197 }
198 pq_set_order(packet, order, metric);
199 if(packet_is_valid(*first)){
[1e2e0c1e]200 item = * first;
[21580dd]201 do{
[aadf01e]202 if(item->order < order){
203 if(item->next){
204 item = pm_find(item->next);
[21580dd]205 }else{
206 item->next = packet->packet_id;
207 packet->previous = item->packet_id;
[1e2e0c1e]208 return EOK;
[21580dd]209 }
210 }else{
211 packet->previous = item->previous;
212 packet->next = item->packet_id;
213 item->previous = packet->packet_id;
[aadf01e]214 item = pm_find(packet->previous);
215 if(item){
[1e2e0c1e]216 item->next = packet->packet_id;
217 }else{
[aadf01e]218 *first = packet;
[1e2e0c1e]219 }
220 return EOK;
[21580dd]221 }
[aadf01e]222 }while(packet_is_valid(item));
[21580dd]223 }
[aadf01e]224 *first = packet;
[1e2e0c1e]225 return EOK;
[21580dd]226}
227
[aadf01e]228packet_t pq_find(packet_t packet, size_t order){
229 packet_t item;
[21580dd]230
[aadf01e]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){
[21580dd]241 return item;
242 }
243 }
244 return NULL;
245}
246
[aadf01e]247int pq_insert_after(packet_t packet, packet_t new_packet){
248 packet_t item;
[21580dd]249
[aadf01e]250 if(!(packet_is_valid(packet) && packet_is_valid(new_packet))){
251 return EINVAL;
252 }
[21580dd]253 new_packet->previous = packet->packet_id;
254 new_packet->next = packet->next;
[aadf01e]255 item = pm_find(packet->next);
256 if(item){
257 item->previous = new_packet->packet_id;
258 }
[21580dd]259 packet->next = new_packet->packet_id;
260 return EOK;
261}
262
[aadf01e]263packet_t pq_detach(packet_t packet){
[21580dd]264 packet_t next;
265 packet_t previous;
266
[aadf01e]267 if(! packet_is_valid(packet)){
268 return NULL;
269 }
270 next = pm_find(packet->next);
271 if(next){
[21580dd]272 next->previous = packet->previous;
[aadf01e]273 previous = pm_find(next->previous);
274 if(previous){
[21580dd]275 previous->next = next->packet_id;
276 }
277 }
278 packet->previous = 0;
279 packet->next = 0;
280 return next;
281}
282
[aadf01e]283int pq_set_order(packet_t packet, size_t order, size_t metric){
284 if(! packet_is_valid(packet)){
285 return EINVAL;
286 }
[21580dd]287 packet->order = order;
288 packet->metric = metric;
289 return EOK;
290}
291
[aadf01e]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 }
[21580dd]302 return EOK;
303}
304
[aadf01e]305void pq_destroy(packet_t first, void (*packet_release)(packet_t packet)){
306 packet_t actual;
307 packet_t next;
[21580dd]308
309 actual = first;
[aadf01e]310 while(packet_is_valid(actual)){
311 next = pm_find(actual->next);
[21580dd]312 actual->next = 0;
313 actual->previous = 0;
[aadf01e]314 if(packet_release){
315 packet_release(actual);
316 }
[21580dd]317 actual = next;
318 }
319}
320
[aadf01e]321packet_t pq_next(packet_t packet){
322 if(! packet_is_valid(packet)){
323 return NULL;
324 }
325 return pm_find(packet->next);
[21580dd]326}
327
[aadf01e]328packet_t pq_previous(packet_t packet){
329 if(! packet_is_valid(packet)){
330 return NULL;
331 }
332 return pm_find(packet->previous);
[21580dd]333}
334
335/** @}
336 */
Note: See TracBrowser for help on using the repository browser.