Subversion Repositories HelenOS

Rev

Rev 3901 | Rev 3914 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3901 Rev 3912
1
/*
1
/*
2
 * Copyright (c) 2008 Lukas Mejdrech
2
 * Copyright (c) 2009 Lukas Mejdrech
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
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
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.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup net
29
/** @addtogroup packet
30
 *  @{
30
 *  @{
31
 */
31
 */
32
 
32
 
33
/** @file
33
/** @file
-
 
34
 *  Packet map and queue implementation.
-
 
35
 *  This file has to be compiled with both the packet server and the client.
34
 */
36
 */
35
 
37
 
36
#include <errno.h>
38
#include <errno.h>
37
#include <malloc.h>
39
#include <malloc.h>
38
//#include <stdio.h>
40
//#include <stdio.h>
39
#include <string.h>
41
#include <string.h>
40
 
42
 
41
#include <sys/mman.h>
43
#include <sys/mman.h>
42
 
44
 
43
#include "../../err.h"
45
#include "../../err.h"
44
 
46
 
45
#include "../generic_field.h"
47
#include "../generic_field.h"
46
 
48
 
47
#include "packet_header.h"
49
#include "packet_header.h"
48
#include "packet.h"
50
#include "packet.h"
49
 
51
 
50
// TODO power of 2 aritmetic => div and mod speedup?
52
// TODO power of 2 aritmetic => div and mod speedup?
-
 
53
/** Packet map page size.
-
 
54
 */
51
#define PACKET_MAP_SIZE 100
55
#define PACKET_MAP_SIZE 100
52
 
56
 
-
 
57
/** Returns the packet map page index.
-
 
58
 *  @param packet_id The packet identifier.
-
 
59
 */
53
#define PACKET_MAP_PAGE( packet_id )    ((( packet_id ) - 1 ) / PACKET_MAP_SIZE )
60
#define PACKET_MAP_PAGE( packet_id )    ((( packet_id ) - 1 ) / PACKET_MAP_SIZE )
54
#define PACKET_MAP_INDEX( packet_id )   ((( packet_id ) - 1 ) % PACKET_MAP_SIZE )
-
 
55
 
-
 
56
 
61
 
-
 
62
/** Returns the packet index in the corresponding packet map page.
57
int packet_destroy( packet_t packet );
63
 *  @param packet_id The packet identifier.
-
 
64
 */
-
 
65
#define PACKET_MAP_INDEX( packet_id )   ((( packet_id ) - 1 ) % PACKET_MAP_SIZE )
58
 
66
 
-
 
67
/** Type definition of the packet map page.
-
 
68
 */
59
typedef packet_t packet_map_t[ PACKET_MAP_SIZE ];
69
typedef packet_t packet_map_t[ PACKET_MAP_SIZE ];
-
 
70
/** Type definition of the packet map page pointer.
-
 
71
 */
60
typedef packet_map_t * packet_map_ref;
72
typedef packet_map_t * packet_map_ref;
61
 
73
 
-
 
74
/** Packet map.
-
 
75
 *  Maps packet identifiers to the packet references.
-
 
76
 *  @see generic_field.h
-
 
77
 */
62
GENERIC_FIELD_DECLARE( gpm, packet_map_t );
78
GENERIC_FIELD_DECLARE( gpm, packet_map_t );
63
 
79
 
-
 
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
 */
64
GENERIC_FIELD_IMPLEMENT( gpm, packet_map_t );
85
int packet_destroy( packet_t packet );
65
 
86
 
-
 
87
/** Packet map global data.
-
 
88
 */
66
static struct{
89
static struct{
67
    // TODO lock
90
    // TODO lock
-
 
91
    /** Packet map.
-
 
92
     */
68
    gpm_t map;
93
    gpm_t packet_map;
69
} pm_globals;
94
} pm_globals;
70
 
95
 
-
 
96
GENERIC_FIELD_IMPLEMENT( gpm, packet_map_t );
-
 
97
 
71
int packet_destroy( packet_t packet ){
98
int packet_destroy( packet_t packet ){
72
    if( ! packet_is_valid( packet )) return EINVAL;
99
    if( ! packet_is_valid( packet )) return EINVAL;
73
    return munmap( packet, packet->length );
100
    return munmap( packet, packet->length );
74
}
101
}
75
 
102
 
76
int pm_init( void ){
103
int pm_init( void ){
77
    return gpm_initialize( & pm_globals.map );
104
    return gpm_initialize( & pm_globals.packet_map );
78
}
105
}
79
 
