Subversion Repositories HelenOS

Rev

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

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