Ignore:
File:
1 edited

Legend:

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

    rdd5046dd rf63a591d  
    2727 */
    2828
    29 /** @addtogroup libpacket
     29/** @addtogroup packet
    3030 *  @{
    3131 */
    3232
    3333/** @file
    34  * Packet server implementation.
    35  */
    36 
    37 #include <packet_server.h>
     34 *  Packet server implementation.
     35 */
    3836
    3937#include <align.h>
     
    4139#include <async.h>
    4240#include <errno.h>
     41#include <err.h>
    4342#include <fibril_synch.h>
    4443#include <unistd.h>
     
    5251#include <net/packet_header.h>
    5352
     53#include <packet_server.h>
     54#include <packet_local.h>
     55
    5456#define FREE_QUEUES_COUNT       7
    5557
    56 /** The default address length reserved for new packets. */
     58/** The default address length reserved for new packets.
     59 */
    5760#define DEFAULT_ADDR_LEN        32
    5861
    59 /** The default prefix reserved for new packets. */
     62/** The default prefix reserved for new packets.
     63 */
    6064#define DEFAULT_PREFIX          64
    6165
    62 /** The default suffix reserved for new packets. */
     66/** The default suffix reserved for new packets.
     67 */
    6368#define DEFAULT_SUFFIX          64
    6469
    65 /** Packet server global data. */
    66 static struct {
    67         /** Safety lock. */
     70/** Packet server global data.
     71 */
     72static struct{
     73        /** Safety lock.
     74         */
    6875        fibril_mutex_t lock;
    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.
     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.
    7682         */
    7783        size_t sizes[FREE_QUEUES_COUNT];
    78        
    79         /** Total packets allocated. */
     84        /** Total packets allocated.
     85        */
    8086        unsigned int count;
    8187} ps_globals = {
    8288        .lock = FIBRIL_MUTEX_INITIALIZER(ps_globals.lock),
    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         },
     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},
    10191        .count = 0
    10292};
    10393
     94int 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
    104103/** Clears and initializes the packet according to the given dimensions.
    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  */
    113 static void
    114 packet_init(packet_t *packet, size_t addr_len, size_t max_prefix,
    115     size_t max_content, size_t max_suffix)
    116 {
     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 */
     110static void packet_init(packet_t packet, size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix){
    117111        // clear the packet content
    118         bzero(((void *) packet) + sizeof(packet_t),
    119             packet->length - sizeof(packet_t));
    120        
     112        bzero(((void *) packet) + sizeof(struct packet), packet->length - sizeof(struct packet));
    121113        // clear the packet header
    122114        packet->order = 0;
     
    125117        packet->next = 0;
    126118        packet->addr_len = 0;
    127         packet->src_addr = sizeof(packet_t);
     119        packet->src_addr = sizeof(struct packet);
    128120        packet->dest_addr = packet->src_addr + addr_len;
    129121        packet->max_prefix = max_prefix;
     
    133125}
    134126
    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  */
    149 static packet_t *
    150 packet_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;
     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 */
     137static 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;
    155141
    156142        // already locked
    157         packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
    158             MAP_SHARED | MAP_ANONYMOUS, 0, 0);
    159         if (packet == MAP_FAILED)
     143        packet = (packet_t) mmap(NULL, length, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
     144        if(packet == MAP_FAILED){
    160145                return NULL;
    161 
    162         ps_globals.count++;
     146        }
     147        ++ ps_globals.count;
    163148        packet->packet_id = ps_globals.count;
    164149        packet->length = length;
    165150        packet_init(packet, addr_len, max_prefix, max_content, max_suffix);
    166151        packet->magic_value = PACKET_MAGIC_VALUE;
    167         rc = pm_add(packet);
    168         if (rc != EOK) {
     152        if(ERROR_OCCURRED(pm_add(packet))){
    169153                munmap(packet, packet->length);
    170154                return NULL;
    171155        }
    172        
    173156        return packet;
    174157}
     
    180163 * Lock the global data during its processing.
    181164 *
    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.
     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.
    185168 * @param[in] max_content The maximal content length in bytes.
    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  */
    190 static packet_t *
    191 packet_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);
     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 */
     175static 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);
    196180       
    197181        fibril_mutex_lock(&ps_globals.lock);
    198182       
    199         packet_t *packet;
     183        packet_t packet;
    200184        unsigned int index;
    201185       
    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);
     186        for (index = 0; index < FREE_QUEUES_COUNT - 1; index++) {
     187                if (length <= ps_globals.sizes[index]) {
     188                        packet = ps_globals.free[index];
    216189                       
    217                         packet_init(packet, addr_len, max_prefix, max_content,
    218                             max_suffix);
    219                         fibril_mutex_unlock(&ps_globals.lock);
     190                        while (packet_is_valid(packet) && (packet->length < length))
     191                                packet = pm_find(packet->next);
    220192                       
    221                         return packet;
     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                        }
    222205                }
    223206        }
     
    231214}
    232215
     216packet_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
     222packet_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
    233228/** Release the packet and returns it to the appropriate free packet queue.
    234229 *
    235  * Should be used only when the global data are locked.
    236  *
    237  * @param[in] packet    The packet to be released.
    238  *
    239  */
    240 static void packet_release(packet_t *packet)
    241 {
     230 *  Should be used only when the global data are locked.
     231 *
     232 *  @param[in] packet The packet to be released.
     233 *
     234 */
     235static void packet_release(packet_t packet){
    242236        int index;
    243237        int result;
    244238
    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);
     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);
    252243        assert(result == EOK);
    253244}
    254245
    255246/** Releases the packet queue.
    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  */
    261 static int packet_release_wrapper(packet_id_t packet_id)
    262 {
    263         packet_t *packet;
     247 *  @param[in] packet_id The first packet identifier.
     248 *  @returns EOK on success.
     249 *  @returns ENOENT if there is no such packet.
     250 */
     251static int packet_release_wrapper(packet_id_t packet_id){
     252        packet_t packet;
    264253
    265254        packet = pm_find(packet_id);
    266         if (!packet_is_valid(packet))
     255        if(! packet_is_valid(packet)){
    267256                return ENOENT;
    268 
     257        }
    269258        fibril_mutex_lock(&ps_globals.lock);
    270259        pq_destroy(packet, packet_release);
    271260        fibril_mutex_unlock(&ps_globals.lock);
    272 
    273261        return EOK;
    274262}
    275263
     264void pq_release_local(int phone, packet_id_t packet_id)
     265{
     266        (void) packet_release_wrapper(packet_id);
     267}
     268
    276269/** Shares the packet memory block.
    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  */
    285 static int packet_reply(packet_t *packet)
    286 {
     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 */
     277static int packet_reply(const packet_t packet){
    287278        ipc_callid_t callid;
    288279        size_t size;
    289280
    290         if (!packet_is_valid(packet))
     281        if(! packet_is_valid(packet)){
    291282                return EINVAL;
    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);
     283        }
     284        if(async_share_in_receive(&callid, &size) <= 0) return EINVAL;
     285        if(size != packet->length){
    300286                return ENOMEM;
    301287        }
    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  */
    322 int
    323 packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    324     int *answer_count)
    325 {
    326         packet_t *packet;
     288        return async_share_in_finalize(callid, packet, PROTO_READ | PROTO_WRITE);
     289}
     290
     291int packet_server_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     292        packet_t packet;
    327293
    328294        *answer_count = 0;
    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        
     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        }
    375333        return ENOTSUP;
    376334}
Note: See TracChangeset for help on using the changeset viewer.