Skip to content

Conversation

@jrouwe
Copy link
Contributor

@jrouwe jrouwe commented Oct 21, 2024

This emits all temporaries as 'static thread_local temp;' instead of 'static temp;' and prevents race conditions when you use the resulting library in a multithreaded environment.

E.g. if you create an IDL file like:

interface Vec3 {
	[Const, Value] Vec3 Cross([Const, Ref] Vec3 inRHS);
};

Previously the generated cpp file would look like:

const Vec3* EMSCRIPTEN_KEEPALIVE emscripten_bind_Vec3_Cross_1(Vec3* self, const Vec3* inRHS) {
  static Vec3 temp;
  return (temp = self->Cross(*inRHS), &temp);
}

Which has a race condition when you call into the Cross function from multiple JavaScript threads as they all use the same temp variable.

With this new parameter the resulting code will look like:

const Vec3* EMSCRIPTEN_KEEPALIVE emscripten_bind_Vec3_Cross_1(Vec3* self, const Vec3* inRHS) {
  static thread_local Vec3 temp;
  return (temp = self->Cross(*inRHS), &temp);
}

Which guarantees that no other threads overwrite temp.

parser = argparse.ArgumentParser()
parser.add_argument('--wasm64', action='store_true', default=False,
help='Build for wasm64')
parser.add_argument('--thread_safe', action='store_true', default=False,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you use dashes in the option name (e.g. "--thread-safe" )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

if non_pointer:
return_prefix += '&'
if thread_safe:
storage_attribute = 'thread_local '
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should just always emit this, when TLS gets lowered away when not building with thread support?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could, and you're right that if you build without -pthread the resulting code is the same:

https://godbolt.org/z/6cE6T8a47

When adding -pthread there is an extra instruction which adds a bit of overhead:

image

I cannot predict if people are ok with this overhead. Their library may use multiple threads internally, but maybe they don't interact with the library from multiple threads. In that case there's no benefit in adding the thread_local attribute.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you are doing a pthread build we should just default to being thread safe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, in that case the change becomes really simple. I've pushed the new code.

@jrouwe jrouwe force-pushed the thread_safe branch 2 times, most recently from f2a2e2a to 7caaa88 Compare October 21, 2024 20:21
jrouwe added a commit to jrouwe/JoltPhysics.js that referenced this pull request Oct 21, 2024
return_prefix += '&'
if copy:
pre += ' static %s temp;\n' % type_to_c(return_type, non_pointing=True)
pre += ' static thread_local %s temp;\n' % type_to_c(return_type, non_pointing=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment, maybe something like "Avoid sharing this static temp var between threads, which could race." Otherwise looks great.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

This emits all temporaries as 'static thread_local <type> temp;' instead of 'static <type> temp;' and prevents race conditions when you use the resulting library in a multithreaded environment.

When compiling without -pthread, the thread_local attribute is ignored and the generated code is as it was before.
@kripken kripken merged commit f88c213 into emscripten-core:main Oct 21, 2024
2 checks passed
@jrouwe jrouwe deleted the thread_safe branch October 22, 2024 05:44
jrouwe added a commit to jrouwe/JoltPhysics.js that referenced this pull request Oct 26, 2024
This pulls in:
- emscripten-core/emscripten#22770
- emscripten-core/emscripten#22772
and gets rid of the custom copy of webidl_binder.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants