Only one lock is used for all songvec traversals since
they're rarely changed. Also, minimize lock time and
release it before calling iterator functions since they
may block (updateSongInfo => stat/open/seek/read).
This lock only protects songvecs (and all of them) during
traversals; not the individual song structures themselves.
Our linked-list implementation is wasteful and the
SongList isn't modified enough to benefit from being a linked
list. So use a more compact array of song pointers which
saves ~200K on a library with ~9K songs (on x86-32).