Subversion Repositories HelenOS

Rev

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