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