Skip to content

Commit 3ff9e93

Browse files
committed
Fix markdownlint warnings
1 parent f4a931a commit 3ff9e93

10 files changed

+347
-319
lines changed

_posts/2016-08-16-lock-free-gc-handles.md

+12-12
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ In addition to programmers’ regular use of handles, Mono uses them in its impl
2828

2929
A `GCHandle` object consists of a type and an index, packed together into a 32-bit unsigned integer. To get the value of a handle, say with `WeakReference.Target`, we first look up the array of handle data corresponding to its type, then look up the value at the given index; in pseudocode:
3030

31-
```
31+
```text
3232
(type, index) = unpack(handle)
3333
value = handles[type][index]
3434
```
3535

3636
The original implementation of GC handles was based on a bitmap allocator. For each handle type, it stored a bitmap indicating the available slots for allocating new handles, and an array of pointers to their target objects:
3737

38-
```
38+
```text
3939
bitmap = 11010…
4040
pointers = [0xPPPPPPPP, 0xPPPPPPPP, NULL, 0xPPPPPPPP, NULL, …]
4141
```
@@ -44,7 +44,7 @@ There’s an interesting constraint, though: when we unload an `AppDomain`, we w
4444

4545
But if the weak reference has expired, we can’t tell what domain it came from, because we no longer have an object to look at! So for weak references, we kept a parallel array of domain pointers:
4646

47-
```
47+
```text
4848
domains = [0xDDDDDDDD, 0xDDDDDDDD, NULL, 0xDDDDDDDD, NULL, …]
4949
```
5050

@@ -65,21 +65,21 @@ After removing the redundant hash table, the first step toward a new lock-free i
6565

6666
We ended up with a single array of *slots* in the following bit format:
6767

68-
```
68+
```text
6969
PPPPPPPP…0VX
7070
```
7171

7272
Where `PPPP…` are pointer bits, `V` is the “valid” flag, and `X` is the “occupied” flag, packed together with bitwise OR:
7373

74-
```
74+
```text
7575
slot = pointer | valid_bit | occupied_bit
7676
```
7777

7878
If the “occupied” flag is clear, the slot is free to be claimed by `GCHandle.Alloc`. To allocate a handle, we use a CAS (“compare and swap”, also known as [`Interlocked.CompareExchange`][Interlocked.CompareExchange]) to replace a null slot with a tagged pointer, where the “occupied” and “valid” flags are set:
7979

8080
[Interlocked.CompareExchange]: https://msdn.microsoft.com/en-us/library/system.threading.interlocked.compareexchange(v=vs.110).aspx
8181

82-
```
82+
```text
8383
cas(slot, tag(pointer), NULL)
8484
8585
00000000…000
@@ -93,7 +93,7 @@ As for `AppDomain` unloading, we can observe that we only need to store a domain
9393

9494
Therefore, when a weak reference expires, all we have to do is clear the “valid” flag and replace the object pointer with a domain pointer:
9595

96-
```
96+
```text
9797
PPPPPPPP…011
9898
9999
DDDDDDDD…001
@@ -116,7 +116,7 @@ Now that we have our representation of slots, how do we grow the handle array wh
116116

117117
To solve this, instead of a single handle array, we use a handle *table* consisting of an array of *buckets*, each twice the size of the last:
118118

119-
```
119+
```text
120120
[0] → xxxxxxxx
121121
[1] → xxxxxxxxxxxxxxxx
122122
[2] → xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
@@ -139,15 +139,15 @@ If the CAS fails, then another thread has already allocated a new bucket, so we
139139

140140
Before this change was implemented, these were the average timings over 5 runs:
141141

142-
```
142+
```bash
143143
real 0m2.441s
144144
user 0m1.591s
145145
sys 0m0.959s
146146
```
147147

148148
After the change:
149149

150-
```
150+
```bash
151151
real 0m0.358s
152152
user 0m0.406s
153153
sys 0m0.063s
@@ -157,15 +157,15 @@ Cool! We got about an 80% improvement.
157157

158158
Let’s look at `monitor-stress`, which stress-tests `Monitor` operations using the C♯ `lock` statement. Before the change, average of 5 runs:
159159

