In the Lua implementation of the link, Lua coroutine has its own Lua stack, which is just an array inside lua_State and has nothing to do with the C stack. Lua cannot save the C stack (because this is not possible in the C standard), therefore it cannot provide a coroutine if function C is currently running.
For example, if you have a Lua a function that calls the C b function that calls the Lua c function, and c tries to execute, Lua will not be able to save the local variables for b (since it is a C function) and it will fail.
This also applies to many of Lua's built-in functions. As you pointed out in Lua 5.1, the implementation did not support the assignment in pcall until Lua 5.2 apparently added special functions to make it work.
Coco is a patch for the standard Lua implementation, which implements individual C-stacks in coroutines, so Lua can now “save” the C function variables. Obviously, LuaJit 1.x also includes it. This does not apply to LuaJit 2.x because it is a completely different implementation of Lua.
LuaJit 2.x has the following paragraph on the Extensions page:
Fully Revolving VM
LuaJIT VM is fully renewable. This means that you can get from coroutines even in contexts where this is not possible using the standard Lua 5.1 VM: for example. you can get through pcall () and xpcall (), through iterators and metamotodes.
Thus, it is obvious that the execution of built-in functions should work, although it is still ambiguous if it is applied to arbitrary functions of the Lua C API. However, it is easy to verify; write a simple C API function that takes a Lua function and calls it, and then passes it a function that gives. If it does not work, it should throw an error.
Note that the simple C functions loaded by FFI cannot generally concern the state of Lua. This includes attempts to yield.