source: mainline/uspace/lib/socket/packet/packet.c@ 849ed54

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 849ed54 was 849ed54, checked in by Martin Decky <martin@…>, 15 years ago

Networking work:
Split the networking stack into end-user library (libsocket) and two helper libraries (libnet and libnetif).
Don't use over-the-hand compiling and linking, but rather separation of conserns.
There might be still some issues and the non-modular networking architecture is currently broken, but this will be fixed soon.

  • Property mode set to 100644
File size: 7.9 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 <unistd.h>
43
44#include <sys/mman.h>
45
[849ed54]46#include <net_err.h>
47#include <adt/generic_field.h>
48#include <packet/packet.h>
49#include <packet/packet_header.h>
[21580dd]50
51/** Packet map page size.
52 */
53#define PACKET_MAP_SIZE 100
54
55/** Returns the packet map page index.
56 * @param[in] packet_id The packet identifier.
57 */
[aadf01e]58#define PACKET_MAP_PAGE(packet_id) (((packet_id) - 1) / PACKET_MAP_SIZE)
[21580dd]59
60/** Returns the packet index in the corresponding packet map page.
61 * @param[in] packet_id The packet identifier.
62 */
[aadf01e]63#define PACKET_MAP_INDEX(packet_id) (((packet_id) - 1) % PACKET_MAP_SIZE)
[21580dd]64
65/** Type definition of the packet map page.
66 */
[aadf01e]67typedef packet_t packet_map_t[PACKET_MAP_SIZE];
[21580dd]68/** Type definition of the packet map page pointer.
69 */
70typedef packet_map_t * packet_map_ref;
71
72/** Packet map.
73 * Maps packet identifiers to the packet references.
74 * @see generic_field.h
75 */
[aadf01e]76GENERIC_FIELD_DECLARE(gpm, packet_map_t);
[21580dd]77
78/** Releases the packet.
79 * @param[in] packet The packet to be released.
80 * @returns EOK on success.
81 * @returns EINVAL if the packet is not valid.
82 */
[aadf01e]83int packet_destroy(packet_t packet);
[21580dd]84
85/** Packet map global data.
86 */
87static struct{
88 /** Safety lock.
89 */
[aadf01e]90 fibril_rwlock_t lock;
[21580dd]91 /** Packet map.
92 */
[aadf01e]93 gpm_t packet_map;
[21580dd]94} pm_globals;
95
[aadf01e]96GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t);
[21580dd]97
[aadf01e]98int packet_destroy(packet_t packet){
99 if(! packet_is_valid(packet)){
100 return EINVAL;
101 }
102 return munmap(packet, packet->length);
[21580dd]103}
104
[aadf01e]105int pm_init(void){
[21580dd]106 ERROR_DECLARE;
107
[aadf01e]108 fibril_rwlock_initialize(&pm_globals.lock);
109 fibril_rwlock_write_lock(&pm_globals.lock);
110 ERROR_PROPAGATE(gpm_initialize(&pm_globals.packet_map));
111 fibril_rwlock_write_unlock(&pm_globals.lock);
[21580dd]112 return EOK;
113}
114
[aadf01e]115packet_t pm_find(packet_id_t packet_id){
[21580dd]116 packet_map_ref map;
117 packet_t packet;
118
[aadf01e]119 if(! packet_id){
120 return NULL;
121 }
122 fibril_rwlock_read_lock(&pm_globals.lock);
123 if(packet_id > PACKET_MAP_SIZE * gpm_count(&pm_globals.packet_map)){
124 fibril_rwlock_read_unlock(&pm_globals.lock);
[21580dd]125 return NULL;
126 }
[aadf01e]127 map = gpm_get_index(&pm_globals.packet_map, PACKET_MAP_PAGE(packet_id));
128 if(! map){
129 fibril_rwlock_read_unlock(&pm_globals.lock);
[21580dd]130 return NULL;
131 }
[aadf01e]132 packet = (*map)[PACKET_MAP_INDEX(packet_id)];
133 fibril_rwlock_read_unlock(&pm_globals.lock);
[21580dd]134 return packet;
135}
136
[aadf01e]137int pm_add(packet_t packet){
[21580dd]138 ERROR_DECLARE;
139
140 packet_map_ref map;
141
[aadf01e]142 if(! packet_is_valid(packet)){
143 return EINVAL;
144 }
145 fibril_rwlock_write_lock(&pm_globals.lock);
146 if(PACKET_MAP_PAGE(packet->packet_id) < gpm_count(&pm_globals.packet_map)){
147 map = gpm_get_index(&pm_globals.packet_map, PACKET_MAP_PAGE(packet->packet_id));
[21580dd]148 }else{
149 do{
[aadf01e]150 map = (packet_map_ref) malloc(sizeof(packet_map_t));
151 if(! map){
152 fibril_rwlock_write_unlock(&pm_globals.lock);
[21580dd]153 return ENOMEM;
154 }
[aadf01e]155 bzero(map, sizeof(packet_map_t));
156 if((ERROR_CODE = gpm_add(&pm_globals.packet_map, map)) < 0){
157 fibril_rwlock_write_unlock(&pm_globals.lock);
158 free(map);
[21580dd]159 return ERROR_CODE;
160 }
[aadf01e]161 }while(PACKET_MAP_PAGE(packet->packet_id) >= gpm_count(&pm_globals.packet_map));
[21580dd]162 }
[aadf01e]163 (*map)[PACKET_MAP_INDEX(packet->packet_id)] = packet;
164 fibril_rwlock_write_unlock(&pm_globals.lock);
[21580dd]165 return EOK;
166}
167
[aadf01e]168void pm_destroy(void){
[21580dd]169 int count;
170 int index;
171 packet_map_ref map;
172 packet_t packet;
173
[aadf01e]174 fibril_rwlock_write_lock(&pm_globals.lock);
175 count = gpm_count(&pm_globals.packet_map);
176 while(count > 0){
177 map = gpm_get_index(&pm_globals.packet_map, count - 1);
178 for(index = PACKET_MAP_SIZE - 1; index >= 0; -- index){
179 packet = (*map)[index];
180 if(packet_is_valid(packet)){
181 munmap(packet, packet->length);
[21580dd]182 }
183 }
184 }
[aadf01e]185 gpm_destroy(&pm_globals.packet_map);
[21580dd]186 // leave locked
187}
188
[aadf01e]189int pq_add(packet_t * first, packet_t packet, size_t order, size_t metric){
190 packet_t item;
[21580dd]191
[aadf01e]192 if((! first) || (! packet_is_valid(packet))){
193 return EINVAL;
194 }
195 pq_set_order(packet, order, metric);
196 if(packet_is_valid(*first)){
[1e2e0c1e]197 item = * first;
[21580dd]198 do{
[aadf01e]199 if(item->order < order){
200 if(item->next){
201 item = pm_find(item->next);
[21580dd]202 }else{
203 item->next = packet->packet_id;
204 packet->previous = item->packet_id;
[1e2e0c1e]205 return EOK;
[21580dd]206 }
207 }else{
208 packet->previous = item->previous;
209 packet->next = item->packet_id;
210 item->previous = packet->packet_id;
[aadf01e]211 item = pm_find(packet->previous);
212 if(item){
[1e2e0c1e]213 item->next = packet->packet_id;
214 }else{
[aadf01e]215 *first = packet;
[1e2e0c1e]216 }
217 return EOK;
[21580dd]218 }
[aadf01e]219 }while(packet_is_valid(item));
[21580dd]220 }
[aadf01e]221 *first = packet;
[1e2e0c1e]222 return EOK;
[21580dd]223}
224
[aadf01e]225packet_t pq_find(packet_t packet, size_t order){
226 packet_t item;
[21580dd]227
[aadf01e]228 if(! packet_is_valid(packet)){
229 return NULL;
230 }
[31c80a5]231 item = packet;
232 do{
[aadf01e]233 if(item->order == order){
[21580dd]234 return item;
235 }
[31c80a5]236 item = pm_find(item->next);
237 }while(item && (item != packet) && packet_is_valid(item));
[21580dd]238 return NULL;
239}
240
[aadf01e]241int pq_insert_after(packet_t packet, packet_t new_packet){
242 packet_t item;
[21580dd]243
[aadf01e]244 if(!(packet_is_valid(packet) && packet_is_valid(new_packet))){
245 return EINVAL;
246 }
[21580dd]247 new_packet->previous = packet->packet_id;
248 new_packet->next = packet->next;
[aadf01e]249 item = pm_find(packet->next);
250 if(item){
251 item->previous = new_packet->packet_id;
252 }
[21580dd]253 packet->next = new_packet->packet_id;
254 return EOK;
255}
256
[aadf01e]257packet_t pq_detach(packet_t packet){
[21580dd]258 packet_t next;
259 packet_t previous;
260
[aadf01e]261 if(! packet_is_valid(packet)){
262 return NULL;
263 }
264 next = pm_find(packet->next);
265 if(next){
[21580dd]266 next->previous = packet->previous;
[aadf01e]267 previous = pm_find(next->previous);
268 if(previous){
[21580dd]269 previous->next = next->packet_id;
270 }
271 }
272 packet->previous = 0;
273 packet->next = 0;
274 return next;
275}
276
[aadf01e]277int pq_set_order(packet_t packet, size_t order, size_t metric){
278 if(! packet_is_valid(packet)){
279 return EINVAL;
280 }
[21580dd]281 packet->order = order;
282 packet->metric = metric;
283 return EOK;
284}
285
[aadf01e]286int pq_get_order(packet_t packet, size_t * order, size_t * metric){
287 if(! packet_is_valid(packet)){
288 return EINVAL;
289 }
290 if(order){
291 *order = packet->order;
292 }
293 if(metric){
294 *metric = packet->metric;
295 }
[21580dd]296 return EOK;
297}
298
[aadf01e]299void pq_destroy(packet_t first, void (*packet_release)(packet_t packet)){
300 packet_t actual;
301 packet_t next;
[21580dd]302
303 actual = first;
[aadf01e]304 while(packet_is_valid(actual)){
305 next = pm_find(actual->next);
[21580dd]306 actual->next = 0;
307 actual->previous = 0;
[aadf01e]308 if(packet_release){
309 packet_release(actual);
310 }
[21580dd]311 actual = next;
312 }
313}
314
[aadf01e]315packet_t pq_next(packet_t packet){
316 if(! packet_is_valid(packet)){
317 return NULL;
318 }
319 return pm_find(packet->next);
[21580dd]320}
321
[aadf01e]322packet_t pq_previous(packet_t packet){
323 if(! packet_is_valid(packet)){
324 return NULL;
325 }
326 return pm_find(packet->previous);
[21580dd]327}
328
329/** @}
330 */
Note: See TracBrowser for help on using the repository browser.