Commit d31591fc04 for openssl.org

commit d31591fc0416f56203d809db1a4c4c90a7f4c5ee
Author: Neil Horman <nhorman@openssl.org>
Date:   Tue Apr 28 10:08:24 2026 -0400

    Add atomic list inserted to method store cache

    Reviewed-by: Saša NedvÄ›dický <sashan@openssl.org>
    Reviewed-by: Bob Beck <beck@openssl.org>
    Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
    MergeDate: Tue Jun  9 18:17:05 2026
    (Merged from https://github.com/openssl/openssl/pull/31018)

diff --git a/crypto/property/property.c b/crypto/property/property.c
index 024d857467..cd7a4ce7b4 100644
--- a/crypto/property/property.c
+++ b/crypto/property/property.c
@@ -37,6 +37,10 @@
 #define NUM_SHARDS 4
 #endif

+#ifndef MAX_CACHE_LINES
+#define MAX_CACHE_LINES 8
+#endif
+
 #if defined(__GNUC__) || defined(__clang__)
 /*
  * ALLOW_VLA enables the use of dynamically sized arrays
@@ -71,6 +75,7 @@ DEFINE_STACK_OF(IMPLEMENTATION)

 typedef struct query_st {
     OSSL_LIST_MEMBER(lru_entry, struct query_st); /* member of our linked list */
+    struct query_st *next;
     void *saptr; /* pointer to our owning STORED_ALGORITHM */
     int nid; /* nid of this query */
     uint64_t specific_hash; /* hash of [nid,prop_query,prov] tuple */
@@ -102,6 +107,8 @@ typedef struct {
     SPARSE_ARRAY_OF(ALGORITHM) * algs;

     HT *cache;
+    QUERY *cache_lists[MAX_CACHE_LINES];
+
     /*
      * This is a list of every element in our query
      * cache.  NOTE: Its named lru list, but to avoid
@@ -116,11 +123,14 @@ typedef struct {
      * by the appropriate functions here.
      */
     CRYPTO_RWLOCK *lock;
+    CRYPTO_RWLOCK *alock;

     /* query cache specific values */

 } STORED_ALGORITHMS;

+static int ossl_method_store_atomic_insert_to_list(STORED_ALGORITHMS *sa, int nid, QUERY *new);
+
 struct ossl_method_store_st {
     OSSL_LIB_CTX *ctx;
     STORED_ALGORITHMS *algs;
@@ -322,6 +332,7 @@ static void stored_algs_free(STORED_ALGORITHMS *sa)
         ossl_sa_ALGORITHM_doall_arg(sa[i].algs, &alg_cleanup, &sa[i]);
         ossl_sa_ALGORITHM_free(sa[i].algs);
         CRYPTO_THREAD_lock_free(sa[i].lock);
+        CRYPTO_THREAD_lock_free(sa[i].alock);
         ossl_ht_free(sa[i].cache);
     }

@@ -353,6 +364,9 @@ static STORED_ALGORITHMS *stored_algs_new(OSSL_LIB_CTX *ctx)
         ret[i].lock = CRYPTO_THREAD_lock_new();
         if (ret[i].lock == NULL)
             goto err;
+        ret[i].alock = CRYPTO_THREAD_lock_new();
+        if (ret[i].alock == NULL)
+            goto err;
         ret[i].cache = ossl_ht_new(&ht_conf);
         if (ret[i].cache == NULL)
             goto err;
@@ -1099,6 +1113,7 @@ int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
                 ret = 0;
             } else {
                 ossl_list_lru_entry_insert_tail(&sa->lru_list, post_insert);
+                ossl_method_store_atomic_insert_to_list(sa, nid, post_insert);
             }
             ossl_property_unlock(sa);
         }
@@ -1106,6 +1121,24 @@ int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
     return ret;
 }

+static int ossl_method_store_atomic_insert_to_list(STORED_ALGORITHMS *sa, int nid, QUERY *new)
+{
+    nid = nid % MAX_CACHE_LINES;
+    QUERY *headptr;
+    int ret = 0;
+
+    if (!CRYPTO_atomic_load_ptr((void **)&sa->cache_lists[nid], (void **)&headptr, sa->alock))
+        goto out;
+try_again:
+    if (!CRYPTO_atomic_store_ptr((void **)&new->next, (void **)&headptr, sa->alock))
+        goto out;
+    if (!CRYPTO_atomic_cmp_exch_ptr((void **)&sa->cache_lists[nid], (void **)&headptr, new, sa->alock))
+        goto try_again;
+    ret = 1;
+out:
+    return ret;
+}
+
 static ossl_inline int ossl_method_store_cache_set_locked(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
     int nid, const char *prop_query, size_t keylen, STORED_ALGORITHMS *sa, void *method,
     int (*method_up_ref)(void *),
@@ -1173,6 +1206,8 @@ static ossl_inline int ossl_method_store_cache_set_locked(OSSL_METHOD_STORE *sto
         if (old != NULL)
             impl_cache_free(old);
         ossl_list_lru_entry_insert_head(&sa->lru_list, p);
+        ossl_method_store_atomic_insert_to_list(sa, nid, p);
+
         /*
          * We also want to add this method into the cache against a key computed _only_
          * from nid and property query.  This lets us match in the event someone does a lookup
@@ -1194,6 +1229,7 @@ static ossl_inline int ossl_method_store_cache_set_locked(OSSL_METHOD_STORE *sto
             p->specific_hash = 0;
             p->generic_hash = old->generic_hash = HT_KEY_GET_HASH(&key);
             ossl_list_lru_entry_insert_tail(&sa->lru_list, p);
+            ossl_method_store_atomic_insert_to_list(sa, nid, p);
         } else {
             impl_cache_free_unlinked(p);
             p = NULL;