函数源码

Linux Kernel

v5.5.9

Brick Technologies Co., Ltd

Source File:lib\lru_cache.c Create Date:2022-07-27 08:15:20
首页 Copyright©Brick

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
static struct lc_element *__lc_get(struct lru_cache *lc, unsigned int enr, unsigned int flags)
{
    struct lc_element *e;
 
    PARANOIA_ENTRY();
    if (lc->flags & LC_STARVING) {
        ++lc->starving;
        RETURN(NULL);
    }
 
    e = __lc_find(lc, enr, 1);
    /* if lc_new_number != lc_number,
     * this enr is currently being pulled in already,
     * and will be available once the pending transaction
     * has been committed. */
    if (e) {
        if (e->lc_new_number != e->lc_number) {
            /* It has been found above, but on the "to_be_changed"
             * list, not yet committed.  Don't pull it in twice,
             * wait for the transaction, then try again...
             */
            if (!(flags & LC_GET_MAY_USE_UNCOMMITTED))
                RETURN(NULL);
            /* ... unless the caller is aware of the implications,
             * probably preparing a cumulative transaction. */
            ++e->refcnt;
            ++lc->hits;
            RETURN(e);
        }
        /* else: lc_new_number == lc_number; a real hit. */
        ++lc->hits;
        if (e->refcnt++ == 0)
            lc->used++;
        list_move(&e->list, &lc->in_use); /* Not evictable... */
        RETURN(e);
    }
    /* e == NULL */
 
    ++lc->misses;
    if (!(flags & LC_GET_MAY_CHANGE))
        RETURN(NULL);
 
    /* To avoid races with lc_try_lock(), first, mark us dirty
     * (using test_and_set_bit, as it implies memory barriers), ... */
    test_and_set_bit(__LC_DIRTY, &lc->flags);
 
    /* ... only then check if it is locked anyways. If lc_unlock clears
     * the dirty bit again, that's not a problem, we will come here again.
     */
    if (test_bit(__LC_LOCKED, &lc->flags)) {
        ++lc->locked;
        RETURN(NULL);
    }
 
    /* In case there is nothing available and we can not kick out
     * the LRU element, we have to wait ...
     */
    if (!lc_unused_element_available(lc)) {
        __set_bit(__LC_STARVING, &lc->flags);
        RETURN(NULL);
    }
 
    /* It was not present in the active set.  We are going to recycle an
     * unused (or even "free") element, but we won't accumulate more than
     * max_pending_changes changes.  */
    if (lc->pending_changes >= lc->max_pending_changes)
        RETURN(NULL);
 
    e = lc_prepare_for_change(lc, enr);
    BUG_ON(!e);
 
    clear_bit(__LC_STARVING, &lc->flags);
    BUG_ON(++e->refcnt != 1);
    lc->used++;
    lc->pending_changes++;
 
    RETURN(e);
}