2 * test-sgen-qsort.c: Our own bzero/memmove.
4 * Copyright (C) 2013 Xamarin Inc
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License 2.0 as published by the Free Software Foundation;
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License 2.0 along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "metadata/gc-internal.h"
24 #define ptr_mask ((sizeof (void*) - 1))
25 #define _toi(ptr) ((size_t)ptr)
26 #define unaligned_bytes(ptr) (_toi(ptr) & ptr_mask)
27 #define align_down(ptr) ((void*)(_toi(ptr) & ~ptr_mask))
28 #define align_up(ptr) ((void*) ((_toi(ptr) + ptr_mask) & ~ptr_mask))
29 #if SIZEOF_VOID_P == 4
30 #define bytes_to_words(n) ((size_t)(n) >> 2)
31 #elif SIZEOF_VOID_P == 8
32 #define bytes_to_words(n) ((size_t)(n) >> 3)
34 #error We only support 32 and 64 bit architectures.
37 #define BZERO_WORDS(dest,words) do { \
38 void **__d = (void**)(dest); \
41 for (__i = 0; __i < __n; ++__i) \
47 * @dest: address to start to clear
48 * @size: size of the region to clear
50 * Zero @size bytes starting at @dest.
52 * Use this to zero memory that can hold managed pointers.
54 * FIXME borrow faster code from some BSD libc or bionic
57 mono_gc_bzero (void *dest, size_t size)
59 char *d = (char*)dest;
60 size_t tail_bytes, word_bytes;
63 If we're copying less than a word, just use memset.
65 We cannot bail out early if both are aligned because some implementations
66 use byte copying for sizes smaller than 16. OSX, on this case.
68 if (size < sizeof(void*)) {
69 memset (dest, 0, size);
73 /*align to word boundary */
74 while (unaligned_bytes (d) && size) {
79 /* copy all words with memmove */
80 word_bytes = (size_t)align_down (size);
82 case sizeof (void*) * 1:
85 case sizeof (void*) * 2:
88 case sizeof (void*) * 3:
91 case sizeof (void*) * 4:
95 BZERO_WORDS (d, bytes_to_words (word_bytes));
98 tail_bytes = unaligned_bytes (size);
103 } while (--tail_bytes);
107 #define MEMMOVE_WORDS_UPWARD(dest,src,words) do { \
108 void **__d = (void**)(dest); \
109 void **__s = (void**)(src); \
110 int __n = (int)(words); \
112 for (__i = 0; __i < __n; ++__i) \
113 __d [__i] = __s [__i]; \
116 #define MEMMOVE_WORDS_DOWNWARD(dest,src,words) do { \
117 void **__d = (void**)(dest); \
118 void **__s = (void**)(src); \
119 int __n = (int)(words); \
121 for (__i = __n - 1; __i >= 0; --__i) \
122 __d [__i] = __s [__i]; \
127 * @dest: destination of the move
129 * @size: size of the block to move
131 * Move @size bytes from @src to @dest.
132 * size MUST be a multiple of sizeof (gpointer)
136 mono_gc_memmove (void *dest, const void *src, size_t size)
139 If we're copying less than a word we don't need to worry about word tearing
140 so we bailout to memmove early.
142 if (size < sizeof(void*)) {
143 memmove (dest, src, size);
148 * A bit of explanation on why we align only dest before doing word copies.
149 * Pointers to managed objects must always be stored in word aligned addresses, so
150 * even if dest is misaligned, src will be by the same amount - this ensure proper atomicity of reads.
152 * We don't need to case when source and destination have different alignments since we only do word stores
153 * using memmove, which must handle it.
155 if (dest > src && ((size_t)((char*)dest - (char*)src) < size)) { /*backward copy*/
156 char *p = (char*)dest + size;
157 char *s = (char*)src + size;
158 char *start = (char*)dest;
159 char *align_end = MAX((char*)dest, (char*)align_down (p));
161 size_t bytes_to_memmove;
163 while (p > align_end)
166 word_start = align_up (start);
167 bytes_to_memmove = p - word_start;
168 p -= bytes_to_memmove;
169 s -= bytes_to_memmove;
170 MEMMOVE_WORDS_DOWNWARD (p, s, bytes_to_words (bytes_to_memmove));
175 char *d = (char*)dest;
176 const char *s = (const char*)src;
179 /*align to word boundary */
180 while (unaligned_bytes (d)) {
185 /* copy all words with memmove */
186 MEMMOVE_WORDS_UPWARD (d, s, bytes_to_words (align_down (size)));
188 tail_bytes = unaligned_bytes (size);
190 d += (size_t)align_down (size);
191 s += (size_t)align_down (size);
194 } while (--tail_bytes);