Allow multiple concurrent readers for X.509 CRT frame and PK context

Previously, only one thread could access the parsing cache of an X.509 CRT
at a time. Firstly, this leads to significant performance penalties on
systems running many concurrent threads which share CRT structures --
for example, server threads sharing an SSL configuration containing the
server CRT. Secondly, the locking should be logically unnecessary, because
the threads are supposed to access the CRT frame and PK in a read-only,
or at least thread-safe manner.

This commit modifies the X.509 CRT cache implementation by allowing an
arbitrary number of concurrent readers, locking only the path of setting
up and clearing the cache.
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 04e8125..03cda69 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -112,17 +112,21 @@
 #if defined(MBEDTLS_THREADING_C)
     if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
-#endif
 
+    /* Can only free the PK context if nobody is using it. */
+    if( crt->cache->pk_readers == 0 )
+#endif
+    {
 #if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
-    /* The cache holds a shallow copy of the PK context
-     * in the legacy struct, so don't free PK context. */
-    mbedtls_free( crt->cache->pk );
+        /* The cache holds a shallow copy of the PK context
+         * in the legacy struct, so don't free PK context. */
+        mbedtls_free( crt->cache->pk );
 #else
-    mbedtls_pk_free( crt->cache->pk );
-    mbedtls_free( crt->cache->pk );
+        mbedtls_pk_free( crt->cache->pk );
+        mbedtls_free( crt->cache->pk );
 #endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
-    crt->cache->pk = NULL;
+        crt->cache->pk = NULL;
+    }
 
 #if defined(MBEDTLS_THREADING_C)
     if( mbedtls_mutex_unlock( &crt->cache->pk_mutex ) != 0 )
@@ -136,10 +140,14 @@
 #if defined(MBEDTLS_THREADING_C)
     if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
-#endif
 
-    mbedtls_free( crt->cache->frame );
-    crt->cache->frame = NULL;
+    /* Can only free the frame if nobody is using it. */
+    if( crt->cache->frame_readers == 0 )
+#endif
+    {
+        mbedtls_free( crt->cache->frame );
+        crt->cache->frame = NULL;
+    }
 
 #if defined(MBEDTLS_THREADING_C)
     if( mbedtls_mutex_unlock( &crt->cache->frame_mutex ) != 0 )