Latest update
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* TODO(3.0) Move this header into provider when dependencies are removed */
|
||||
#ifndef HEADER_BLAKE2_H
|
||||
# define HEADER_BLAKE2_H
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# include <openssl/e_os2.h>
|
||||
# include <stddef.h>
|
||||
|
||||
# define BLAKE2S_BLOCKBYTES 64
|
||||
# define BLAKE2S_OUTBYTES 32
|
||||
# define BLAKE2S_KEYBYTES 32
|
||||
# define BLAKE2S_SALTBYTES 8
|
||||
# define BLAKE2S_PERSONALBYTES 8
|
||||
|
||||
# define BLAKE2B_BLOCKBYTES 128
|
||||
# define BLAKE2B_OUTBYTES 64
|
||||
# define BLAKE2B_KEYBYTES 64
|
||||
# define BLAKE2B_SALTBYTES 16
|
||||
# define BLAKE2B_PERSONALBYTES 16
|
||||
|
||||
struct blake2s_param_st {
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint8_t leaf_length[4];/* 8 */
|
||||
uint8_t node_offset[6];/* 14 */
|
||||
uint8_t node_depth; /* 15 */
|
||||
uint8_t inner_length; /* 16 */
|
||||
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
|
||||
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
|
||||
};
|
||||
|
||||
typedef struct blake2s_param_st BLAKE2S_PARAM;
|
||||
|
||||
struct blake2s_ctx_st {
|
||||
uint32_t h[8];
|
||||
uint32_t t[2];
|
||||
uint32_t f[2];
|
||||
uint8_t buf[BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
};
|
||||
|
||||
struct blake2b_param_st {
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint8_t leaf_length[4];/* 8 */
|
||||
uint8_t node_offset[8];/* 16 */
|
||||
uint8_t node_depth; /* 17 */
|
||||
uint8_t inner_length; /* 18 */
|
||||
uint8_t reserved[14]; /* 32 */
|
||||
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
|
||||
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
|
||||
};
|
||||
|
||||
typedef struct blake2b_param_st BLAKE2B_PARAM;
|
||||
|
||||
struct blake2b_ctx_st {
|
||||
uint64_t h[8];
|
||||
uint64_t t[2];
|
||||
uint64_t f[2];
|
||||
uint8_t buf[BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
};
|
||||
|
||||
#define BLAKE2B_DIGEST_LENGTH 64
|
||||
#define BLAKE2S_DIGEST_LENGTH 32
|
||||
|
||||
typedef struct blake2s_ctx_st BLAKE2S_CTX;
|
||||
typedef struct blake2b_ctx_st BLAKE2B_CTX;
|
||||
|
||||
int blake2s256_init(void *ctx);
|
||||
int blake2b512_init(void *ctx);
|
||||
|
||||
int blake2b_init(BLAKE2B_CTX *c, const BLAKE2B_PARAM *P);
|
||||
int blake2b_init_key(BLAKE2B_CTX *c, const BLAKE2B_PARAM *P, const void *key);
|
||||
int blake2b_update(BLAKE2B_CTX *c, const void *data, size_t datalen);
|
||||
int blake2b_final(unsigned char *md, BLAKE2B_CTX *c);
|
||||
|
||||
/*
|
||||
* These setters are internal and do not check the validity of their parameters.
|
||||
* See blake2b_mac_ctrl for validation logic.
|
||||
*/
|
||||
|
||||
void blake2b_param_init(BLAKE2B_PARAM *P);
|
||||
void blake2b_param_set_digest_length(BLAKE2B_PARAM *P, uint8_t outlen);
|
||||
void blake2b_param_set_key_length(BLAKE2B_PARAM *P, uint8_t keylen);
|
||||
void blake2b_param_set_personal(BLAKE2B_PARAM *P, const uint8_t *personal, size_t length);
|
||||
void blake2b_param_set_salt(BLAKE2B_PARAM *P, const uint8_t *salt, size_t length);
|
||||
|
||||
int blake2s_init(BLAKE2S_CTX *c, const BLAKE2S_PARAM *P);
|
||||
int blake2s_init_key(BLAKE2S_CTX *c, const BLAKE2S_PARAM *P, const void *key);
|
||||
int blake2s_update(BLAKE2S_CTX *c, const void *data, size_t datalen);
|
||||
int blake2s_final(unsigned char *md, BLAKE2S_CTX *c);
|
||||
|
||||
void blake2s_param_init(BLAKE2S_PARAM *P);
|
||||
void blake2s_param_set_digest_length(BLAKE2S_PARAM *P, uint8_t outlen);
|
||||
void blake2s_param_set_key_length(BLAKE2S_PARAM *P, uint8_t keylen);
|
||||
void blake2s_param_set_personal(BLAKE2S_PARAM *P, const uint8_t *personal, size_t length);
|
||||
void blake2s_param_set_salt(BLAKE2S_PARAM *P, const uint8_t *salt, size_t length);
|
||||
|
||||
#endif /* HEADER_BLAKE2_H */
|
||||
@@ -32,11 +32,13 @@ typedef struct ossl_method_construct_method_st {
|
||||
/* Remove a store */
|
||||
void (*dealloc_tmp_store)(void *store);
|
||||
/* Get an already existing method from a store */
|
||||
void *(*get)(OPENSSL_CTX *libctx, void *store, const char *name,
|
||||
const char *propquery, void *data);
|
||||
void *(*get)(OPENSSL_CTX *libctx, void *store,
|
||||
int operation_id, const char *name, const char *propquery,
|
||||
void *data);
|
||||
/* Store a method in a store */
|
||||
int (*put)(OPENSSL_CTX *libctx, void *store, void *method,
|
||||
const char *name, const char *propdef, void *data);
|
||||
int operation_id, const char *name, const char *propdef,
|
||||
void *data);
|
||||
/* Construct a new method */
|
||||
void *(*construct)(const char *name, const OSSL_DISPATCH *fns,
|
||||
OSSL_PROVIDER *prov, void *data);
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
# include <string.h>
|
||||
|
||||
# ifdef OPENSSL_USE_APPLINK
|
||||
# undef BIO_FLAGS_UPLINK
|
||||
# define BIO_FLAGS_UPLINK 0x8000
|
||||
# define BIO_FLAGS_UPLINK_INTERNAL 0x8000
|
||||
# include "ms/uplink.h"
|
||||
# else
|
||||
# define BIO_FLAGS_UPLINK_INTERNAL 0
|
||||
# endif
|
||||
|
||||
# include <openssl/crypto.h>
|
||||
@@ -146,13 +147,20 @@ typedef struct ossl_ex_data_global_st {
|
||||
# define OPENSSL_CTX_PROPERTY_DEFN_INDEX 2
|
||||
# define OPENSSL_CTX_PROPERTY_STRING_INDEX 3
|
||||
# define OPENSSL_CTX_NAMEMAP_INDEX 4
|
||||
# define OPENSSL_CTX_MAX_INDEXES 5
|
||||
# define OPENSSL_CTX_DRBG_INDEX 5
|
||||
# define OPENSSL_CTX_DRBG_NONCE_INDEX 6
|
||||
# define OPENSSL_CTX_RAND_CRNGT_INDEX 7
|
||||
# define OPENSSL_CTX_THREAD_EVENT_HANDLER_INDEX 8
|
||||
# define OPENSSL_CTX_FIPS_PROV_INDEX 9
|
||||
# define OPENSSL_CTX_MAX_INDEXES 10
|
||||
|
||||
typedef struct openssl_ctx_method {
|
||||
void *(*new_func)(OPENSSL_CTX *ctx);
|
||||
void (*free_func)(void *);
|
||||
} OPENSSL_CTX_METHOD;
|
||||
|
||||
OPENSSL_CTX *openssl_ctx_get_concrete(OPENSSL_CTX *ctx);
|
||||
|
||||
/* Functions to retrieve pointers to data by index */
|
||||
void *openssl_ctx_get_data(OPENSSL_CTX *, int /* index */,
|
||||
const OPENSSL_CTX_METHOD * ctx);
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* TODO(3.0) Move this header into provider when dependencies are removed */
|
||||
#ifndef HEADER_MD5_SHA1_H
|
||||
# define HEADER_MD5_SHA1_H
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifndef OPENSSL_NO_MD5
|
||||
# include <openssl/e_os2.h>
|
||||
# include <stddef.h>
|
||||
# include <openssl/md5.h>
|
||||
# include <openssl/sha.h>
|
||||
|
||||
# define MD5_SHA1_DIGEST_LENGTH (MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH)
|
||||
# define MD5_SHA1_CBLOCK MD5_CBLOCK
|
||||
|
||||
typedef struct md5_sha1_st {
|
||||
MD5_CTX md5;
|
||||
SHA_CTX sha1;
|
||||
} MD5_SHA1_CTX;
|
||||
|
||||
int md5_sha1_init(MD5_SHA1_CTX *mctx);
|
||||
int md5_sha1_update(MD5_SHA1_CTX *mctx, const void *data, size_t count);
|
||||
int md5_sha1_final(unsigned char *md, MD5_SHA1_CTX *mctx);
|
||||
int md5_sha1_ctrl(MD5_SHA1_CTX *mctx, int cmd, int mslen, void *ms);
|
||||
|
||||
# endif /* OPENSSL_NO_MD5 */
|
||||
|
||||
#endif /* HEADER_MD5_SHA1_H */
|
||||
@@ -16,6 +16,14 @@ OSSL_NAMEMAP *ossl_namemap_stored(OPENSSL_CTX *libctx);
|
||||
OSSL_NAMEMAP *ossl_namemap_new(void);
|
||||
void ossl_namemap_free(OSSL_NAMEMAP *namemap);
|
||||
|
||||
int ossl_namemap_add(OSSL_NAMEMAP *namemap, const char *name);
|
||||
const char *ossl_namemap_name(const OSSL_NAMEMAP *namemap, int number);
|
||||
int ossl_namemap_number(const OSSL_NAMEMAP *namemap, const char *name);
|
||||
int ossl_namemap_add(OSSL_NAMEMAP *namemap, int number, const char *name);
|
||||
|
||||
/*
|
||||
* The number<->name relationship is 1<->many
|
||||
* Therefore, the name->number mapping is a simple function, while the
|
||||
* number->name mapping is an iterator.
|
||||
*/
|
||||
int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name);
|
||||
void ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
|
||||
void (*fn)(const char *name, void *data),
|
||||
void *data);
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef HEADER_O_STR_H
|
||||
# define HEADER_O_STR_H
|
||||
|
||||
# include <stddef.h> /* to get size_t */
|
||||
|
||||
int OPENSSL_memcmp(const void *p1, const void *p2, size_t n);
|
||||
|
||||
#endif
|
||||
@@ -28,7 +28,7 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
|
||||
int ossl_method_store_set_global_properties(OSSL_METHOD_STORE *store,
|
||||
const char *prop_query);
|
||||
|
||||
/* proeprty query cache functions */
|
||||
/* property query cache functions */
|
||||
int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid,
|
||||
const char *prop_query, void **result);
|
||||
int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid,
|
||||
|
||||
@@ -29,7 +29,7 @@ extern "C" {
|
||||
OSSL_PROVIDER *ossl_provider_find(OPENSSL_CTX *libctx, const char *name);
|
||||
OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
|
||||
OSSL_provider_init_fn *init_function);
|
||||
int ossl_provider_upref(OSSL_PROVIDER *prov);
|
||||
int ossl_provider_up_ref(OSSL_PROVIDER *prov);
|
||||
void ossl_provider_free(OSSL_PROVIDER *prov);
|
||||
|
||||
/* Setters */
|
||||
@@ -55,16 +55,15 @@ int ossl_provider_forall_loaded(OPENSSL_CTX *,
|
||||
void *cbdata);
|
||||
|
||||
/* Getters for other library functions */
|
||||
const char *ossl_provider_name(OSSL_PROVIDER *prov);
|
||||
const DSO *ossl_provider_dso(OSSL_PROVIDER *prov);
|
||||
const char *ossl_provider_module_name(OSSL_PROVIDER *prov);
|
||||
const char *ossl_provider_module_path(OSSL_PROVIDER *prov);
|
||||
const char *ossl_provider_name(const OSSL_PROVIDER *prov);
|
||||
const DSO *ossl_provider_dso(const OSSL_PROVIDER *prov);
|
||||
const char *ossl_provider_module_name(const OSSL_PROVIDER *prov);
|
||||
const char *ossl_provider_module_path(const OSSL_PROVIDER *prov);
|
||||
|
||||
/* Thin wrappers around calls to the provider */
|
||||
void ossl_provider_teardown(const OSSL_PROVIDER *prov);
|
||||
const OSSL_ITEM *ossl_provider_get_param_types(const OSSL_PROVIDER *prov);
|
||||
int ossl_provider_get_params(const OSSL_PROVIDER *prov,
|
||||
const OSSL_PARAM params[]);
|
||||
int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]);
|
||||
const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
|
||||
int operation_id,
|
||||
int *no_cache);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* TODO(3.0) Move this header into provider when dependencies are removed */
|
||||
#ifndef HEADER_INTERNAL_SHA3_H
|
||||
# define HEADER_INTERNAL_SHA3_H
|
||||
|
||||
# include <openssl/e_os2.h>
|
||||
# include <stddef.h>
|
||||
|
||||
# define KECCAK1600_WIDTH 1600
|
||||
# define SHA3_MDSIZE(bitlen) (bitlen / 8)
|
||||
# define KMAC_MDSIZE(bitlen) 2 * (bitlen / 8)
|
||||
# define SHA3_BLOCKSIZE(bitlen) (KECCAK1600_WIDTH - bitlen * 2) / 8
|
||||
|
||||
typedef struct keccak_st KECCAK1600_CTX;
|
||||
|
||||
typedef size_t (sha3_absorb_fn)(void *vctx, const void *inp, size_t len);
|
||||
typedef int (sha3_final_fn)(unsigned char *md, void *vctx);
|
||||
|
||||
typedef struct prov_sha3_meth_st
|
||||
{
|
||||
sha3_absorb_fn *absorb;
|
||||
sha3_final_fn *final;
|
||||
} PROV_SHA3_METHOD;
|
||||
|
||||
struct keccak_st {
|
||||
uint64_t A[5][5];
|
||||
size_t block_size; /* cached ctx->digest->block_size */
|
||||
size_t md_size; /* output length, variable in XOF */
|
||||
size_t bufsz; /* used bytes in below buffer */
|
||||
unsigned char buf[KECCAK1600_WIDTH / 8 - 32];
|
||||
unsigned char pad;
|
||||
PROV_SHA3_METHOD meth;
|
||||
};
|
||||
|
||||
void sha3_reset(KECCAK1600_CTX *ctx);
|
||||
int sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen);
|
||||
int keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen);
|
||||
int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len);
|
||||
int sha3_final(unsigned char *md, KECCAK1600_CTX *ctx);
|
||||
|
||||
size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len,
|
||||
size_t r);
|
||||
|
||||
#endif /* HEADER_INTERNAL_SHA3_H */
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2017 Ribose Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* TODO(3.0) Move this header into provider when dependencies are removed */
|
||||
#ifndef HEADER_SM3_H
|
||||
# define HEADER_SM3_H
|
||||
|
||||
# include <openssl/opensslconf.h>
|
||||
|
||||
# ifdef OPENSSL_NO_SM3
|
||||
# error SM3 is disabled.
|
||||
# endif
|
||||
|
||||
# define SM3_DIGEST_LENGTH 32
|
||||
# define SM3_WORD unsigned int
|
||||
|
||||
# define SM3_CBLOCK 64
|
||||
# define SM3_LBLOCK (SM3_CBLOCK/4)
|
||||
|
||||
typedef struct SM3state_st {
|
||||
SM3_WORD A, B, C, D, E, F, G, H;
|
||||
SM3_WORD Nl, Nh;
|
||||
SM3_WORD data[SM3_LBLOCK];
|
||||
unsigned int num;
|
||||
} SM3_CTX;
|
||||
|
||||
int sm3_init(SM3_CTX *c);
|
||||
int sm3_update(SM3_CTX *c, const void *data, size_t len);
|
||||
int sm3_final(unsigned char *md, SM3_CTX *c);
|
||||
|
||||
#endif /* HEADER_SM3_H */
|
||||
@@ -9,6 +9,13 @@
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
/*
|
||||
* Initialisation of global data should never happen via "RUN_ONCE" inside the
|
||||
* FIPS module. Global data should instead always be associated with a specific
|
||||
* OPENSSL_CTX object. In this way data will get cleaned up correctly when the
|
||||
* module gets unloaded.
|
||||
*/
|
||||
#ifndef FIPS_MODE
|
||||
/*
|
||||
* DEFINE_RUN_ONCE: Define an initialiser function that should be run exactly
|
||||
* once. It takes no arguments and returns and int result (1 for success or
|
||||
@@ -23,7 +30,7 @@
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
#define DEFINE_RUN_ONCE(init) \
|
||||
# define DEFINE_RUN_ONCE(init) \
|
||||
static int init(void); \
|
||||
int init##_ossl_ret_ = 0; \
|
||||
void init##_ossl_(void) \
|
||||
@@ -36,7 +43,7 @@
|
||||
* DECLARE_RUN_ONCE: Declare an initialiser function that should be run exactly
|
||||
* once that has been defined in another file via DEFINE_RUN_ONCE().
|
||||
*/
|
||||
#define DECLARE_RUN_ONCE(init) \
|
||||
# define DECLARE_RUN_ONCE(init) \
|
||||
extern int init##_ossl_ret_; \
|
||||
void init##_ossl_(void);
|
||||
|
||||
@@ -55,7 +62,7 @@
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
#define DEFINE_RUN_ONCE_STATIC(init) \
|
||||
# define DEFINE_RUN_ONCE_STATIC(init) \
|
||||
static int init(void); \
|
||||
static int init##_ossl_ret_ = 0; \
|
||||
static void init##_ossl_(void) \
|
||||
@@ -72,9 +79,9 @@
|
||||
* function defined via DEFINE_ONCE_STATIC where both functions use the same
|
||||
* CRYPTO_ONCE object to synchronise. Where an alternative initialiser function
|
||||
* is used only one of the primary or the alternative initialiser function will
|
||||
* ever be called - and that function will be called exactly once. Definitition
|
||||
* ever be called - and that function will be called exactly once. Definition
|
||||
* of an alternative initialiser function MUST occur AFTER the definition of the
|
||||
* primiary initialiser function.
|
||||
* primary initialiser function.
|
||||
*
|
||||
* Typical usage might be:
|
||||
*
|
||||
@@ -96,7 +103,7 @@
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
#define DEFINE_RUN_ONCE_STATIC_ALT(initalt, init) \
|
||||
# define DEFINE_RUN_ONCE_STATIC_ALT(initalt, init) \
|
||||
static int initalt(void); \
|
||||
static void initalt##_ossl_(void) \
|
||||
{ \
|
||||
@@ -115,7 +122,7 @@
|
||||
*
|
||||
* (*) by convention, since the init function must return 1 on success.
|
||||
*/
|
||||
#define RUN_ONCE(once, init) \
|
||||
# define RUN_ONCE(once, init) \
|
||||
(CRYPTO_THREAD_run_once(once, init##_ossl_) ? init##_ossl_ret_ : 0)
|
||||
|
||||
/*
|
||||
@@ -133,5 +140,7 @@
|
||||
*
|
||||
* (*) by convention, since the init function must return 1 on success.
|
||||
*/
|
||||
#define RUN_ONCE_ALT(once, initalt, init) \
|
||||
# define RUN_ONCE_ALT(once, initalt, init) \
|
||||
(CRYPTO_THREAD_run_once(once, initalt##_ossl_) ? init##_ossl_ret_ : 0)
|
||||
|
||||
#endif /* FIPS_MODE */
|
||||
@@ -18,7 +18,7 @@
|
||||
* if (var == NOT_YET_INITIALIZED)
|
||||
* var = function_returning_same_value();
|
||||
*
|
||||
* This does work provided that loads and stores are single-instuction
|
||||
* This does work provided that loads and stores are single-instruction
|
||||
* operations (and integer ones are on *all* supported platforms), but
|
||||
* it upsets Thread Sanitizer. Suggested solution is
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user