Source file
src/runtime/runtime1.go
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "internal/bytealg"
10 "internal/goarch"
11 "internal/runtime/atomic"
12 "internal/strconv"
13 "unsafe"
14 )
15
16
17
18
19
20
21 const (
22 tracebackCrash = 1 << iota
23 tracebackAll
24 tracebackShift = iota
25 )
26
27 var traceback_cache uint32 = 2 << tracebackShift
28 var traceback_env uint32
29
30
31
32
33
34
35
36
37
38
39 func gotraceback() (level int32, all, crash bool) {
40 gp := getg()
41 t := atomic.Load(&traceback_cache)
42 crash = t&tracebackCrash != 0
43 all = gp.m.throwing > throwTypeUser || t&tracebackAll != 0
44 if gp.m.traceback != 0 {
45 level = int32(gp.m.traceback)
46 } else if gp.m.throwing >= throwTypeRuntime {
47
48
49 level = 2
50 } else {
51 level = int32(t >> tracebackShift)
52 }
53 return
54 }
55
56 var (
57 argc int32
58 argv **byte
59 )
60
61
62
63
64 func argv_index(argv **byte, i int32) *byte {
65 return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*goarch.PtrSize))
66 }
67
68 func args(c int32, v **byte) {
69 argc = c
70 argv = v
71 sysargs(c, v)
72 }
73
74 func goargs() {
75 if GOOS == "windows" {
76 return
77 }
78 argslice = make([]string, argc)
79 for i := int32(0); i < argc; i++ {
80 argslice[i] = gostringnocopy(argv_index(argv, i))
81 }
82 }
83
84 func goenvs_unix() {
85
86
87
88 n := int32(0)
89 for argv_index(argv, argc+1+n) != nil {
90 n++
91 }
92
93 envs = make([]string, n)
94 for i := int32(0); i < n; i++ {
95 envs[i] = gostring(argv_index(argv, argc+1+i))
96 }
97 }
98
99 func environ() []string {
100 return envs
101 }
102
103
104
105 var test_z64, test_x64 uint64
106
107 func testAtomic64() {
108 test_z64 = 42
109 test_x64 = 0
110 if atomic.Cas64(&test_z64, test_x64, 1) {
111 throw("cas64 failed")
112 }
113 if test_x64 != 0 {
114 throw("cas64 failed")
115 }
116 test_x64 = 42
117 if !atomic.Cas64(&test_z64, test_x64, 1) {
118 throw("cas64 failed")
119 }
120 if test_x64 != 42 || test_z64 != 1 {
121 throw("cas64 failed")
122 }
123 if atomic.Load64(&test_z64) != 1 {
124 throw("load64 failed")
125 }
126 atomic.Store64(&test_z64, (1<<40)+1)
127 if atomic.Load64(&test_z64) != (1<<40)+1 {
128 throw("store64 failed")
129 }
130 if atomic.Xadd64(&test_z64, (1<<40)+1) != (2<<40)+2 {
131 throw("xadd64 failed")
132 }
133 if atomic.Load64(&test_z64) != (2<<40)+2 {
134 throw("xadd64 failed")
135 }
136 if atomic.Xchg64(&test_z64, (3<<40)+3) != (2<<40)+2 {
137 throw("xchg64 failed")
138 }
139 if atomic.Load64(&test_z64) != (3<<40)+3 {
140 throw("xchg64 failed")
141 }
142 }
143
144 func check() {
145 var (
146 a int8
147 b uint8
148 c int16
149 d uint16
150 e int32
151 f uint32
152 g int64
153 h uint64
154 i, i1 float32
155 j, j1 float64
156 k unsafe.Pointer
157 l *uint16
158 m [4]byte
159 )
160 type x1t struct {
161 x uint8
162 }
163 type y1t struct {
164 x1 x1t
165 y uint8
166 }
167 var x1 x1t
168 var y1 y1t
169
170 if unsafe.Sizeof(a) != 1 {
171 throw("bad a")
172 }
173 if unsafe.Sizeof(b) != 1 {
174 throw("bad b")
175 }
176 if unsafe.Sizeof(c) != 2 {
177 throw("bad c")
178 }
179 if unsafe.Sizeof(d) != 2 {
180 throw("bad d")
181 }
182 if unsafe.Sizeof(e) != 4 {
183 throw("bad e")
184 }
185 if unsafe.Sizeof(f) != 4 {
186 throw("bad f")
187 }
188 if unsafe.Sizeof(g) != 8 {
189 throw("bad g")
190 }
191 if unsafe.Sizeof(h) != 8 {
192 throw("bad h")
193 }
194 if unsafe.Sizeof(i) != 4 {
195 throw("bad i")
196 }
197 if unsafe.Sizeof(j) != 8 {
198 throw("bad j")
199 }
200 if unsafe.Sizeof(k) != goarch.PtrSize {
201 throw("bad k")
202 }
203 if unsafe.Sizeof(l) != goarch.PtrSize {
204 throw("bad l")
205 }
206 if unsafe.Sizeof(x1) != 1 {
207 throw("bad unsafe.Sizeof x1")
208 }
209 if unsafe.Offsetof(y1.y) != 1 {
210 throw("bad offsetof y1.y")
211 }
212 if unsafe.Sizeof(y1) != 2 {
213 throw("bad unsafe.Sizeof y1")
214 }
215
216 var z uint32
217 z = 1
218 if !atomic.Cas(&z, 1, 2) {
219 throw("cas1")
220 }
221 if z != 2 {
222 throw("cas2")
223 }
224
225 z = 4
226 if atomic.Cas(&z, 5, 6) {
227 throw("cas3")
228 }
229 if z != 4 {
230 throw("cas4")
231 }
232
233 z = 0xffffffff
234 if !atomic.Cas(&z, 0xffffffff, 0xfffffffe) {
235 throw("cas5")
236 }
237 if z != 0xfffffffe {
238 throw("cas6")
239 }
240
241 m = [4]byte{1, 1, 1, 1}
242 atomic.Or8(&m[1], 0xf0)
243 if m[0] != 1 || m[1] != 0xf1 || m[2] != 1 || m[3] != 1 {
244 throw("atomicor8")
245 }
246
247 m = [4]byte{0xff, 0xff, 0xff, 0xff}
248 atomic.And8(&m[1], 0x1)
249 if m[0] != 0xff || m[1] != 0x1 || m[2] != 0xff || m[3] != 0xff {
250 throw("atomicand8")
251 }
252
253 *(*uint64)(unsafe.Pointer(&j)) = ^uint64(0)
254 if j == j {
255 throw("float64nan")
256 }
257 if !(j != j) {
258 throw("float64nan1")
259 }
260
261 *(*uint64)(unsafe.Pointer(&j1)) = ^uint64(1)
262 if j == j1 {
263 throw("float64nan2")
264 }
265 if !(j != j1) {
266 throw("float64nan3")
267 }
268
269 *(*uint32)(unsafe.Pointer(&i)) = ^uint32(0)
270 if i == i {
271 throw("float32nan")
272 }
273 if i == i {
274 throw("float32nan1")
275 }
276
277 *(*uint32)(unsafe.Pointer(&i1)) = ^uint32(1)
278 if i == i1 {
279 throw("float32nan2")
280 }
281 if i == i1 {
282 throw("float32nan3")
283 }
284
285 testAtomic64()
286
287 if fixedStack != round2(fixedStack) {
288 throw("FixedStack is not power-of-2")
289 }
290 }
291
292 type dbgVar struct {
293 name string
294 value *int32
295 atomic *atomic.Int32
296 def int32
297 }
298
299
300
301
302
303 var debug struct {
304 cgocheck int32
305 clobberfree int32
306 containermaxprocs int32
307 decoratemappings int32
308 disablethp int32
309 dontfreezetheworld int32
310 efence int32
311 gccheckmark int32
312 gcpacertrace int32
313 gcshrinkstackoff int32
314 gcstoptheworld int32
315 gctrace int32
316 invalidptr int32
317 madvdontneed int32
318 scavtrace int32
319 scheddetail int32
320 schedtrace int32
321 tracebackancestors int32
322 updatemaxprocs int32
323 asyncpreemptoff int32
324 harddecommit int32
325 adaptivestackstart int32
326 tracefpunwindoff int32
327 traceadvanceperiod int32
328 traceCheckStackOwnership int32
329 profstackdepth int32
330 dataindependenttiming int32
331
332
333
334
335 malloc bool
336 inittrace int32
337 sbrk int32
338 checkfinalizers int32
339
340
341
342
343
344
345
346
347 traceallocfree atomic.Int32
348
349 panicnil atomic.Int32
350
351
352
353
354
355
356
357
358
359 asynctimerchan atomic.Int32
360
361
362
363 tracebacklabels atomic.Int32
364 }
365
366 var dbgvars = []*dbgVar{
367 {name: "adaptivestackstart", value: &debug.adaptivestackstart},
368 {name: "asyncpreemptoff", value: &debug.asyncpreemptoff},
369 {name: "asynctimerchan", atomic: &debug.asynctimerchan},
370 {name: "cgocheck", value: &debug.cgocheck},
371 {name: "clobberfree", value: &debug.clobberfree},
372 {name: "containermaxprocs", value: &debug.containermaxprocs, def: 1},
373 {name: "dataindependenttiming", value: &debug.dataindependenttiming},
374 {name: "decoratemappings", value: &debug.decoratemappings, def: 1},
375 {name: "disablethp", value: &debug.disablethp},
376 {name: "dontfreezetheworld", value: &debug.dontfreezetheworld},
377 {name: "checkfinalizers", value: &debug.checkfinalizers},
378 {name: "efence", value: &debug.efence},
379 {name: "gccheckmark", value: &debug.gccheckmark},
380 {name: "gcpacertrace", value: &debug.gcpacertrace},
381 {name: "gcshrinkstackoff", value: &debug.gcshrinkstackoff},
382 {name: "gcstoptheworld", value: &debug.gcstoptheworld},
383 {name: "gctrace", value: &debug.gctrace},
384 {name: "harddecommit", value: &debug.harddecommit},
385 {name: "inittrace", value: &debug.inittrace},
386 {name: "invalidptr", value: &debug.invalidptr},
387 {name: "madvdontneed", value: &debug.madvdontneed},
388 {name: "panicnil", atomic: &debug.panicnil},
389 {name: "profstackdepth", value: &debug.profstackdepth, def: 128},
390 {name: "sbrk", value: &debug.sbrk},
391 {name: "scavtrace", value: &debug.scavtrace},
392 {name: "scheddetail", value: &debug.scheddetail},
393 {name: "schedtrace", value: &debug.schedtrace},
394 {name: "traceadvanceperiod", value: &debug.traceadvanceperiod},
395 {name: "traceallocfree", atomic: &debug.traceallocfree},
396 {name: "tracecheckstackownership", value: &debug.traceCheckStackOwnership},
397 {name: "tracebackancestors", value: &debug.tracebackancestors},
398 {name: "tracebacklabels", atomic: &debug.tracebacklabels, def: 1},
399 {name: "tracefpunwindoff", value: &debug.tracefpunwindoff},
400 {name: "updatemaxprocs", value: &debug.updatemaxprocs, def: 1},
401 }
402
403 func parseRuntimeDebugVars(godebug string) {
404
405 debug.cgocheck = 1
406 debug.invalidptr = 1
407 debug.adaptivestackstart = 1
408 if GOOS == "linux" {
409
410
411
412
413
414
415
416
417 debug.madvdontneed = 1
418 }
419 debug.traceadvanceperiod = defaultTraceAdvancePeriod
420
421
422 for _, v := range dbgvars {
423 if v.def != 0 {
424
425 if v.value != nil {
426 *v.value = v.def
427 } else if v.atomic != nil {
428 v.atomic.Store(v.def)
429 }
430 }
431 }
432
433 parsegodebug(godebugDefault, nil)
434
435
436 parsegodebug(godebug, nil)
437
438 debug.malloc = (debug.inittrace | debug.sbrk | debug.checkfinalizers) != 0
439 debug.profstackdepth = min(debug.profstackdepth, maxProfStackDepth)
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454 if debug.gccheckmark > 0 {
455 debug.asyncpreemptoff = 1
456 }
457 }
458
459 func finishDebugVarsSetup() {
460 p := new(string)
461 *p = gogetenv("GODEBUG")
462 godebugEnv.Store(p)
463
464 setTraceback(gogetenv("GOTRACEBACK"))
465 traceback_env = traceback_cache
466 }
467
468
469
470 func reparsedebugvars(env string) {
471 seen := make(map[string]bool)
472
473 parsegodebug(env, seen)
474
475 parsegodebug(godebugDefault, seen)
476
477 for _, v := range dbgvars {
478 if v.atomic != nil && !seen[v.name] {
479 v.atomic.Store(0)
480 }
481 }
482 }
483
484
485
486
487
488
489
490
491
492
493
494 func parsegodebug(godebug string, seen map[string]bool) {
495 for p := godebug; p != ""; {
496 var field string
497 if seen == nil {
498
499 i := bytealg.IndexByteString(p, ',')
500 if i < 0 {
501 field, p = p, ""
502 } else {
503 field, p = p[:i], p[i+1:]
504 }
505 } else {
506
507 i := len(p) - 1
508 for i >= 0 && p[i] != ',' {
509 i--
510 }
511 if i < 0 {
512 p, field = "", p
513 } else {
514 p, field = p[:i], p[i+1:]
515 }
516 }
517 i := bytealg.IndexByteString(field, '=')
518 if i < 0 {
519 continue
520 }
521 key, value := field[:i], field[i+1:]
522 if seen[key] {
523 continue
524 }
525 if seen != nil {
526 seen[key] = true
527 }
528
529
530
531
532 if seen == nil && key == "memprofilerate" {
533 if n, err := strconv.Atoi(value); err == nil {
534 MemProfileRate = n
535 }
536 } else {
537 for _, v := range dbgvars {
538 if v.name == key {
539 if n, err := strconv.ParseInt(value, 10, 32); err == nil {
540 if seen == nil && v.value != nil {
541 *v.value = int32(n)
542 } else if v.atomic != nil {
543 v.atomic.Store(int32(n))
544 }
545 }
546 }
547 }
548 }
549 }
550
551 if debug.cgocheck > 1 {
552 throw("cgocheck > 1 mode is no longer supported at runtime. Use GOEXPERIMENT=cgocheck2 at build time instead.")
553 }
554 }
555
556
557 func setTraceback(level string) {
558 var t uint32
559 switch level {
560 case "none":
561 t = 0
562 case "single", "":
563 t = 1 << tracebackShift
564 case "all":
565 t = 1<<tracebackShift | tracebackAll
566 case "system":
567 t = 2<<tracebackShift | tracebackAll
568 case "crash":
569 t = 2<<tracebackShift | tracebackAll | tracebackCrash
570 case "wer":
571 if GOOS == "windows" {
572 t = 2<<tracebackShift | tracebackAll | tracebackCrash
573 enableWER()
574 break
575 }
576 fallthrough
577 default:
578 t = tracebackAll
579 if n, err := strconv.Atoi(level); err == nil && n == int(uint32(n)) {
580 t |= uint32(n) << tracebackShift
581 }
582 }
583
584
585 if islibrary || isarchive {
586 t |= tracebackCrash
587 }
588
589 t |= traceback_env
590
591 atomic.Store(&traceback_cache, t)
592 }
593
594
595
596
597 func acquirem() *m {
598 gp := getg()
599 gp.m.locks++
600 return gp.m
601 }
602
603
604 func releasem(mp *m) {
605 gp := getg()
606 mp.locks--
607 if mp.locks == 0 && gp.preempt {
608
609 gp.stackguard0 = stackPreempt
610 }
611 }
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631 func reflect_typelinks() ([]unsafe.Pointer, [][]int32) {
632 modules := activeModules()
633
634 typesToOffsets := func(md *moduledata) []int32 {
635 types := moduleTypelinks(md)
636 ret := make([]int32, 0, len(types))
637 for _, typ := range types {
638 ret = append(ret, int32(uintptr(unsafe.Pointer(typ))-md.types))
639 }
640 return ret
641 }
642
643 sections := []unsafe.Pointer{unsafe.Pointer(modules[0].types)}
644 ret := [][]int32{typesToOffsets(modules[0])}
645 for _, md := range modules[1:] {
646 sections = append(sections, unsafe.Pointer(md.types))
647 ret = append(ret, typesToOffsets(md))
648 }
649 return sections, ret
650 }
651
652
653
654
655
656
657
658
659 func reflect_compiledTypelinks() ([]*abi.Type, [][]*abi.Type) {
660 modules := activeModules()
661 firstTypes := moduleTypelinks(modules[0])
662 var rest [][]*abi.Type
663 for _, md := range modules[1:] {
664 rest = append(rest, moduleTypelinks(md))
665 }
666 return firstTypes, rest
667 }
668
669
670
671
672
673
674
675
676
677
678
679
680 func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
681 return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).Bytes)
682 }
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698 func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
699 return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
700 }
701
702
703
704
705
706
707
708
709
710
711
712
713 func reflect_resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
714 return toRType((*_type)(rtype)).textOff(textOff(off))
715 }
716
717
718
719
720 func reflectlite_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
721 return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).Bytes)
722 }
723
724
725
726
727 func reflectlite_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
728 return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
729 }
730
731
732
733
734 func reflect_addReflectOff(ptr unsafe.Pointer) int32 {
735 reflectOffsLock()
736 if reflectOffs.m == nil {
737 reflectOffs.m = make(map[int32]unsafe.Pointer)
738 reflectOffs.minv = make(map[unsafe.Pointer]int32)
739 reflectOffs.next = -1
740 }
741 id, found := reflectOffs.minv[ptr]
742 if !found {
743 id = reflectOffs.next
744 reflectOffs.next--
745 reflectOffs.m[id] = ptr
746 reflectOffs.minv[ptr] = id
747 }
748 reflectOffsUnlock()
749 return id
750 }
751
752
753
754
755
756
757 func reflect_adjustAIXGCDataForRuntime(addr *byte) *byte {
758 return (*byte)(add(unsafe.Pointer(addr), aixStaticDataBase-firstmoduledata.data))
759 }
760
761
762 func fips_getIndicator() uint8 {
763 return getg().fipsIndicator
764 }
765
766
767 func fips_setIndicator(indicator uint8) {
768 getg().fipsIndicator = indicator
769 }
770
View as plain text