* Copyright (c) 2022 Huawei Technologies Co.,Ltd.
*
* GR is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* gr_hash_optimized.h
*
* Optimized hash calculation module providing high-performance SHA256 computation
*
* IDENTIFICATION
* src/common/gr_hash_optimized.h
*
* -------------------------------------------------------------------------
*/
#ifndef __GR_HASH_OPTIMIZED_H__
#define __GR_HASH_OPTIMIZED_H__
#include "cm_base.h"
#include "gr_defs.h"
#include "gr_log.h"
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <pthread.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define GR_HASH_CTX_POOL_SIZE 8
#define GR_HASH_BATCH_SIZE 16
#define GR_HASH_ALIGN_SIZE 64
typedef struct st_gr_hash_ctx {
EVP_MD_CTX *mdctx;
bool32 in_use;
uint64_t last_used_time;
uint32_t ref_count;
} gr_hash_ctx_t;
typedef struct st_gr_hash_batch {
const void *data[GR_HASH_BATCH_SIZE];
size_t sizes[GR_HASH_BATCH_SIZE];
uint8_t hashes[GR_HASH_BATCH_SIZE][SHA256_DIGEST_LENGTH];
uint32_t count;
} gr_hash_batch_t;
typedef struct st_gr_hash_mgr {
gr_hash_ctx_t ctx_pool[GR_HASH_CTX_POOL_SIZE];
pthread_mutex_t pool_mutex;
uint32_t pool_usage;
uint64_t total_operations;
uint64_t total_bytes;
} gr_hash_mgr_t;
typedef struct st_gr_hash_stats {
uint64_t total_calls;
uint64_t total_bytes;
uint64_t total_time_us;
uint64_t batch_calls;
uint64_t batch_bytes;
uint64_t batch_time_us;
uint64_t ctx_reuses;
uint64_t ctx_creates;
} gr_hash_stats_t;
status_t gr_hash_optimized_init(void);
void gr_hash_optimized_cleanup(void);
status_t gr_calculate_hash_optimized(const void *data, size_t size, uint8_t *hash);
status_t gr_calculate_hash_batch(const void **data_array, const size_t *size_array,
uint32_t count, uint8_t (*hashes)[SHA256_DIGEST_LENGTH]);
status_t gr_hash_stream_init(EVP_MD_CTX **stream_ctx);
status_t gr_hash_stream_update(EVP_MD_CTX *stream_ctx, const void *data, size_t size);
status_t gr_hash_stream_final(EVP_MD_CTX *stream_ctx, uint8_t *hash);
void gr_hash_stream_cleanup(EVP_MD_CTX *stream_ctx);
void gr_hash_get_stats(gr_hash_stats_t *stats);
void gr_hash_reset_stats(void);
status_t gr_calculate_hash_aligned(const void *data, size_t size, uint8_t *hash);
status_t gr_calculate_hash_parallel(const void *data, size_t size, uint8_t *hash, uint32_t thread_count);
bool32 gr_hash_hw_acceleration_available(void);
gr_hash_ctx_t* gr_hash_ctx_acquire(void);
void gr_hash_ctx_release(gr_hash_ctx_t *ctx);
static inline status_t gr_hash_ctx_init(gr_hash_ctx_t *ctx)
{
if (ctx->mdctx == NULL) {
ctx->mdctx = EVP_MD_CTX_new();
if (ctx->mdctx == NULL) {
LOG_RUN_ERR("[hash]: Failed to create EVP_MD_CTX.");
return CM_ERROR;
}
}
if (EVP_DigestInit_ex(ctx->mdctx, EVP_sha256(), NULL) != 1) {
LOG_RUN_ERR("[hash]: Failed to init sha256.");
return CM_ERROR;
}
ctx->in_use = CM_TRUE;
ctx->last_used_time = 0;
ctx->ref_count = 1;
return CM_SUCCESS;
}
static inline status_t gr_hash_ctx_update(gr_hash_ctx_t *ctx, const void *data, size_t size)
{
if (EVP_DigestUpdate(ctx->mdctx, data, size) != 1) {
LOG_RUN_ERR("[hash]: Failed to update sha256.");
return CM_ERROR;
}
return CM_SUCCESS;
}
static inline status_t gr_hash_ctx_final(gr_hash_ctx_t *ctx, uint8_t *hash)
{
unsigned int digest_len = SHA256_DIGEST_LENGTH;
if (EVP_DigestFinal_ex(ctx->mdctx, hash, &digest_len) != 1) {
LOG_RUN_ERR("[hash]: Failed to calculate sha256.");
return CM_ERROR;
}
return CM_SUCCESS;
}
static inline bool32 gr_is_aligned(const void *ptr, size_t alignment)
{
return ((uintptr_t)ptr & (alignment - 1)) == 0;
}
static inline status_t gr_calculate_hash_fast(const void *data, size_t size, uint8_t *hash)
{
if (size <= 1024) {
return gr_calculate_hash_optimized(data, size, hash);
}
return gr_calculate_hash_optimized(data, size, hash);
}
typedef struct {
uint64_t total_calls;
uint64_t total_bytes;
uint64_t total_time_us;
uint64_t batch_calls;
uint64_t batch_bytes;
uint64_t batch_time_us;
} gr_hash_stats_simple_t;
status_t gr_calculate_hash_optimized_simple(const void *data, size_t size, uint8_t *hash);
status_t gr_calculate_hash_batch_simple(const void **data_array, const size_t *size_array,
uint32_t count, uint8_t (*hashes)[SHA256_DIGEST_LENGTH]);
status_t gr_calculate_hash_aligned_simple(const void *data, size_t size, uint8_t *hash);
bool32 gr_hash_hw_acceleration_available_simple(void);
void gr_hash_get_stats_simple(gr_hash_stats_simple_t *stats);
void gr_hash_reset_stats_simple(void);
#ifdef __cplusplus
}
#endif
#endif