pk11_destroy_{rsa,dsa,dh}_key_objects() functions accept a 'session' argument which is a pointer to PK11_SESSION structure. In case the pointer is NULL, global freelist is traversed and all objects of the given type are deleted.
Each of the functions has the following construct in the beginning of it:
CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
if (session)
local_free_session = session;
else
local_free_session = free_session;
then it proceeds to iterating over local_free_session and performing delete operation via call to pk11_destroy_object().
This is suboptimal because in case where 'session' argument is not NULL, we only want to delete single object and we do not need to access the global freelist. Hence, we do not need any protection for that because pk11_get_session() ensures that 'next' member of PK11_SESSION structure points to NULL after extracting the structure from the freelist which means strcture returned from pk11_get_session() cannot be linked to the freelist.
If one thread which already 'owns' a PK11_SESSION structure decides to delete some keys referenced by the structure it will block all other threads performing operation in the engine which requires access to the global CRYPTO_LOCK_PK11_ENGINE lock.