1/*
2 * Copyright (C) 2018 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "PerProcess.h"
27
28#include "VMAllocate.h"
29#include <stdio.h>
30
31namespace bmalloc {
32
33static constexpr unsigned tableSize = 100;
34static constexpr bool verbose = false;
35
36static Mutex s_mutex;
37
38static char* s_bumpBase;
39static size_t s_bumpOffset;
40static size_t s_bumpLimit;
41
42static PerProcessData* s_table[tableSize];
43
44// Returns zero-filled memory by virtual of using vmAllocate.
45static void* allocate(size_t size, size_t alignment)
46{
47 s_bumpOffset = roundUpToMultipleOf(alignment, s_bumpOffset);
48 void* result = s_bumpBase + s_bumpOffset;
49 s_bumpOffset += size;
50 if (s_bumpOffset <= s_bumpLimit)
51 return result;
52
53 size_t allocationSize = vmSize(size);
54 void* allocation = vmAllocate(allocationSize);
55 s_bumpBase = static_cast<char*>(allocation);
56 s_bumpOffset = 0;
57 s_bumpLimit = allocationSize;
58 return allocate(size, alignment);
59}
60
61PerProcessData* getPerProcessData(unsigned hash, const char* disambiguator, size_t size, size_t alignment)
62{
63 std::lock_guard<Mutex> lock(s_mutex);
64
65 PerProcessData*& bucket = s_table[hash % tableSize];
66
67 for (PerProcessData* data = bucket; data; data = data->next) {
68 if (!strcmp(data->disambiguator, disambiguator)) {
69 if (verbose)
70 fprintf(stderr, "%d: Using existing %s\n", getpid(), disambiguator);
71 RELEASE_BASSERT(data->size == size);
72 RELEASE_BASSERT(data->alignment == alignment);
73 return data;
74 }
75 }
76
77 if (verbose)
78 fprintf(stderr, "%d: Creating new %s\n", getpid(), disambiguator);
79 void* rawDataPtr = allocate(sizeof(PerProcessData), std::alignment_of<PerProcessData>::value);
80 PerProcessData* data = static_cast<PerProcessData*>(rawDataPtr);
81 data->disambiguator = disambiguator;
82 data->memory = allocate(size, alignment);
83 data->size = size;
84 data->alignment = alignment;
85 data->next = bucket;
86 bucket = data;
87 return data;
88}
89
90} // namespace bmalloc
91
92