LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 #include "runtime.h" | 5 #include "runtime.h" |
6 #include "arch_GOARCH.h" | 6 #include "arch_GOARCH.h" |
7 #include "zaexperiment.h" | 7 #include "zaexperiment.h" |
8 #include "malloc.h" | 8 #include "malloc.h" |
9 #include "stack.h" | 9 #include "stack.h" |
10 #include "race.h" | 10 #include "race.h" |
(...skipping 1712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1723 // make g->sched refer to the caller's stack segment, because | 1723 // make g->sched refer to the caller's stack segment, because |
1724 // entersyscall is going to return immediately after. | 1724 // entersyscall is going to return immediately after. |
1725 // | 1725 // |
1726 // Nothing entersyscall calls can split the stack either. | 1726 // Nothing entersyscall calls can split the stack either. |
1727 // We cannot safely move the stack during an active call to syscall, | 1727 // We cannot safely move the stack during an active call to syscall, |
1728 // because we do not know which of the uintptr arguments are | 1728 // because we do not know which of the uintptr arguments are |
1729 // really pointers (back into the stack). | 1729 // really pointers (back into the stack). |
1730 // In practice, this means that we make the fast path run through | 1730 // In practice, this means that we make the fast path run through |
1731 // entersyscall doing no-split things, and the slow path has to use onM | 1731 // entersyscall doing no-split things, and the slow path has to use onM |
1732 // to run bigger things on the m stack. | 1732 // to run bigger things on the m stack. |
| 1733 // |
| 1734 // reentersyscall is the entry point used by cgo callbacks, where explicitly |
| 1735 // saved SP and PC are restored. This is needed when exitsyscall will be called |
| 1736 // from a function further up in the call stack than the parent, as g->syscallsp |
| 1737 // must always point to a valid stack frame. entersyscall below is the normal |
| 1738 // entry point for syscalls, which obtains the SP and PC from the caller. |
1733 #pragma textflag NOSPLIT | 1739 #pragma textflag NOSPLIT |
1734 void | 1740 void |
1735 ·entersyscall(int32 dummy) | 1741 runtime·reentersyscall(uintptr pc, uintptr sp) |
1736 { | 1742 { |
1737 void (*fn)(void); | 1743 void (*fn)(void); |
1738 | 1744 |
1739 // Disable preemption because during this function g is in Gsyscall stat
us, | 1745 // Disable preemption because during this function g is in Gsyscall stat
us, |
1740 // but can have inconsistent g->sched, do not let GC observe it. | 1746 // but can have inconsistent g->sched, do not let GC observe it. |
1741 g->m->locks++; | 1747 g->m->locks++; |
1742 ········ | 1748 ········ |
1743 // Entersyscall must not call any function that might split/grow the sta
ck. | 1749 // Entersyscall must not call any function that might split/grow the sta
ck. |
1744 // (See details in comment above.) | 1750 // (See details in comment above.) |
1745 // Catch calls that might, by replacing the stack guard with something t
hat | 1751 // Catch calls that might, by replacing the stack guard with something t
hat |
1746 // will trip any stack check and leaving a flag to tell newstack to die. | 1752 // will trip any stack check and leaving a flag to tell newstack to die. |
1747 g->stackguard0 = StackPreempt; | 1753 g->stackguard0 = StackPreempt; |
1748 g->throwsplit = 1; | 1754 g->throwsplit = 1; |
1749 | 1755 |
1750 // Leave SP around for GC and traceback. | 1756 // Leave SP around for GC and traceback. |
1751 » save(runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy)); | 1757 » save((void *)pc, sp); |
1752 » g->syscallsp = g->sched.sp; | 1758 » g->syscallsp = sp; |
1753 » g->syscallpc = g->sched.pc; | 1759 » g->syscallpc = pc; |
1754 runtime·casgstatus(g, Grunning, Gsyscall); | 1760 runtime·casgstatus(g, Grunning, Gsyscall); |
1755 if(g->syscallsp < g->stack.lo || g->stack.hi < g->syscallsp) { | 1761 if(g->syscallsp < g->stack.lo || g->stack.hi < g->syscallsp) { |
1756 fn = entersyscall_bad; | 1762 fn = entersyscall_bad; |
1757 runtime·onM(&fn); | 1763 runtime·onM(&fn); |
1758 } | 1764 } |
1759 | 1765 |
1760 if(runtime·atomicload(&runtime·sched.sysmonwait)) { // TODO: fast atomi
c | 1766 if(runtime·atomicload(&runtime·sched.sysmonwait)) { // TODO: fast atomi
c |
1761 fn = entersyscall_sysmon; | 1767 fn = entersyscall_sysmon; |
1762 runtime·onM(&fn); | 1768 runtime·onM(&fn); |
1763 » » save(runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy)); | 1769 » » save((void *)pc, sp); |
1764 } | 1770 } |
1765 | 1771 |
1766 g->m->mcache = nil; | 1772 g->m->mcache = nil; |
1767 g->m->p->m = nil; | 1773 g->m->p->m = nil; |
1768 runtime·atomicstore(&g->m->p->status, Psyscall); | 1774 runtime·atomicstore(&g->m->p->status, Psyscall); |
1769 if(runtime·sched.gcwaiting) { | 1775 if(runtime·sched.gcwaiting) { |
1770 fn = entersyscall_gcwait; | 1776 fn = entersyscall_gcwait; |
1771 runtime·onM(&fn); | 1777 runtime·onM(&fn); |
1772 » » save(runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy)); | 1778 » » save((void *)pc, sp); |
1773 } | 1779 } |
1774 | 1780 |
1775 // Goroutines must not split stacks in Gsyscall status (it would corrupt
g->sched). | 1781 // Goroutines must not split stacks in Gsyscall status (it would corrupt
g->sched). |
1776 // We set stackguard to StackPreempt so that first split stack check cal
ls morestack. | 1782 // We set stackguard to StackPreempt so that first split stack check cal
ls morestack. |
1777 // Morestack detects this case and throws. | 1783 // Morestack detects this case and throws. |
1778 g->stackguard0 = StackPreempt; | 1784 g->stackguard0 = StackPreempt; |
1779 g->m->locks--; | 1785 g->m->locks--; |
| 1786 } |
| 1787 |
| 1788 // Standard syscall entry used by the go syscall library and normal cgo calls. |
| 1789 #pragma textflag NOSPLIT |
| 1790 void |
| 1791 ·entersyscall(int32 dummy) |
| 1792 { |
| 1793 runtime·reentersyscall((uintptr)runtime·getcallerpc(&dummy), runtime·get
callersp(&dummy)); |
1780 } | 1794 } |
1781 | 1795 |
1782 static void | 1796 static void |
1783 entersyscall_bad(void) | 1797 entersyscall_bad(void) |
1784 { | 1798 { |
1785 G *gp; | 1799 G *gp; |
1786 ········ | 1800 ········ |
1787 gp = g->m->curg; | 1801 gp = g->m->curg; |
1788 runtime·printf("entersyscall inconsistent %p [%p,%p]\n", | 1802 runtime·printf("entersyscall inconsistent %p [%p,%p]\n", |
1789 gp->syscallsp, gp->stack.lo, gp->stack.hi); | 1803 gp->syscallsp, gp->stack.lo, gp->stack.hi); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1849 { | 1863 { |
1850 handoffp(releasep()); | 1864 handoffp(releasep()); |
1851 } | 1865 } |
1852 | 1866 |
1853 // The goroutine g exited its system call. | 1867 // The goroutine g exited its system call. |
1854 // Arrange for it to run on a cpu again. | 1868 // Arrange for it to run on a cpu again. |
1855 // This is called only from the go syscall library, not | 1869 // This is called only from the go syscall library, not |
1856 // from the low-level system calls used by the runtime. | 1870 // from the low-level system calls used by the runtime. |
1857 #pragma textflag NOSPLIT | 1871 #pragma textflag NOSPLIT |
1858 void | 1872 void |
1859 runtime·exitsyscall(void) | 1873 ·exitsyscall(int32 dummy) |
1860 { | 1874 { |
1861 void (*fn)(G*); | 1875 void (*fn)(G*); |
1862 | 1876 |
1863 g->m->locks++; // see comment in entersyscall | 1877 g->m->locks++; // see comment in entersyscall |
| 1878 |
| 1879 if(runtime·getcallersp(&dummy) > g->syscallsp) |
| 1880 runtime·throw("exitsyscall: syscall frame is no longer valid"); |
1864 | 1881 |
1865 g->waitsince = 0; | 1882 g->waitsince = 0; |
1866 if(exitsyscallfast()) { | 1883 if(exitsyscallfast()) { |
1867 // There's a cpu for us, so we can run. | 1884 // There's a cpu for us, so we can run. |
1868 g->m->p->syscalltick++; | 1885 g->m->p->syscalltick++; |
1869 // We need to cas the status and scan before resuming... | 1886 // We need to cas the status and scan before resuming... |
1870 runtime·casgstatus(g, Gsyscall, Grunning); | 1887 runtime·casgstatus(g, Gsyscall, Grunning); |
1871 | 1888 |
1872 // Garbage collector isn't running (since we are), | 1889 // Garbage collector isn't running (since we are), |
1873 // so okay to clear syscallsp. | 1890 // so okay to clear syscallsp. |
(...skipping 1581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3455 p = mp->p->id; | 3472 p = mp->p->id; |
3456 FLUSH(&p); | 3473 FLUSH(&p); |
3457 } | 3474 } |
3458 | 3475 |
3459 #pragma textflag NOSPLIT | 3476 #pragma textflag NOSPLIT |
3460 void | 3477 void |
3461 sync·runtime_procUnpin() | 3478 sync·runtime_procUnpin() |
3462 { | 3479 { |
3463 g->m->locks--; | 3480 g->m->locks--; |
3464 } | 3481 } |
LEFT | RIGHT |