Subversion Repositories HelenOS

Rev

Rev 3901 | Rev 3914 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3886 mejdrech 1
/*
3912 mejdrech 2
 * Copyright (c) 2009 Lukas Mejdrech
3886 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
 
3912 mejdrech 29
/** @addtogroup packet
3901 mejdrech 30
 *  @{
3886 mejdrech 31
 */
32
 
33
/** @file
3912 mejdrech 34
 *  Packet map and queue implementation.
35
 *  This file has to be compiled with both the packet server and the client.
3886 mejdrech 36
 */
37
 
38
#include <errno.h>
3901 mejdrech 39
#include <malloc.h>
40
//#include <stdio.h>
3886 mejdrech 41
#include <string.h>
42
 
43
#include <sys/mman.h>
44
 
45
#include "../../err.h"
46
 
3901 mejdrech 47
#include "../generic_field.h"
48
 
49
#include "packet_header.h"
3886 mejdrech 50
#include "packet.h"
51
 
3901 mejdrech 52
// TODO power of 2 aritmetic => div and mod speedup?
3912 mejdrech 53
/** Packet map page size.
54
 */
3901 mejdrech 55
#define PACKET_MAP_SIZE	100
3886 mejdrech 56
 
3912 mejdrech 57
/** Returns the packet map page index.
58
 *  @param packet_id The packet identifier.
59
 */
3901 mejdrech 60
#define PACKET_MAP_PAGE( packet_id )	((( packet_id ) - 1 ) / PACKET_MAP_SIZE )
3912 mejdrech 61
 
62
/** Returns the packet index in the corresponding packet map page.
63
 *  @param packet_id The packet identifier.
64
 */
3901 mejdrech 65
#define PACKET_MAP_INDEX( packet_id )	((( packet_id ) - 1 ) % PACKET_MAP_SIZE )
3886 mejdrech 66
 
3912 mejdrech 67
/** Type definition of the packet map page.
68
 */
3901 mejdrech 69
typedef packet_t packet_map_t[ PACKET_MAP_SIZE ];
3912 mejdrech 70
/** Type definition of the packet map page pointer.
71
 */
3901 mejdrech 72
typedef packet_map_t * packet_map_ref;
73
 
3912 mejdrech 74
/** Packet map.
75
 *  Maps packet identifiers to the packet references.
76
 *  @see generic_field.h
77
 */
3901 mejdrech 78
GENERIC_FIELD_DECLARE( gpm, packet_map_t );
79
 
3912 mejdrech 80
/** Releases the packet.
81
 *  @param packet The packet to be released. Input parameter.
82
 *  @returns EOK on success.
83
 *  @returns EINVAL if the packet is not valid.
84
 */
85
int packet_destroy( packet_t packet );
3901 mejdrech 86
 
3912 mejdrech 87
/** Packet map global data.
88
 */
3901 mejdrech 89
static struct{
90
	// TODO lock
3912 mejdrech 91
	/** Packet map.
92
	 */
93
	gpm_t packet_map;
3901 mejdrech 94
} pm_globals;
95
 
3912 mejdrech 96
GENERIC_FIELD_IMPLEMENT( gpm, packet_map_t );
97
 
3901 mejdrech 98
int packet_destroy( packet_t packet ){
99
	if( ! packet_is_valid( packet )) return EINVAL;
100
	return munmap( packet, packet->length );
3886 mejdrech 101
}
102
 
3901 mejdrech 103
int pm_init( void ){
3912 mejdrech 104
	return gpm_initialize( & pm_globals.packet_map );
3886 mejdrech 105
}
106
 
3901 mejdrech 107
packet_t pm_find( packet_id_t packet_id ){
108
	packet_map_ref map;
3886 mejdrech 109
 
3901 mejdrech 110
	if( ! packet_id ) return NULL;
3912 mejdrech 111
	if( packet_id > PACKET_MAP_SIZE * gpm_count( & pm_globals.packet_map )) return NULL;
112
	map = gpm_get_index( & pm_globals.packet_map, PACKET_MAP_PAGE( packet_id ));
3901 mejdrech 113
	if( ! map ) return NULL;
114
	return ( * map )[ PACKET_MAP_INDEX( packet_id ) ];
3886 mejdrech 115
}
116
 
