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 parseRuntimeDebugVars(godebug string) {
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
424 for _, v := range dbgvars {
425 if v.def != 0 {
426
427 if v.value != nil {
428 *v.value = v.def
429 } else if v.atomic != nil {
430 v.atomic.Store(v.def)
431 }
432 }
433 }
434
435 parsegodebug(godebugDefault, nil)
436
437
438 parsegodebug(godebug, nil)
439
440 debug.malloc = (debug.inittrace | debug.sbrk | debug.checkfinalizers) != 0
441 debug.profstackdepth = min(debug.profstackdepth, maxProfStackDepth)
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456 if debug.gccheckmark > 0 {
457 debug.asyncpreemptoff = 1
458 }
459 }
460
461 func finishDebugVarsSetup() {
462 p := new(string)
463 *p = gogetenv("GODEBUG")
464 godebugEnv.Store(p)
465
466 setTraceback(gogetenv("GOTRACEBACK"))
467 traceback_env = traceback_cache
468 }
469
470
471
472 func reparsedebugvars(env string) {
473 seen := make(map[string]bool)
474
475 parsegodebug(env, seen)
476
477 parsegodebug(godebugDefault, seen)
478
479 for _, v := range dbgvars {
480 if v.atomic != nil && !seen[v.name] {
481 v.atomic.Store(0)
482 }
483 }
484 }
485
486
487
488
489
490
491
492
493
494
495
496 func parsegodebug(godebug string, seen map[string]bool) {
497 for p := godebug; p != ""; {
498 var field string
499 if seen == nil {
500
501 i := bytealg.IndexByteString(p, ',')
502 if i < 0 {
503 field, p = p, ""
504 } else {
505 field, p = p[:i], p[i+1:]
506 }
507 } else {
508
509 i := len(p) - 1
510 for i >= 0 && p[i] != ',' {
511 i--
512 }
513 if i < 0 {
514 p, field = "", p
515 } else {
516 p, field = p[:i], p[i+1:]
517 }
518 }
519 i := bytealg.IndexByteString(field, '=')
520 if i < 0 {
521 continue
522 }
523 key, value := field[:i], field[i+1:]
524 if seen[key] {
525 continue
526 }
527 if seen != nil {
528 seen[key] = true
529 }
530
531
532
533
534 if seen == nil && key == "memprofilerate" {
535 if n, ok := strconv.Atoi(value); ok {
536 MemProfileRate = n
537 }
538 } else {
539 for _, v := range dbgvars {
540 if v.name == key {
541 if n, ok := strconv.Atoi32(value); ok {
542 if seen == nil && v.value != nil {
543 *v.value = n
544 } else if v.atomic != nil {
545 v.atomic.Store(n)
546 }
547 }
548 }
549 }
550 }
551 }
552
553 if debug.cgocheck > 1 {
554 throw("cgocheck > 1 mode is no longer supported at runtime. Use GOEXPERIMENT=cgocheck2 at build time instead.")
555 }
556 }
557
558
559 func setTraceback(level string) {
560 var t uint32
561 switch level {
562 case "none":
563 t = 0
564 case "single", "":
565 t = 1 << tracebackShift
566 case "all":
567 t = 1<<tracebackShift | tracebackAll
568 case "system":
569 t = 2<<tracebackShift | tracebackAll
570 case "crash":
571 t = 2<<tracebackShift | tracebackAll | tracebackCrash
572 case "wer":
573 if GOOS == "windows" {
574 t = 2<<tracebackShift | tracebackAll | tracebackCrash
575 enableWER()
576 break
577 }
578 fallthrough
579 default:
580 t = tracebackAll
581 if n, ok := strconv.Atoi(level); ok && n == int(uint32(n)) {
582 t |= uint32(n) << tracebackShift
583 }
584 }
585
586
587 if islibrary || isarchive {
588 t |= tracebackCrash
589 }
590
591 t |= traceback_env
592
593 atomic.Store(&traceback_cache, t)
594 }
595
596
597
598
599
600
601
602
603 func timediv(v int64, div int32, rem *int32) int32 {
604 res := int32(0)
605 for bit := 30; bit >= 0; bit-- {
606 if v >= int64(div)<<uint(bit) {
607 v = v - (int64(div) << uint(bit))
608
609
610 res |= 1 << uint(bit)
611 }
612 }
613 if v >= int64(div) {
614 if rem != nil {
615 *rem = 0
616 }
617 return 0x7fffffff
618 }
619 if rem != nil {
620 *rem = int32(v)
621 }
622 return res
623 }
624
625
626
627
628 func acquirem() *m {
629 gp := getg()
630 gp.m.locks++
631 return gp.m
632 }
633
634
635 func releasem(mp *m) {
636 gp := getg()
637 mp.locks--
638 if mp.locks == 0 && gp.preempt {
639
640 gp.stackguard0 = stackPreempt
641 }
642 }
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659 func reflect_typelinks() ([]unsafe.Pointer, [][]int32) {
660 modules := activeModules()
661 sections := []unsafe.Pointer{unsafe.Pointer(modules[0].types)}
662 ret := [][]int32{modules[0].typelinks}
663 for _, md := range modules[1:] {
664 sections = append(sections, unsafe.Pointer(md.types))
665 ret = append(ret, md.typelinks)
666 }
667 return sections, ret
668 }
669
670
671
672
673
674
675
676
677
678
679
680
681 func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
682 return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).Bytes)
683 }
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699 func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
700 return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
701 }
702
703
704
705
706
707
708
709
710
711
712
713
714 func reflect_resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
715 return toRType((*_type)(rtype)).textOff(textOff(off))
716 }
717
718
719
720
721 func reflectlite_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
722 return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).Bytes)
723 }
724
725
726
727
728 func reflectlite_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
729 return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
730 }
731
732
733
734
735 func reflect_addReflectOff(ptr unsafe.Pointer) int32 {
736 reflectOffsLock()
737 if reflectOffs.m == nil {
738 reflectOffs.m = make(map[int32]unsafe.Pointer)
739 reflectOffs.minv = make(map[unsafe.Pointer]int32)
740 reflectOffs.next = -1
741 }
742 id, found := reflectOffs.minv[ptr]
743 if !found {
744 id = reflectOffs.next
745 reflectOffs.next--
746 reflectOffs.m[id] = ptr
747 reflectOffs.minv[ptr] = id
748 }
749 reflectOffsUnlock()
750 return id
751 }
752
753
754 func fips_getIndicator() uint8 {
755 return getg().fipsIndicator
756 }
757
758
759 func fips_setIndicator(indicator uint8) {
760 getg().fipsIndicator = indicator
761 }
762
View as plain text