160-
```
160+
```bash
161161
real 0m2.714s
162162
user 0m6.963s
163163
sys 0m0.244s
164164
```
165165

166166
Now, with the change:
167167

168-
```
168+
```bash
169169
real 0m2.681s
170170
user 0m6.783s
171171
sys 0m0.242s

_posts/2016-09-07-profiler-managed-allocators.md

+56-56
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,19 @@ the actual source code):
4343
static gboolean
4444
is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip)
4545
{
46-
/*
47-
* ip is the instruction pointer of the thread, as obtained by the STW
48-
* machinery when it temporarily suspends the thread.
49-
*/
46+
/*
47+
* ip is the instruction pointer of the thread, as obtained by the STW
48+
* machinery when it temporarily suspends the thread.
49+
*/
5050

51-
MonoJitInfo *ji = mono_jit_info_table_find_internal (domain, ip, FALSE, FALSE);
51+
MonoJitInfo *ji = mono_jit_info_table_find_internal (domain, ip, FALSE, FALSE);
5252

53-
if (!ji)
54-
return FALSE;
53+
if (!ji)
54+
return FALSE;
5555

56-
MonoMethod *m = mono_jit_info_get_method (ji);
56+
MonoMethod *m = mono_jit_info_get_method (ji);
5757

58-
return sgen_is_managed_allocator (m);
58+
return sgen_is_managed_allocator (m);
5959
}
6060
```
6161
@@ -66,7 +66,7 @@ two separate signal handlers for `SIGUSR1` and `SIGUSR2`, both of which simply
6666
do `while (1);` to spin forever, and you send `SIGUSR1` followed by `SIGUSR2`
6767
to your program, you'll see a stack trace looking something like this:
6868
69-
```
69+
```gdb
7070
(gdb) bt
7171
#0 0x0000000000400564 in sigusr2_signal_handler ()
7272
#1 <signal handler called>
@@ -78,7 +78,7 @@ to your program, you'll see a stack trace looking something like this:
7878
Unsurprisingly, if we print the instruction pointer, we'll find that it's
7979
pointing into the most recently called signal handler:
8080

81-
```
81+
```gdb
8282
(gdb) p $pc
8383
$1 = (void (*)()) 0x400564 <sigusr2_signal_handler+15>
8484
```
@@ -90,7 +90,7 @@ arrive at any point, including while the other is being handled. In an
9090
allocation-heavy program, we could very easily see a stack looking something
9191
like this:
9292

93-
```
93+
```gdb
9494
#0 suspend_signal_handler ()
9595
#1 <signal handler called>
9696
#2 profiler_signal_handler ()
@@ -103,7 +103,7 @@ like this:
103103

104104
Under normal (non-profiling) circumstances, it would look like this:
105105

106-
```
106+
```gdb
107107
#0 suspend_signal_handler ()
108108
#1 <signal handler called>
109109
#2 AllocSmall ()
@@ -180,29 +180,29 @@ at how SGen allocates a `System.String` in the native allocation functions:
180180
MonoString *
181181
mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len)
182182
{
183-
TLAB_ACCESS_INIT;
183+
TLAB_ACCESS_INIT;
184184

185-
ENTER_CRITICAL_REGION;
185+
ENTER_CRITICAL_REGION;
186186

187-
MonoString *str = sgen_try_alloc_obj_nolock (vtable, size);
187+
MonoString *str = sgen_try_alloc_obj_nolock (vtable, size);
188188

189-
if (str)
190-
str->length = len;
189+
if (str)
190+
str->length = len;
191191

192-
EXIT_CRITICAL_REGION;
192+
EXIT_CRITICAL_REGION;
193193

194-
if (!str) {
195-
LOCK_GC;
194+
if (!str) {
195+
LOCK_GC;
196196

197-
str = sgen_alloc_obj_nolock (vtable, size);
197+
str = sgen_alloc_obj_nolock (vtable, size);
198198

199-
if (str)
200-
str->length = len;
199+
if (str)
200+
str->length = len;
201201

202-
UNLOCK_GC;
203-
}
202+
UNLOCK_GC;
203+
}
204204

205-
return str;
205+
return str;
206206
}
207207
```
208208
@@ -233,35 +233,35 @@ so:
233233
static MonoMethod *
234234
create_allocator (int atype, ManagedAllocatorVariant variant)
235235
{
236-
// ... snip ...
236+
// ... snip ...
237237

238-
MonoMethodBuilder *mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_ALLOC);
239-
int thread_var;
238+
MonoMethodBuilder *mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_ALLOC);
239+
int thread_var;
240240

241-
// ... snip ...
241+
// ... snip ...
242242

243-
EMIT_TLS_ACCESS_VAR (mb, thread_var);
243+
EMIT_TLS_ACCESS_VAR (mb, thread_var);
244244

245-
EMIT_TLS_ACCESS_IN_CRITICAL_REGION_ADDR (mb, thread_var);
246-
mono_mb_emit_byte (mb, CEE_LDC_I4_1);
247-
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
248-
mono_mb_emit_byte (mb, CEE_MONO_ATOMIC_STORE_I4);
249-
mono_mb_emit_i4 (mb, MONO_MEMORY_BARRIER_NONE);
245+
EMIT_TLS_ACCESS_IN_CRITICAL_REGION_ADDR (mb, thread_var);
246+
mono_mb_emit_byte (mb, CEE_LDC_I4_1);
247+
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
248+
mono_mb_emit_byte (mb, CEE_MONO_ATOMIC_STORE_I4);
249+
mono_mb_emit_i4 (mb, MONO_MEMORY_BARRIER_NONE);
250250

