// File: /workspace/github_c_makefile_star2_O0/gplessis[P]dotdeb-redis/src/server.c
// Function: freeMemoryIfNeeded
int freeMemoryIfNeeded(void) {
    size_t mem_used, mem_tofree, mem_freed;
    int slaves = listLength(server.slaves);
    mstime_t latency, eviction_latency;

    /* When clients are paused the dataset should be static not just from the
     * POV of clients not being able to write, but also from the POV of
     * expires and evictions of keys not being performed. */
    if (clientsArePaused()) return C_OK;

    /* Remove the size of slaves output buffers and AOF buffer from the
     * count of used memory. */
    mem_used = zmalloc_used_memory();
    if (slaves) {
        listIter li;
        listNode *ln;

        listRewind(server.slaves,&li);
        while((ln = listNext(&li))) {
            client *slave = listNodeValue(ln);
            unsigned long obuf_bytes = getClientOutputBufferMemoryUsage(slave);
            if (obuf_bytes > mem_used)
                mem_used = 0;
            else
                mem_used -= obuf_bytes;
        }
    }
    if (server.aof_state != AOF_OFF) {
        mem_used -= sdslen(server.aof_buf);
        mem_used -= aofRewriteBufferSize();
    }

    /* Check if we are over the memory limit. */
    if (mem_used <= server.maxmemory) return C_OK;

    if (server.maxmemory_policy == MAXMEMORY_NO_EVICTION)
        return C_ERR; /* We need to free memory, but policy forbids. */

    /* Compute how much memory we need to free. */
    mem_tofree = mem_used - server.maxmemory;
    mem_freed = 0;
    latencyStartMonitor(latency);
    while (mem_freed < mem_tofree) {
        int j, k, keys_freed = 0;

        for (j = 0; j < server.dbnum; j++) {
            long bestval = 0; /* just to prevent warning */
            sds bestkey = NULL;
            dictEntry *de;
            redisDb *db = server.db+j;
            dict *dict;

            if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU ||
                server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM)
            {
                dict = server.db[j].dict;
            } else {
                dict = server.db[j].expires;
            }
            if (dictSize(dict) == 0) continue;

            /* volatile-random and allkeys-random policy */
            if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM ||
                server.maxmemory_policy == MAXMEMORY_VOLATILE_RANDOM)
            {
                de = dictGetRandomKey(dict);
                bestkey = dictGetKey(de);
            }

            /* volatile-lru and allkeys-lru policy */
            else if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU ||
                server.maxmemory_policy == MAXMEMORY_VOLATILE_LRU)
            {
                struct evictionPoolEntry *pool = db->eviction_pool;

                while(bestkey == NULL) {
                    evictionPoolPopulate(dict, db->dict, db->eviction_pool);
                    /* Go backward from best to worst element to evict. */
                    for (k = MAXMEMORY_EVICTION_POOL_SIZE-1; k >= 0; k--) {
                        if (pool[k].key == NULL) continue;
                        de = dictFind(dict,pool[k].key);

                        /* Remove the entry from the pool. */
                        sdsfree(pool[k].key);
                        /* Shift all elements on its right to left. */
                        memmove(pool+k,pool+k+1,
                            sizeof(pool[0])*(MAXMEMORY_EVICTION_POOL_SIZE-k-1));
                        /* Clear the element on the right which is empty
                         * since we shifted one position to the left.  */
                        pool[MAXMEMORY_EVICTION_POOL_SIZE-1].key = NULL;
                        pool[MAXMEMORY_EVICTION_POOL_SIZE-1].idle = 0;

                        /* If the key exists, is our pick. Otherwise it is
                         * a ghost and we need to try the next element. */
                        if (de) {
                            bestkey = dictGetKey(de);
                            break;
                        } else {
                            /* Ghost... */
                            continue;
                        }
                    }
                }
            }

            /* volatile-ttl */
            else if (server.maxmemory_policy == MAXMEMORY_VOLATILE_TTL) {
                for (k = 0; k < server.maxmemory_samples; k++) {
                    sds thiskey;
                    long thisval;

                    de = dictGetRandomKey(dict);
                    thiskey = dictGetKey(de);
                    thisval = (long) dictGetVal(de);

                    /* Expire sooner (minor expire unix timestamp) is better
                     * candidate for deletion */
                    if (bestkey == NULL || thisval < bestval) {
                        bestkey = thiskey;
                        bestval = thisval;
                    }
                }
            }

            /* Finally remove the selected key. */
            if (bestkey) {
                long long delta;

                robj *keyobj = createStringObject(bestkey,sdslen(bestkey));
                propagateExpire(db,keyobj);
                /* We compute the amount of memory freed by dbDelete() alone.
                 * It is possible that actually the memory needed to propagate
                 * the DEL in AOF and replication link is greater than the one
                 * we are freeing removing the key, but we can't account for
                 * that otherwise we would never exit the loop.
                 *
                 * AOF and Output buffer memory will be freed eventually so
                 * we only care about memory used by the key space. */
                delta = (long long) zmalloc_used_memory();
                latencyStartMonitor(eviction_latency);
                dbDelete(db,keyobj);
                latencyEndMonitor(eviction_latency);
                latencyAddSampleIfNeeded("eviction-del",eviction_latency);
                latencyRemoveNestedEvent(latency,eviction_latency);
                delta -= (long long) zmalloc_used_memory();
                mem_freed += delta;
                server.stat_evictedkeys++;
                notifyKeyspaceEvent(NOTIFY_EVICTED, "evicted",
                    keyobj, db->id);
                decrRefCount(keyobj);
                keys_freed++;

                /* When the memory to free starts to be big enough, we may
                 * start spending so much time here that is impossible to
                 * deliver data to the slaves fast enough, so we force the
                 * transmission here inside the loop. */
                if (slaves) flushSlavesOutputBuffers();
            }
        }
        if (!keys_freed) {
            latencyEndMonitor(latency);
            latencyAddSampleIfNeeded("eviction-cycle",latency);
            return C_ERR; /* nothing to free... */
        }
    }
    latencyEndMonitor(latency);
    latencyAddSampleIfNeeded("eviction-cycle",latency);
    return C_OK;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq 0x143a96(%rip), %rax    # 0x1783b8
