Navigation


Changeset 1232:9e92fa478c23 in freeDiameter for libfdcore


Ignore:
Timestamp:
Aug 11, 2013, 6:52:36 PM (11 years ago)
Author:
Sebastien Decugis <sdecugis@freediameter.net>
Branch:
default
Phase:
public
Message:

Performance improvements for fd_p_sr_store based on Guangming proposal http://lists.freediameter.net/pipermail/dev/2013-July/000225.html

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfdcore/p_sr.c

    r1207 r1232  
    4242        uint32_t        prevhbh;/* The value to set back in the hbh header when the message is retrieved */
    4343        struct fd_list  expire; /* the list of expiring requests */
     44        struct timespec timeout; /* Cache the expire date of the request so that the timeout thread does not need to get it each time. */
    4445        struct timespec added_on; /* the time the request was added */
    4546};
     
    6162}
    6263
     64/* Similar but start from the end, since we add requests in growing hbh order usually */
     65static struct fd_list * find_or_prev(struct fd_list * srlist, uint32_t hbh, int * match)
     66{
     67        struct fd_list * li;
     68        *match = 0;
     69        for (li = srlist->prev; li != srlist; li = li->prev) {
     70                uint32_t * prevhbh = li->o;
     71                if (*prevhbh > hbh)
     72                        continue;
     73                if (*prevhbh == hbh)
     74                        *match = 1;
     75                break;
     76        }
     77        return li;
     78}
     79
    6380static void srl_dump(const char * text, struct fd_list * srlist)
    6481{
     
    8097}
    8198
    82 struct expire_data {
    83         struct msg * request;
    84         struct fd_peer * sentto;
    85 };
    86 
    87 /* (detached) thread that calls the anscb on expired messages.
    88   We do it in a separate thread to avoid blocking the reception of new messages during this time */
    89 static void * call_expirecb(void * arg) {
    90         struct expire_data * ed = arg;
    91        
    92         void (*expirecb)(void *, DiamId_t, size_t, struct msg **);
    93         void * data;
    94        
    95         TRACE_ENTRY("%p", arg);
    96         CHECK_PARAMS_DO( arg, return NULL );
    97        
    98         /* Set the thread name */
    99         fd_log_threadname ( "Expired req cb." );
    100        
    101         /* Log */
    102         TRACE_DEBUG(INFO, "The expiration timer for a request has been reached, aborting this attempt now & calling cb...");
    103        
    104         /* Retrieve callback in the message */
    105         CHECK_FCT_DO( fd_msg_anscb_get( ed->request, NULL, &expirecb, &data ), return NULL);
    106         ASSERT(expirecb);
    107        
    108         /* Clean up this data from the message */
    109         CHECK_FCT_DO( fd_msg_anscb_associate( ed->request, NULL, NULL, NULL, NULL ), return NULL);
    110 
    111         /* Call it */
    112         (*expirecb)(data, ed->sentto->p_hdr.info.pi_diamid, ed->sentto->p_hdr.info.pi_diamidlen, &ed->request);
    113        
    114         /* If the callback did not dispose of the message, do it now */
    115         if (ed->request) {
    116                 fd_hook_call(HOOK_MESSAGE_DROPPED, ed->request, NULL, "Expiration period completed without an answer, and the expiry callback did not dispose of the message.", fd_msg_pmdl_get(ed->request));
    117                 CHECK_FCT_DO( fd_msg_free(ed->request), /* ignore */ );
    118         }
    119        
    120         free(ed);
    121        
    122         /* Finish */
    123         return NULL;
    124 }
    125 
    12699/* thread that handles messages expiring. The thread is started only when needed */
    127100static void * sr_expiry_th(void * arg) {
    128101        struct sr_list * srlist = arg;
    129         pthread_attr_t detached;
    130         struct expire_data * ed;
    131102       
    132103        TRACE_ENTRY("%p", arg);
     
    140111        }
    141112       
    142         CHECK_POSIX_DO( pthread_attr_init(&detached), return NULL );
    143         CHECK_POSIX_DO( pthread_attr_setdetachstate(&detached, PTHREAD_CREATE_DETACHED), return NULL );
    144        
    145         CHECK_POSIX_DO( pthread_mutex_lock(&srlist->mtx),  return NULL );
    146         pthread_cleanup_push( fd_cleanup_mutex, &srlist->mtx );
    147        
    148113        do {
    149                 struct timespec now, *t;
     114                struct timespec now;
    150115                struct sentreq * first;
    151                 pthread_t th;
    152                
     116                struct msg * request;
     117                struct fd_peer * sentto;
     118                void (*expirecb)(void *, DiamId_t, size_t, struct msg **);
     119                void (*anscb)(void *, struct msg **);
     120                void * data;
     121                int no_error;
     122
     123                CHECK_POSIX_DO( pthread_mutex_lock(&srlist->mtx),  return NULL );
     124                pthread_cleanup_push( fd_cleanup_mutex, &srlist->mtx );
     125
     126loop:   
     127                no_error = 0;
     128
    153129                /* Check if there are expiring requests available */
    154130                if (FD_IS_LIST_EMPTY(&srlist->exp)) {
    155131                        /* Just wait for a change or cancelation */
    156                         CHECK_POSIX_DO( pthread_cond_wait( &srlist->cnd, &srlist->mtx ), goto error );
     132                        CHECK_POSIX_DO( pthread_cond_wait( &srlist->cnd, &srlist->mtx ), goto unlock );
    157133                        /* Restart the loop on wakeup */
    158                         continue;
     134                        goto loop;
    159135                }
    160136               
    161137                /* Get the pointer to the request that expires first */
    162138                first = (struct sentreq *)(srlist->exp.next->o);
    163                 t = fd_msg_anscb_gettimeout( first->req );
    164                 ASSERT(t);
    165139               
    166140                /* Get the current time */
    167                 CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now),  goto error  );
     141                CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &now),  goto unlock  );
    168142
    169143                /* If first request is not expired, we just wait until it happens */
    170                 if ( TS_IS_INFERIOR( &now, t ) ) {
    171                        
    172                         CHECK_POSIX_DO2(  pthread_cond_timedwait( &srlist->cnd, &srlist->mtx, t ), 
     144                if ( TS_IS_INFERIOR( &now, &first->timeout ) ) {
     145                       
     146                        CHECK_POSIX_DO2(  pthread_cond_timedwait( &srlist->cnd, &srlist->mtx, &first->timeout ), 
    173147                                        ETIMEDOUT, /* ETIMEDOUT is a normal return value, continue */,
    174                                         /* on other error, */ goto error );
     148                                        /* on other error, */ goto unlock );
    175149       
    176150                        /* on wakeup, loop */
    177                         continue;
    178                 }
    179                
    180                 /* Now, the first request in the list is expired; remove it and call the anscb for it in a new thread */
    181                 CHECK_MALLOC_DO( ed = malloc(sizeof(struct expire_data)), goto error );
    182                 ed->sentto = first->chain.head->o;
    183                 ed->request = first->req;
    184                 *((uint32_t *)first->chain.o) = first->prevhbh; /* Restore the hbhid */
     151                        goto loop;
     152                }
     153               
     154                /* Now, the first request in the list is expired; remove it and call the expirecb for it */
     155                request = first->req;
     156                sentto = first->chain.head->o;
     157               
     158                TRACE_DEBUG(FULL, "Request %x was not answered by %s within the timer delay", *((uint32_t *)first->chain.o), sentto->p_hdr.info.pi_diamid);
     159               
     160                /* Restore the hbhid */
     161                *((uint32_t *)first->chain.o) = first->prevhbh;
     162               
     163                /* Free the sentreq information */
    185164                fd_list_unlink(&first->chain);
    186165                fd_list_unlink(&first->expire);
    187166                free(first);
    188167               
    189                 CHECK_POSIX_DO( pthread_create( &th, &detached, call_expirecb, ed ), goto error );
    190 
    191                 /* loop */
     168                no_error = 1;
     169unlock:
     170                ; /* pthread_cleanup_pop sometimes expands as "} ..." and the label before this cause some compilers to complain... */
     171                pthread_cleanup_pop( 1 ); /* unlock the mutex */
     172                if (!no_error)
     173                        break;
     174
     175               
     176                /* Retrieve callback in the message */
     177                CHECK_FCT_DO( fd_msg_anscb_get( request, &anscb, &expirecb, &data ), break);
     178                ASSERT(expirecb);
     179       
     180                /* Clean up this expirecb from the message */
     181                CHECK_FCT_DO( fd_msg_anscb_associate( request, anscb, data, NULL, NULL ), break);
     182
     183                /* Call it */
     184                (*expirecb)(data, sentto->p_hdr.info.pi_diamid, sentto->p_hdr.info.pi_diamidlen, &request);
     185       
     186                /* If the callback did not dispose of the message, do it now */
     187                if (request) {
     188                        fd_hook_call(HOOK_MESSAGE_DROPPED, request, NULL, "Expiration period completed without an answer, and the expiry callback did not dispose of the message.", fd_msg_pmdl_get(request));
     189                        CHECK_FCT_DO( fd_msg_free(request), /* ignore */ );
     190                }
     191       
    192192        } while (1);
    193 error: 
    194         ; /* pthread_cleanup_pop sometimes expands as "} ..." and the label before this cause some compilers to complain... */
    195         pthread_cleanup_pop( 1 );
     193       
    196194        ASSERT(0); /* we have encountered a problem, maybe time to signal the framework to terminate? */
    197195        return NULL;
     
    203201{
    204202        struct sentreq * sr;
    205         struct fd_list * next;
     203        struct fd_list * prev;
    206204        int match;
    207205        struct timespec * ts;
     
    220218        /* Search the place in the list */
    221219        CHECK_POSIX( pthread_mutex_lock(&srlist->mtx) );
    222         next = find_or_next(&srlist->srs, *hbhloc, &match);
     220        prev = find_or_prev(&srlist->srs, *hbhloc, &match);
    223221        if (match) {
    224222                TRACE_DEBUG(INFO, "A request with the same hop-by-hop Id (0x%x) was already sent: error", *hbhloc);
     
    231229        /* Save in the list */
    232230        *req = NULL;
    233         fd_list_insert_before(next, &sr->chain);
     231        fd_list_insert_after(prev, &sr->chain);
    234232        srlist->cnt++;
    235233       
     
    238236        if (ts) {
    239237                struct fd_list * li;
    240                 struct timespec * t;
     238               
     239                memcpy(&sr->timeout, ts, sizeof(struct timespec));
    241240               
    242241                /* browse srlist->exp from the end */
    243242                for (li = srlist->exp.prev; li != &srlist->exp; li = li->prev) {
    244243                        struct sentreq * s = (struct sentreq *)(li->o);
    245                         t = fd_msg_anscb_gettimeout( s->req );
    246                         ASSERT( t ); /* sanity */
    247                         if (TS_IS_INFERIOR(t, ts))
     244                        if (TS_IS_INFERIOR(&s->timeout, ts))
    248245                                break;
    249246                }
Note: See TracChangeset for help on using the changeset viewer.