- /*
- * FIXME: We have a race condition here. It's possible that this function returns
- * to its caller with `instance_size` set to `0` instead of the actual size. This
- * is not a problem when the function is called recursively on the same class,
- * because the size will be initialized by the outer invocation. What follows is a
- * description of how it can occur in other cases, too. There it is a problem,
- * because it can lead to the GC being asked to allocate an object of size `0`,
- * which SGen chokes on. The race condition is triggered infrequently by
- * `tests/sgen-suspend.cs`.
- *
- * This function is called for a class whenever one of its subclasses is inited.
- * For example, it's called for every subclass of Object. What it does is this:
- *
- * if (klass->setup_fields_called)
- * return;
- * ...
- * klass->instance_size = 0;
- * ...
- * klass->setup_fields_called = 1;
- * ... critical point
- * klass->instance_size = actual_instance_size;
- *
- * The last two steps are sometimes reversed, but that only changes the way in which
- * the race condition works.
- *
- * Assume thread A goes through this function and makes it to the critical point.
- * Now thread B runs the function and, since `setup_fields_called` is set, returns
- * immediately, but `instance_size` is incorrect.
- *
- * The other case looks like this:
- *
- * if (klass->setup_fields_called)
- * return;
- * ... critical point X
- * klass->instance_size = 0;
- * ... critical point Y
- * klass->instance_size = actual_instance_size;
- * ...
- * klass->setup_fields_called = 1;
- *
- * Assume thread A goes through the function and makes it to critical point X. Now
- * thread B runs through the whole of the function, returning, assuming
- * `instance_size` is set. At that point thread A gets to run and makes it to
- * critical point Y, at which time `instance_size` is `0` again, invalidating thread
- * B's assumption.
- */
- if (klass->setup_fields_called)