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