This source file includes following definitions.
- mca_rcache_rgpusm_deregister_lru
- mca_rcache_rgpusm_module_init
- mca_rcache_rgpusm_register
- mca_rcache_rgpusm_find
- registration_is_cachebale
- mca_rcache_rgpusm_deregister
- mca_rcache_rgpusm_deregister_no_lock
- mca_rcache_rgpusm_finalize
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 #define OPAL_DISABLE_ENABLE_MEM_DEBUG 1
  81 #include "opal_config.h"
  82 #include "opal/align.h"
  83 #include "opal/mca/rcache/rgpusm/rcache_rgpusm.h"
  84 #include <errno.h>
  85 #include <string.h>
  86 #ifdef HAVE_MALLOC_H
  87 #include <malloc.h>
  88 #endif
  89 #include "opal/util/proc.h"
  90 #include "opal/mca/rcache/rcache.h"
  91 #include "opal/mca/rcache/base/base.h"
  92 #include "opal/mca/rcache/base/base.h"
  93 #include "opal/mca/common/cuda/common_cuda.h"
  94 
  95 
  96 static int mca_rcache_rgpusm_deregister_no_lock(struct mca_rcache_base_module_t *,
  97                                                mca_rcache_base_registration_t *);
  98 static inline bool mca_rcache_rgpusm_deregister_lru (mca_rcache_base_module_t *rcache) {
  99     mca_rcache_rgpusm_module_t *rcache_rgpusm = (mca_rcache_rgpusm_module_t *) rcache;
 100     mca_rcache_base_registration_t *old_reg;
 101     int rc;
 102 
 103     
 104 
 105     old_reg = (mca_rcache_base_registration_t*)
 106         opal_list_remove_first (&rcache_rgpusm->lru_list);
 107     if (NULL == old_reg) {
 108         opal_output_verbose(10, mca_rcache_rgpusm_component.output,
 109                             "RGPUSM: The LRU list is empty. There is nothing to deregister");
 110         return false;
 111     }
 112 
 113     mca_rcache_base_vma_delete (rcache_rgpusm->vma_module, old_reg);
 114 
 115     
 116     OPAL_THREAD_UNLOCK(&rcache->lock);
 117     assert(old_reg->ref_count == 0);
 118     rc = cuda_closememhandle (NULL, old_reg);
 119     OPAL_THREAD_LOCK(&rcache->lock);
 120 
 121     
 122 
 123 
 124     if (OPAL_SUCCESS != rc) {
 125         opal_output_verbose(10, mca_rcache_rgpusm_component.output,
 126                             "RGPUSM: Failed to deregister the memory addr=%p, size=%d",
 127                             old_reg->base, (int)(old_reg->bound - old_reg->base + 1));
 128         return false;
 129     }
 130 
 131     opal_free_list_return (&rcache_rgpusm->reg_list,
 132                            (opal_free_list_item_t*)old_reg);
 133     rcache_rgpusm->stat_evicted++;
 134 
 135     return true;
 136 }
 137 
 138 
 139 
 140 
 141 
 142 void mca_rcache_rgpusm_module_init(mca_rcache_rgpusm_module_t* rcache)
 143 {
 144     rcache->super.rcache_component = &mca_rcache_rgpusm_component.super;
 145     rcache->super.rcache_register = mca_rcache_rgpusm_register;
 146     rcache->super.rcache_find = mca_rcache_rgpusm_find;
 147     rcache->super.rcache_deregister = mca_rcache_rgpusm_deregister;
 148     rcache->super.rcache_finalize = mca_rcache_rgpusm_finalize;
 149     rcache->vma_module = mca_rcache_base_vma_module_alloc ();
 150 
 151     OBJ_CONSTRUCT(&rcache->reg_list, opal_free_list_t);
 152     opal_free_list_init (&rcache->reg_list, sizeof(struct mca_rcache_common_cuda_reg_t),
 153             opal_cache_line_size,
 154             OBJ_CLASS(mca_rcache_base_registration_t),
 155             0,opal_cache_line_size,
 156             0, -1, 32, NULL, 0, NULL, NULL, NULL);
 157     OBJ_CONSTRUCT(&rcache->lru_list, opal_list_t);
 158     rcache->stat_cache_hit = rcache->stat_cache_miss = rcache->stat_evicted = 0;
 159     rcache->stat_cache_found = rcache->stat_cache_notfound = 0;
 160     rcache->stat_cache_valid = rcache->stat_cache_invalid = 0;
 161 
 162 }
 163 
 164 
 165 
 166 
 167 
 168 
 169 int mca_rcache_rgpusm_register (mca_rcache_base_module_t *rcache, void *addr,
 170                                size_t size, uint32_t flags, int32_t access_flags,
 171                                mca_rcache_base_registration_t **reg)
 172 {
 173     mca_rcache_rgpusm_module_t *rcache_rgpusm = (mca_rcache_rgpusm_module_t*)rcache;
 174     mca_rcache_common_cuda_reg_t *rgpusm_reg;
 175     mca_rcache_common_cuda_reg_t *rget_reg;
 176     opal_free_list_item_t *item;
 177     int rc;
 178     int mypeer;  
 179 
 180     
 181 
 182 
 183 
 184     rget_reg = (mca_rcache_common_cuda_reg_t *)*reg;
 185 
 186     mypeer = flags;
 187     flags = 0;
 188     
 189     assert(0 == (flags & MCA_RCACHE_FLAGS_CACHE_BYPASS));
 190 
 191     
 192 
 193 
 194 
 195 
 196 
 197     if(!mca_rcache_rgpusm_component.leave_pinned && 0 == mca_rcache_rgpusm_component.rcache_size_limit) {
 198         item = opal_free_list_get (&rcache_rgpusm->reg_list);
 199         if(NULL == item) {
 200             return OPAL_ERR_OUT_OF_RESOURCE;
 201         }
 202         rgpusm_reg = (mca_rcache_common_cuda_reg_t*)item;
 203         rgpusm_reg->base.rcache = rcache;
 204         rgpusm_reg->base.base = addr;
 205         rgpusm_reg->base.bound = (unsigned char *)addr + size - 1;;
 206         rgpusm_reg->base.flags = flags;
 207 
 208         
 209         memcpy(rgpusm_reg->data.memHandle, rget_reg->data.memHandle, sizeof(rget_reg->data.memHandle));
 210 
 211         
 212 
 213 
 214         rc = cuda_openmemhandle (addr, size, (mca_rcache_base_registration_t *)rgpusm_reg,
 215                                  (mca_rcache_base_registration_t *)rget_reg);
 216 
 217         
 218         assert(OPAL_ERR_WOULD_BLOCK != rc);
 219 
 220         if(rc != OPAL_SUCCESS) {
 221             opal_free_list_return (&rcache_rgpusm->reg_list, item);
 222             return rc;
 223         }
 224         rgpusm_reg->base.ref_count++;
 225         *reg = (mca_rcache_base_registration_t *)rgpusm_reg;
 226         return OPAL_SUCCESS;
 227     }
 228 
 229     
 230     OPAL_THREAD_LOCK(&rcache->lock);
 231     mca_rcache_base_vma_find (rcache_rgpusm->vma_module, addr, size, reg);
 232 
 233     
 234 
 235 
 236 
 237 
 238 
 239 
 240     if (*reg != NULL) {
 241         rcache_rgpusm->stat_cache_hit++;
 242         opal_output_verbose(10, mca_rcache_rgpusm_component.output,
 243                             "RGPUSM: Found addr=%p,size=%d (base=%p,size=%d) in cache",
 244                             addr, (int)size, (*reg)->base,
 245                             (int)((*reg)->bound - (*reg)->base));
 246 
 247         if (mca_common_cuda_memhandle_matches((mca_rcache_common_cuda_reg_t *)*reg, rget_reg)) {
 248             
 249             rcache_rgpusm->stat_cache_valid++;
 250         } else {
 251             
 252             opal_output_verbose(10, mca_rcache_rgpusm_component.output,
 253                                 "RGPUSM: Mismatched Handle: Evicting/unregistering "
 254                                 "addr=%p,size=%d (base=%p,size=%d) from cache",
 255                                 addr, (int)size, (*reg)->base,
 256                                 (int)((*reg)->bound - (*reg)->base));
 257 
 258             
 259 
 260             assert(0 == (*reg)->ref_count);
 261             if (mca_rcache_rgpusm_component.leave_pinned) {
 262                 opal_list_remove_item(&rcache_rgpusm->lru_list,
 263                                       (opal_list_item_t*)(*reg));
 264             }
 265 
 266             
 267             (*reg)->ref_count++;
 268             
 269             (*reg)->flags |= MCA_RCACHE_FLAGS_INVALID;
 270             mca_rcache_rgpusm_deregister_no_lock(rcache, *reg);
 271             *reg = NULL;
 272             rcache_rgpusm->stat_cache_invalid++;
 273         }
 274     } else {
 275         
 276         rcache_rgpusm->stat_cache_miss++;
 277     }
 278 
 279     
 280     if (*reg != NULL) {
 281         opal_output_verbose(10, mca_rcache_rgpusm_component.output,
 282                             "RGPUSM: CACHE HIT is good: ep=%d, addr=%p, size=%d in cache",
 283                             mypeer, addr, (int)size);
 284 
 285         
 286         if ((0 == (*reg)->ref_count) && mca_rcache_rgpusm_component.leave_pinned) {
 287             opal_output_verbose(20, mca_rcache_rgpusm_component.output,
 288                                 "RGPUSM: POP OFF LRU: ep=%d, addr=%p, size=%d in cache",
 289                                 mypeer, addr, (int)size);
 290             opal_list_remove_item(&rcache_rgpusm->lru_list,
 291                                   (opal_list_item_t*)(*reg));
 292         }
 293         (*reg)->ref_count++;
 294         OPAL_THREAD_UNLOCK(&rcache->lock);
 295         opal_output(-1, "reg->ref_count=%d", (int)(*reg)->ref_count);
 296         opal_output_verbose(80, mca_rcache_rgpusm_component.output,
 297                            "RGPUSM: Found entry in cache addr=%p, size=%d", addr, (int)size);
 298         return OPAL_SUCCESS;
 299     }
 300 
 301     
 302 
 303     assert(NULL == *reg);
 304     opal_output_verbose(10, mca_rcache_rgpusm_component.output,
 305                         "RGPUSM: New registration ep=%d, addr=%p, size=%d. Need to register and insert in cache",
 306                          mypeer, addr, (int)size);
 307 
 308     item = opal_free_list_get (&rcache_rgpusm->reg_list);
 309     if(NULL == item) {
 310         OPAL_THREAD_UNLOCK(&rcache->lock);
 311         return OPAL_ERR_OUT_OF_RESOURCE;
 312     }
 313     rgpusm_reg = (mca_rcache_common_cuda_reg_t*)item;
 314 
 315     rgpusm_reg->base.rcache = rcache;
 316     rgpusm_reg->base.base = addr;
 317     rgpusm_reg->base.bound = (unsigned char *)addr + size - 1;
 318     rgpusm_reg->base.flags = flags;
 319 
 320     
 321     memcpy(rgpusm_reg->data.memHandle, rget_reg->data.memHandle, sizeof(rget_reg->data.memHandle));
 322 
 323     
 324 
 325 
 326 
 327 
 328     rc = cuda_openmemhandle (addr, size, (mca_rcache_base_registration_t *)rgpusm_reg,
 329                              (mca_rcache_base_registration_t *)rget_reg);
 330     
 331 
 332 
 333 
 334 
 335 
 336 
 337 
 338 
 339 
 340 
 341     if (OPAL_ERR_WOULD_BLOCK == rc) {
 342         mca_rcache_base_registration_t *oldreg;
 343 
 344         
 345 
 346         mca_rcache_base_vma_find (rcache_rgpusm->vma_module, addr, 4, &oldreg);
 347 
 348         
 349 
 350 
 351         if (NULL != oldreg) {
 352             
 353 
 354             assert(0 == oldreg->ref_count);
 355             if (mca_rcache_rgpusm_component.leave_pinned) {
 356                 opal_list_remove_item(&rcache_rgpusm->lru_list,
 357                                       (opal_list_item_t*)oldreg);
 358             }
 359 
 360             
 361             oldreg->ref_count++;
 362             
 363             oldreg->flags |= MCA_RCACHE_FLAGS_INVALID;
 364             mca_rcache_rgpusm_deregister_no_lock(rcache, oldreg);
 365             rcache_rgpusm->stat_evicted++;
 366 
 367             
 368             rc = cuda_openmemhandle (addr, size, (mca_rcache_base_registration_t *)rgpusm_reg,
 369                                      (mca_rcache_base_registration_t *)rget_reg);
 370         }
 371 
 372         
 373 
 374 
 375         while (OPAL_SUCCESS != rc) {
 376             if (true != mca_rcache_rgpusm_deregister_lru(rcache)) {
 377                 rc = OPAL_ERROR;
 378                 break;
 379             }
 380             
 381             rc = cuda_openmemhandle (addr, size, (mca_rcache_base_registration_t *)rgpusm_reg,
 382                                      (mca_rcache_base_registration_t *)rget_reg);
 383         }
 384     }
 385 
 386     if(rc != OPAL_SUCCESS) {
 387         OPAL_THREAD_UNLOCK(&rcache->lock);
 388         opal_free_list_return (&rcache_rgpusm->reg_list, item);
 389         return rc;
 390     }
 391 
 392     opal_output_verbose(80, mca_rcache_rgpusm_component.output,
 393                         "RGPUSM: About to insert in rgpusm cache addr=%p, size=%d", addr, (int)size);
 394     rc = mca_rcache_base_vma_insert (rcache_rgpusm->vma_module, (mca_rcache_base_registration_t *)rgpusm_reg,
 395                                       mca_rcache_rgpusm_component.rcache_size_limit);
 396     if (OPAL_ERR_TEMP_OUT_OF_RESOURCE == rc) {
 397         opal_output_verbose(40, mca_rcache_rgpusm_component.output,
 398                             "RGPUSM: No room in the cache - boot the first one out");
 399         (void)mca_rcache_rgpusm_deregister_lru(rcache);
 400         if (mca_rcache_rgpusm_component.empty_cache) {
 401             int remNum = 1;
 402             
 403             opal_output_verbose(40, mca_rcache_rgpusm_component.output,
 404                                 "RGPUSM: About to delete all the unused entries in the cache");
 405             while (mca_rcache_rgpusm_deregister_lru(rcache)) {
 406                 remNum++;
 407             }
 408             opal_output_verbose(40, mca_rcache_rgpusm_component.output,
 409                                 "RGPUSM: Deleted and deregistered %d entries", remNum);
 410             rc = mca_rcache_base_vma_insert (rcache_rgpusm->vma_module, (mca_rcache_base_registration_t *)rgpusm_reg,
 411                                              mca_rcache_rgpusm_component.rcache_size_limit);
 412         } else {
 413             
 414             while((rc = mca_rcache_base_vma_insert (rcache_rgpusm->vma_module, (mca_rcache_base_registration_t *)rgpusm_reg,
 415                                                     mca_rcache_rgpusm_component.rcache_size_limit)) ==
 416                   OPAL_ERR_TEMP_OUT_OF_RESOURCE) {
 417                 opal_output_verbose(40, mca_rcache_rgpusm_component.output,
 418                                     "RGPUSM: No room in the cache - boot one out");
 419                 if (!mca_rcache_rgpusm_deregister_lru(rcache)) {
 420                     break;
 421                 }
 422             }
 423         }
 424     }
 425 
 426     if(rc != OPAL_SUCCESS) {
 427         OPAL_THREAD_UNLOCK(&rcache->lock);
 428         opal_free_list_return (&rcache_rgpusm->reg_list, item);
 429         
 430 
 431 
 432 
 433 
 434 
 435         opal_output_verbose(10, mca_rcache_rgpusm_component.output,
 436                             "RGPUSM: Failed to register addr=%p, size=%d", addr, (int)size);
 437         return OPAL_ERROR;
 438     }
 439 
 440     rgpusm_reg->base.ref_count++;
 441     *reg = (mca_rcache_base_registration_t *)rgpusm_reg;
 442     OPAL_THREAD_UNLOCK(&rcache->lock);
 443 
 444     return OPAL_SUCCESS;
 445 }
 446 
 447 int mca_rcache_rgpusm_find(struct mca_rcache_base_module_t *rcache, void *addr,
 448         size_t size, mca_rcache_base_registration_t **reg)
 449 {
 450     mca_rcache_rgpusm_module_t *rcache_rgpusm = (mca_rcache_rgpusm_module_t*)rcache;
 451     int rc;
 452     unsigned char *base, *bound;
 453 
 454     base = addr;
 455     bound = base + size - 1; 
 456 
 457     OPAL_THREAD_LOCK(&rcache->lock);
 458     opal_output(-1, "Looking for addr=%p, size=%d", addr, (int)size);
 459     rc = mca_rcache_base_vma_find (rcache_rgpusm->vma_module, addr, size, reg);
 460     if(*reg != NULL && mca_rcache_rgpusm_component.leave_pinned) {
 461         if(0 == (*reg)->ref_count && mca_rcache_rgpusm_component.leave_pinned) {
 462             opal_list_remove_item(&rcache_rgpusm->lru_list, (opal_list_item_t*)(*reg));
 463         }
 464         rcache_rgpusm->stat_cache_found++;
 465         (*reg)->ref_count++;
 466     } else {
 467         rcache_rgpusm->stat_cache_notfound++;
 468     }
 469     OPAL_THREAD_UNLOCK(&rcache->lock);
 470 
 471     return rc;
 472 }
 473 
 474 static inline bool registration_is_cachebale(mca_rcache_base_registration_t *reg)
 475 {
 476      return !(reg->flags &
 477              (MCA_RCACHE_FLAGS_CACHE_BYPASS |
 478               MCA_RCACHE_FLAGS_INVALID));
 479 }
 480 
 481 int mca_rcache_rgpusm_deregister(struct mca_rcache_base_module_t *rcache,
 482                             mca_rcache_base_registration_t *reg)
 483 {
 484     mca_rcache_rgpusm_module_t *rcache_rgpusm = (mca_rcache_rgpusm_module_t*)rcache;
 485     int rc = OPAL_SUCCESS;
 486     assert(reg->ref_count > 0);
 487 
 488     OPAL_THREAD_LOCK(&rcache->lock);
 489     reg->ref_count--;
 490     opal_output(-1, "Deregister: reg->ref_count=%d", (int)reg->ref_count);
 491     if(reg->ref_count > 0) {
 492         OPAL_THREAD_UNLOCK(&rcache->lock);
 493         return OPAL_SUCCESS;
 494     }
 495     if(mca_rcache_rgpusm_component.leave_pinned && registration_is_cachebale(reg))
 496     {
 497         
 498 
 499         opal_output_verbose(20, mca_rcache_rgpusm_component.output,
 500                             "RGPUSM: Deregister: addr=%p, size=%d: cacheable and pinned, leave in cache, PUSH IN LRU",
 501                             reg->base, (int)(reg->bound - reg->base + 1));
 502         opal_list_prepend(&rcache_rgpusm->lru_list, (opal_list_item_t*)reg);
 503     } else {
 504         
 505         if(!(reg->flags & MCA_RCACHE_FLAGS_CACHE_BYPASS))
 506             mca_rcache_base_vma_delete (rcache_rgpusm->vma_module, reg);
 507 
 508         
 509         OPAL_THREAD_UNLOCK(&rcache->lock);
 510 
 511         {
 512              assert(reg->ref_count == 0);
 513              rc = cuda_closememhandle (NULL, reg);
 514          }
 515 
 516         OPAL_THREAD_LOCK(&rcache->lock);
 517 
 518         if(OPAL_SUCCESS == rc) {
 519             opal_free_list_return (&rcache_rgpusm->reg_list,
 520                                    (opal_free_list_item_t*)reg);
 521         }
 522     }
 523     OPAL_THREAD_UNLOCK(&rcache->lock);
 524 
 525     return rc;
 526 }
 527 
 528 int mca_rcache_rgpusm_deregister_no_lock(struct mca_rcache_base_module_t *rcache,
 529                             mca_rcache_base_registration_t *reg)
 530 {
 531     mca_rcache_rgpusm_module_t *rcache_rgpusm = (mca_rcache_rgpusm_module_t*)rcache;
 532     int rc = OPAL_SUCCESS;
 533     assert(reg->ref_count > 0);
 534 
 535     reg->ref_count--;
 536     opal_output(-1, "Deregister: reg->ref_count=%d", (int)reg->ref_count);
 537     if(reg->ref_count > 0) {
 538         return OPAL_SUCCESS;
 539     }
 540     if(mca_rcache_rgpusm_component.leave_pinned && registration_is_cachebale(reg))
 541     {
 542         
 543 
 544         opal_list_prepend(&rcache_rgpusm->lru_list, (opal_list_item_t*)reg);
 545     } else {
 546         
 547         if(!(reg->flags & MCA_RCACHE_FLAGS_CACHE_BYPASS))
 548             mca_rcache_base_vma_delete (rcache_rgpusm->vma_module, reg);
 549 
 550         assert(reg->ref_count == 0);
 551         rc = cuda_closememhandle (NULL, reg);
 552 
 553         if(OPAL_SUCCESS == rc) {
 554             opal_free_list_return (&rcache_rgpusm->reg_list,
 555                                    (opal_free_list_item_t*)reg);
 556         }
 557     }
 558 
 559     return rc;
 560 }
 561 
 562 #define RGPUSM_RCACHE_NREGS 100
 563 
 564 void mca_rcache_rgpusm_finalize(struct mca_rcache_base_module_t *rcache)
 565 {
 566     mca_rcache_rgpusm_module_t *rcache_rgpusm = (mca_rcache_rgpusm_module_t*)rcache;
 567     mca_rcache_base_registration_t *reg;
 568     mca_rcache_base_registration_t *regs[RGPUSM_RCACHE_NREGS];
 569     int reg_cnt, i;
 570     int rc;
 571 
 572     
 573     if(true == mca_rcache_rgpusm_component.print_stats) {
 574         opal_output(0, "%s rgpusm: stats "
 575                 "(hit/valid/invalid/miss/evicted): %d/%d/%d/%d/%d\n",
 576                 OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
 577                 rcache_rgpusm->stat_cache_hit, rcache_rgpusm->stat_cache_valid,
 578                 rcache_rgpusm->stat_cache_invalid, rcache_rgpusm->stat_cache_miss,
 579                 rcache_rgpusm->stat_evicted);
 580     }
 581 
 582     OPAL_THREAD_LOCK(&rcache->lock);
 583     do {
 584         reg_cnt = mca_rcache_base_vma_find_all (rcache_rgpusm->vma_module, 0, (size_t)-1,
 585                 regs, RGPUSM_RCACHE_NREGS);
 586         opal_output(-1, "Registration size at finalize = %d", reg_cnt);
 587 
 588         for(i = 0; i < reg_cnt; i++) {
 589             reg = regs[i];
 590 
 591             if(reg->ref_count) {
 592                 reg->ref_count = 0; 
 593             } else if (mca_rcache_rgpusm_component.leave_pinned) {
 594                 opal_list_remove_item(&rcache_rgpusm->lru_list,
 595                         (opal_list_item_t*)reg);
 596             }
 597 
 598             
 599             mca_rcache_base_vma_delete (rcache_rgpusm->vma_module, reg);
 600 
 601             
 602             OPAL_THREAD_UNLOCK(&rcache->lock);
 603             assert(reg->ref_count == 0);
 604             rc = cuda_closememhandle (NULL, reg);
 605             OPAL_THREAD_LOCK(&rcache->lock);
 606 
 607             if(rc != OPAL_SUCCESS) {
 608                 
 609 
 610                 continue;
 611             }
 612 
 613             opal_free_list_return (&rcache_rgpusm->reg_list,
 614                                    (opal_free_list_item_t *) reg);
 615         }
 616     } while(reg_cnt == RGPUSM_RCACHE_NREGS);
 617 
 618     OBJ_DESTRUCT(&rcache_rgpusm->lru_list);
 619     OBJ_DESTRUCT(&rcache_rgpusm->reg_list);
 620     OPAL_THREAD_UNLOCK(&rcache->lock);
 621 }