[Go] Adjust last patch to avoid write-after-write data race on global

variable.  Only set the variable if another global variable is true,
but that variable is always false.  The effect is that the variable is
never written, but as far as the compiler is concerned it might escape.
This commit is contained in:
Ian Lance Taylor 2014-10-14 10:05:43 -07:00
commit 0577ff2220
2 changed files with 41 additions and 14 deletions

View file

@ -225,6 +225,16 @@ type _ unsafe.Pointer
%}
/* Swig_always_false is used to conditionally assign parameters to
Swig_escape_val so that the compiler thinks that they escape. We
only assign them if Swig_always_false is true, which it never is.
We export the variable so that the compiler doesn't realize that it
is never set. */
%insert(go_header) %{
var Swig_escape_always_false bool
var Swig_escape_val interface{}
%}
/* Function pointers are translated by the code in go.cxx into
_swig_fnptr. Member pointers are translated to _swig_memberptr. */

View file

@ -920,15 +920,8 @@ private:
needs_wrapper = true;
}
// If the parameter has an argout or freearg typemap, we need to
// make sure that it escapes, in case it contains any pointers.
if (Getattr(p, "tmap:argout") || Getattr(p, "tmap:freearg")) {
if (!goTypeIsInterface(p, Getattr(p, "type"))) {
String *tm = goWrapperType(p, Getattr(p, "type"), false);
Printf(f_go_wrappers, "var %s_escape_%d %s\n", wname, i, tm);
Delete(tm);
needs_wrapper = true;
}
if (paramNeedsEscape(p)) {
needs_wrapper = true;
}
p = nextParm(p);
@ -1218,11 +1211,10 @@ private:
// If the parameter has an argout or freearg typemap, make
// sure that it escapes.
if (Getattr(p, "tmap:argout") || Getattr(p, "tmap:freearg")) {
// No need to do anything for C++ class type.
if (!goTypeIsInterface(p, pt)) {
Printf(f_go_wrappers, "\t%s_escape_%d = %s\n", wname, i, Getattr(p, "emit:goinput"));
}
if (paramNeedsEscape(p)) {
Printv(f_go_wrappers, "\tif Swig_escape_always_false {\n", NULL);
Printv(f_go_wrappers, "\t\tSwig_escape_val = ", Getattr(p, "emit:goinput"), "\n", NULL);
Printv(f_go_wrappers, "\t}\n", NULL);
}
p = nextParm(p);
@ -1291,6 +1283,31 @@ private:
return "base";
}
/* ----------------------------------------------------------------------
* paramNeedsEscape()
*
* A helper for goFunctionWrapper that returns whether a parameter
* needs to explicitly escape. This is true if the parameter has a
* non-empty argout or freearg typemap, because in those cases the
* Go argument might be or contain a pointer. We need to ensure
* that that pointer does not oint into the stack, which means that
* it needs to escape.
* ---------------------------------------------------------------------- */
bool paramNeedsEscape(Parm *p) {
String *argout = Getattr(p, "tmap:argout");
String *freearg = Getattr(p, "tmap:freearg");
if ((!argout || Len(argout) == 0) && (!freearg || Len(freearg) == 0)) {
return false;
}
// If a C++ type is represented as an interface type in Go, then
// we don't care whether it escapes, because we know that the
// pointer is a C++ pointer.
if (goTypeIsInterface(p, Getattr(p, "type"))) {
return false;
}
return true;
}
/* ----------------------------------------------------------------------
* gcFunctionWrapper()
*