3901 mejdrech 117
int pm_add( packet_t packet ){
118
	ERROR_DECLARE;
119
 
120
	packet_map_ref map;
121
 
3912 mejdrech 122
	if(( ! packet_is_valid( packet )) || ( gpm_count( & pm_globals.packet_map ) < 0 )) return EINVAL;
123
	if( PACKET_MAP_PAGE( packet->packet_id ) < gpm_count( & pm_globals.packet_map )){
124
		map = gpm_get_index( & pm_globals.packet_map, PACKET_MAP_PAGE( packet->packet_id ));
3901 mejdrech 125
	}else{
126
		do{
127
			map = ( packet_map_ref ) malloc( sizeof( packet_map_t ));
128
			if( ! map ) return ENOMEM;
129
			memset( map, 0, sizeof( packet_map_t ));
3912 mejdrech 130
			if(( ERROR_CODE = gpm_add( & pm_globals.packet_map, map )) < 0 ){
3901 mejdrech 131
				free( map );
132
				return ERROR_CODE;
133
			}
3912 mejdrech 134
		}while( PACKET_MAP_PAGE( packet->packet_id ) >= gpm_count( & pm_globals.packet_map ));
3886 mejdrech 135
	}
3901 mejdrech 136
	( * map )[ PACKET_MAP_INDEX( packet->packet_id ) ] = packet;
3886 mejdrech 137
	return EOK;
138
}
139
 
3901 mejdrech 140
void pm_destroy( void ){
141
	int count;
142
	int index;
143
	packet_map_ref map;
144
	packet_t packet;
3886 mejdrech 145
 
3912 mejdrech 146
	count = gpm_count( & pm_globals.packet_map );
3901 mejdrech 147
	while( count > 0 ){
3912 mejdrech 148
		map = gpm_get_index( & pm_globals.packet_map, count - 1 );
3901 mejdrech 149
		for( index = PACKET_MAP_SIZE - 1; index >= 0; -- index ){
150
			packet = ( * map )[ index ];
151
			if( packet_is_valid( packet )){
152
				munmap( packet, packet->length );
153
			}
154
		}
155
	}
3912 mejdrech 156
	gpm_destroy( & pm_globals.packet_map );
3886 mejdrech 157
}
158
 
3901 mejdrech 159
packet_t pq_add( packet_t first, packet_t packet, int order, size_t metric ){
160
	packet_t	item;
3886 mejdrech 161
 
3901 mejdrech 162
	if( ! packet_is_valid( packet )) return NULL;
163
	pq_set( packet, order, metric );
164
	if( packet_is_valid( first )){
165
		item = first;
166
		do{
167
			if( item->order < order ){
168
				if( item->next ){
169
					item = pm_find( item->next );
170
				}else{
171
					item->next = packet->packet_id;
172
					packet->previous = item->packet_id;
173
					return first;
174
				}
175
			}else{
176
				packet->previous = item->previous;
177
				packet->next = item->packet_id;
178
				item->previous = packet->packet_id;
179
				item = pm_find( packet->previous );
180
				if( item ) item->next = packet->packet_id;
181
				return item;
182
			}
183
		}while( packet_is_valid( item ));
184
	}
185
	return packet;
3886 mejdrech 186
}
187
 
3901 mejdrech 188
packet_t pq_detach( packet_t packet ){
189
	packet_t next;
190
	packet_t previous;
3886 mejdrech 191
 
3901 mejdrech 192
	if( ! packet_is_valid( packet )) return NULL;
193
	next = pm_find( packet->next );
194
	if( next ){
195
		next->previous = packet->previous;
196
		previous = pm_find( next->previous );
197
		if( previous ){
198
			previous->next = next->packet_id;
199
		}
3886 mejdrech 200
	}
3901 mejdrech 201
	packet->previous = 0;
202
	packet->next = 0;
203
	return next;
3886 mejdrech 204
}
205
 
3901 mejdrech 206
int pq_set( packet_t packet, int order, size_t metric ){
3886 mejdrech 207
	if( ! packet_is_valid( packet )) return EINVAL;
3901 mejdrech 208
	packet->order = order;
209
	packet->metric = metric;
210
	return EOK;
3886 mejdrech 211
}
212
 
3901 mejdrech 213
void pq_destroy( packet_t first, void ( * packet_release )( packet_t packet )){
214
	packet_t	actual;
215
	packet_t	next;
3886 mejdrech 216
 
3901 mejdrech 217
	actual = first;
218
	while( packet_is_valid( actual )){
219
		next = pm_find( actual->next );
220
		actual->next = 0;
221
		actual->previous = 0;
222
		if( packet_release ) packet_release( actual );
223
		actual = next;
224
	}
3886 mejdrech 225
}
226
 
227
/** @}
228
 */