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 }
480
481
482
483
484
485
486
487
488
489
490
491 func parsegodebug(godebug string, seen map[string]bool) {
492 for p := godebug; p != ""; {
493 var field string
494 if seen == nil {
495
496 i := bytealg.IndexByteString(p, ',')
497 if i < 0 {
498 field, p = p, ""
499 } else {
500 field, p = p[:i], p[i+1:]
501 }
502 } else {
503
504 i := len(p) - 1
505 for i >= 0 && p[i] != ',' {
506 i--
507 }
508 if i < 0 {
509 p, field = "", p
510 } else {
511 p, field = p[:i], p[i+1:]
512 }
513 }
514 i := bytealg.IndexByteString(field, '=')
515 if i < 0 {
516 continue
517 }
518 key, value := field[:i], field[i+1:]
519
520
521
522 if seen == nil {
523 for _, info := range godebugs.Removed {
524 if info.Name == key {
525 if info.Old(value) {
526 invalidGODEBUG.key = key
527 invalidGODEBUG.value = value
528 return
529 }
530 break
531 }
532 }
533 }
534
535 if seen[key] {
536 continue
537 }
538 if seen != nil {
539 seen[key] = true
540 }
541
542
543
544
545 if seen == nil && key == "memprofilerate" {
546 if n, err := strconv.Atoi(value); err == nil {
547 MemProfileRate = n
548 }
549 } else {
550 for _, v := range dbgvars {
551 if v.name == key {
552 if n, err := strconv.ParseInt(value, 10, 32); err == nil {
553 if seen == nil && v.value != nil {
554 *v.value = int32(n)
555 } else if v.atomic != nil {
556 v.atomic.Store(int32(n))
557 }
558 }
559 }
560 }
561 }
562 }
563
564 if debug.cgocheck > 1 {
565 throw("cgocheck > 1 mode is no longer supported at runtime. Use GOEXPERIMENT=cgocheck2 at build time instead.")
566 }
567 }
568
569
570 func setTraceback(level string) {
571 var t uint32
572 switch level {
573 case "none":
574 t = 0
575 case "single", "":
576 t = 1 << tracebackShift
577 case "all":
578 t = 1<<tracebackShift | tracebackAll
579 case "system":
580 t = 2<<tracebackShift | tracebackAll
581 case "crash":
582 t = 2<<tracebackShift | tracebackAll | tracebackCrash
583 case "wer":
584 if GOOS == "windows" {
585 t = 2<<tracebackShift | tracebackAll | tracebackCrash
586 enableWER()
587 break
588 }
589 fallthrough
590 default:
591 t = tracebackAll
592 if n, err := strconv.Atoi(level); err == nil && n == int(uint32(n)) {
593 t |= uint32(n) << tracebackShift
594 }
595 }
596
597
598 if islibrary || isarchive {
599 t |= tracebackCrash
600 }
601
602 t |= traceback_env
603
604 atomic.Store(&traceback_cache, t)
605 }
606
607
608
609
610 func acquirem() *m {
611 gp := getg()
612 gp.m.locks++
613 return gp.m
614 }
615
616
617 func releasem(mp *m) {
618 gp := getg()
619 mp.locks--
620 if mp.locks == 0 && gp.preempt {
621
622 gp.stackguard0 = stackPreempt
623 }
624 }
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644 func reflect_typelinks() ([]unsafe.Pointer, [][]int32) {
645 modules := activeModules()
646
647 typesToOffsets := func(md *moduledata) []int32 {
648 types := moduleTypelinks(md)
649 ret := make([]int32, 0, len(types))
650 for _, typ := range types {
651 ret = append(ret, int32(uintptr(unsafe.Pointer(typ))-md.types))
652 }
653 return ret
654 }
655
656 sections := []unsafe.Pointer{unsafe.Pointer(modules[0].types)}
657 ret := [][]int32{typesToOffsets(modules[0])}
658 for _, md := range modules[1:] {
659 sections = append(sections, unsafe.Pointer(md.types))
660 ret = append(ret, typesToOffsets(md))
661 }
662 return sections, ret
663 }
664
665
666
667
668
669
670
671
672 func reflect_compiledTypelinks() ([]*abi.Type, [][]*abi.Type) {
673 modules := activeModules()
674 firstTypes := moduleTypelinks(modules[0])
675 var rest [][]*abi.Type
676 for _, md := range modules[1:] {
677 rest = append(rest, moduleTypelinks(md))
678 }
679 return firstTypes, rest
680 }
681
682
683
684
685
686
687
688
689
690
691
692
693 func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
694 return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).Bytes)
695 }
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711 func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
712 return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
713 }
714
715
716
717
718
719
720
721
722
723
724
725
726 func reflect_resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
727 return toRType((*_type)(rtype)).textOff(textOff(off))
728 }
729
730
731
732
733 func reflectlite_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
734 return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).Bytes)
735 }
736
737
738
739
740 func reflectlite_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
741 return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
742 }
743
744
745
746
747 func reflect_addReflectOff(ptr unsafe.Pointer) int32 {
748 reflectOffsLock()
749 if reflectOffs.m == nil {
750 reflectOffs.m = make(map[int32]unsafe.Pointer)
751 reflectOffs.minv = make(map[unsafe.Pointer]int32)
752 reflectOffs.next = -1
753 }
754 id, found := reflectOffs.minv[ptr]
755 if !found {
756 id = reflectOffs.next
757 reflectOffs.next--
758 reflectOffs.m[id] = ptr
759 reflectOffs.minv[ptr] = id
760 }
761 reflectOffsUnlock()
762 return id
763 }
764
765
766
767
768
769
770 func reflect_adjustAIXGCDataForRuntime(addr *byte) *byte {
771 return (*byte)(add(unsafe.Pointer(addr), aixStaticDataBase-firstmoduledata.data))
772 }
773
774
775 func fips_getIndicator() uint8 {
776 return getg().fipsIndicator
777 }
778
779
780 func fips_setIndicator(indicator uint8) {
781 getg().fipsIndicator = indicator
782 }
783
View as plain text