#pragma textflag NOSPLITvoid·entersyscall(int32dummy){// Disable preemption because during this function g is in Gsyscall status,// but can have inconsistent g->sched, do not let GC observe it.m->locks++;// Leave SP around for GC and traceback.save(runtime·getcallerpc(&dummy),runtime·getcallersp(&dummy));g->syscallsp=g->sched.sp;g->syscallpc=g->sched.pc;g->syscallstack=g->stackbase;g->syscallguard=g->stackguard;g->status=Gsyscall;if(g->syscallsp<g->syscallguard-StackGuard||g->syscallstack<g->syscallsp){// runtime·printf("entersyscall inconsistent %p [%p,%p]\n",// g->syscallsp, g->syscallguard-StackGuard, g->syscallstack);runtime·throw("entersyscall");}
if(runtime·atomicload(&runtime·sched.sysmonwait)){// TODO: fast atomicruntime·lock(&runtime·sched);if(runtime·atomicload(&runtime·sched.sysmonwait)){runtime·atomicstore(&runtime·sched.sysmonwait,0);runtime·notewakeup(&runtime·sched.sysmonnote);}runtime·unlock(&runtime·sched);save(runtime·getcallerpc(&dummy),runtime·getcallersp(&dummy));}
m->mcache=nil;m->p->m=nil;runtime·atomicstore(&m->p->status,Psyscall);if(runtime·sched.gcwaiting){runtime·lock(&runtime·sched);if(runtime·sched.stopwait>0&&runtime·cas(&m->p->status,Psyscall,Pgcstop)){if(--runtime·sched.stopwait==0)runtime·notewakeup(&runtime·sched.stopnote);}runtime·unlock(&runtime·sched);save(runtime·getcallerpc(&dummy),runtime·getcallersp(&dummy));}// Goroutines must not split stacks in Gsyscall status (it would corrupt g->sched).// We set stackguard to StackPreempt so that first split stack check calls morestack.// Morestack detects this case and throws.g->stackguard0=StackPreempt;m->locks--;}
#pragma textflag NOSPLITvoid·entersyscallblock(int32dummy){P*p;m->locks++;// see comment in entersyscall// Leave SP around for GC and traceback.save(runtime·getcallerpc(&dummy),runtime·getcallersp(&dummy));g->syscallsp=g->sched.sp;g->syscallpc=g->sched.pc;g->syscallstack=g->stackbase;g->syscallguard=g->stackguard;g->status=Gsyscall;if(g->syscallsp<g->syscallguard-StackGuard||g->syscallstack<g->syscallsp){// runtime·printf("entersyscall inconsistent %p [%p,%p]\n",// g->syscallsp, g->syscallguard-StackGuard, g->syscallstack);runtime·throw("entersyscallblock");}
后面的部分就不太一样了,基本上就是直接将当前M与P解耦,P重新回到Pidle状态。
p=releasep();handoffp(p);if(g->isbackground)// do not consider blocked scavenger for deadlock detectionincidlelocked(1);// Resave for traceback during blocked call.save(runtime·getcallerpc(&dummy),runtime·getcallersp(&dummy));g->stackguard0=StackPreempt;// see comment in entersyscallm->locks--;}
// The goroutine g exited its system call.// Arrange for it to run on a cpu again.// This is called only from the go syscall library, not// from the low-level system calls used by the runtime.#pragma textflag NOSPLITvoidruntime·exitsyscall(void){m->locks++;// see comment in entersyscallif(g->isbackground)// do not consider blocked scavenger for deadlock detectionincidlelocked(-1);if(exitsyscallfast()){// There's a cpu for us, so we can run.m->p->syscalltick++;g->status=Grunning;// Garbage collector isn't running (since we are),// so okay to clear gcstack and gcsp.g->syscallstack=(uintptr)nil;g->syscallsp=(uintptr)nil;m->locks--;if(g->preempt){// restore the preemption request in case we've cleared it in newstackg->stackguard0=StackPreempt;}else{// otherwise restore the real stackguard, we've spoiled it in entersyscall/entersyscallblockg->stackguard0=g->stackguard;}return;}m->locks--;
// Call the scheduler.runtime·mcall(exitsyscall0);// Scheduler returned, so we're allowed to run now.// Delete the gcstack information that we left for// the garbage collector during the system call.// Must wait until now because until gosched returns// we don't know for sure that the garbage collector// is not running.g->syscallstack=(uintptr)nil;g->syscallsp=(uintptr)nil;m->p->syscalltick++;}
The golang version
```
package main
import (
"bytes"
"flag"
"fmt"
"strings"
)
func main() {
//take input from flag
str := flag.String("str", "", "input a string")
flag.Parse()
if len(*str) == 0 {
flag.PrintDefaults()
return
}
replacer := strings.NewReplacer("'", "", " ", "")
*str = replacer.Replace(*str)
counter := make(map[rune]int)
//count individual character
for _, ch := range bytes.Runes([]byte(*str)) {
counter[ch]++
}
//print out the result
for k, v := range counter {
fmt.Print(string(k))
fmt.Println(" ", v)
}
}
```
#pragma textflag NOSPLITvoid·entersyscall(int32dummy){// Disable preemption because during this function g is in Gsyscall status,// but can have inconsistent g->sched, do not let GC observe it.m->locks++;// Leave SP around for GC and traceback.save(runtime·getcallerpc(&dummy),runtime·getcallersp(&dummy));g->syscallsp=g->sched.sp;g->syscallpc=g->sched.pc;g->syscallstack=g->stackbase;g->syscallguard=g->stackguard;g->status=Gsyscall;if(g->syscallsp<g->syscallguard-StackGuard||g->syscallstack<g->syscallsp){// runtime·printf("entersyscall inconsistent %p [%p,%p]\n",// g->syscallsp, g->syscallguard-StackGuard, g->syscallstack);runtime·throw("entersyscall");}
if(runtime·atomicload(&runtime·sched.sysmonwait)){// TODO: fast atomicruntime·lock(&runtime·sched);if(runtime·atomicload(&runtime·sched.sysmonwait)){runtime·atomicstore(&runtime·sched.sysmonwait,0);runtime·notewakeup(&runtime·sched.sysmonnote);}runtime·unlock(&runtime·sched);save(runtime·getcallerpc(&dummy),runtime·getcallersp(&dummy));}
m->mcache=nil;m->p->m=nil;runtime·atomicstore(&m->p->status,Psyscall);if(runtime·sched.gcwaiting){runtime·lock(&runtime·sched);if(runtime·sched.stopwait>0&&runtime·cas(&m->p->status,Psyscall,Pgcstop)){if(--runtime·sched.stopwait==0)runtime·notewakeup(&runtime·sched.stopnote);}runtime·unlock(&runtime·sched);save(runtime·getcallerpc(&dummy),runtime·getcallersp(&dummy));}// Goroutines must not split stacks in Gsyscall status (it would corrupt g->sched).// We set stackguard to StackPreempt so that first split stack check calls morestack.// Morestack detects this case and throws.g->stackguard0=StackPreempt;m->locks--;}
#pragma textflag NOSPLITvoid·entersyscallblock(int32dummy){P*p;m->locks++;// see comment in entersyscall// Leave SP around for GC and traceback.save(runtime·getcallerpc(&dummy),runtime·getcallersp(&dummy));g->syscallsp=g->sched.sp;g->syscallpc=g->sched.pc;g->syscallstack=g->stackbase;g->syscallguard=g->stackguard;g->status=Gsyscall;if(g->syscallsp<g->syscallguard-StackGuard||g->syscallstack<g->syscallsp){// runtime·printf("entersyscall inconsistent %p [%p,%p]\n",// g->syscallsp, g->syscallguard-StackGuard, g->syscallstack);runtime·throw("entersyscallblock");}
后面的部分就不太一样了,基本上就是直接将当前M与P解耦,P重新回到Pidle状态。
p=releasep();handoffp(p);if(g->isbackground)// do not consider blocked scavenger for deadlock detectionincidlelocked(1);// Resave for traceback during blocked call.save(runtime·getcallerpc(&dummy),runtime·getcallersp(&dummy));g->stackguard0=StackPreempt;// see comment in entersyscallm->locks--;}
// The goroutine g exited its system call.// Arrange for it to run on a cpu again.// This is called only from the go syscall library, not// from the low-level system calls used by the runtime.#pragma textflag NOSPLITvoidruntime·exitsyscall(void){m->locks++;// see comment in entersyscallif(g->isbackground)// do not consider blocked scavenger for deadlock detectionincidlelocked(-1);if(exitsyscallfast()){// There's a cpu for us, so we can run.m->p->syscalltick++;g->status=Grunning;// Garbage collector isn't running (since we are),// so okay to clear gcstack and gcsp.g->syscallstack=(uintptr)nil;g->syscallsp=(uintptr)nil;m->locks--;if(g->preempt){// restore the preemption request in case we've cleared it in newstackg->stackguard0=StackPreempt;}else{// otherwise restore the real stackguard, we've spoiled it in entersyscall/entersyscallblockg->stackguard0=g->stackguard;}return;}m->locks--;
// Call the scheduler.runtime·mcall(exitsyscall0);// Scheduler returned, so we're allowed to run now.// Delete the gcstack information that we left for// the garbage collector during the system call.// Must wait until now because until gosched returns// we don't know for sure that the garbage collector// is not running.g->syscallstack=(uintptr)nil;g->syscallsp=(uintptr)nil;m->p->syscalltick++;}