106
 
80
packet_t pm_find( packet_id_t packet_id ){
107
packet_t pm_find( packet_id_t packet_id ){
81
    packet_map_ref map;
108
    packet_map_ref map;
82
 
109
 
83
    if( ! packet_id ) return NULL;
110
    if( ! packet_id ) return NULL;
84
    if( packet_id > PACKET_MAP_SIZE * gpm_count( & pm_globals.map )) return NULL;
111
    if( packet_id > PACKET_MAP_SIZE * gpm_count( & pm_globals.packet_map )) return NULL;
85
    map = gpm_get_index( & pm_globals.map, PACKET_MAP_PAGE( packet_id ));
112
    map = gpm_get_index( & pm_globals.packet_map, PACKET_MAP_PAGE( packet_id ));
86
    if( ! map ) return NULL;
113
    if( ! map ) return NULL;
87
    return ( * map )[ PACKET_MAP_INDEX( packet_id ) ];
114
    return ( * map )[ PACKET_MAP_INDEX( packet_id ) ];
88
}
115
}
89
 
116
 
90
int pm_add( packet_t packet ){
117
int pm_add( packet_t packet ){
91
    ERROR_DECLARE;
118
    ERROR_DECLARE;
92
 
119
 
93
    packet_map_ref map;
120
    packet_map_ref map;
94
 
121
 
95
    if(( ! packet_is_valid( packet )) || ( gpm_count( & pm_globals.map ) < -1 )) return EINVAL;
122
    if(( ! packet_is_valid( packet )) || ( gpm_count( & pm_globals.packet_map ) < 0 )) return EINVAL;
96
    if( PACKET_MAP_PAGE( packet->packet_id ) < gpm_count( & pm_globals.map )){
123
    if( PACKET_MAP_PAGE( packet->packet_id ) < gpm_count( & pm_globals.packet_map )){
97
        map = gpm_get_index( & pm_globals.map, PACKET_MAP_PAGE( packet->packet_id ));
124
        map = gpm_get_index( & pm_globals.packet_map, PACKET_MAP_PAGE( packet->packet_id ));
98
    }else{
125
    }else{
99
        do{
126
        do{
100
            map = ( packet_map_ref ) malloc( sizeof( packet_map_t ));
127
            map = ( packet_map_ref ) malloc( sizeof( packet_map_t ));
101
            if( ! map ) return ENOMEM;
128
            if( ! map ) return ENOMEM;
102
            memset( map, 0, sizeof( packet_map_t ));
129
            memset( map, 0, sizeof( packet_map_t ));
103
            if(( ERROR_CODE = gpm_add( & pm_globals.map, map )) < 0 ){
130
            if(( ERROR_CODE = gpm_add( & pm_globals.packet_map, map )) < 0 ){
104
                free( map );
131
                free( map );
105
                return ERROR_CODE;
132
                return ERROR_CODE;
106
            }
133
            }
107
        }while( PACKET_MAP_PAGE( packet->packet_id ) >= gpm_count( & pm_globals.map ));
134
        }while( PACKET_MAP_PAGE( packet->packet_id ) >= gpm_count( & pm_globals.packet_map ));
108
    }
135
    }
109
    ( * map )[ PACKET_MAP_INDEX( packet->packet_id ) ] = packet;
136
    ( * map )[ PACKET_MAP_INDEX( packet->packet_id ) ] = packet;
110
    return EOK;
137
    return EOK;
111
}
138
}
112
 
139
 
113
void pm_destroy( void ){
140
void pm_destroy( void ){
114
    int count;
141
    int count;
115
    int index;
142
    int index;
116
    packet_map_ref map;
143
    packet_map_ref map;
117
    packet_t packet;
144
    packet_t packet;
118
 
145
 
119
    count = gpm_count( & pm_globals.map );
146
    count = gpm_count( & pm_globals.packet_map );
120
    while( count > 0 ){
147
    while( count > 0 ){
121
        map = gpm_get_index( & pm_globals.map, count - 1 );
148
        map = gpm_get_index( & pm_globals.packet_map, count - 1 );
122
        for( index = PACKET_MAP_SIZE - 1; index >= 0; -- index ){
149
        for( index = PACKET_MAP_SIZE - 1; index >= 0; -- index ){
123
            packet = ( * map )[ index ];
150
            packet = ( * map )[ index ];
124
            if( packet_is_valid( packet )){
151
            if( packet_is_valid( packet )){
125
                munmap( packet, packet->length );
152
                munmap( packet, packet->length );
126
            }
153
            }
127
        }
154
        }
128
    }
155
    }
129
    gpm_destroy( & pm_globals.map );
156
    gpm_destroy( & pm_globals.packet_map );
130
}
157
}
131
 
