Ignore:
Timestamp:
2010-11-25T13:42:50Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8df8415
Parents:
a93d79a (diff), eb667613 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/packet/generic/packet_server.c

    ra93d79a r8fb1bf82  
    2727 */
    2828
    29 /** @addtogroup packet
     29/** @addtogroup libpacket
    3030 *  @{
    3131 */
    3232
    3333/** @file
    34  *  Packet server implementation.
    35  */
     34 * Packet server implementation.
     35 */
     36
     37#include <packet_server.h>
    3638
    3739#include <align.h>
     
    3941#include <async.h>
    4042#include <errno.h>
    41 #include <err.h>
    4243#include <fibril_synch.h>
    4344#include <unistd.h>
     
    5152#include <net/packet_header.h>
    5253
    53 #include <packet_server.h>
    54 #include <packet_local.h>
    55 
    5654#define FREE_QUEUES_COUNT       7
    5755
    58 /** The default address length reserved for new packets.
    59  */
     56/** The default address length reserved for new packets. */
    6057#define DEFAULT_ADDR_LEN        32
    6158
    62 /** The default prefix reserved for new packets.
    63  */
     59/** The default prefix reserved for new packets. */
    6460#define DEFAULT_PREFIX          64
    6561
    66 /** The default suffix reserved for new packets.
    67  */
     62/** The default suffix reserved for new packets. */
    6863#define DEFAULT_SUFFIX          64
    6964
    70 /** Packet server global data.
    71  */
    72 static struct{
    73         /** Safety lock.
    74          */
     65/** Packet server global data. */
     66static struct {
     67        /** Safety lock. */
    7568        fibril_mutex_t lock;
    76         /** Free packet queues.
    77          */
    78         packet_t free[FREE_QUEUES_COUNT];
    79         /** Packet length upper bounds of the free packet queues.
    80          *  The maximal lengths of packets in each queue in the ascending order.
    81          *  The last queue is not limited.
     69        /** Free packet queues. */
     70        packet_t *free[FREE_QUEUES_COUNT];
     71       
     72        /**
     73         * Packet length upper bounds of the free packet queues. The maximal
     74         * lengths of packets in each queue in the ascending order. The last
     75         * queue is not limited.
    8276         */
    8377        size_t sizes[FREE_QUEUES_COUNT];
    84         /** Total packets allocated.
    85         */
     78       
     79        /** Total packets allocated. */
    8680        unsigned int count;
    8781} ps_globals = {
    8882        .lock = FIBRIL_MUTEX_INITIALIZER(ps_globals.lock),
    89         .free = {NULL, NULL, NULL, NULL, NULL, NULL, NULL},
    90         .sizes = {PAGE_SIZE, PAGE_SIZE * 2, PAGE_SIZE * 4, PAGE_SIZE * 8, PAGE_SIZE * 16, PAGE_SIZE * 32, PAGE_SIZE * 64},
     83        .free = {
     84                NULL,
     85                NULL,
     86                NULL,
     87                NULL,
     88                NULL,
     89                NULL,
     90                NULL
     91        },
     92        .sizes = {
     93                PAGE_SIZE,
     94                PAGE_SIZE * 2,
     95                PAGE_SIZE * 4,
     96                PAGE_SIZE * 8,
     97                PAGE_SIZE * 16,
     98                PAGE_SIZE * 32,
     99                PAGE_SIZE * 64
     100        },
    91101        .count = 0
    92102};
    93103
    94 int packet_translate_local(int phone, packet_ref packet, packet_id_t packet_id)
    95 {
    96         if (!packet)
    97                 return EINVAL;
    98        
    99         *packet = pm_find(packet_id);
    100         return (*packet) ? EOK : ENOENT;
    101 }
    102 
    103104/** Clears and initializes the packet according to the given dimensions.
    104  *  @param[in] packet The packet to be initialized.
    105  *  @param[in] addr_len The source and destination addresses maximal length in bytes.
    106  *  @param[in] max_prefix The maximal prefix length in bytes.
    107  *  @param[in] max_content The maximal content length in bytes.
    108  *  @param[in] max_suffix The maximal suffix length in bytes.
    109  */
    110 static void packet_init(packet_t packet, size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix){
     105 *
     106 * @param[in] packet    The packet to be initialized.
     107 * @param[in] addr_len  The source and destination addresses maximal length in
     108 *                      bytes.
     109 * @param[in] max_prefix The maximal prefix length in bytes.
     110 * @param[in] max_content The maximal content length in bytes.
     111 * @param[in] max_suffix The maximal suffix length in bytes.
     112 */
     113static void
     114packet_init(packet_t *packet, size_t addr_len, size_t max_prefix,
     115    size_t max_content, size_t max_suffix)
     116{
    111117        // clear the packet content
    112         bzero(((void *) packet) + sizeof(struct packet), packet->length - sizeof(struct packet));
     118        bzero(((void *) packet) + sizeof(packet_t),
     119            packet->length - sizeof(packet_t));
     120       
    113121        // clear the packet header
    114122        packet->order = 0;
     
    117125        packet->next = 0;
    118126        packet->addr_len = 0;
    119         packet->src_addr = sizeof(struct packet);
     127        packet->src_addr = sizeof(packet_t);
    120128        packet->dest_addr = packet->src_addr + addr_len;
    121129        packet->max_prefix = max_prefix;
     
    125133}
    126134
    127 /** Creates a&nbsp;new packet of dimensions at least as given.
    128  *  Should be used only when the global data are locked.
    129  *  @param[in] length The total length of the packet, including the header, the addresses and the data of the packet.
    130  *  @param[in] addr_len The source and destination addresses maximal length in bytes.
    131  *  @param[in] max_prefix The maximal prefix length in bytes.
    132  *  @param[in] max_content The maximal content length in bytes.
    133  *  @param[in] max_suffix The maximal suffix length in bytes.
    134  *  @returns The packet of dimensions at least as given.
    135  *  @returns NULL if there is not enough memory left.
    136  */
    137 static packet_t packet_create(size_t length, size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix){
    138         ERROR_DECLARE;
    139 
    140         packet_t packet;
     135/** Creates a new packet of dimensions at least as given.
     136 *
     137 * Should be used only when the global data are locked.
     138 *
     139 * @param[in] length    The total length of the packet, including the header,
     140 *                      the addresses and the data of the packet.
     141 * @param[in] addr_len  The source and destination addresses maximal length in
     142 *                      bytes.
     143 * @param[in] max_prefix The maximal prefix length in bytes.
     144 * @param[in] max_content The maximal content length in bytes.
     145 * @param[in] max_suffix The maximal suffix length in bytes.
     146 * @return              The packet of dimensions at least as given.
     147 * @return              NULL if there is not enough memory left.
     148 */
     149static packet_t *
     150packet_create(size_t length, size_t addr_len, size_t max_prefix,
     151    size_t max_content, size_t max_suffix)
     152{
     153        packet_t *packet;
     154        int rc;
    141155
    142156        // already locked
    143         packet = (packet_t) mmap(NULL, length, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
    144         if(packet == MAP_FAILED){
     157        packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
     158            MAP_SHARED | MAP_ANONYMOUS, 0, 0);
     159        if (packet == MAP_FAILED)
    145160                return NULL;
    146         }
    147         ++ ps_globals.count;
     161
     162        ps_globals.count++;
    148163        packet->packet_id = ps_globals.count;
    149164        packet->length = length;
    150165        packet_init(packet, addr_len, max_prefix, max_content, max_suffix);
    151166        packet->magic_value = PACKET_MAGIC_VALUE;
    152         if(ERROR_OCCURRED(pm_add(packet))){
     167        rc = pm_add(packet);
     168        if (rc != EOK) {
    153169                munmap(packet, packet->length);
    154170                return NULL;
    155171        }
     172       
    156173        return packet;
    157174}
     
    163180 * Lock the global data during its processing.
    164181 *
    165  * @param[in] addr_len    The source and destination addresses
    166  *                        maximal length in bytes.
    167  * @param[in] max_prefix  The maximal prefix length in bytes.
     182 * @param[in] addr_len  The source and destination addresses maximal length in
     183 *                      bytes.
     184 * @param[in] max_prefix The maximal prefix length in bytes.
    168185 * @param[in] max_content The maximal content length in bytes.
    169  * @param[in] max_suffix  The maximal suffix length in bytes.
    170  *
    171  * @return The packet of dimensions at least as given.
    172  * @return NULL if there is not enough memory left.
    173  *
    174  */
    175 static packet_t packet_get_local(size_t addr_len, size_t max_prefix,
    176     size_t max_content, size_t max_suffix)
    177 {
    178         size_t length = ALIGN_UP(sizeof(struct packet) + 2 * addr_len + max_prefix
    179             + max_content + max_suffix, PAGE_SIZE);
     186 * @param[in] max_suffix The maximal suffix length in bytes.
     187 * @return              The packet of dimensions at least as given.
     188 * @return              NULL if there is not enough memory left.
     189 */
     190static packet_t *
     191packet_get_local(size_t addr_len, size_t max_prefix, size_t max_content,
     192    size_t max_suffix)
     193{
     194        size_t length = ALIGN_UP(sizeof(packet_t) + 2 * addr_len +
     195            max_prefix + max_content + max_suffix, PAGE_SIZE);
    180196       
    181197        fibril_mutex_lock(&ps_globals.lock);
    182198       
    183         packet_t packet;
     199        packet_t *packet;
    184200        unsigned int index;
    185201       
    186         for (index = 0; index < FREE_QUEUES_COUNT - 1; index++) {
    187                 if (length <= ps_globals.sizes[index]) {
    188                         packet = ps_globals.free[index];
     202        for (index = 0; index < FREE_QUEUES_COUNT; index++) {
     203                if ((length > ps_globals.sizes[index]) &&
     204                    (index < FREE_QUEUES_COUNT - 1))
     205                        continue;
     206               
     207                packet = ps_globals.free[index];
     208                while (packet_is_valid(packet) && (packet->length < length))
     209                        packet = pm_find(packet->next);
     210               
     211                if (packet_is_valid(packet)) {
     212                        if (packet == ps_globals.free[index])
     213                                ps_globals.free[index] = pq_detach(packet);
     214                        else
     215                                pq_detach(packet);
    189216                       
    190                         while (packet_is_valid(packet) && (packet->length < length))
    191                                 packet = pm_find(packet->next);
     217                        packet_init(packet, addr_len, max_prefix, max_content,
     218                            max_suffix);
     219                        fibril_mutex_unlock(&ps_globals.lock);
    192220                       
    193                         if (packet_is_valid(packet)) {
    194                                 if (packet == ps_globals.free[index])
    195                                         ps_globals.free[index] = pq_detach(packet);
    196                                 else
    197                                         pq_detach(packet);
    198                                
    199                                 packet_init(packet, addr_len, max_prefix, max_content,
    200                                     max_suffix);
    201                                 fibril_mutex_unlock(&ps_globals.lock);
    202                                
    203                                 return packet;
    204                         }
     221                        return packet;
    205222                }
    206223        }
     
    214231}
    215232
    216 packet_t packet_get_4_local(int phone, size_t max_content, size_t addr_len,
    217     size_t max_prefix, size_t max_suffix)
    218 {
    219         return packet_get_local(addr_len, max_prefix, max_content, max_suffix);
    220 }
    221 
    222 packet_t packet_get_1_local(int phone, size_t content)
    223 {
    224         return packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX, content,
    225             DEFAULT_SUFFIX);
    226 }
    227 
    228233/** Release the packet and returns it to the appropriate free packet queue.
    229234 *
    230  *  Should be used only when the global data are locked.
    231  *
    232  *  @param[in] packet The packet to be released.
    233  *
    234  */
    235 static void packet_release(packet_t packet){
     235 * Should be used only when the global data are locked.
     236 *
     237 * @param[in] packet    The packet to be released.
     238 *
     239 */
     240static void packet_release(packet_t *packet)
     241{
    236242        int index;
    237243        int result;
    238244
    239         // remove debug dump
    240 //      printf("packet %d released\n", packet->packet_id);
    241         for(index = 0; (index < FREE_QUEUES_COUNT - 1) && (packet->length > ps_globals.sizes[index]); ++ index);
    242         result = pq_add(&ps_globals.free[index], packet, packet->length, packet->length);
     245        for (index = 0; (index < FREE_QUEUES_COUNT - 1) &&
     246            (packet->length > ps_globals.sizes[index]); index++) {
     247                ;
     248        }
     249       
     250        result = pq_add(&ps_globals.free[index], packet, packet->length,
     251            packet->length);
    243252        assert(result == EOK);
    244253}
    245254
    246255/** Releases the packet queue.
    247  *  @param[in] packet_id The first packet identifier.
    248  *  @returns EOK on success.
    249  *  @returns ENOENT if there is no such packet.
    250  */
    251 static int packet_release_wrapper(packet_id_t packet_id){
    252         packet_t packet;
     256 *
     257 * @param[in] packet_id The first packet identifier.
     258 * @return              EOK on success.
     259 * @return              ENOENT if there is no such packet.
     260 */
     261static int packet_release_wrapper(packet_id_t packet_id)
     262{
     263        packet_t *packet;
    253264
    254265        packet = pm_find(packet_id);
    255         if(! packet_is_valid(packet)){
     266        if (!packet_is_valid(packet))
    256267                return ENOENT;
    257         }
     268
    258269        fibril_mutex_lock(&ps_globals.lock);
    259270        pq_destroy(packet, packet_release);
    260271        fibril_mutex_unlock(&ps_globals.lock);
     272
    261273        return EOK;
    262274}
    263275
    264 void pq_release_local(int phone, packet_id_t packet_id)
    265 {
    266         (void) packet_release_wrapper(packet_id);
    267 }
    268 
    269276/** Shares the packet memory block.
    270  *  @param[in] packet The packet to be shared.
    271  *  @returns EOK on success.
    272  *  @returns EINVAL if the packet is not valid.
    273  *  @returns EINVAL if the calling module does not accept the memory.
    274  *  @returns ENOMEM if the desired and actual sizes differ.
    275  *  @returns Other error codes as defined for the async_share_in_finalize() function.
    276  */
    277 static int packet_reply(const packet_t packet){
     277 * @param[in] packet    The packet to be shared.
     278 * @return              EOK on success.
     279 * @return              EINVAL if the packet is not valid.
     280 * @return              EINVAL if the calling module does not accept the memory.
     281 * @return              ENOMEM if the desired and actual sizes differ.
     282 * @return              Other error codes as defined for the
     283 *                      async_share_in_finalize() function.
     284 */
     285static int packet_reply(packet_t *packet)
     286{
    278287        ipc_callid_t callid;
    279288        size_t size;
    280289
    281         if(! packet_is_valid(packet)){
     290        if (!packet_is_valid(packet))
    282291                return EINVAL;
    283         }
    284         if(async_share_in_receive(&callid, &size) <= 0) return EINVAL;
    285         if(size != packet->length){
     292
     293        if (!async_share_in_receive(&callid, &size)) {
     294                ipc_answer_0(callid, EINVAL);
     295                return EINVAL;
     296        }
     297
     298        if (size != packet->length) {
     299                ipc_answer_0(callid, ENOMEM);
    286300                return ENOMEM;
    287301        }
    288         return async_share_in_finalize(callid, packet, PROTO_READ | PROTO_WRITE);
    289 }
    290 
    291 int packet_server_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    292         packet_t packet;
     302       
     303        return async_share_in_finalize(callid, packet,
     304            PROTO_READ | PROTO_WRITE);
     305}
     306
     307/** Processes the packet server message.
     308 *
     309 * @param[in] callid    The message identifier.
     310 * @param[in] call      The message parameters.
     311 * @param[out] answer   The message answer parameters.
     312 * @param[out] answer_count The last parameter for the actual answer in the
     313 *                      answer parameter.
     314 * @return              EOK on success.
     315 * @return              ENOMEM if there is not enough memory left.
     316 * @return              ENOENT if there is no such packet as in the packet
     317 *                      message parameter.
     318 * @return              ENOTSUP if the message is not known.
     319 * @return              Other error codes as defined for the
     320 *                      packet_release_wrapper() function.
     321 */
     322int
     323packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     324    int *answer_count)
     325{
     326        packet_t *packet;
    293327
    294328        *answer_count = 0;
    295         switch(IPC_GET_METHOD(*call)){
    296                 case IPC_M_PHONE_HUNGUP:
    297                         return EOK;
    298                 case NET_PACKET_CREATE_1:
    299                         packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX, IPC_GET_CONTENT(call), DEFAULT_SUFFIX);
    300                         if(! packet){
    301                                 return ENOMEM;
    302                         }
    303                         *answer_count = 2;
    304                         IPC_SET_ARG1(*answer, (ipcarg_t) packet->packet_id);
    305                         IPC_SET_ARG2(*answer, (ipcarg_t) packet->length);
    306                         return EOK;
    307                 case NET_PACKET_CREATE_4:
    308                         packet = packet_get_local(((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(call)) ? IPC_GET_ADDR_LEN(call) : DEFAULT_ADDR_LEN), DEFAULT_PREFIX + IPC_GET_PREFIX(call), IPC_GET_CONTENT(call), DEFAULT_SUFFIX + IPC_GET_SUFFIX(call));
    309                         if(! packet){
    310                                 return ENOMEM;
    311                         }
    312                         *answer_count = 2;
    313                         IPC_SET_ARG1(*answer, (ipcarg_t) packet->packet_id);
    314                         IPC_SET_ARG2(*answer, (ipcarg_t) packet->length);
    315                         return EOK;
    316                 case NET_PACKET_GET:
    317                         packet = pm_find(IPC_GET_ID(call));
    318                         if(! packet_is_valid(packet)){
    319                                 return ENOENT;
    320                         }
    321                         return packet_reply(packet);
    322                 case NET_PACKET_GET_SIZE:
    323                         packet = pm_find(IPC_GET_ID(call));
    324                         if(! packet_is_valid(packet)){
    325                                 return ENOENT;
    326                         }
    327                         IPC_SET_ARG1(*answer, (ipcarg_t) packet->length);
    328                         *answer_count = 1;
    329                         return EOK;
    330                 case NET_PACKET_RELEASE:
    331                         return packet_release_wrapper(IPC_GET_ID(call));
    332         }
     329        switch (IPC_GET_METHOD(*call)) {
     330        case IPC_M_PHONE_HUNGUP:
     331                return EOK;
     332       
     333        case NET_PACKET_CREATE_1:
     334                packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX,
     335                    IPC_GET_CONTENT(call), DEFAULT_SUFFIX);
     336                if (!packet)
     337                        return ENOMEM;
     338                *answer_count = 2;
     339                IPC_SET_ARG1(*answer, (ipcarg_t) packet->packet_id);
     340                IPC_SET_ARG2(*answer, (ipcarg_t) packet->length);
     341                return EOK;
     342       
     343        case NET_PACKET_CREATE_4:
     344                packet = packet_get_local(
     345                    ((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(call)) ?
     346                    IPC_GET_ADDR_LEN(call) : DEFAULT_ADDR_LEN),
     347                    DEFAULT_PREFIX + IPC_GET_PREFIX(call),
     348                    IPC_GET_CONTENT(call),
     349                    DEFAULT_SUFFIX + IPC_GET_SUFFIX(call));
     350                if (!packet)
     351                        return ENOMEM;
     352                *answer_count = 2;
     353                IPC_SET_ARG1(*answer, (ipcarg_t) packet->packet_id);
     354                IPC_SET_ARG2(*answer, (ipcarg_t) packet->length);
     355                return EOK;
     356       
     357        case NET_PACKET_GET:
     358                packet = pm_find(IPC_GET_ID(call));
     359                if (!packet_is_valid(packet))
     360                        return ENOENT;
     361                return packet_reply(packet);
     362       
     363        case NET_PACKET_GET_SIZE:
     364                packet = pm_find(IPC_GET_ID(call));
     365                if (!packet_is_valid(packet))
     366                        return ENOENT;
     367                IPC_SET_ARG1(*answer, (ipcarg_t) packet->length);
     368                *answer_count = 1;
     369                return EOK;
     370       
     371        case NET_PACKET_RELEASE:
     372                return packet_release_wrapper(IPC_GET_ID(call));
     373        }
     374       
    333375        return ENOTSUP;
    334376}
Note: See TracChangeset for help on using the changeset viewer.