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 tracebackcrash int32
324 updatemaxprocs int32
325 asyncpreemptoff int32
326 harddecommit int32
327 adaptivestackstart int32
328 tracefpunwindoff int32
329 traceadvanceperiod int32
330 traceCheckStackOwnership int32
331 profstackdepth int32
332 dataindependenttiming int32
333
334
335
336
337 malloc bool
338 inittrace int32
339 sbrk int32
340 checkfinalizers int32
341
342
343
344
345
346
347
348
349 traceallocfree atomic.Int32
350
351 panicnil atomic.Int32
352
353
354
355 tracebacklabels atomic.Int32
356 }
357
358 var dbgvars = []*dbgVar{
359 {name: "adaptivestackstart", value: &debug.adaptivestackstart},
360 {name: "asyncpreemptoff", value: &debug.asyncpreemptoff},
361 {name: "cgocheck", value: &debug.cgocheck},
362 {name: "clobberfree", value: &debug.clobberfree},
363 {name: "containermaxprocs", value: &debug.containermaxprocs, def: 1},
364 {name: "dataindependenttiming", value: &debug.dataindependenttiming},
365 {name: "decoratemappings", value: &debug.decoratemappings, def: 1},
366 {name: "disablethp", value: &debug.disablethp},
367 {name: "dontfreezetheworld", value: &debug.dontfreezetheworld},
368 {name: "checkfinalizers", value: &debug.checkfinalizers},
369 {name: "efence", value: &debug.efence},
370 {name: "gccheckmark", value: &debug.gccheckmark},
371 {name: "gcpacertrace", value: &debug.gcpacertrace},
372 {name: "gcshrinkstackoff", value: &debug.gcshrinkstackoff},
373 {name: "gcstoptheworld", value: &debug.gcstoptheworld},
374 {name: "gctrace", value: &debug.gctrace},
375 {name: "harddecommit", value: &debug.harddecommit},
376 {name: "inittrace", value: &debug.inittrace},
377 {name: "invalidptr", value: &debug.invalidptr},
378 {name: "madvdontneed", value: &debug.madvdontneed},
379 {name: "panicnil", atomic: &debug.panicnil},
380 {name: "profstackdepth", value: &debug.profstackdepth, def: 128},
381 {name: "sbrk", value: &debug.sbrk},
382 {name: "scavtrace", value: &debug.scavtrace},
383 {name: "scheddetail", value: &debug.scheddetail},
384 {name: "schedtrace", value: &debug.schedtrace},
385 {name: "traceadvanceperiod", value: &debug.traceadvanceperiod},
386 {name: "traceallocfree", atomic: &debug.traceallocfree},
387 {name: "tracecheckstackownership", value: &debug.traceCheckStackOwnership},
388 {name: "tracebackancestors", value: &debug.tracebackancestors},
389 {name: "tracebackcrash", value: &debug.tracebackcrash},
390 {name: "tracebacklabels", atomic: &debug.tracebacklabels, def: 1},
391 {name: "tracefpunwindoff", value: &debug.tracefpunwindoff},
392 {name: "updatemaxprocs", value: &debug.updatemaxprocs, def: 1},
393 }
394
395 func parseRuntimeDebugVars(godebug string) {
396
397 debug.cgocheck = 1
398 debug.invalidptr = 1
399 debug.adaptivestackstart = 1
400 if GOOS == "linux" {
401
402
403
404
405
406
407
408
409 debug.madvdontneed = 1
410 }
411 debug.traceadvanceperiod = defaultTraceAdvancePeriod
412
413
414 for _, v := range dbgvars {
415 if v.def != 0 {
416
417 if v.value != nil {
418 *v.value = v.def
419 } else if v.atomic != nil {
420 v.atomic.Store(v.def)
421 }
422 }
423 }
424
425 parsegodebug(godebugDefault, nil)
426
427
428 parsegodebug(godebug, nil)
429
430 debug.malloc = (debug.inittrace | debug.sbrk | debug.checkfinalizers) != 0
431 debug.profstackdepth = min(debug.profstackdepth, maxProfStackDepth)
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446 if debug.gccheckmark > 0 {
447 debug.asyncpreemptoff = 1
448 }
449 }
450
451 func finishDebugVarsSetup() {
452 p := new(string)
453 *p = gogetenv("GODEBUG")
454 godebugEnv.Store(p)
455
456 setTraceback(gogetenv("GOTRACEBACK"))
457 traceback_env = traceback_cache
458 }
459
460
461
462 func reparsedebugvars(env string) {
463 seen := make(map[string]bool)
464
465 parsegodebug(env, seen)
466
467 parsegodebug(godebugDefault, seen)
468
469 for _, v := range dbgvars {
470 if v.atomic != nil && !seen[v.name] {
471 v.atomic.Store(0)
472 }
473 }
474 }
475
476
477
478
479 var invalidGODEBUG struct {
480 key, value string
481 removed int
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
523
524
525 if seen == nil {
526 for _, info := range godebugs.Removed {
527 if info.Name == key {
528 if info.Old(value) {
529 invalidGODEBUG.key = key
530 invalidGODEBUG.value = value
531 invalidGODEBUG.removed = info.Removed
532 return
533 }
534 break
535 }
536 }
537 }
538
539 if seen[key] {
540 continue
541 }
542 if seen != nil {
543 seen[key] = true
544 }
545
546
547
548
549 if seen == nil && key == "memprofilerate" {
550 if n, err := strconv.Atoi(value); err == nil {
551 MemProfileRate = n
552 }
553 } else {
554 for _, v := range dbgvars {
555 if v.name == key {
556 if n, err := strconv.ParseInt(value, 10, 32); err == nil {
557 if seen == nil && v.value != nil {
558 *v.value = int32(n)
559 } else if v.atomic != nil {
560 v.atomic.Store(int32(n))
561 }
562 }
563 }
564 }
565 }
566 }
567
568 if debug.cgocheck > 1 {
569 throw("cgocheck > 1 mode is no longer supported at runtime. Use GOEXPERIMENT=cgocheck2 at build time instead.")
570 }
571 }
572
573
574 func setTraceback(level string) {
575 var t uint32
576 switch level {
577 case "none":
578 t = 0
579 case "single", "":
580 t = 1 << tracebackShift
581 case "all":
582 t = 1<<tracebackShift | tracebackAll
583 case "system":
584 t = 2<<tracebackShift | tracebackAll
585 case "crash":
586 t = 2<<tracebackShift | tracebackAll | tracebackCrash
587 case "wer":
588 if GOOS == "windows" {
589 t = 2<<tracebackShift | tracebackAll | tracebackCrash
590 enableWER()
591 break
592 }
593 fallthrough
594 default:
595 t = tracebackAll
596 if n, err := strconv.Atoi(level); err == nil && n == int(uint32(n)) {
597 t |= uint32(n) << tracebackShift
598 }
599 }
600
601
602 if islibrary || isarchive {
603 t |= tracebackCrash
604 }
605
606 t |= traceback_env
607
608 atomic.Store(&traceback_cache, t)
609 }
610
611
612
613
614 func acquirem() *m {
615 gp := getg()
616 gp.m.locks++
617 return gp.m
618 }
619
620
621 func releasem(mp *m) {
622 gp := getg()
623 mp.locks--
624 if mp.locks == 0 && gp.preempt {
625
626 gp.stackguard0 = stackPreempt
627 }
628 }
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648 func reflect_typelinks() ([]unsafe.Pointer, [][]int32) {
649 modules := activeModules()
650
651 typesToOffsets := func(md *moduledata) []int32 {
652 types := moduleTypelinks(md)
653 ret := make([]int32, 0, len(types))
654 for _, typ := range types {
655 ret = append(ret, int32(uintptr(unsafe.Pointer(typ))-md.types))
656 }
657 return ret
658 }
659
660 sections := []unsafe.Pointer{unsafe.Pointer(modules[0].types)}
661 ret := [][]int32{typesToOffsets(modules[0])}
662 for _, md := range modules[1:] {
663 sections = append(sections, unsafe.Pointer(md.types))
664 ret = append(ret, typesToOffsets(md))
665 }
666 return sections, ret
667 }
668
669
670
671
672
673
674
675
676 func reflect_compiledTypelinks() ([]*abi.Type, [][]*abi.Type) {
677 modules := activeModules()
678 firstTypes := moduleTypelinks(modules[0])
679 var rest [][]*abi.Type
680 for _, md := range modules[1:] {
681 rest = append(rest, moduleTypelinks(md))
682 }
683 return firstTypes, rest
684 }
685
686
687
688
689
690
691
692
693
694
695
696
697 func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
698 return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).Bytes)
699 }
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715 func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
716 return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
717 }
718
719
720
721
722
723
724
725
726
727
728
729
730 func reflect_resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
731 return toRType((*_type)(rtype)).textOff(textOff(off))
732 }
733
734
735
736
737 func reflectlite_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
738 return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).Bytes)
739 }
740
741
742
743
744 func reflectlite_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
745 return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
746 }
747
748
749
750
751 func reflect_addReflectOff(ptr unsafe.Pointer) int32 {
752 reflectOffsLock()
753 if reflectOffs.m == nil {
754 reflectOffs.m = make(map[int32]unsafe.Pointer)
755 reflectOffs.minv = make(map[unsafe.Pointer]int32)
756 reflectOffs.next = -1
757 }
758 id, found := reflectOffs.minv[ptr]
759 if !found {
760 id = reflectOffs.next
761 reflectOffs.next--
762 reflectOffs.m[id] = ptr
763 reflectOffs.minv[ptr] = id
764 }
765 reflectOffsUnlock()
766 return id
767 }
768
769
770
771
772
773
774 func reflect_adjustAIXGCDataForRuntime(addr *byte) *byte {
775 return (*byte)(add(unsafe.Pointer(addr), aixStaticDataBase-firstmoduledata.data))
776 }
777
778
779 func fips_getIndicator() uint8 {
780 return getg().fipsIndicator
781 }
782
783
784 func fips_setIndicator(indicator uint8) {
785 getg().fipsIndicator = indicator
786 }
787
View as plain text