158
 
132
packet_t pq_add( packet_t first, packet_t packet, int order, size_t metric ){
159
packet_t pq_add( packet_t first, packet_t packet, int order, size_t metric ){
133
    packet_t    item;
160
    packet_t    item;
134
 
161
 
135
    if( ! packet_is_valid( packet )) return NULL;
162
    if( ! packet_is_valid( packet )) return NULL;
136
    pq_set( packet, order, metric );
163
    pq_set( packet, order, metric );
137
    if( packet_is_valid( first )){
164
    if( packet_is_valid( first )){
138
        item = first;
165
        item = first;
139
        do{
166
        do{
140
            if( item->order < order ){
167
            if( item->order < order ){
141
                if( item->next ){
168
                if( item->next ){
142
                    item = pm_find( item->next );
169
                    item = pm_find( item->next );
143
                }else{
170
                }else{
144
                    item->next = packet->packet_id;
171
                    item->next = packet->packet_id;
145
                    packet->previous = item->packet_id;
172
                    packet->previous = item->packet_id;
146
                    return first;
173
                    return first;
147
                }
174
                }
148
            }else{
175
            }else{
149
                packet->previous = item->previous;
176
                packet->previous = item->previous;
150
                packet->next = item->packet_id;
177
                packet->next = item->packet_id;
151
                item->previous = packet->packet_id;
178
                item->previous = packet->packet_id;
152
                item = pm_find( packet->previous );
179
                item = pm_find( packet->previous );
153
                if( item ) item->next = packet->packet_id;
180
                if( item ) item->next = packet->packet_id;
154
                return item;
181
                return item;
155
            }
182
            }
156
        }while( packet_is_valid( item ));
183
        }while( packet_is_valid( item ));
157
    }
184
    }
158
    return packet;
185
    return packet;
159
}
186
}
160
 
187
 
161
packet_t pq_detach( packet_t packet ){
188
packet_t pq_detach( packet_t packet ){
162
    packet_t next;
189
    packet_t next;
163
    packet_t previous;
190
    packet_t previous;
164
 
191
 
165
    if( ! packet_is_valid( packet )) return NULL;
192
    if( ! packet_is_valid( packet )) return NULL;
166
    next = pm_find( packet->next );
193
    next = pm_find( packet->next );
167
    if( next ){
194
    if( next ){
168
        next->previous = packet->previous;
195
        next->previous = packet->previous;
169
        previous = pm_find( next->previous );
196
        previous = pm_find( next->previous );
170
        if( previous ){
197
        if( previous ){
171
            previous->next = next->packet_id;
198
            previous->next = next->packet_id;
172
        }
199
        }
173
    }
200
    }
174
    packet->previous = 0;
201
    packet->previous = 0;
175
    packet->next = 0;
202
    packet->next = 0;
176
    return next;
203
    return next;
177
}
204
}
178
 
205
 
179
int pq_set( packet_t packet, int order, size_t metric ){
206
int pq_set( packet_t packet, int order, size_t metric ){
180
    if( ! packet_is_valid( packet )) return EINVAL;
207
    if( ! packet_is_valid( packet )) return EINVAL;
181
    packet->order = order;
208
    packet->order = order;
182
    packet->metric = metric;
209
    packet->metric = metric;
183
    return EOK;
210
    return EOK;
184
}
211
}
185
 
212
 
186
void pq_destroy( packet_t first, void ( * packet_release )( packet_t packet )){
213
void pq_destroy( packet_t first, void ( * packet_release )( packet_t packet )){
187
    packet_t    actual;
214
    packet_t    actual;
188
    packet_t    next;
215
    packet_t    next;
189
 
216
 
190
    actual = first;
217
    actual = first;
191
    while( packet_is_valid( actual )){
218
    while( packet_is_valid( actual )){
192
        next = pm_find( actual->next );
219
        next = pm_find( actual->next );
193
        actual->next = 0;
220
        actual->next = 0;
194
        actual->previous = 0;
221
        actual->previous = 0;
195
        if( packet_release ) packet_release( actual );
222
        if( packet_release ) packet_release( actual );
196
        actual = next;
223
        actual = next;
197
    }
224
    }
198
}
225
}
199
 
226
 
200
/** @}
227
/** @}
201
 */
228
 */
202
 
229