Skip to content

Commit 9413785

Browse files
committed
WIP runtime: lock output in print/println
This ensures that calls to print/println happening in different threads are not interleaved. TODO: this lock might need to be recursive, so that signal handlers (such as SIGSEGV) can print things when a segmentation fault happens while the lock is held.
1 parent 6c3cfa3 commit 9413785

File tree

5 files changed

+47
-5
lines changed

5 files changed

+47
-5
lines changed

compiler/compiler.go

+2
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
16861686
b.createRuntimeInvoke("_panic", argValues, "")
16871687
return llvm.Value{}, nil
16881688
case "print", "println":
1689+
b.createRuntimeCall("printlock", nil, "")
16891690
for i, value := range argValues {
16901691
if i >= 1 && callName == "println" {
16911692
b.createRuntimeCall("printspace", nil, "")
@@ -1746,6 +1747,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
17461747
if callName == "println" {
17471748
b.createRuntimeCall("printnl", nil, "")
17481749
}
1750+
b.createRuntimeCall("printunlock", nil, "")
17491751
return llvm.Value{}, nil // print() or println() returns void
17501752
case "real":
17511753
cplx := argValues[0]

compiler/testdata/defer-cortex-m-qemu.ll

+10
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,18 @@ declare void @runtime.destroyDeferFrame(ptr dereferenceable_or_null(24), ptr) #2
122122
; Function Attrs: nounwind
123123
define internal void @"main.deferSimple$1"(ptr %context) unnamed_addr #1 {
124124
entry:
125+
call void @runtime.printlock(ptr undef) #4
125126
call void @runtime.printint32(i32 3, ptr undef) #4
127+
call void @runtime.printunlock(ptr undef) #4
126128
ret void
127129
}
128130

131+
declare void @runtime.printlock(ptr) #2
132+
129133
declare void @runtime.printint32(i32, ptr) #2
130134

135+
declare void @runtime.printunlock(ptr) #2
136+
131137
; Function Attrs: nounwind
132138
define hidden void @main.deferMultiple(ptr %context) unnamed_addr #1 {
133139
entry:
@@ -250,14 +256,18 @@ rundefers.end7: ; preds = %rundefers.loophead1
250256
; Function Attrs: nounwind
251257
define internal void @"main.deferMultiple$1"(ptr %context) unnamed_addr #1 {
252258
entry:
259+
call void @runtime.printlock(ptr undef) #4
253260
call void @runtime.printint32(i32 3, ptr undef) #4
261+
call void @runtime.printunlock(ptr undef) #4
254262
ret void
255263
}
256264

257265
; Function Attrs: nounwind
258266
define internal void @"main.deferMultiple$2"(ptr %context) unnamed_addr #1 {
259267
entry:
268+
call void @runtime.printlock(ptr undef) #4
260269
call void @runtime.printint32(i32 5, ptr undef) #4
270+
call void @runtime.printunlock(ptr undef) #4
261271
ret void
262272
}
263273

compiler/testdata/goroutine-cortex-m-qemu-tasks.ll

+6
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ entry:
7070
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr undef) #9
7171
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9
7272
%2 = load i32, ptr %n, align 4
73+
call void @runtime.printlock(ptr undef) #9
7374
call void @runtime.printint32(i32 %2, ptr undef) #9
75+
call void @runtime.printunlock(ptr undef) #9
7476
ret void
7577
}
7678

@@ -91,8 +93,12 @@ entry:
9193
ret void
9294
}
9395

96+
declare void @runtime.printlock(ptr) #2
97+
9498
declare void @runtime.printint32(i32, ptr) #2
9599

100+
declare void @runtime.printunlock(ptr) #2
101+
96102
; Function Attrs: nounwind
97103
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 {
98104
entry:

compiler/testdata/goroutine-wasm-asyncify.ll

+6
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ entry:
7676
store ptr %n, ptr %1, align 4
7777
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #9
7878
%2 = load i32, ptr %n, align 4
79+
call void @runtime.printlock(ptr undef) #9
7980
call void @runtime.printint32(i32 %2, ptr undef) #9
81+
call void @runtime.printunlock(ptr undef) #9
8082
ret void
8183
}
8284

@@ -98,8 +100,12 @@ entry:
98100
unreachable
99101
}
100102

103+
declare void @runtime.printlock(ptr) #1
104+
101105
declare void @runtime.printint32(i32, ptr) #1
102106

107+
declare void @runtime.printunlock(ptr) #1
108+
103109
; Function Attrs: nounwind
104110
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #2 {
105111
entry:

src/runtime/print.go

+23-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
package runtime
22

33
import (
4+
"internal/task"
45
"unsafe"
56
)
67

78
type stringer interface {
89
String() string
910
}
1011

12+
var printLock task.PMutex
13+
14+
func printlock() {
15+
printLock.Lock()
16+
}
17+
18+
func printunlock() {
19+
printLock.Unlock()
20+
}
21+
1122
//go:nobounds
1223
func printstring(s string) {
1324
for i := 0; i < len(s); i++ {
@@ -336,24 +347,31 @@ func printitf(msg interface{}) {
336347
putchar('(')
337348
printuintptr(uintptr(itf.typecode))
338349
putchar(':')
339-
print(itf.value)
350+
printptr(uintptr(itf.value))
340351
putchar(')')
341352
}
342353
}
343354

344355
func printmap(m *hashmap) {
345-
print("map[")
356+
printstring("map[")
346357
if m == nil {
347-
print("nil")
358+
printstring("nil")
348359
} else {
349-
print(uint(m.count))
360+
switch TargetBits {
361+
case 64:
362+
printuint64(uint64(m.count))
363+
case 32:
364+
printuint32(uint32(m.count))
365+
case 16:
366+
printuint16(uint16(m.count))
367+
}
350368
}
351369
putchar(']')
352370
}
353371

354372
func printptr(ptr uintptr) {
355373
if ptr == 0 {
356-
print("nil")
374+
printstring("nil")
357375
return
358376
}
359377
putchar('0')

0 commit comments

Comments
 (0)