So, if the only queue-writing task is running on Core 0 and the only queue-reading task is running on Core 1, must the queue be locked with a common mutex while each of these tasks is doing its thing?
Or, since only one task is writing and only one task is reading (even though on independently-running cores), there won't be a conflict and mutex-locking isn't required?
Note that having one task that reads and another that writes in general does require some form of synchronization, if not locks or mutexes then at least atomic variables.
In this case, the FreeRTOS kernel just handles it for you.
OK, thanks. That's pretty much what I figured. My only doubt was because the "vanilla FreeRTOS" documentation seems to assume a single-core environment while ESP32 has two cores. Good to know that the ESP32 port takes this into account with regard to queue management.
It would indeed be a surprise if the Queue API would behave differently on ESP32, but I agree that it would be nice if the docs were more explicit about it.
Synchronization in a single-core system with preemptive scheduling isn't all that different from a multiprocessor environment, in both cases, you need mutexes/critical sections and atomic variables (although you don't need actual memory barriers on a single core, you still need to prevent the compiler from reordering your reads/writes to shared data). There are of course some differences, especially if you're writing the kernel/scheduler, but from user space it doesn't matter too much in most cases.
A final remark: given that the FreeRTOS Queue uses locks to allow any number of threads to access the queue at the same time, you might want to use a lock-free alternative if you have a single producer and a single consumer. This is important if performance of the queue is an issue, locks can slow things down significantly. You could Google for "SPSC queue" or "lock-free queue", for example. IIRC, Boost has one, and so does Folly.