mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
multibit, fatbit: make _size build-time only
This commit makes mmbit_size() and fatbit_size compile-time only, and adds a resource limit for very large multibits.
This commit is contained in:
parent
8b7b06d2a4
commit
e271781d95
@ -553,7 +553,6 @@ set (hs_exec_SRCS
|
||||
src/util/copybytes.h
|
||||
src/util/exhaust.h
|
||||
src/util/fatbit.h
|
||||
src/util/fatbit.c
|
||||
src/util/join.h
|
||||
src/util/masked_move.h
|
||||
src/util/multibit.h
|
||||
@ -924,6 +923,8 @@ SET (hs_SRCS
|
||||
src/util/determinise.h
|
||||
src/util/dump_mask.cpp
|
||||
src/util/dump_mask.h
|
||||
src/util/fatbit_build.cpp
|
||||
src/util/fatbit_build.h
|
||||
src/util/graph.h
|
||||
src/util/hash.h
|
||||
src/util/multibit_build.cpp
|
||||
|
@ -49,7 +49,6 @@
|
||||
#include "util/graph.h"
|
||||
#include "util/make_unique.h"
|
||||
#include "util/multibit_build.h"
|
||||
#include "util/multibit_internal.h"
|
||||
#include "util/report_manager.h"
|
||||
#include "util/ue2_containers.h"
|
||||
#include "util/verify_types.h"
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "shufticompile.h"
|
||||
#include "trufflecompile.h"
|
||||
#include "util/alloc.h"
|
||||
#include "util/multibit_internal.h"
|
||||
#include "util/multibit_build.h"
|
||||
#include "util/order_check.h"
|
||||
#include "util/report_manager.h"
|
||||
#include "util/verify_types.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Intel Corporation
|
||||
* Copyright (c) 2015-2016, Intel Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@ -34,7 +34,7 @@
|
||||
#include "util/charreach.h"
|
||||
#include "util/depth.h"
|
||||
#include "util/dump_charclass.h"
|
||||
#include "util/multibit_internal.h"
|
||||
#include "util/multibit_build.h"
|
||||
#include "util/verify_types.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -81,6 +81,7 @@
|
||||
#include "util/compile_context.h"
|
||||
#include "util/compile_error.h"
|
||||
#include "util/container.h"
|
||||
#include "util/fatbit_build.h"
|
||||
#include "util/graph_range.h"
|
||||
#include "util/make_unique.h"
|
||||
#include "util/multibit_build.h"
|
||||
@ -5435,11 +5436,13 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
|
||||
|
||||
engine->ekeyCount = rm.numEkeys();
|
||||
engine->dkeyCount = rm.numDkeys();
|
||||
engine->dkeyLogSize = fatbit_size(engine->dkeyCount);
|
||||
engine->invDkeyOffset = dkeyOffset;
|
||||
copy_bytes(ptr + dkeyOffset, rm.getDkeyToReportTable());
|
||||
|
||||
engine->somHorizon = ssm.somPrecision();
|
||||
engine->somLocationCount = ssm.numSomSlots();
|
||||
engine->somLocationFatbitSize = fatbit_size(engine->somLocationCount);
|
||||
|
||||
engine->needsCatchup = bc.needs_catchup ? 1 : 0;
|
||||
|
||||
@ -5454,8 +5457,10 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
|
||||
engine->activeArrayCount = activeArrayCount;
|
||||
engine->activeLeftCount = activeLeftCount;
|
||||
engine->queueCount = queue_count;
|
||||
engine->activeQueueArraySize = fatbit_size(queue_count);
|
||||
engine->eagerIterOffset = eagerIterOffset;
|
||||
engine->handledKeyCount = bc.handledKeys.size();
|
||||
engine->handledKeyFatbitSize = fatbit_size(engine->handledKeyCount);
|
||||
|
||||
engine->rolesWithStateCount = bc.numStates;
|
||||
|
||||
@ -5475,11 +5480,13 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
|
||||
|
||||
engine->lastByteHistoryIterOffset = lastByteOffset;
|
||||
|
||||
u32 delay_count = verify_u32(final_id_to_literal.size() - delay_base_id);
|
||||
engine->delay_count = delay_count;
|
||||
engine->delay_count =
|
||||
verify_u32(final_id_to_literal.size() - delay_base_id);
|
||||
engine->delay_fatbit_size = fatbit_size(engine->delay_count);
|
||||
engine->delay_base_id = delay_base_id;
|
||||
engine->anchored_base_id = anchored_base_id;
|
||||
engine->anchored_count = delay_base_id - anchored_base_id;
|
||||
engine->anchored_fatbit_size = fatbit_size(engine->anchored_count);
|
||||
|
||||
engine->rosePrefixCount = rosePrefixCount;
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "nfa/nfa_internal.h"
|
||||
#include "nfa/nfa_kind.h"
|
||||
#include "util/dump_charclass.h"
|
||||
#include "util/multibit_internal.h"
|
||||
#include "util/multibit_build.h"
|
||||
#include "util/multibit.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -1232,8 +1232,10 @@ void roseDumpStructRaw(const RoseEngine *t, FILE *f) {
|
||||
DUMP_U32(t, historyRequired);
|
||||
DUMP_U32(t, ekeyCount);
|
||||
DUMP_U32(t, dkeyCount);
|
||||
DUMP_U32(t, dkeyLogSize);
|
||||
DUMP_U32(t, invDkeyOffset);
|
||||
DUMP_U32(t, somLocationCount);
|
||||
DUMP_U32(t, somLocationFatbitSize);
|
||||
DUMP_U32(t, rolesWithStateCount);
|
||||
DUMP_U32(t, stateSize);
|
||||
DUMP_U32(t, anchorStateSize);
|
||||
@ -1258,8 +1260,10 @@ void roseDumpStructRaw(const RoseEngine *t, FILE *f) {
|
||||
DUMP_U32(t, activeArrayCount);
|
||||
DUMP_U32(t, activeLeftCount);
|
||||
DUMP_U32(t, queueCount);
|
||||
DUMP_U32(t, activeQueueArraySize);
|
||||
DUMP_U32(t, eagerIterOffset);
|
||||
DUMP_U32(t, handledKeyCount);
|
||||
DUMP_U32(t, handledKeyFatbitSize);
|
||||
DUMP_U32(t, leftOffset);
|
||||
DUMP_U32(t, roseCount);
|
||||
DUMP_U32(t, lookaroundTableOffset);
|
||||
@ -1280,8 +1284,10 @@ void roseDumpStructRaw(const RoseEngine *t, FILE *f) {
|
||||
DUMP_U64(t, floating_group_mask);
|
||||
DUMP_U32(t, size);
|
||||
DUMP_U32(t, delay_count);
|
||||
DUMP_U32(t, delay_fatbit_size);
|
||||
DUMP_U32(t, delay_base_id);
|
||||
DUMP_U32(t, anchored_count);
|
||||
DUMP_U32(t, anchored_fatbit_size);
|
||||
DUMP_U32(t, anchored_base_id);
|
||||
DUMP_U32(t, maxFloatingDelayedMatch);
|
||||
DUMP_U32(t, delayRebuildLength);
|
||||
|
@ -309,9 +309,11 @@ struct RoseEngine {
|
||||
u32 historyRequired; /**< max amount of history required for streaming */
|
||||
u32 ekeyCount; /**< number of exhaustion keys */
|
||||
u32 dkeyCount; /**< number of dedupe keys */
|
||||
u32 dkeyLogSize; /**< size of fatbit for storing dkey log (bytes) */
|
||||
u32 invDkeyOffset; /**< offset to table mapping from dkeys to the external
|
||||
* report ids */
|
||||
u32 somLocationCount; /**< number of som locations required */
|
||||
u32 somLocationFatbitSize; /**< size of SOM location fatbit (bytes) */
|
||||
u32 rolesWithStateCount; // number of roles with entries in state bitset
|
||||
u32 stateSize; /* size of the state bitset
|
||||
* WARNING: not the size of the rose state */
|
||||
@ -370,14 +372,18 @@ struct RoseEngine {
|
||||
u32 activeArrayCount; //number of nfas tracked in the active array
|
||||
u32 activeLeftCount; //number of nfas tracked in the active rose array
|
||||
u32 queueCount; /**< number of nfa queues */
|
||||
u32 activeQueueArraySize; //!< size of fatbit for active queues (bytes)
|
||||
|
||||
u32 eagerIterOffset; /**< offset to sparse iter for eager prefixes or 0 if
|
||||
* none */
|
||||
|
||||
/** \brief Number of keys used by CHECK_SET_HANDLED instructions in role
|
||||
* programs. Used to size the handled_roles fatbit in scratch. */
|
||||
* programs. */
|
||||
u32 handledKeyCount;
|
||||
|
||||
/** \brief Size of the handled keys fatbit in scratch (bytes). */
|
||||
u32 handledKeyFatbitSize;
|
||||
|
||||
u32 leftOffset;
|
||||
u32 roseCount;
|
||||
u32 lookaroundTableOffset; //!< base of lookaround offset list (of s8 values)
|
||||
@ -412,9 +418,11 @@ struct RoseEngine {
|
||||
rose_group floating_group_mask; /* groups that are used by the ftable */
|
||||
u32 size; // (bytes)
|
||||
u32 delay_count; /* number of delayed literal ids. */
|
||||
u32 delay_fatbit_size; //!< size of each delay fatbit in scratch (bytes)
|
||||
u32 delay_base_id; /* literal id of the first delayed literal.
|
||||
* delayed literal ids are contiguous */
|
||||
u32 anchored_count; /* number of anchored literal ids */
|
||||
u32 anchored_fatbit_size; //!< size of each anch fatbit in scratch (bytes)
|
||||
u32 anchored_base_id; /* literal id of the first literal in the A table.
|
||||
* anchored literal ids are contiguous */
|
||||
u32 maxFloatingDelayedMatch; /* max offset that a delayed literal can
|
||||
|
@ -55,7 +55,6 @@
|
||||
#include "state.h"
|
||||
#include "ue2common.h"
|
||||
#include "util/exhaust.h"
|
||||
#include "util/fatbit.h"
|
||||
#include "util/multibit.h"
|
||||
|
||||
static really_inline
|
||||
|
@ -43,17 +43,19 @@
|
||||
#include "nfa/nfa_api_queue.h"
|
||||
#include "rose/rose_internal.h"
|
||||
#include "util/fatbit.h"
|
||||
#include "util/multibit.h"
|
||||
|
||||
/**
|
||||
* Determine the space required for a correctly aligned array of fatbit
|
||||
* structure, laid out as:
|
||||
*
|
||||
* - an array of num_entries pointers, each to a fatbit.
|
||||
* - an array of fatbit structures, each of size fatbit_size(num_keys).
|
||||
* - an array of fatbit structures, each of size fatbit_len.
|
||||
*
|
||||
* fatbit_len should have been determined at compile time, via the
|
||||
* fatbit_size() call.
|
||||
*/
|
||||
static
|
||||
size_t fatbit_array_size(u32 num_entries, u32 num_keys) {
|
||||
size_t fatbit_array_size(u32 num_entries, u32 fatbit_len) {
|
||||
size_t len = 0;
|
||||
|
||||
// Array of pointers to each fatbit entry.
|
||||
@ -61,7 +63,7 @@ size_t fatbit_array_size(u32 num_entries, u32 num_keys) {
|
||||
|
||||
// Fatbit entries themselves.
|
||||
len = ROUNDUP_N(len, alignof(struct fatbit));
|
||||
len += (size_t)fatbit_size(num_keys) * num_entries;
|
||||
len += (size_t)fatbit_len * num_entries;
|
||||
|
||||
return ROUNDUP_N(len, 8); // Round up for potential padding.
|
||||
}
|
||||
@ -71,17 +73,19 @@ size_t fatbit_array_size(u32 num_entries, u32 num_keys) {
|
||||
static
|
||||
hs_error_t alloc_scratch(const hs_scratch_t *proto, hs_scratch_t **scratch) {
|
||||
u32 queueCount = proto->queueCount;
|
||||
u32 deduperCount = proto->deduper.log_size;
|
||||
u32 activeQueueArraySize = proto->activeQueueArraySize;
|
||||
u32 deduperCount = proto->deduper.dkey_count;
|
||||
u32 deduperLogSize = proto->deduper.log_size;
|
||||
u32 bStateSize = proto->bStateSize;
|
||||
u32 tStateSize = proto->tStateSize;
|
||||
u32 fullStateSize = proto->fullStateSize;
|
||||
u32 anchored_literal_region_len = proto->anchored_literal_region_len;
|
||||
u32 anchored_literal_region_width = proto->anchored_literal_count;
|
||||
u32 anchored_literal_fatbit_size = proto->anchored_literal_fatbit_size;
|
||||
|
||||
u32 som_store_size = proto->som_store_count * sizeof(u64a);
|
||||
u32 som_attempted_store_size = proto->som_store_count * sizeof(u64a);
|
||||
u32 som_now_size = fatbit_size(proto->som_store_count);
|
||||
u32 som_attempted_size = fatbit_size(proto->som_store_count);
|
||||
u32 som_now_size = proto->som_fatbit_size;
|
||||
u32 som_attempted_size = proto->som_fatbit_size;
|
||||
|
||||
struct hs_scratch *s;
|
||||
struct hs_scratch *s_tmp;
|
||||
@ -91,18 +95,18 @@ hs_error_t alloc_scratch(const hs_scratch_t *proto, hs_scratch_t **scratch) {
|
||||
assert(anchored_literal_region_len < 8 * sizeof(s->al_log_sum));
|
||||
|
||||
size_t anchored_literal_region_size = fatbit_array_size(
|
||||
anchored_literal_region_len, anchored_literal_region_width);
|
||||
anchored_literal_region_len, proto->anchored_literal_fatbit_size);
|
||||
size_t delay_region_size =
|
||||
fatbit_array_size(DELAY_SLOT_COUNT, proto->delay_count);
|
||||
fatbit_array_size(DELAY_SLOT_COUNT, proto->delay_fatbit_size);
|
||||
|
||||
// the size is all the allocated stuff, not including the struct itself
|
||||
size_t size = queue_size + 63
|
||||
+ bStateSize + tStateSize
|
||||
+ fullStateSize + 63 /* cacheline padding */
|
||||
+ fatbit_size(proto->handledKeyCount) /* handled roles */
|
||||
+ fatbit_size(queueCount) /* active queue array */
|
||||
+ 2 * fatbit_size(deduperCount) /* need odd and even logs */
|
||||
+ 2 * fatbit_size(deduperCount) /* ditto som logs */
|
||||
+ proto->handledKeyFatbitSize /* handled roles */
|
||||
+ activeQueueArraySize /* active queue array */
|
||||
+ 2 * deduperLogSize /* need odd and even logs */
|
||||
+ 2 * deduperLogSize /* ditto som logs */
|
||||
+ 2 * sizeof(u64a) * deduperCount /* start offsets for som */
|
||||
+ anchored_literal_region_size + qmpq_size
|
||||
+ delay_region_size
|
||||
@ -157,7 +161,7 @@ hs_error_t alloc_scratch(const hs_scratch_t *proto, hs_scratch_t **scratch) {
|
||||
for (u32 i = 0; i < DELAY_SLOT_COUNT; i++) {
|
||||
s->delay_slots[i] = (struct fatbit *)current;
|
||||
assert(ISALIGNED(s->delay_slots[i]));
|
||||
current += fatbit_size(proto->delay_count);
|
||||
current += proto->delay_fatbit_size;
|
||||
}
|
||||
|
||||
current = ROUNDUP_PTR(current, alignof(struct fatbit *));
|
||||
@ -167,7 +171,7 @@ hs_error_t alloc_scratch(const hs_scratch_t *proto, hs_scratch_t **scratch) {
|
||||
for (u32 i = 0; i < anchored_literal_region_len; i++) {
|
||||
s->al_log[i] = (struct fatbit *)current;
|
||||
assert(ISALIGNED(s->al_log[i]));
|
||||
current += fatbit_size(anchored_literal_region_width);
|
||||
current += anchored_literal_fatbit_size;
|
||||
}
|
||||
|
||||
current = ROUNDUP_PTR(current, 8);
|
||||
@ -193,22 +197,22 @@ hs_error_t alloc_scratch(const hs_scratch_t *proto, hs_scratch_t **scratch) {
|
||||
|
||||
assert(ISALIGNED_N(current, 8));
|
||||
s->aqa = (struct fatbit *)current;
|
||||
current += fatbit_size(queueCount);
|
||||
current += activeQueueArraySize;
|
||||
|
||||
s->handled_roles = (struct fatbit *)current;
|
||||
current += fatbit_size(proto->handledKeyCount);
|
||||
current += proto->handledKeyFatbitSize;
|
||||
|
||||
s->deduper.log[0] = (struct fatbit *)current;
|
||||
current += fatbit_size(deduperCount);
|
||||
current += deduperLogSize;
|
||||
|
||||
s->deduper.log[1] = (struct fatbit *)current;
|
||||
current += fatbit_size(deduperCount);
|
||||
current += deduperLogSize;
|
||||
|
||||
s->deduper.som_log[0] = (struct fatbit *)current;
|
||||
current += fatbit_size(deduperCount);
|
||||
current += deduperLogSize;
|
||||
|
||||
s->deduper.som_log[1] = (struct fatbit *)current;
|
||||
current += fatbit_size(deduperCount);
|
||||
current += deduperLogSize;
|
||||
|
||||
s->som_set_now = (struct fatbit *)current;
|
||||
current += som_now_size;
|
||||
@ -293,19 +297,19 @@ hs_error_t hs_alloc_scratch(const hs_database_t *db, hs_scratch_t **scratch) {
|
||||
proto->anchored_literal_region_len = rose->anchoredDistance;
|
||||
}
|
||||
|
||||
if (rose->anchored_count > proto->anchored_literal_count) {
|
||||
if (rose->anchored_fatbit_size > proto->anchored_literal_fatbit_size) {
|
||||
resize = 1;
|
||||
proto->anchored_literal_count = rose->anchored_count;
|
||||
proto->anchored_literal_fatbit_size = rose->anchored_fatbit_size;
|
||||
}
|
||||
|
||||
if (rose->delay_count > proto->delay_count) {
|
||||
if (rose->delay_fatbit_size > proto->delay_fatbit_size) {
|
||||
resize = 1;
|
||||
proto->delay_count = rose->delay_count;
|
||||
proto->delay_fatbit_size = rose->delay_fatbit_size;
|
||||
}
|
||||
|
||||
if (rose->handledKeyCount > proto->handledKeyCount) {
|
||||
if (rose->handledKeyFatbitSize > proto->handledKeyFatbitSize) {
|
||||
resize = 1;
|
||||
proto->handledKeyCount = rose->handledKeyCount;
|
||||
proto->handledKeyFatbitSize = rose->handledKeyFatbitSize;
|
||||
}
|
||||
|
||||
if (rose->tStateSize > proto->tStateSize) {
|
||||
@ -319,12 +323,22 @@ hs_error_t hs_alloc_scratch(const hs_database_t *db, hs_scratch_t **scratch) {
|
||||
proto->som_store_count = som_store_count;
|
||||
}
|
||||
|
||||
if (rose->somLocationFatbitSize > proto->som_fatbit_size) {
|
||||
resize = 1;
|
||||
proto->som_fatbit_size = rose->somLocationFatbitSize;
|
||||
}
|
||||
|
||||
u32 queueCount = rose->queueCount;
|
||||
if (queueCount > proto->queueCount) {
|
||||
resize = 1;
|
||||
proto->queueCount = queueCount;
|
||||
}
|
||||
|
||||
if (rose->activeQueueArraySize > proto->activeQueueArraySize) {
|
||||
resize = 1;
|
||||
proto->activeQueueArraySize = rose->activeQueueArraySize;
|
||||
}
|
||||
|
||||
u32 bStateSize = 0;
|
||||
if (rose->mode == HS_MODE_BLOCK) {
|
||||
bStateSize = rose->stateOffsets.end;
|
||||
@ -344,9 +358,10 @@ hs_error_t hs_alloc_scratch(const hs_database_t *db, hs_scratch_t **scratch) {
|
||||
proto->fullStateSize = fullStateSize;
|
||||
}
|
||||
|
||||
if (rose->dkeyCount > proto->deduper.log_size) {
|
||||
if (rose->dkeyCount > proto->deduper.dkey_count) {
|
||||
resize = 1;
|
||||
proto->deduper.log_size = rose->dkeyCount;
|
||||
proto->deduper.dkey_count = rose->dkeyCount;
|
||||
proto->deduper.log_size = rose->dkeyLogSize;
|
||||
}
|
||||
|
||||
if (resize) {
|
||||
|
@ -148,6 +148,7 @@ struct match_deduper {
|
||||
struct fatbit *log[2]; /**< even, odd logs */
|
||||
struct fatbit *som_log[2]; /**< even, odd fatbit logs for som */
|
||||
u64a *som_start_log[2]; /**< even, odd start offset logs for som */
|
||||
u32 dkey_count;
|
||||
u32 log_size;
|
||||
u64a current_report_offset;
|
||||
u8 som_log_dirty;
|
||||
@ -162,6 +163,7 @@ struct ALIGN_CL_DIRECTIVE hs_scratch {
|
||||
u32 magic;
|
||||
u8 in_use; /**< non-zero when being used by an API call. */
|
||||
u32 queueCount;
|
||||
u32 activeQueueArraySize; /**< size of active queue array fatbit in bytes */
|
||||
u32 bStateSize; /**< sizeof block mode states */
|
||||
u32 tStateSize; /**< sizeof transient rose states */
|
||||
u32 fullStateSize; /**< size of uncompressed nfa state */
|
||||
@ -179,7 +181,7 @@ struct ALIGN_CL_DIRECTIVE hs_scratch {
|
||||
struct core_info core_info;
|
||||
struct match_deduper deduper;
|
||||
u32 anchored_literal_region_len;
|
||||
u32 anchored_literal_count;
|
||||
u32 anchored_literal_fatbit_size; /**< size of each anch fatbit in bytes */
|
||||
struct fatbit *handled_roles; /**< fatbit of ROLES (not states) already
|
||||
* handled by this literal */
|
||||
u64a *som_store; /**< array of som locations */
|
||||
@ -191,8 +193,9 @@ struct ALIGN_CL_DIRECTIVE hs_scratch {
|
||||
* location had been writable */
|
||||
u64a som_set_now_offset; /**< offset at which som_set_now represents */
|
||||
u32 som_store_count;
|
||||
u32 handledKeyCount;
|
||||
u32 delay_count;
|
||||
u32 som_fatbit_size; /**< size of som location fatbit structures in bytes */
|
||||
u32 handledKeyFatbitSize; /**< size of handled_keys fatbit in bytes */
|
||||
u32 delay_fatbit_size; /**< size of each delay fatbit in bytes */
|
||||
u32 scratchSize;
|
||||
char *scratch_alloc; /* user allocated scratch object */
|
||||
u8 ALIGN_DIRECTIVE fdr_temp_buf[FDR_TEMP_BUF_SIZE];
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Intel Corporation
|
||||
* Copyright (c) 2015-2016, Intel Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@ -32,7 +32,7 @@
|
||||
#include "scratch_dump.h"
|
||||
#include "hs_internal.h"
|
||||
#include "ue2common.h"
|
||||
#include "util/multibit_internal.h"
|
||||
#include "util/multibit_build.h"
|
||||
#include "nfa/nfa_api_queue.h"
|
||||
#include "rose/rose_internal.h"
|
||||
|
||||
@ -54,12 +54,11 @@ void dumpScratch(const struct hs_scratch *s, FILE *f) {
|
||||
fprintf(f, " queues : %zu bytes\n",
|
||||
s->queueCount * sizeof(struct mq));
|
||||
fprintf(f, " bStateSize : %u bytes\n", s->bStateSize);
|
||||
fprintf(f, " active queue array : %u bytes\n",
|
||||
mmbit_size(s->queueCount));
|
||||
fprintf(f, " active queue array : %u bytes\n", s->activeQueueArraySize);
|
||||
fprintf(f, " qmpq : %zu bytes\n",
|
||||
s->queueCount * sizeof(struct queue_match));
|
||||
fprintf(f, " delay info : %u bytes\n",
|
||||
mmbit_size(s->delay_count) * DELAY_SLOT_COUNT);
|
||||
s->delay_fatbit_size * DELAY_SLOT_COUNT);
|
||||
}
|
||||
|
||||
} // namespace ue2
|
||||
|
@ -40,6 +40,10 @@
|
||||
#include "multibit.h"
|
||||
#include "ue2common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MIN_FAT_SIZE 32
|
||||
|
||||
struct fatbit {
|
||||
@ -82,11 +86,8 @@ u32 fatbit_iterate(const struct fatbit *bits, u32 total_bits, u32 it_in) {
|
||||
return mmbit_iterate(bits->fb_int.raw, total_bits, it_in);
|
||||
}
|
||||
|
||||
/** \brief Return the size in bytes of a fatbit that can store the given
|
||||
* number of bits.
|
||||
*
|
||||
* Not for use in performance-critical code, implementation is in fatbit.c.
|
||||
*/
|
||||
u32 fatbit_size(u32 total_bits);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Intel Corporation
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@ -26,9 +26,19 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fatbit_build.h"
|
||||
|
||||
#include "fatbit.h"
|
||||
#include "multibit.h"
|
||||
#include "multibit_build.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace ue2 {
|
||||
|
||||
u32 fatbit_size(u32 total_bits) {
|
||||
return MAX(sizeof(struct fatbit), mmbit_size(total_bits));
|
||||
return max(u32{sizeof(struct fatbit)}, mmbit_size(total_bits));
|
||||
}
|
||||
|
||||
} // namespace ue2
|
48
src/util/fatbit_build.h
Normal file
48
src/util/fatbit_build.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Fatbit: build code
|
||||
*/
|
||||
|
||||
#ifndef FATBIT_BUILD_H
|
||||
#define FATBIT_BUILD_H
|
||||
|
||||
#include "ue2common.h"
|
||||
|
||||
namespace ue2 {
|
||||
|
||||
/**
|
||||
* \brief Return the size in bytes of a fatbit that can store the given
|
||||
* number of bits.
|
||||
*/
|
||||
u32 fatbit_size(u32 total_bits);
|
||||
|
||||
} // namespace ue2
|
||||
|
||||
#endif // FATBIT_BUILD_H
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Intel Corporation
|
||||
* Copyright (c) 2015-2016, Intel Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@ -138,62 +138,3 @@ const u32 mmbit_root_offset_from_level[7] = {
|
||||
1 + (1 << MMB_KEY_SHIFT) + (1 << MMB_KEY_SHIFT * 2) + (1 << MMB_KEY_SHIFT * 3) + (1 << MMB_KEY_SHIFT * 4),
|
||||
1 + (1 << MMB_KEY_SHIFT) + (1 << MMB_KEY_SHIFT * 2) + (1 << MMB_KEY_SHIFT * 3) + (1 << MMB_KEY_SHIFT * 4) + (1 << MMB_KEY_SHIFT * 5),
|
||||
};
|
||||
|
||||
u32 mmbit_size(u32 total_bits) {
|
||||
MDEBUG_PRINTF("%u\n", total_bits);
|
||||
|
||||
// Flat model multibit structures are just stored as a bit vector.
|
||||
if (total_bits <= MMB_FLAT_MAX_BITS) {
|
||||
return ROUNDUP_N(total_bits, 8) / 8;
|
||||
}
|
||||
|
||||
u64a current_level = 1; // Number of blocks on current level.
|
||||
u64a total = 0; // Total number of blocks.
|
||||
while (current_level * MMB_KEY_BITS < total_bits) {
|
||||
total += current_level;
|
||||
current_level <<= MMB_KEY_SHIFT;
|
||||
}
|
||||
|
||||
// Last level is a one-for-one bit vector. It needs room for total_bits
|
||||
// elements, rounded up to the nearest block.
|
||||
u64a last_level = ((u64a)total_bits + MMB_KEY_BITS - 1) / MMB_KEY_BITS;
|
||||
total += last_level;
|
||||
|
||||
assert(total * sizeof(MMB_TYPE) <= UINT32_MAX);
|
||||
return (u32)(total * sizeof(MMB_TYPE));
|
||||
}
|
||||
|
||||
#ifdef DUMP_SUPPORT
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** \brief Dump a sparse iterator's keys to stdout. */
|
||||
void mmbit_sparse_iter_dump(const struct mmbit_sparse_iter *it,
|
||||
u32 total_bits) {
|
||||
// Expediency and future-proofing: create a temporary multibit of the right
|
||||
// size with all the bits on, then walk it with this sparse iterator.
|
||||
size_t bytes = mmbit_size(total_bits);
|
||||
u8 *bits = malloc(bytes);
|
||||
if (!bits) {
|
||||
printf("Failed to alloc %zu bytes for temp multibit", bytes);
|
||||
return;
|
||||
}
|
||||
for (u32 i = 0; i < total_bits; i++) {
|
||||
mmbit_set_i(bits, total_bits, i);
|
||||
}
|
||||
|
||||
struct mmbit_sparse_state s[MAX_SPARSE_ITER_STATES];
|
||||
u32 idx = 0;
|
||||
for (u32 i = mmbit_sparse_iter_begin(bits, total_bits, &idx, it, s);
|
||||
i != MMB_INVALID;
|
||||
i = mmbit_sparse_iter_next(bits, total_bits, i, &idx, it, s)) {
|
||||
printf("%u ", i);
|
||||
}
|
||||
|
||||
printf("(%u keys)", idx + 1);
|
||||
|
||||
free(bits);
|
||||
}
|
||||
|
||||
#endif // DUMP_SUPPORT
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Intel Corporation
|
||||
* Copyright (c) 2015-2016, Intel Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@ -34,6 +34,7 @@
|
||||
#include "scatter.h"
|
||||
#include "ue2common.h"
|
||||
#include "rose/rose_build_scatter.h"
|
||||
#include "util/compile_error.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring> // for memset
|
||||
@ -45,6 +46,32 @@ using namespace std;
|
||||
|
||||
namespace ue2 {
|
||||
|
||||
u32 mmbit_size(u32 total_bits) {
|
||||
if (total_bits > MMB_MAX_BITS) {
|
||||
throw ResourceLimitError();
|
||||
}
|
||||
|
||||
// Flat model multibit structures are just stored as a bit vector.
|
||||
if (total_bits <= MMB_FLAT_MAX_BITS) {
|
||||
return ROUNDUP_N(total_bits, 8) / 8;
|
||||
}
|
||||
|
||||
u64a current_level = 1; // Number of blocks on current level.
|
||||
u64a total = 0; // Total number of blocks.
|
||||
while (current_level * MMB_KEY_BITS < total_bits) {
|
||||
total += current_level;
|
||||
current_level <<= MMB_KEY_SHIFT;
|
||||
}
|
||||
|
||||
// Last level is a one-for-one bit vector. It needs room for total_bits
|
||||
// elements, rounded up to the nearest block.
|
||||
u64a last_level = ((u64a)total_bits + MMB_KEY_BITS - 1) / MMB_KEY_BITS;
|
||||
total += last_level;
|
||||
|
||||
assert(total * sizeof(MMB_TYPE) <= UINT32_MAX);
|
||||
return (u32)(total * sizeof(MMB_TYPE));
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct TreeNode {
|
||||
MMB_TYPE mask = 0;
|
||||
@ -133,6 +160,7 @@ void mmbBuildSparseIterator(vector<mmbit_sparse_iter> &out,
|
||||
assert(out.empty());
|
||||
assert(!bits.empty());
|
||||
assert(total_bits > 0);
|
||||
assert(total_bits <= MMB_MAX_BITS);
|
||||
|
||||
DEBUG_PRINTF("building sparse iter for %zu of %u bits\n",
|
||||
bits.size(), total_bits);
|
||||
|
@ -50,6 +50,15 @@ size_t hash_value(const mmbit_sparse_iter &iter) {
|
||||
|
||||
namespace ue2 {
|
||||
|
||||
/**
|
||||
* \brief Return the size in bytes of a multibit that can store the given
|
||||
* number of bits.
|
||||
*
|
||||
* This will throw a resource limit assertion if the requested mmbit is too
|
||||
* large.
|
||||
*/
|
||||
u32 mmbit_size(u32 total_bits);
|
||||
|
||||
/** \brief Construct a sparse iterator over the values in \a bits for a
|
||||
* multibit of size \a total_bits. */
|
||||
void mmbBuildSparseIterator(std::vector<mmbit_sparse_iter> &out,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Intel Corporation
|
||||
* Copyright (c) 2015-2016, Intel Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@ -47,6 +47,9 @@ extern "C" {
|
||||
typedef u64a MMB_TYPE; /**< Basic block type for mmbit operations. */
|
||||
#define MMB_MAX_LEVEL 6 /**< Maximum level in the mmbit pyramid. */
|
||||
|
||||
/** \brief Maximum number of keys (bits) in a multibit. */
|
||||
#define MMB_MAX_BITS (1U << 31)
|
||||
|
||||
/** \brief Sparse iterator record type.
|
||||
*
|
||||
* A sparse iterator is a tree of these records, where val identifies the
|
||||
@ -71,13 +74,6 @@ struct mmbit_sparse_state {
|
||||
/** \brief Maximum number of \ref mmbit_sparse_state that could be needed. */
|
||||
#define MAX_SPARSE_ITER_STATES (6 + 1)
|
||||
|
||||
/** \brief Return the size in bytes of a multibit that can store the given
|
||||
* number of bits.
|
||||
*
|
||||
* Not for use in performance-critical code, implementation is in multibit.c.
|
||||
*/
|
||||
u32 mmbit_size(u32 total_bits);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@ -30,10 +30,10 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ue2common.h"
|
||||
#include "util/compile_error.h"
|
||||
#include "util/make_unique.h"
|
||||
#include "util/multibit.h"
|
||||
#include "util/multibit_build.h"
|
||||
#include "util/target_info.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
@ -1303,9 +1303,11 @@ static const MultiBitTestParam multibitTests[] = {
|
||||
{ 1U << 29, 24413 },
|
||||
{ 1U << 30, 50377 },
|
||||
{ 1U << 31, 104729 },
|
||||
|
||||
// { UINT32_MAX, 104729 }, // Very slow
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(MultiBit, MultiBitTest, ValuesIn(multibitTests));
|
||||
|
||||
TEST(MultiBit, SizeTooBig) {
|
||||
ASSERT_NO_THROW(mmbit_size(MMB_MAX_BITS));
|
||||
ASSERT_THROW(mmbit_size(MMB_MAX_BITS + 1), ResourceLimitError);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user