Earlier quoted context omitted.
While I'm sure it would bring its own problems, could you just stick a semaphore or similar around the function?
Yes, but it will not work in a generic case because you have to handle the situations of deadlocks (i.e recursive mutexes for nested locking ..etc). Also you will introduce more problems of creating performance deadlocks. There will not be out of box solutions to all these. Once you start considering solving case on its own then this does not provide out of box solution as the original premise.
In any other scenario, if some execution thread reaches the point where it returns from calling lock() on the mutex guarding malloc(), it must eventually reach the call to unlock().