Changeset 8dab988 in mainline


Ignore:
Timestamp:
2018-06-27T18:44:07Z (6 years ago)
Author:
Jiří Zárevúcky <jiri.zarevucky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
62c4297
Parents:
45c39ad
Message:

Put notifications into a dynamic queue instead of forgetting them.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/async/server.c

    r45c39ad r8dab988  
    122122#include "../private/fibril.h"
    123123
     124#define DPRINTF(...)  ((void) 0)
     125
    124126/** Async framework global futex */
    125127futex_t async_futex = FUTEX_INITIALIZER;
     
    180182} connection_t;
    181183
     184/* Member of notification_t::msg_list. */
     185typedef struct {
     186        link_t link;
     187        ipc_call_t calldata;
     188} notification_msg_t;
     189
    182190/* Notification data */
    183191typedef struct {
     
    197205        void *arg;
    198206
    199         /** Data of the most recent notification. */
    200         ipc_call_t calldata;
    201 
    202         /**
    203          * How many notifications with this `imethod` arrived since it was last
    204          * handled. If `count` > 1, `calldata` only holds the data for the most
    205          * recent such notification, all the older data being lost.
    206          *
    207          * `async_spawn_notification_handler()` can be used to increase the
    208          * number of notifications that can be processed simultaneously,
    209          * reducing the likelihood of losing them when the handler blocks.
    210          */
    211         long count;
     207        /** List of arrived notifications. */
     208        list_t msg_list;
    212209} notification_t;
    213210
     
    249246static LIST_INITIALIZE(notification_queue);
    250247static FIBRIL_SEMAPHORE_INITIALIZE(notification_semaphore, 0);
     248
     249static LIST_INITIALIZE(notification_freelist);
     250static long notification_freelist_total = 0;
     251static long notification_freelist_used = 0;
    251252
    252253static sysarg_t notification_avail = 0;
     
    709710                notification_t *notification = list_get_instance(
    710711                    list_first(&notification_queue), notification_t, qlink);
    711                 list_remove(&notification->qlink);
    712712
    713713                async_notification_handler_t handler = notification->handler;
    714714                void *arg = notification->arg;
    715                 ipc_call_t calldata = notification->calldata;
    716                 long count = notification->count;
    717 
    718                 notification->count = 0;
     715
     716                notification_msg_t *m = list_pop(&notification->msg_list,
     717                    notification_msg_t, link);
     718                assert(m);
     719                ipc_call_t calldata = m->calldata;
     720
     721                notification_freelist_used--;
     722
     723                if (notification_freelist_total > 64 &&
     724                    notification_freelist_total > 2 * notification_freelist_used) {
     725                        /* Going to free the structure if we have too much. */
     726                        notification_freelist_total--;
     727                } else {
     728                        /* Otherwise add to freelist. */
     729                        list_append(&m->link, &notification_freelist);
     730                        m = NULL;
     731                }
     732
     733                if (list_empty(&notification->msg_list))
     734                        list_remove(&notification->qlink);
    719735
    720736                futex_unlock(&notification_futex);
    721 
    722                 // FIXME: Pass count to the handler. It might be important.
    723                 (void) count;
    724737
    725738                if (handler)
    726739                        handler(&calldata, arg);
     740
     741                free(m);
    727742        }
    728743
     
    760775        futex_lock(&notification_futex);
    761776
     777        notification_msg_t *m = list_pop(&notification_freelist,
     778            notification_msg_t, link);
     779
     780        if (!m) {
     781                futex_unlock(&notification_futex);
     782                m = malloc(sizeof(notification_msg_t));
     783                if (!m) {
     784                        DPRINTF("Out of memory.\n");
     785                        abort();
     786                }
     787
     788                futex_lock(&notification_futex);
     789                notification_freelist_total++;
     790        }
     791
    762792        ht_link_t *link = hash_table_find(&notification_hash_table,
    763793            &IPC_GET_IMETHOD(*call));
     
    765795                /* Invalid notification. */
    766796                // TODO: Make sure this can't happen and turn it into assert.
     797                notification_freelist_total--;
    767798                futex_unlock(&notification_futex);
     799                free(m);
    768800                return;
    769801        }
     
    772804            hash_table_get_inst(link, notification_t, htlink);
    773805
    774         notification->count++;
    775         notification->calldata = *call;
    776 
    777         if (link_in_use(&notification->qlink)) {
    778                 /* Notification already queued. */
    779                 futex_unlock(&notification_futex);
    780                 return;
    781         }
    782 
    783         list_append(&notification->qlink, &notification_queue);
     806        notification_freelist_used++;
     807        m->calldata = *call;
     808        list_append(&m->link, &notification->msg_list);
     809
     810        if (!link_in_use(&notification->qlink))
     811                list_append(&notification->qlink, &notification_queue);
     812
    784813        futex_unlock(&notification_futex);
    785814
     
    802831        notification->handler = handler;
    803832        notification->arg = arg;
     833
     834        list_initialize(&notification->msg_list);
    804835
    805836        fid_t fib = 0;
Note: See TracChangeset for help on using the changeset viewer.