STDIO is initialized in the early_init() function. If vfs is used, the vfs_bind_stdio() function is called, but the OS is not yet running. If the processor is not ready to work with NULL pointers, calling mutex_lock_internal from vfs_bind causes a panic because thread_get_active() returns NULL..
Next changes in mutex_lock_internal resolve this problem:
bool mutex_lock_internal(mutex_t \*mutex, bool block)
{
uinttxtptr_t pc = 0;
#if IS_USED(MODULE_CORE_MUTEX_DEBUG)
pc = cpu_get_caller_pc();
#endif
unsigned irq_state = irq_disable();
DEBUG("PID\[%" PRIkernel_pid "\] mutex_lock_internal(block=%u).\\n",
thread_getpid(), (unsigned)block);
if (mutex->queue.next == NULL) {
/\* mutex is unlocked. \*/
mutex->queue.next = MUTEX_LOCKED;
#if IS_USED(MODULE_CORE_MUTEX_PRIORITY_INHERITANCE) \\
|| IS_USED(MODULE_CORE_MUTEX_DEBUG)
thread_t \*me = thread_get_active();
if (me != NULL) {
mutex->owner = me->pid;
}
else {
mutex->owner = KERNEL_PID_UNDEF;
}
#endif
#if IS_USED(MODULE_CORE_MUTEX_DEBUG)
mutex->owner_calling_pc = pc;
#endif
#if IS_USED(MODULE_CORE_MUTEX_PRIORITY_INHERITANCE)
if (me != NULL) {
mutex->owner_original_priority = me->priority;
}
else {
mutex->owner_original_priority = 0;
}
#endif
DEBUG("PID\[%" PRIkernel_pid "\] mutex_lock(): early out.\\n",
thread_getpid());
irq_restore(irq_state);
}
else {
if (!block) {
irq_restore(irq_state);
return false;
}
\_block(mutex, irq_state, pc);
}
return true;
}