Subversion Repositories HelenOS

Rev

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

  1. /*
  2.  * Copyright (c) 2009 Lukas 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.  
  29. /** @addtogroup packet
  30.  *  @{
  31.  */
  32.  
  33. /** @file
  34.  *  Packet map and queue implementation.
  35.  *  This file has to be compiled with both the packet server and the client.
  36.  */
  37.  
  38. #include <errno.h>
  39. #include <malloc.h>
  40. //#include <stdio.h>
  41. #include <string.h>
  42.  
  43. #include <sys/mman.h>
  44.  
  45. #include "../../err.h"
  46.  
  47. #include "../generic_field.h"
  48.  
  49. #include "packet_header.h"
  50. #include "packet.h"
  51.  
  52. // TODO power of 2 aritmetic => div and mod speedup?
  53. /** Packet map page size.
  54.  */
  55. #define PACKET_MAP_SIZE 100
  56.  
  57. /** Returns the packet map page index.
  58.  *  @param packet_id The packet identifier.
  59.  */
  60. #define PACKET_MAP_PAGE( packet_id )    ((( packet_id ) - 1 ) / PACKET_MAP_SIZE )
  61.  
  62. /** Returns the packet index in the corresponding packet map page.
  63.  *  @param packet_id The packet identifier.
  64.  */
  65. #define PACKET_MAP_INDEX( packet_id )   ((( packet_id ) - 1 ) % PACKET_MAP_SIZE )
  66.  
  67. /** Type definition of the packet map page.
  68.  */
  69. typedef packet_t packet_map_t[ PACKET_MAP_SIZE ];
  70. /** Type definition of the packet map page pointer.
  71.  */
  72. typedef packet_map_t * packet_map_ref;
  73.  
  74. /** Packet map.
  75.  *  Maps packet identifiers to the packet references.
  76.  *  @see generic_field.h
  77.  */
  78. GENERIC_FIELD_DECLARE( gpm, packet_map_t );
  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.  */
  85. int packet_destroy( packet_t packet );
  86.  
  87. /** Packet map global data.
  88.  */
  89. static struct{
  90.     // TODO lock
  91.     /** Packet map.
  92.      */
  93.     gpm_t packet_map;
  94. } pm_globals;
  95.  
  96. GENERIC_FIELD_IMPLEMENT( gpm, packet_map_t );
  97.  
  98. int packet_destroy( packet_t packet ){
  99.     if( ! packet_is_valid( packet )) return EINVAL;
  100.     return munmap( packet, packet->length );
  101. }
  102.  
  103. int pm_init( void ){
  104.     return gpm_initialize( & pm_globals.packet_map );
  105. }
  106.  
  107. packet_t pm_find( packet_id_t packet_id ){
  108.     packet_map_ref map;
  109.  
  110.     if( ! packet_id ) return NULL;
  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 ));
  113.     if( ! map ) return NULL;
  114.     return ( * map )[ PACKET_MAP_INDEX( packet_id ) ];
  115. }
  116.  
  117. int pm_add( packet_t packet ){
  118.     ERROR_DECLARE;
  119.  
  120.     packet_map_ref map;
  121.  
  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 ));
  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 ));
  130.             if(( ERROR_CODE = gpm_add( & pm_globals.packet_map, map )) < 0 ){
  131.                 free( map );
  132.                 return ERROR_CODE;
  133.             }
  134.         }while( PACKET_MAP_PAGE( packet->packet_id ) >= gpm_count( & pm_globals.packet_map ));
  135.     }
  136.     ( * map )[ PACKET_MAP_INDEX( packet->packet_id ) ] = packet;
  137.     return EOK;
  138. }
  139.  
  140. void pm_destroy( void ){
  141.     int count;
  142.     int index;
  143.     packet_map_ref map;
  144.     packet_t packet;
  145.  
  146.     count = gpm_count( & pm_globals.packet_map );
  147.     while( count > 0 ){
  148.         map = gpm_get_index( & pm_globals.packet_map, count - 1 );
  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.     }
  156.     gpm_destroy( & pm_globals.packet_map );
  157. }
  158.  
  159. packet_t pq_add( packet_t first, packet_t packet, int order, size_t metric ){
  160.     packet_t    item;
  161.  
  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;
  186. }
  187.  
  188. packet_t pq_detach( packet_t packet ){
  189.     packet_t next;
  190.     packet_t previous;
  191.  
  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.         }
  200.     }
  201.     packet->previous = 0;
  202.     packet->next = 0;
  203.     return next;
  204. }
  205.  
  206. int pq_set( packet_t packet, int order, size_t metric ){
  207.     if( ! packet_is_valid( packet )) return EINVAL;
  208.     packet->order = order;
  209.     packet->metric = metric;
  210.     return EOK;
  211. }
  212.  
  213. void pq_destroy( packet_t first, void ( * packet_release )( packet_t packet )){
  214.     packet_t    actual;
  215.     packet_t    next;
  216.  
  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.     }
  225. }
  226.  
  227. /** @}
  228.  */
  229.