00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <malloc.h>
00039 #include <mem.h>
00040 #include <fibril_synch.h>
00041 #include <unistd.h>
00042 #include <errno.h>
00043
00044 #include <sys/mman.h>
00045
00046 #include <adt/generic_field.h>
00047 #include <net/packet.h>
00048 #include <net/packet_header.h>
00049
00051 #define PACKET_MAP_SIZE 100
00052
00056 #define PACKET_MAP_PAGE(packet_id) (((packet_id) - 1) / PACKET_MAP_SIZE)
00057
00061 #define PACKET_MAP_INDEX(packet_id) (((packet_id) - 1) % PACKET_MAP_SIZE)
00062
00064 typedef packet_t *packet_map_t[PACKET_MAP_SIZE];
00065
00070 GENERIC_FIELD_DECLARE(gpm, packet_map_t);
00071
00073 static struct {
00075 fibril_rwlock_t lock;
00077 gpm_t packet_map;
00078 } pm_globals;
00079
00080 GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t);
00081
00087 int pm_init(void)
00088 {
00089 int rc;
00090
00091 fibril_rwlock_initialize(&pm_globals.lock);
00092
00093 fibril_rwlock_write_lock(&pm_globals.lock);
00094 rc = gpm_initialize(&pm_globals.packet_map);
00095 fibril_rwlock_write_unlock(&pm_globals.lock);
00096
00097 return rc;
00098 }
00099
00106 packet_t *pm_find(packet_id_t packet_id)
00107 {
00108 packet_map_t *map;
00109 packet_t *packet;
00110
00111 if (!packet_id)
00112 return NULL;
00113
00114 fibril_rwlock_read_lock(&pm_globals.lock);
00115 if (packet_id > PACKET_MAP_SIZE * gpm_count(&pm_globals.packet_map)) {
00116 fibril_rwlock_read_unlock(&pm_globals.lock);
00117 return NULL;
00118 }
00119 map = gpm_get_index(&pm_globals.packet_map, PACKET_MAP_PAGE(packet_id));
00120 if (!map) {
00121 fibril_rwlock_read_unlock(&pm_globals.lock);
00122 return NULL;
00123 }
00124 packet = (*map) [PACKET_MAP_INDEX(packet_id)];
00125 fibril_rwlock_read_unlock(&pm_globals.lock);
00126 return packet;
00127 }
00128
00137 int pm_add(packet_t *packet)
00138 {
00139 packet_map_t *map;
00140 int rc;
00141
00142 if (!packet_is_valid(packet))
00143 return EINVAL;
00144
00145 fibril_rwlock_write_lock(&pm_globals.lock);
00146
00147 if (PACKET_MAP_PAGE(packet->packet_id) <
00148 gpm_count(&pm_globals.packet_map)) {
00149 map = gpm_get_index(&pm_globals.packet_map,
00150 PACKET_MAP_PAGE(packet->packet_id));
00151 } else {
00152 do {
00153 map = (packet_map_t *) malloc(sizeof(packet_map_t));
00154 if (!map) {
00155 fibril_rwlock_write_unlock(&pm_globals.lock);
00156 return ENOMEM;
00157 }
00158 bzero(map, sizeof(packet_map_t));
00159 rc = gpm_add(&pm_globals.packet_map, map);
00160 if (rc < 0) {
00161 fibril_rwlock_write_unlock(&pm_globals.lock);
00162 free(map);
00163 return rc;
00164 }
00165 } while (PACKET_MAP_PAGE(packet->packet_id) >=
00166 gpm_count(&pm_globals.packet_map));
00167 }
00168
00169 (*map) [PACKET_MAP_INDEX(packet->packet_id)] = packet;
00170 fibril_rwlock_write_unlock(&pm_globals.lock);
00171 return EOK;
00172 }
00173
00175 void pm_destroy(void)
00176 {
00177 int count;
00178 int index;
00179 packet_map_t *map;
00180 packet_t *packet;
00181
00182 fibril_rwlock_write_lock(&pm_globals.lock);
00183 count = gpm_count(&pm_globals.packet_map);
00184 while (count > 0) {
00185 map = gpm_get_index(&pm_globals.packet_map, count - 1);
00186 for (index = PACKET_MAP_SIZE - 1; index >= 0; --index) {
00187 packet = (*map)[index];
00188 if (packet_is_valid(packet))
00189 munmap(packet, packet->length);
00190 }
00191 }
00192 gpm_destroy(&pm_globals.packet_map, free);
00193
00194 }
00195
00211 int pq_add(packet_t **first, packet_t *packet, size_t order, size_t metric)
00212 {
00213 packet_t *item;
00214
00215 if (!first || !packet_is_valid(packet))
00216 return EINVAL;
00217
00218 pq_set_order(packet, order, metric);
00219 if (packet_is_valid(*first)) {
00220 item = * first;
00221 do {
00222 if (item->order < order) {
00223 if (item->next) {
00224 item = pm_find(item->next);
00225 } else {
00226 item->next = packet->packet_id;
00227 packet->previous = item->packet_id;
00228 return EOK;
00229 }
00230 } else {
00231 packet->previous = item->previous;
00232 packet->next = item->packet_id;
00233 item->previous = packet->packet_id;
00234 item = pm_find(packet->previous);
00235 if (item)
00236 item->next = packet->packet_id;
00237 else
00238 *first = packet;
00239 return EOK;
00240 }
00241 } while (packet_is_valid(item));
00242 }
00243 *first = packet;
00244 return EOK;
00245 }
00246
00255 packet_t *pq_find(packet_t *packet, size_t order)
00256 {
00257 packet_t *item;
00258
00259 if (!packet_is_valid(packet))
00260 return NULL;
00261
00262 item = packet;
00263 do {
00264 if (item->order == order)
00265 return item;
00266
00267 item = pm_find(item->next);
00268 } while (item && (item != packet) && packet_is_valid(item));
00269
00270 return NULL;
00271 }
00272
00280 int pq_insert_after(packet_t *packet, packet_t *new_packet)
00281 {
00282 packet_t *item;
00283
00284 if (!packet_is_valid(packet) || !packet_is_valid(new_packet))
00285 return EINVAL;
00286
00287 new_packet->previous = packet->packet_id;
00288 new_packet->next = packet->next;
00289 item = pm_find(packet->next);
00290 if (item)
00291 item->previous = new_packet->packet_id;
00292 packet->next = new_packet->packet_id;
00293
00294 return EOK;
00295 }
00296
00305 packet_t *pq_detach(packet_t *packet)
00306 {
00307 packet_t *next;
00308 packet_t *previous;
00309
00310 if (!packet_is_valid(packet))
00311 return NULL;
00312
00313 next = pm_find(packet->next);
00314 if (next) {
00315 next->previous = packet->previous;
00316 previous = pm_find(next->previous);
00317 if (previous)
00318 previous->next = next->packet_id;
00319 }
00320 packet->previous = 0;
00321 packet->next = 0;
00322 return next;
00323 }
00324
00333 int pq_set_order(packet_t *packet, size_t order, size_t metric)
00334 {
00335 if (!packet_is_valid(packet))
00336 return EINVAL;
00337
00338 packet->order = order;
00339 packet->metric = metric;
00340 return EOK;
00341 }
00342
00351 int pq_get_order(packet_t *packet, size_t *order, size_t *metric)
00352 {
00353 if (!packet_is_valid(packet))
00354 return EINVAL;
00355
00356 if (order)
00357 *order = packet->order;
00358
00359 if (metric)
00360 *metric = packet->metric;
00361
00362 return EOK;
00363 }
00364
00374 void pq_destroy(packet_t *first, void (*packet_release)(packet_t *packet))
00375 {
00376 packet_t *actual;
00377 packet_t *next;
00378
00379 actual = first;
00380 while (packet_is_valid(actual)) {
00381 next = pm_find(actual->next);
00382 actual->next = 0;
00383 actual->previous = 0;
00384 if(packet_release)
00385 packet_release(actual);
00386 actual = next;
00387 }
00388 }
00389
00397 packet_t *pq_next(packet_t *packet)
00398 {
00399 if (!packet_is_valid(packet))
00400 return NULL;
00401
00402 return pm_find(packet->next);
00403 }
00404
00412 packet_t *pq_previous(packet_t *packet)
00413 {
00414 if (!packet_is_valid(packet))
00415 return NULL;
00416
00417 return pm_find(packet->previous);
00418 }
00419