Subversion Repositories HelenOS

Rev

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

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