251-
// ... snip: allocation logic ...
251+
// ... snip: allocation logic ...
252252

253-
EMIT_TLS_ACCESS_IN_CRITICAL_REGION_ADDR (mb, thread_var);
254-
mono_mb_emit_byte (mb, CEE_LDC_I4_0);
255-
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
256-
mono_mb_emit_byte (mb, CEE_MONO_ATOMIC_STORE_I4);
257-
mono_mb_emit_i4 (mb, MONO_MEMORY_BARRIER_REL);
253+
EMIT_TLS_ACCESS_IN_CRITICAL_REGION_ADDR (mb, thread_var);
254+
mono_mb_emit_byte (mb, CEE_LDC_I4_0);
255+
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
256+
mono_mb_emit_byte (mb, CEE_MONO_ATOMIC_STORE_I4);
257+
mono_mb_emit_i4 (mb, MONO_MEMORY_BARRIER_REL);
258258

259-
// ... snip ...
259+
// ... snip ...
260260

261-
MonoMethod *m = mono_mb_create (mb, csig, 8, info);
262-
mono_mb_free (mb);
261+
MonoMethod *m = mono_mb_create (mb, csig, 8, info);
262+
mono_mb_free (mb);
263263

264-
return m;
264+
return m;
265265
}
266266
```
267267
@@ -278,27 +278,27 @@ I ran this small program before and after the changes:
278278
using System;
279279
280280
class Program {
281-
public static object o;
281+
public static object o;
282282
283-
static void Main ()
284-
{
285-
for (var i = 0; i < 100000000; i++)
286-
o = new object ();
287-
}
283+
static void Main ()
284+
285+
for (var i = 0; i < 100000000; i++)
286+
o = new object ();
287+
}
288288
}
289289
```
290290

291291
Before:
292292

293-
```
293+
```bash
294294
real 0m0.625s
295295
user 0m0.652s
296296
sys 0m0.032s
297297
```
298298

299299
After:
300300

301-
```
301+
```bash
302302
real 0m0.883s
303303
user 0m0.948s
304304
sys 0m0.012s
@@ -314,7 +314,7 @@ point in being fast if Mono is crashy as a result. To put things in
314314
perspective, this program is still way slower without managed allocators
315315
(`MONO_GC_DEBUG=no-managed-allocator`):
316316

317-
```
317+
```bash
318318
real 0m7.678s
319319
user 0m8.529s
320320
sys 0m0.024s

_posts/2016-09-12-arm64-icache.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ title: "A tale of an impossible bug: big.LITTLE and caching"
44
author: Rodrigo Kumpera and Bernhard Urban
55
tags: [runtime]
66
---
7+
78
When someone says multi-core, we unconsciously think SMP. That worked out well for us until recently when ARM announced big.LITTLE.
89
ARM's [big.LITTLE architecture](https://en.wikipedia.org/wiki/ARM_big.LITTLE)
910
is the first mass produced
@@ -38,7 +39,7 @@ This was our only clue, and there are no coincidences when it comes to this sort
3839
and the `SIGILL` would [always happen to be somewhere between](https://gist.github.com/lewurm/97dff0a56929b56a0fc5ab49af06fd06) `0x40-0x7f` or `0xc0-0xff`.
3940
We aligned the memory dump to help verify whether the code allocator was doing something funky:
4041

41-
```
42+
```bash
4243
$ grep SIGILL *.log
4344
custom_01.log:E/mono (13964): SIGILL at ip=0x0000007f4f15e8d0
4445
custom_02.log:E/mono (13088): SIGILL at ip=0x0000007f8ff76cc0
@@ -58,12 +59,12 @@ Here is a pseudo version of how `libgcc` [does cache flushing on arm64](https://
5859
```c
5960
void __clear_cache (char *address, size_t size)
6061
{
61-
static int cache_line_size = 0;
62-
if (!cache_line_size)
63-
cache_line_size = get_current_cpu_cache_line_size ();
62+
static int cache_line_size = 0;
63+
if (!cache_line_size)
64+
cache_line_size = get_current_cpu_cache_line_size ();
6465

65-
for (int i = 0; i < size; i += cache_line_size)
66-
flush_cache_line (address + i);
66+
for (int i = 0; i < size; i += cache_line_size)
67+
flush_cache_line (address + i);
6768
}
6869
```
6970

_posts/2016-11-29-mono-code-sharing.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Mono's use of Reference Source Code
1010

1111
Since the first release of the .NET open source code, the Mono project
1212
has been integrating the published [Reference
13-
Source](https://github.com/microsoft/referencesource) code into Mono.
13+
Source](https://github.com/microsoft/referencesource) code into Mono.
1414

1515
We have been using the Reference Source code instead of the
1616
[CoreFX](https://github.com/dotnet/corefx), as Mono implements a

0 commit comments

Comments
 (0)