<commit_before>#include <assert.h>

#include "chunk.h"
#include "extent.h"
#include "memory.h"
#include "mutex.h"

static extent_tree chunks_addr;
static extent_tree chunks_size_addr;
static mutex chunks_mutex = MUTEX_INITIALIZER;

void chunk_init(void) {
    extent_tree_ad_new(&chunks_addr);
    extent_tree_szad_new(&chunks_size_addr);
}

void chunk_free(void *chunk, size_t size) {
    mutex_lock(&chunks_mutex);
    struct extent_node key;
    key.addr = (void *)((uintptr_t)chunk + size);
    struct extent_node *node = extent_tree_ad_nsearch(&chunks_addr, &key);
    /* Try to coalesce forward. */
    if (node && node->addr == key.addr) {
        /*
         * Coalesce chunk with the following address range.  This does
         * not change the position within chunks_ad, so only
         * remove/insert from/into chunks_szad.
         */
        extent_tree_szad_remove(&chunks_size_addr, node);
        node->addr = chunk;
        node->size += size;
        extent_tree_szad_insert(&chunks_size_addr, node);
    } else {
        node = node_alloc();
        /* Coalescing forward failed, so insert a new node. */
        if (!node) {
            /*
             * node_alloc() failed, which is an exceedingly
             * unlikely failure.  Leak chunk; its pages have
             * already been purged, so this is only a virtual
             * memory leak.
             */
            goto label_return;
        }
        node->addr = chunk;
        node->size = size;
        extent_tree_ad_insert(&chunks_addr, node);
        extent_tree_szad_insert(&chunks_size_addr, node);
    }

    /* Try to coalesce backward. */
    struct extent_node *prev = extent_tree_ad_prev(&chunks_addr, node);
    if (prev && (void *)((uintptr_t)prev->addr + prev->size) == chunk) {
        /*
         * Coalesce chunk with the previous address range.  This does
         * not change the position within chunks_ad, so only
         * remove/insert node from/into chunks_szad.
         */
        extent_tree_szad_remove(&chunks_size_addr, prev);
        extent_tree_ad_remove(&chunks_addr, prev);

        extent_tree_szad_remove(&chunks_size_addr, node);
        node->addr = prev->addr;<commit_msg>chunk: improve handling of the rare OOM case<commit_after>#include <assert.h>

#include "chunk.h"
#include "extent.h"
#include "memory.h"
#include "mutex.h"

static extent_tree chunks_addr;
static extent_tree chunks_size_addr;
static mutex chunks_mutex = MUTEX_INITIALIZER;

void chunk_init(void) {
    extent_tree_ad_new(&chunks_addr);
    extent_tree_szad_new(&chunks_size_addr);
}

void chunk_free(void *chunk, size_t size) {
    mutex_lock(&chunks_mutex);
    struct extent_node key;
    key.addr = (void *)((uintptr_t)chunk + size);
    struct extent_node *node = extent_tree_ad_nsearch(&chunks_addr, &key);
    /* Try to coalesce forward. */
    if (node && node->addr == key.addr) {
        /*
         * Coalesce chunk with the following address range.  This does
         * not change the position within chunks_ad, so only
         * remove/insert from/into chunks_szad.
         */
        extent_tree_szad_remove(&chunks_size_addr, node);
        node->addr = chunk;
        node->size += size;
        extent_tree_szad_insert(&chunks_size_addr, node);
    } else {
        node = node_alloc();
        /* Coalescing forward failed, so insert a new node. */
        if (!node) {
            // Failed to allocate an extent node, so just unmap the chunk(s).
            memory_unmap(chunk, size);
            goto label_return;
        }
        node->addr = chunk;
        node->size = size;
        extent_tree_ad_insert(&chunks_addr, node);
        extent_tree_szad_insert(&chunks_size_addr, node);
    }

    /* Try to coalesce backward. */
    struct extent_node *prev = extent_tree_ad_prev(&chunks_addr, node);
    if (prev && (void *)((uintptr_t)prev->addr + prev->size) == chunk) {
        /*
         * Coalesce chunk with the previous address range.  This does
         * not change the position within chunks_ad, so only
         * remove/insert node from/into chunks_szad.
         */
        extent_tree_szad_remove(&chunks_size_addr, prev);
        extent_tree_ad_remove(&chunks_addr, prev);

        extent_tree_szad_remove(&chunks_size_addr, node);
        node->addr = prev->addr;
{'fraction_non_alphanumeric': 0.10580046403712297, 'fraction_numerical': 0.0, 'mean_word_length': 2.644125105663567, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1898279', 'n_tokens_mistral': 1355, 'n_tokens_neox': 1363, 'n_words': 333}