]> git.pld-linux.org Git - packages/neovim.git/blob - armv7-memalign.patch
f5935b0eb93a312d9e9b80291219ac892bcd2179
[packages/neovim.git] / armv7-memalign.patch
1 From 0240fd6d0f7e27c459b243578ad51100ff6e2b66 Mon Sep 17 00:00:00 2001
2 From: Jan Palus <jpalus@fastmail.com>
3 Date: Wed, 5 Oct 2022 00:18:09 +0200
4 Subject: [PATCH 1/2] fix(memory): fix memory alignment for dynamic allocation
5
6 all pointers returned by arena_alloc residing in arena block should be
7 properly aligned
8
9 to meet neovim's alignment requirements but keeping it simple settle on
10 ARENA_ALIGN = MAX(sizeof(void *), sizeof(double)).
11 ---
12  src/nvim/memory.c | 32 +++++++++++++++++++-------------
13  src/nvim/memory.h |  2 +-
14  2 files changed, 20 insertions(+), 14 deletions(-)
15
16 diff --git a/src/nvim/memory.c b/src/nvim/memory.c
17 index 61c43d8f995a..93aa9bd6e55e 100644
18 --- a/src/nvim/memory.c
19 +++ b/src/nvim/memory.c
20 @@ -6,6 +6,7 @@
21  #include <assert.h>
22  #include <inttypes.h>
23  #include <stdbool.h>
24 +#include <stdint.h>
25  #include <string.h>
26  
27  #include "nvim/api/extmark.h"
28 @@ -576,6 +577,12 @@ void alloc_block(Arena *arena)
29    blk->prev = prev_blk;
30  }
31  
32 +static size_t arena_align_offset(void *ptr, size_t alignment)
33 +{
34 +  uintptr_t uptr = (uintptr_t)ptr;
35 +  return ((uptr + (alignment - 1)) & ~(alignment - 1)) - uptr;
36 +}
37 +
38  /// @param arena if NULL, do a global allocation. caller must then free the value!
39  /// @param size if zero, will still return a non-null pointer, but not a unique one
40  void *arena_alloc(Arena *arena, size_t size, bool align)
41 @@ -583,34 +590,33 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
42    if (!arena) {
43      return xmalloc(size);
44    }
45 -  if (align) {
46 -    arena->pos = (arena->pos + (ARENA_ALIGN - 1)) & ~(ARENA_ALIGN - 1);
47 +  if (!arena->cur_blk) {
48 +    alloc_block(arena);
49    }
50 -  if (arena->pos + size > arena->size || !arena->cur_blk) {
51 -    if (size > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk)) >> 1) {
52 +  size_t align_pos = align ? arena_align_offset(arena->cur_blk + arena->pos, ARENA_ALIGN) : 0;
53 +  if (arena->pos + align_pos + size > arena->size) {
54 +    if (size + (align ? (ARENA_ALIGN - 1) : 0) > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk))
55 +        >> 1) {
56        // if allocation is too big, allocate a large block with the requested
57        // size, but still with block pointer head. We do this even for
58        // arena->size / 2, as there likely is space left for the next
59        // small allocation in the current block.
60 -      if (!arena->cur_blk) {
61 -        // to simplify free-list management, arena->cur_blk must
62 -        // always be a normal, ARENA_BLOCK_SIZE sized, block
63 -        alloc_block(arena);
64 -      }
65        arena_alloc_count++;
66 -      char *alloc = xmalloc(size + sizeof(struct consumed_blk));
67 +      char *alloc = xmalloc(size + sizeof(struct consumed_blk) + (align ? (ARENA_ALIGN - 1) : 0));
68        struct consumed_blk *cur_blk = (struct consumed_blk *)arena->cur_blk;
69        struct consumed_blk *fix_blk = (struct consumed_blk *)alloc;
70        fix_blk->prev = cur_blk->prev;
71        cur_blk->prev = fix_blk;
72 -      return (alloc + sizeof(struct consumed_blk));
73 +      char *mem = (alloc + sizeof(struct consumed_blk));
74 +      return mem + (align ? arena_align_offset(mem, ARENA_ALIGN) : 0);
75      } else {
76        alloc_block(arena);
77 +      align_pos = align ? arena_align_offset(arena->cur_blk + arena->pos, ARENA_ALIGN) : 0;
78      }
79    }
80  
81 -  char *mem = arena->cur_blk + arena->pos;
82 -  arena->pos += size;
83 +  char *mem = arena->cur_blk + arena->pos + align_pos;
84 +  arena->pos += (size + align_pos);
85    return mem;
86  }
87  
88 diff --git a/src/nvim/memory.h b/src/nvim/memory.h
89 index f40719233165..1c2ed2ba3b20 100644
90 --- a/src/nvim/memory.h
91 +++ b/src/nvim/memory.h
92 @@ -45,7 +45,7 @@ typedef struct consumed_blk {
93    struct consumed_blk *prev;
94  } *ArenaMem;
95  
96 -#define ARENA_ALIGN sizeof(void *)
97 +#define ARENA_ALIGN MAX(sizeof(void *), sizeof(double))
98  
99  typedef struct {
100    char *cur_blk;
101
102 From 8b7247af7dc613a7e4248ba14760f586a8a66a32 Mon Sep 17 00:00:00 2001
103 From: bfredl <bjorn.linse@gmail.com>
104 Date: Mon, 31 Oct 2022 10:07:21 +0100
105 Subject: [PATCH 2/2] refactor(memory): simplify new alignment logic
106
107 In particular, we can assume the xmalloc-ed pointer is at least
108 double-aligned, otherwise nothing work work.
109 ---
110  src/nvim/memory.c | 32 +++++++++++++++++---------------
111  1 file changed, 17 insertions(+), 15 deletions(-)
112
113 diff --git a/src/nvim/memory.c b/src/nvim/memory.c
114 index 93aa9bd6e55e..16033e9c63f5 100644
115 --- a/src/nvim/memory.c
116 +++ b/src/nvim/memory.c
117 @@ -577,14 +577,13 @@ void alloc_block(Arena *arena)
118    blk->prev = prev_blk;
119  }
120  
121 -static size_t arena_align_offset(void *ptr, size_t alignment)
122 +static size_t arena_align_offset(uint64_t off)
123  {
124 -  uintptr_t uptr = (uintptr_t)ptr;
125 -  return ((uptr + (alignment - 1)) & ~(alignment - 1)) - uptr;
126 +  return ((off + (ARENA_ALIGN - 1)) & ~(ARENA_ALIGN - 1));
127  }
128  
129  /// @param arena if NULL, do a global allocation. caller must then free the value!
130 -/// @param size if zero, will still return a non-null pointer, but not a unique one
131 +/// @param size if zero, will still return a non-null pointer, but not a usable or unique one
132  void *arena_alloc(Arena *arena, size_t size, bool align)
133  {
134    if (!arena) {
135 @@ -593,30 +592,33 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
136    if (!arena->cur_blk) {
137      alloc_block(arena);
138    }
139 -  size_t align_pos = align ? arena_align_offset(arena->cur_blk + arena->pos, ARENA_ALIGN) : 0;
140 -  if (arena->pos + align_pos + size > arena->size) {
141 -    if (size + (align ? (ARENA_ALIGN - 1) : 0) > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk))
142 -        >> 1) {
143 +  size_t alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos;
144 +  if (alloc_pos + size > arena->size) {
145 +    if (size > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk)) >> 1) {
146        // if allocation is too big, allocate a large block with the requested
147        // size, but still with block pointer head. We do this even for
148        // arena->size / 2, as there likely is space left for the next
149        // small allocation in the current block.
150        arena_alloc_count++;
151 -      char *alloc = xmalloc(size + sizeof(struct consumed_blk) + (align ? (ARENA_ALIGN - 1) : 0));
152 +      size_t hdr_size = sizeof(struct consumed_blk);
153 +      size_t aligned_hdr_size = (align ? arena_align_offset(hdr_size) : hdr_size);
154 +      char *alloc = xmalloc(size + aligned_hdr_size);
155 +
156 +      // to simplify free-list management, arena->cur_blk must
157 +      // always be a normal, ARENA_BLOCK_SIZE sized, block
158        struct consumed_blk *cur_blk = (struct consumed_blk *)arena->cur_blk;
159        struct consumed_blk *fix_blk = (struct consumed_blk *)alloc;
160        fix_blk->prev = cur_blk->prev;
161        cur_blk->prev = fix_blk;
162 -      char *mem = (alloc + sizeof(struct consumed_blk));
163 -      return mem + (align ? arena_align_offset(mem, ARENA_ALIGN) : 0);
164 +      return alloc + aligned_hdr_size;
165      } else {
166 -      alloc_block(arena);
167 -      align_pos = align ? arena_align_offset(arena->cur_blk + arena->pos, ARENA_ALIGN) : 0;
168 +      alloc_block(arena);  // resets arena->pos
169 +      alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos;
170      }
171    }
172  
173 -  char *mem = arena->cur_blk + arena->pos + align_pos;
174 -  arena->pos += (size + align_pos);
175 +  char *mem = arena->cur_blk + alloc_pos;
176 +  arena->pos = alloc_pos + size;
177    return mem;
178  }
179  
This page took 0.073081 seconds and 2 git commands to generate.