63
61
#define PACKET_MAP_INDEX(packet_id) (((packet_id) - 1) % PACKET_MAP_SIZE)
65
/** Type definition of the packet map page.
67
typedef packet_t packet_map_t[PACKET_MAP_SIZE];
68
/** Type definition of the packet map page pointer.
70
typedef packet_map_t * packet_map_ref;
63
/** Type definition of the packet map page. */
64
typedef packet_t *packet_map_t[PACKET_MAP_SIZE];
73
* Maps packet identifiers to the packet references.
74
* @see generic_field.h
67
* Maps packet identifiers to the packet references.
68
* @see generic_field.h
76
70
GENERIC_FIELD_DECLARE(gpm, packet_map_t);
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.
83
int packet_destroy(packet_t packet);
85
/** Packet map global data.
72
/** Packet map global data. */
90
75
fibril_rwlock_t lock;
96
80
GENERIC_FIELD_IMPLEMENT(gpm, packet_map_t);
98
int packet_destroy(packet_t packet){
99
if(! packet_is_valid(packet)){
102
return munmap(packet, packet->length);
82
/** Initializes the packet map.
84
* @return EOK on success.
85
* @return ENOMEM if there is not enough memory left.
108
91
fibril_rwlock_initialize(&pm_globals.lock);
109
93
fibril_rwlock_write_lock(&pm_globals.lock);
110
ERROR_PROPAGATE(gpm_initialize(&pm_globals.packet_map));
94
rc = gpm_initialize(&pm_globals.packet_map);
111
95
fibril_rwlock_write_unlock(&pm_globals.lock);
115
packet_t pm_find(packet_id_t packet_id){
100
/** Finds the packet mapping.
102
* @param[in] packet_id The packet identifier to be found.
103
* @return The found packet reference.
104
* @return NULL if the mapping does not exist.
106
packet_t *pm_find(packet_id_t packet_id)
122
114
fibril_rwlock_read_lock(&pm_globals.lock);
123
if(packet_id > PACKET_MAP_SIZE * gpm_count(&pm_globals.packet_map)){
115
if (packet_id > PACKET_MAP_SIZE * gpm_count(&pm_globals.packet_map)) {
124
116
fibril_rwlock_read_unlock(&pm_globals.lock);
127
119
map = gpm_get_index(&pm_globals.packet_map, PACKET_MAP_PAGE(packet_id));
129
121
fibril_rwlock_read_unlock(&pm_globals.lock);
132
packet = (*map)[PACKET_MAP_INDEX(packet_id)];
124
packet = (*map) [PACKET_MAP_INDEX(packet_id)];
133
125
fibril_rwlock_read_unlock(&pm_globals.lock);
137
int pm_add(packet_t packet){
142
if(! packet_is_valid(packet)){
129
/** Adds the packet mapping.
131
* @param[in] packet The packet to be remembered.
132
* @return EOK on success.
133
* @return EINVAL if the packet is not valid.
134
* @return EINVAL if the packet map is not initialized.
135
* @return ENOMEM if there is not enough memory left.
137
int pm_add(packet_t *packet)
142
if (!packet_is_valid(packet))
145
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));
150
map = (packet_map_ref) malloc(sizeof(packet_map_t));
147
if (PACKET_MAP_PAGE(packet->packet_id) <
148
gpm_count(&pm_globals.packet_map)) {
149
map = gpm_get_index(&pm_globals.packet_map,
150
PACKET_MAP_PAGE(packet->packet_id));
153
map = (packet_map_t *) malloc(sizeof(packet_map_t));
152
155
fibril_rwlock_write_unlock(&pm_globals.lock);
155
158
bzero(map, sizeof(packet_map_t));
156
if((ERROR_CODE = gpm_add(&pm_globals.packet_map, map)) < 0){
159
rc = gpm_add(&pm_globals.packet_map, map);
157
161
fibril_rwlock_write_unlock(&pm_globals.lock);
161
}while(PACKET_MAP_PAGE(packet->packet_id) >= gpm_count(&pm_globals.packet_map));
165
} while (PACKET_MAP_PAGE(packet->packet_id) >=
166
gpm_count(&pm_globals.packet_map));
163
(*map)[PACKET_MAP_INDEX(packet->packet_id)] = packet;
169
(*map) [PACKET_MAP_INDEX(packet->packet_id)] = packet;
164
170
fibril_rwlock_write_unlock(&pm_globals.lock);
168
void pm_destroy(void){
174
/** Releases the packet map. */
175
void pm_destroy(void)
174
182
fibril_rwlock_write_lock(&pm_globals.lock);
175
183
count = gpm_count(&pm_globals.packet_map);
177
185
map = gpm_get_index(&pm_globals.packet_map, count - 1);
178
for(index = PACKET_MAP_SIZE - 1; index >= 0; -- index){
186
for (index = PACKET_MAP_SIZE - 1; index >= 0; --index) {
179
187
packet = (*map)[index];
180
if(packet_is_valid(packet)){
188
if (packet_is_valid(packet))
181
189
munmap(packet, packet->length);
185
gpm_destroy(&pm_globals.packet_map);
192
gpm_destroy(&pm_globals.packet_map, free);
189
int pq_add(packet_t * first, packet_t packet, size_t order, size_t metric){
196
/** Add packet to the sorted queue.
198
* The queue is sorted in the ascending order.
199
* The packet is inserted right before the packets of the same order value.
201
* @param[in,out] first The first packet of the queue. Sets the first packet of
202
* the queue. The original first packet may be shifted by
204
* @param[in] packet The packet to be added.
205
* @param[in] order The packet order value.
206
* @param[in] metric The metric value of the packet.
207
* @return EOK on success.
208
* @return EINVAL if the first parameter is NULL.
209
* @return EINVAL if the packet is not valid.
211
int pq_add(packet_t **first, packet_t *packet, size_t order, size_t metric)
192
if((! first) || (! packet_is_valid(packet))){
215
if (!first || !packet_is_valid(packet))
195
218
pq_set_order(packet, order, metric);
196
if(packet_is_valid(*first)){
219
if (packet_is_valid(*first)) {
199
if(item->order < order){
222
if (item->order < order) {
201
224
item = pm_find(item->next);
203
226
item->next = packet->packet_id;
204
227
packet->previous = item->packet_id;
208
231
packet->previous = item->previous;
209
232
packet->next = item->packet_id;
210
233
item->previous = packet->packet_id;
211
234
item = pm_find(packet->previous);
213
236
item->next = packet->packet_id;
219
}while(packet_is_valid(item));
241
} while (packet_is_valid(item));
225
packet_t pq_find(packet_t packet, size_t order){
247
/** Finds the packet with the given order.
249
* @param[in] first The first packet of the queue.
250
* @param[in] order The packet order value.
251
* @return The packet with the given order.
252
* @return NULL if the first packet is not valid.
253
* @return NULL if the packet is not found.
255
packet_t *pq_find(packet_t *packet, size_t order)
228
if(! packet_is_valid(packet)){
259
if (!packet_is_valid(packet))
233
if(item->order == order){
264
if (item->order == order)
236
267
item = pm_find(item->next);
237
}while(item && (item != packet) && packet_is_valid(item));
268
} while (item && (item != packet) && packet_is_valid(item));
241
int pq_insert_after(packet_t packet, packet_t new_packet){
273
/** Inserts packet after the given one.
275
* @param[in] packet The packet in the queue.
276
* @param[in] new_packet The new packet to be inserted.
277
* @return EOK on success.
278
* @return EINVAL if etiher of the packets is invalid.
280
int pq_insert_after(packet_t *packet, packet_t *new_packet)
244
if(!(packet_is_valid(packet) && packet_is_valid(new_packet))){
284
if (!packet_is_valid(packet) || !packet_is_valid(new_packet))
247
287
new_packet->previous = packet->packet_id;
248
288
new_packet->next = packet->next;
249
289
item = pm_find(packet->next);
251
291
item->previous = new_packet->packet_id;
253
292
packet->next = new_packet->packet_id;
257
packet_t pq_detach(packet_t packet){
297
/** Detach the packet from the queue.
299
* @param[in] packet The packet to be detached.
300
* @return The next packet in the queue. If the packet is the first
301
* one of the queue, this becomes the new first one.
302
* @return NULL if there is no packet left.
303
* @return NULL if the packet is not valid.
305
packet_t *pq_detach(packet_t *packet)
261
if(! packet_is_valid(packet)){
310
if (!packet_is_valid(packet))
264
313
next = pm_find(packet->next);
266
315
next->previous = packet->previous;
267
316
previous = pm_find(next->previous);
269
318
previous->next = next->packet_id;
272
320
packet->previous = 0;
273
321
packet->next = 0;
277
int pq_set_order(packet_t packet, size_t order, size_t metric){
278
if(! packet_is_valid(packet)){
325
/** Sets the packet order and metric attributes.
327
* @param[in] packeti The packet to be set.
328
* @param[in] order The packet order value.
329
* @param[in] metric The metric value of the packet.
330
* @return EOK on success.
331
* @return EINVAL if the packet is invalid.
333
int pq_set_order(packet_t *packet, size_t order, size_t metric)
335
if (!packet_is_valid(packet))
281
338
packet->order = order;
282
339
packet->metric = metric;
286
int pq_get_order(packet_t packet, size_t * order, size_t * metric){
287
if(! packet_is_valid(packet)){
343
/** Sets the packet order and metric attributes.
345
* @param[in] packet The packet to be set.
346
* @param[out] order The packet order value.
347
* @param[out] metric The metric value of the packet.
348
* @return EOK on success.
349
* @return EINVAL if the packet is invalid.
351
int pq_get_order(packet_t *packet, size_t *order, size_t *metric)
353
if (!packet_is_valid(packet))
291
357
*order = packet->order;
294
360
*metric = packet->metric;
299
void pq_destroy(packet_t first, void (*packet_release)(packet_t packet)){
365
/** Releases the whole queue.
367
* Detaches all packets of the queue and calls the packet_release() for each of
370
* @param[in] first The first packet of the queue.
371
* @param[in] packet_release The releasing function called for each of the
372
* packets after its detachment.
374
void pq_destroy(packet_t *first, void (*packet_release)(packet_t *packet))
304
while(packet_is_valid(actual)){
380
while (packet_is_valid(actual)) {
305
381
next = pm_find(actual->next);
306
382
actual->next = 0;
307
383
actual->previous = 0;
309
385
packet_release(actual);
315
packet_t pq_next(packet_t packet){
316
if(! packet_is_valid(packet)){
390
/** Returns the next packet in the queue.
392
* @param[in] packet The packet queue member.
393
* @return The next packet in the queue.
394
* @return NULL if there is no next packet.
395
* @return NULL if the packet is not valid.
397
packet_t *pq_next(packet_t *packet)
399
if (!packet_is_valid(packet))
319
402
return pm_find(packet->next);
322
packet_t pq_previous(packet_t packet){
323
if(! packet_is_valid(packet)){
405
/** Returns the previous packet in the queue.
407
* @param[in] packet The packet queue member.
408
* @return The previous packet in the queue.
409
* @return NULL if there is no previous packet.
410
* @return NULL if the packet is not valid.
412
packet_t *pq_previous(packet_t *packet)
414
if (!packet_is_valid(packet))
326
417
return pm_find(packet->previous);