From gcc go see the code language and channel to achieve goroutine

A, go parsing key documents

front-end language interpreted code go located gcc-4.8.2 \ gcc \ go \ gofrontend \ parse.cc file, parses the source file for the start of the Parse :: program. From the look of this function, the beginning of the source file must indicate their name by package; if there is import, they must be hit in the back package, before the first statement; from the highest level point of view, the entire source file consists of declarations, these declarations including const, type, var, func four. Helloworld a typical example, the content for the
package main

import "fmt"

main func () {
fmt.Println ( "the Hello, World")
}
by the package start of the next import declaration and the final func composition.

Two, go syntax to achieve

1, to convert calls to go to the run-time library __go_go

gcc-4.8.2\gcc\go\gofrontend\runtime.def
// Start a new goroutine.
DEF_GO_RUNTIME(GO, "__go_go", P2(FUNC_PTR, POINTER), R0())

void
Parse::go_or_defer_stat()
{
……
Statement* stat;
if (is_go)
stat = Statement::make_go_statement(call_expr, stat_location);
else
stat = Statement::make_defer_statement(call_expr, stat_location);
this->gogo_->add_statement(stat);
this->gogo_->add_block(this->gogo_->finish_block(stat_location),
stat_location);
}

Statement*
Statement::make_go_statement(Call_expression* call, Location location)
{
return new Go_statement(call, location);
}

Bstatement*
Go_statement::do_get_backend(Translate_context* context)
{
Expression* fn;
Expression* arg;
if (!this->get_fn_and_arg(&fn, &arg))
return context->backend()->error_statement();

Expression* call = Runtime::make_call(Runtime::GO, this->location(), 2,
fn, arg);
tree call_tree = call->get_tree(context);
Bexpression* call_bexpr = tree_to_expr(call_tree);
return context->backend()->expression_statement(call_bexpr);
}

2, run-time library __go_go implementation

From the realization point of view, this is expressed as a goroutine structure is then added to a queue by runqput runtime function, and the bottom layer is built by glibc context switching implemented.
4.8.2-GCC \ libgo \ Runtime \ proc.c
G *
__go_go (void (* Fn) (void *), void * Arg)
{
......
// Represents warnings About Variables clobbered by the Avoid
// longjmp.
byte volatile VSP * SP =;
size_t volatile vspsize = spsize;
G * = newg volatile vnewg;

getcontext(&vnewg->context);
vnewg->context.uc_stack.ss_sp = vsp;
#ifdef MAKECONTEXT_STACK_TOP
vnewg->context.uc_stack.ss_sp += vspsize;
#endif
vnewg->context.uc_stack.ss_size = vspsize;
makecontext(&vnewg->context, kickoff, 0);

runqput(m->p, vnewg);

if(runtime_atomicload(&runtime_sched.npidle) != 0 && runtime_atomicload(&runtime_sched.nmspinning) == 0 && fn != runtime_main) // TODO: fast atomic
wakep();
m->locks--;
return vnewg;
}

3, goroutine scheduling

The following article has reference https://tonybai.com/2017/06/23/an-intro-about-goroutine-scheduler/: roughly speaking, equivalent to its own virtual thread scheduling in the operating system and on the basis of the goroutine assigned different scheduling procesor

Three, channel realization

1, channel creation

Expression*
Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
Statement_inserter* inserter, int)
{
……
case BUILTIN_MAKE:
return this->lower_make();
……
}

Expression*
Builtin_call_expression::lower_make()
{
……
call = Runtime::make_call((have_big_args
? Runtime::MAKEMAPBIG
: Runtime::MAKEMAP),
loc, 2, type_arg, len_arg);
……
}

// The garbage collector is assuming that Hchan can only contain pointers into the stack
// and cannot contain pointers into the heap.
struct Hchan
{
uintgo qcount; // total data in the q
uintgo dataqsiz; // size of the circular q
uint16 elemsize;
bool closed;
uint8 elemalign;
uintgo sendx; // send index
uintgo recvx; // receive index
WaitQ recvq; // list of recv waiters
WaitQ sendq; // list of send waiters
Lock;
};

2, send runtime

Bstatement*
Send_statement::do_get_backend(Translate_context* context)
{
……
else if (can_take_address)
{
// Must pass address of value. The function doesn't change the
// value, so just take its address directly.
code = Runtime::SEND_BIG;
val = Expression::make_unary(OPERATOR_AND, val, loc);
}
……
Expression* call = Runtime::make_call(code, loc, 3, td, this->channel_, val);
……
}

It can be seen, where there is no transmission data and re own copy, simply pass the data pointer,
void
runtime_chansend (ChanType T *, C * Hchan, EP * byte, PRES BOOL *, void * PC)
{
......
mysg. EP = elem;
mysg.g = G;
mysg.selgen = NOSELGEN;
G-> param = nil;
the enqueue (& the C-> SendQ, & mysg);
runtime_park (runtime_unlock, C, "Chan Send");
......
}

Fourth, some built-reserved words

gcc-4.8.2\libgo\go\builtin\builtin.go
func make(Type, size IntegerType) Type

// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type

// The complex built-in function constructs a complex value from two
// floating-point values. The real and imaginary parts must be of the same
// size, either float32 or float64 (or assignable to them), and the return
// value will be the corresponding complex type (complex64 for float32,
// complex128 for float64).
func complex(r, i FloatType) ComplexType

// The real built-in function returns the real part of the complex number c.
// The return value will be floating point type corresponding to the type of c.
func real(c ComplexType) FloatType

gcc-4.8.2\gcc\go\gofrontend\gogo.cc
Function_type* complex_type = Type::make_function_type(NULL, NULL, NULL, loc);
complex_type->set_is_varargs();
complex_type->set_is_builtin();
this->globals_->add_function_declaration("complex", NULL, complex_type, loc);


gcc-4.8.2\gcc\go\gofrontend\gogo-tree.cc
tree
Gogo::allocate_memory(Type* type, tree size, Location location)
{
// If the package imports unsafe, then it may play games with
// pointers that look like integers.
if (this->imported_unsafe_ || type->has_pointer())
{
static tree new_fndecl;
return Gogo::call_builtin(&new_fndecl,
location,
"__go_new",
1,
ptr_type_node,
sizetype,
size);
}
else
{
static tree new_nopointers_fndecl;
return Gogo::call_builtin(&new_nopointers_fndecl,
location,
"__go_new_nopointers",
1,
ptr_type_node,
sizetype,
size);
}
}

Guess you like

Origin www.cnblogs.com/tsecer/p/11460552.html