movq 0x28(%rax), %rax
movl %eax, -0x24(%rbp)
callq 0x454e0
cmpl $0x0, %eax
je 0x3493f
movl $0x0, -0x4(%rbp)
jmp 0x34f28
callq 0x3b090
movq %rax, -0x10(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0x349b1
movq 0x143a63(%rip), %rdi    # 0x1783b8
leaq -0x48(%rbp), %rsi
callq 0x27320
leaq -0x48(%rbp), %rdi
callq 0x27380
movq %rax, -0x50(%rbp)
cmpq $0x0, %rax
je 0x349af
movq -0x50(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rdi
callq 0x45d60
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
cmpq -0x10(%rbp), %rax
jbe 0x3499e
movq $0x0, -0x10(%rbp)
jmp 0x349ad
movq -0x60(%rbp), %rcx
movq -0x10(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x10(%rbp)
jmp 0x3495e
jmp 0x349b1
cmpl $0x0, 0x143e88(%rip)    # 0x178840
je 0x349e7
movq 0x143ebf(%rip), %rdi    # 0x178880
callq 0x30060
movq %rax, %rcx
movq -0x10(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x10(%rbp)
callq 0x70600
movq %rax, %rcx
movq -0x10(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
cmpq 0x1440ee(%rip), %rax    # 0x178ae0
ja 0x34a00
movl $0x0, -0x4(%rbp)
jmp 0x34f28
cmpl $0x5, 0x1440e1(%rip)    # 0x178ae8
jne 0x34a15
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x34f28
movq -0x10(%rbp), %rax
subq 0x1440c0(%rip), %rax    # 0x178ae0
movq %rax, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
cmpq $0x0, 0x1441bc(%rip)    # 0x178bf0
je 0x34a41
callq 0x2ff70
movq %rax, -0x30(%rbp)
jmp 0x34a49
movq $0x0, -0x30(%rbp)
jmp 0x34a4b
movq -0x20(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0x34ee3
movl $0x0, -0x6c(%rbp)
movl $0x0, -0x64(%rbp)
movl -0x64(%rbp), %eax
cmpl 0x143d78(%rip), %eax    # 0x1787e8
jge 0x34e91
movq $0x0, -0x78(%rbp)
movq $0x0, -0x80(%rbp)
movq 0x143773(%rip), %rax    # 0x178200
movslq -0x64(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x90(%rbp)
cmpl $0x3, 0x144042(%rip)    # 0x178ae8
je 0x34ab1
cmpl $0x4, 0x144039(%rip)    # 0x178ae8
jne 0x34acf
movq 0x143748(%rip), %rax    # 0x178200
movslq -0x64(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq (%rax), %rax
movq %rax, -0x98(%rbp)
jmp 0x34aec
movq 0x14372a(%rip), %rax    # 0x178200
movslq -0x64(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x98(%rbp), %rcx
addq 0x48(%rcx), %rax
cmpq $0x0, %rax
jne 0x34b0d
jmp 0x34e83
cmpl $0x4, 0x143fd4(%rip)    # 0x178ae8
je 0x34b1f
cmpl $0x2, 0x143fcb(%rip)    # 0x178ae8
jne 0x34b45
movq -0x98(%rbp), %rdi
callq 0x2e6a0
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x80(%rbp)
jmp 0x34d35
cmpl $0x3, 0x143f9c(%rip)    # 0x178ae8
je 0x34b5b
cmpl $0x0, 0x143f93(%rip)    # 0x178ae8
jne 0x34ca3
movq -0x90(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0xa0(%rbp)
cmpq $0x0, -0x80(%rbp)
jne 0x34c9e
movq -0x98(%rbp), %rdi
movq -0x90(%rbp), %rax
movq (%rax), %rsi
movq -0x90(%rbp), %rax
movq 0x28(%rax), %rdx
callq 0x36e10
movl $0xf, -0x68(%rbp)
cmpl $0x0, -0x68(%rbp)
jl 0x34c99
movq -0xa0(%rbp), %rax
movslq -0x68(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
cmpq $0x0, 0x8(%rax)
jne 0x34bc8
jmp 0x34c8b
movq -0x98(%rbp), %rdi
movq -0xa0(%rbp), %rax
movslq -0x68(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rsi
callq 0x2dcb0
movq %rax, -0x88(%rbp)
movq -0xa0(%rbp), %rax
movslq -0x68(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rdi
callq 0x38620
movq -0xa0(%rbp), %rdi
movslq -0x68(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
movq -0xa0(%rbp), %rsi
movslq -0x68(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rsi
addq $0x10, %rsi
movl $0x10, %eax
subl -0x68(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rdx
shlq $0x4, %rdx
callq 0x267e0
movq -0xa0(%rbp), %rax
movq $0x0, 0xf8(%rax)
movq -0xa0(%rbp), %rax
movq $0x0, 0xf0(%rax)
cmpq $0x0, -0x88(%rbp)
je 0x34c89
movq -0x88(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x80(%rbp)
jmp 0x34c99
jmp 0x34c8b
movl -0x68(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0x34ba0
jmp 0x34b6d
jmp 0x34d33
cmpl $0x1, 0x143e3e(%rip)    # 0x178ae8
jne 0x34d31
movl $0x0, -0x68(%rbp)
movl -0x68(%rbp), %eax
cmpl 0x143e2c(%rip), %eax    # 0x178aec
jge 0x34d2f
movq -0x98(%rbp), %rdi
callq 0x2e6a0
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xa8(%rbp)
movq -0x88(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0xb0(%rbp)
cmpq $0x0, -0x80(%rbp)
je 0x34d0c
movq -0xb0(%rbp), %rax
cmpq -0x78(%rbp), %rax
jge 0x34d22
movq -0xa8(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0xb0(%rbp), %rax
movq %rax, -0x78(%rbp)
jmp 0x34d24
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0x34cb7
jmp 0x34d31
jmp 0x34d33
jmp 0x34d35
cmpq $0x0, -0x80(%rbp)
je 0x34e81
movq -0x80(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0x80(%rbp), %rdi
callq 0x30060
movq -0xc8(%rbp), %rdi
movq %rax, %rsi
callq 0x486a0
movq %rax, -0xc0(%rbp)
movq -0x90(%rbp), %rdi
movq -0xc0(%rbp), %rsi
callq 0x4c7d0
callq 0x3b090
movq %rax, -0xb8(%rbp)
cmpq $0x0, 0x143e5f(%rip)    # 0x178bf0
je 0x34d9e
callq 0x2ff70
movq %rax, -0x38(%rbp)
jmp 0x34da6
movq $0x0, -0x38(%rbp)
movq -0x90(%rbp), %rdi
movq -0xc0(%rbp), %rsi
callq 0x4ac10
cmpq $0x0, 0x143e2f(%rip)    # 0x178bf0
je 0x34dd0
callq 0x2ff70
subq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, 0x143e18(%rip)    # 0x178bf0
je 0x34df7
movq -0x38(%rbp), %rax
cmpq 0x143e0b(%rip), %rax    # 0x178bf0
jl 0x34df7
movq -0x38(%rbp), %rsi
leaq 0x10469d(%rip), %rdi    # 0x13948f
callq 0xa1210
movq -0x38(%rbp), %rax
addq -0x30(%rbp), %rax
movq %rax, -0x30(%rbp)
callq 0x3b090
movq %rax, %rcx
movq -0xb8(%rbp), %rax
subq %rcx, %rax
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rax
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
movq 0x14374e(%rip), %rax    # 0x178580
addq $0x1, %rax
movq %rax, 0x143743(%rip)    # 0x178580
movq -0xc0(%rbp), %rdx
movq -0x90(%rbp), %rax
movl 0x30(%rax), %ecx
movl $0x200, %edi            # imm = 0x200
leaq 0x104642(%rip), %rsi    # 0x13949c
callq 0x9ce20
movq -0xc0(%rbp), %rdi
callq 0x48f70
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0x34e7f
callq 0x46de0
jmp 0x34e81
jmp 0x34e83
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x34a67
cmpl $0x0, -0x6c(%rbp)
jne 0x34ede
cmpq $0x0, 0x143d51(%rip)    # 0x178bf0
je 0x34eae
callq 0x2ff70
subq -0x30(%rbp), %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, 0x143d3a(%rip)    # 0x178bf0
je 0x34ed5
movq -0x30(%rbp), %rax
cmpq 0x143d2d(%rip), %rax    # 0x178bf0
jl 0x34ed5
movq -0x30(%rbp), %rsi
leaq 0x1045d4(%rip), %rdi    # 0x1394a4
callq 0xa1210
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x34f28
jmp 0x34a4b
cmpq $0x0, 0x143d05(%rip)    # 0x178bf0
je 0x34efa
callq 0x2ff70
subq -0x30(%rbp), %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, 0x143cee(%rip)    # 0x178bf0
je 0x34f21
movq -0x30(%rbp), %rax
cmpq 0x143ce1(%rip), %rax    # 0x178bf0
jl 0x34f21
movq -0x30(%rbp), %rsi
leaq 0x104588(%rip), %rdi    # 0x1394a4
callq 0xa1210
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xd0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)