Skip to content

Commit 3a0a96e

Browse files
committed
First draft of minimal-mt
1 parent b3cffa3 commit 3a0a96e

File tree

8 files changed

+680
-593
lines changed

8 files changed

+680
-593
lines changed

Diff for: cli/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ export async function main(argv, options) {
300300
switch (opts.runtime) {
301301
case "stub": runtime = 0; break;
302302
case "minimal": runtime = 1; break;
303+
case "minimal-mt": runtime = 4; break;
303304
/* incremental */
304305
default: runtime = 2; break;
305306
}

Diff for: std/assembly/rt/index-incremental.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
import "rt/tlsf";
2-
import "rt/itcms";
1+
import "rt/tlsf-base";
2+
import "rt/tlsf-st";
3+
import "rt/itcms";

Diff for: std/assembly/rt/index-minimal-mt.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import "rt/tlsf-base";
2+
import "rt/tlsf-mt";
3+
import "rt/tcms";

Diff for: std/assembly/rt/index-minimal.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
import "rt/tlsf";
2-
import "rt/tcms";
1+
import "rt/tlsf-base";
2+
import "rt/tlsf-st";
3+
import "rt/tcms";

Diff for: std/assembly/rt/tlsf.ts renamed to std/assembly/rt/tlsf-base.ts

+567-589
Large diffs are not rendered by default.

Diff for: std/assembly/rt/tlsf-mt.ts

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import {BLOCK_OVERHEAD} from "./common";
2+
import {allocateBlock, freeBlock, reallocateBlock, ROOT, TLSFinitialize, moveBlock, checkUsedBlock} from "./tlsf-base";
3+
import {TlsfMutex_lock, TlsfMutex_unlock} from './tlsf-mutex'
4+
5+
const mutex_ptr = memory.data(4, 16);
6+
7+
// @ts-ignore: decorator
8+
@global @unsafe
9+
export function __alloc(size: usize): usize {
10+
TlsfMutex_lock(mutex_ptr);
11+
12+
if (!ROOT) TLSFinitialize();
13+
let r: usize = changetype<usize>(allocateBlock(ROOT, size)) + BLOCK_OVERHEAD;
14+
15+
TlsfMutex_unlock(mutex_ptr);
16+
return r;
17+
}
18+
19+
// @ts-ignore: decorator
20+
@global @unsafe
21+
export function __realloc(ptr: usize, size: usize): usize {
22+
TlsfMutex_lock(mutex_ptr);
23+
24+
if (!ROOT) TLSFinitialize();
25+
let r: usize = (ptr < __heap_base
26+
? changetype<usize>(moveBlock(ROOT, checkUsedBlock(ptr), size))
27+
: changetype<usize>(reallocateBlock(ROOT, checkUsedBlock(ptr), size))
28+
) + BLOCK_OVERHEAD;
29+
30+
TlsfMutex_unlock(mutex_ptr);
31+
return r;
32+
}
33+
34+
// @ts-ignore: decorator
35+
@global @unsafe
36+
export function __free(ptr: usize): void {
37+
if (ptr < __heap_base) return;
38+
39+
TlsfMutex_lock(mutex_ptr);
40+
41+
if (!ROOT) TLSFinitialize();
42+
freeBlock(ROOT, checkUsedBlock(ptr));
43+
44+
TlsfMutex_unlock(mutex_ptr);
45+
}

Diff for: std/assembly/rt/tlsf-mutex.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// This just implements a super-simple lock for tlsf-mt.ts
2+
3+
enum TlsfMutexState {
4+
unlocked,
5+
locked
6+
}
7+
8+
// Basic spinlock. Spinning is not a performance issue since this only takes as long as an allocation
9+
// @ts-ignore: decorator
10+
@inline
11+
export function TlsfMutex_lock(mutex_ptr: usize): void {
12+
for (; ;) {
13+
// If we succesfully atomically compare and exchange unlocked for locked, we have the mutex
14+
if (atomic.cmpxchg<i32>(mutex_ptr, TlsfMutexState.unlocked, TlsfMutexState.locked) === TlsfMutexState.unlocked)
15+
return;
16+
// Wait for unlocked state to try for locked
17+
for (; ;) {
18+
if (atomic.load<i32>(mutex_ptr) === TlsfMutexState.unlocked) break;
19+
}
20+
}
21+
}
22+
23+
// @ts-ignore: decorator
24+
@inline
25+
export function TlsfMutex_unlock(mutex_ptr: usize): void {
26+
if (atomic.cmpxchg<i32>(mutex_ptr, TlsfMutexState.locked, TlsfMutexState.unlocked) !== TlsfMutexState.locked) {
27+
// This only happens if someone else unlocked our mutex, or we did it more than once...
28+
throw new Error('Is this the right thing to do here? Mutex in inconsistent state');
29+
}
30+
}

Diff for: std/assembly/rt/tlsf-st.ts

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {BLOCK_OVERHEAD} from "./common";
2+
import {allocateBlock, freeBlock, reallocateBlock, ROOT, TLSFinitialize, moveBlock, checkUsedBlock} from "./tlsf-base";
3+
4+
// @ts-ignore: decorator
5+
@global @unsafe
6+
export function __alloc(size: usize): usize {
7+
if (!ROOT) TLSFinitialize();
8+
9+
return changetype<usize>(allocateBlock(ROOT, size)) + BLOCK_OVERHEAD;
10+
}
11+
12+
// @ts-ignore: decorator
13+
@global @unsafe
14+
export function __realloc(ptr: usize, size: usize): usize {
15+
if (!ROOT) TLSFinitialize();
16+
return (ptr < __heap_base
17+
? changetype<usize>(moveBlock(ROOT, checkUsedBlock(ptr), size))
18+
: changetype<usize>(reallocateBlock(ROOT, checkUsedBlock(ptr), size))
19+
) + BLOCK_OVERHEAD;
20+
}
21+
22+
// @ts-ignore: decorator
23+
@global @unsafe
24+
export function __free(ptr: usize): void {
25+
if (ptr < __heap_base) return;
26+
if (!ROOT) TLSFinitialize();
27+
freeBlock(ROOT, checkUsedBlock(ptr));
28+
}

0 commit comments

Comments
 (0)