fix(free-threading): cast `self` directly in `cpp_function::dispatcher` (#6177)

* fix(free-threading): cast `self` directly in `cpp_function::dispatcher`

Part of #6159 (item 59).

Under Py_GIL_DISABLED, cpp_function::dispatcher() took the internals lock
on every bound call: it reached its function_record through
function_record_ptr_from_PyObject(), which calls
get_function_record_PyTypeObject() (PYBIND11_LOCK_INTERNALS on
internals.mutex).

dispatcher is installed in exactly one place (initialize_generic), and the
PyCFunction there is created with m_self set to the function_record_PyObject
allocated a few lines above, so self is always that object. The new
function_record_ptr_from_dispatcher_self() states that invariant once and
casts directly; its assert compares the versioned tp_name instead of calling
is_function_record_PyObject(), which would reacquire the lock in non-NDEBUG
builds. is_function_record_PyObject() and function_record_ptr_from_PyObject()
are unchanged, so the call sites that can see a foreign object keep the
checked conversion.

Adds test_dispatch_does_not_need_internals_lock (free-threaded builds only):
a native thread holds internals.mutex through raw PyCFunction helpers and the
test checks that a bound call returns before the holder's watchdog releases
the mutex, with a positive control proving the held mutex is the one internals
users take. Fails without the fix, passes with it.

Assisted-by: Claude Code:claude-opus-5

* test: put the source tests dir on the subprocess path

pybind11_tests imports custom_exceptions from the source tests directory at
init, so the subprocess must see that directory as well as the build
directory, as test_custom_type_setup.py does.

Assisted-by: Claude Code:claude-opus-5

* style: qualify function-record name comparisons with std::strcmp

Apply the review suggestion to both sibling comparisons; retain the existing cstring include.

Assisted-by: Codex:GPT-6
4 files changed