mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-09-29 19:24:25 +03:00
runtime: add error for "scratch in use"
This commit adds the HS_SCRATCH_IN_USE error, which is returned when Hyperscan detects that a scratch region is already in use on entry to an API function.
This commit is contained in:
committed by
Matthew Barr
parent
11896dcf42
commit
c12b953131
@@ -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:
|
||||
@@ -500,6 +500,25 @@ const char *hs_version(void);
|
||||
*/
|
||||
#define HS_BAD_ALLOC (-9)
|
||||
|
||||
/**
|
||||
* The scratch region was already in use.
|
||||
*
|
||||
* This error is returned when Hyperscan is able to detect that the scratch
|
||||
* region given is already in use by another Hyperscan API call.
|
||||
*
|
||||
* A separate scratch region, allocated with @ref hs_alloc_scratch() or @ref
|
||||
* hs_clone_scratch(), is required for every concurrent caller of the Hyperscan
|
||||
* API.
|
||||
*
|
||||
* For example, this error might be returned when @ref hs_scan() has been
|
||||
* called inside a callback delivered by a currently-executing @ref hs_scan()
|
||||
* call using the same scratch region.
|
||||
*
|
||||
* Note: Not all concurrent uses of scratch regions may be detected. This error
|
||||
* is intended as a best-effort debugging tool, not a guarantee.
|
||||
*/
|
||||
#define HS_SCRATCH_IN_USE (-10)
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -319,8 +319,13 @@ hs_error_t hs_scan(const hs_database_t *db, const char *data, unsigned length,
|
||||
return HS_INVALID;
|
||||
}
|
||||
|
||||
if (unlikely(markScratchInUse(scratch))) {
|
||||
return HS_SCRATCH_IN_USE;
|
||||
}
|
||||
|
||||
if (rose->minWidth > length) {
|
||||
DEBUG_PRINTF("minwidth=%u > length=%u\n", rose->minWidth, length);
|
||||
unmarkScratchInUse(scratch);
|
||||
return HS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -394,12 +399,14 @@ hs_error_t hs_scan(const hs_database_t *db, const char *data, unsigned length,
|
||||
|
||||
done_scan:
|
||||
if (told_to_stop_matching(scratch)) {
|
||||
unmarkScratchInUse(scratch);
|
||||
return HS_SCAN_TERMINATED;
|
||||
}
|
||||
|
||||
if (rose->hasSom) {
|
||||
int halt = flushStoredSomMatches(scratch, ~0ULL);
|
||||
if (halt) {
|
||||
unmarkScratchInUse(scratch);
|
||||
return HS_SCAN_TERMINATED;
|
||||
}
|
||||
}
|
||||
@@ -412,7 +419,10 @@ done_scan:
|
||||
set_retval:
|
||||
DEBUG_PRINTF("done. told_to_stop_matching=%d\n",
|
||||
told_to_stop_matching(scratch));
|
||||
return told_to_stop_matching(scratch) ? HS_SCAN_TERMINATED : HS_SUCCESS;
|
||||
hs_error_t rv = told_to_stop_matching(scratch) ? HS_SCAN_TERMINATED
|
||||
: HS_SUCCESS;
|
||||
unmarkScratchInUse(scratch);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static really_inline
|
||||
@@ -674,7 +684,11 @@ hs_error_t hs_reset_and_copy_stream(hs_stream_t *to_id,
|
||||
if (!scratch || !validScratch(to_id->rose, scratch)) {
|
||||
return HS_INVALID;
|
||||
}
|
||||
if (unlikely(markScratchInUse(scratch))) {
|
||||
return HS_SCRATCH_IN_USE;
|
||||
}
|
||||
report_eod_matches(to_id, scratch, onEvent, context);
|
||||
unmarkScratchInUse(scratch);
|
||||
}
|
||||
|
||||
size_t stateSize
|
||||
@@ -784,7 +798,10 @@ hs_error_t hs_scan_stream_internal(hs_stream_t *id, const char *data,
|
||||
unsigned length, UNUSED unsigned flags,
|
||||
hs_scratch_t *scratch,
|
||||
match_event_handler onEvent, void *context) {
|
||||
if (unlikely(!id || !scratch || !data || !validScratch(id->rose, scratch))) {
|
||||
assert(id);
|
||||
assert(scratch);
|
||||
|
||||
if (unlikely(!data)) {
|
||||
return HS_INVALID;
|
||||
}
|
||||
|
||||
@@ -878,8 +895,18 @@ HS_PUBLIC_API
|
||||
hs_error_t hs_scan_stream(hs_stream_t *id, const char *data, unsigned length,
|
||||
unsigned flags, hs_scratch_t *scratch,
|
||||
match_event_handler onEvent, void *context) {
|
||||
return hs_scan_stream_internal(id, data, length, flags, scratch,
|
||||
onEvent, context);
|
||||
if (unlikely(!id || !scratch || !data ||
|
||||
!validScratch(id->rose, scratch))) {
|
||||
return HS_INVALID;
|
||||
}
|
||||
|
||||
if (unlikely(markScratchInUse(scratch))) {
|
||||
return HS_SCRATCH_IN_USE;
|
||||
}
|
||||
hs_error_t rv = hs_scan_stream_internal(id, data, length, flags, scratch,
|
||||
onEvent, context);
|
||||
unmarkScratchInUse(scratch);
|
||||
return rv;
|
||||
}
|
||||
|
||||
HS_PUBLIC_API
|
||||
@@ -893,7 +920,11 @@ hs_error_t hs_close_stream(hs_stream_t *id, hs_scratch_t *scratch,
|
||||
if (!scratch || !validScratch(id->rose, scratch)) {
|
||||
return HS_INVALID;
|
||||
}
|
||||
if (unlikely(markScratchInUse(scratch))) {
|
||||
return HS_SCRATCH_IN_USE;
|
||||
}
|
||||
report_eod_matches(id, scratch, onEvent, context);
|
||||
unmarkScratchInUse(scratch);
|
||||
}
|
||||
|
||||
hs_stream_free(id);
|
||||
@@ -913,7 +944,11 @@ hs_error_t hs_reset_stream(hs_stream_t *id, UNUSED unsigned int flags,
|
||||
if (!scratch || !validScratch(id->rose, scratch)) {
|
||||
return HS_INVALID;
|
||||
}
|
||||
if (unlikely(markScratchInUse(scratch))) {
|
||||
return HS_SCRATCH_IN_USE;
|
||||
}
|
||||
report_eod_matches(id, scratch, onEvent, context);
|
||||
unmarkScratchInUse(scratch);
|
||||
}
|
||||
|
||||
init_stream(id, id->rose);
|
||||
@@ -995,6 +1030,10 @@ hs_error_t hs_scan_vector(const hs_database_t *db, const char * const * data,
|
||||
return HS_INVALID;
|
||||
}
|
||||
|
||||
if (unlikely(markScratchInUse(scratch))) {
|
||||
return HS_SCRATCH_IN_USE;
|
||||
}
|
||||
|
||||
hs_stream_t *id = (hs_stream_t *)(scratch->bstate);
|
||||
|
||||
init_stream(id, rose); /* open stream */
|
||||
@@ -1009,6 +1048,7 @@ hs_error_t hs_scan_vector(const hs_database_t *db, const char * const * data,
|
||||
= hs_scan_stream_internal(id, data[i], length[i], 0, scratch,
|
||||
onEvent, context);
|
||||
if (ret != HS_SUCCESS) {
|
||||
unmarkScratchInUse(scratch);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1018,9 +1058,12 @@ hs_error_t hs_scan_vector(const hs_database_t *db, const char * const * data,
|
||||
report_eod_matches(id, scratch, onEvent, context);
|
||||
|
||||
if (told_to_stop_matching(scratch)) {
|
||||
unmarkScratchInUse(scratch);
|
||||
return HS_SCAN_TERMINATED;
|
||||
}
|
||||
}
|
||||
|
||||
unmarkScratchInUse(scratch);
|
||||
|
||||
return HS_SUCCESS;
|
||||
}
|
||||
|
@@ -129,6 +129,7 @@ hs_error_t alloc_scratch(const hs_scratch_t *proto, hs_scratch_t **scratch) {
|
||||
*s = *proto;
|
||||
|
||||
s->magic = SCRATCH_MAGIC;
|
||||
s->in_use = 1;
|
||||
s->scratchSize = alloc_size;
|
||||
s->scratch_alloc = (char *)s_tmp;
|
||||
|
||||
@@ -254,6 +255,9 @@ hs_error_t hs_alloc_scratch(const hs_database_t *db, hs_scratch_t **scratch) {
|
||||
if ((*scratch)->magic != SCRATCH_MAGIC) {
|
||||
return HS_INVALID;
|
||||
}
|
||||
if (markScratchInUse(*scratch)) {
|
||||
return HS_SCRATCH_IN_USE;
|
||||
}
|
||||
}
|
||||
|
||||
const struct RoseEngine *rose = hs_get_bytecode(db);
|
||||
@@ -355,6 +359,7 @@ hs_error_t hs_alloc_scratch(const hs_database_t *db, hs_scratch_t **scratch) {
|
||||
hs_scratch_free(proto_tmp); /* kill off temp used for sizing */
|
||||
}
|
||||
|
||||
unmarkScratchInUse(*scratch);
|
||||
return HS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -384,6 +389,10 @@ hs_error_t hs_free_scratch(hs_scratch_t *scratch) {
|
||||
if (scratch->magic != SCRATCH_MAGIC) {
|
||||
return HS_INVALID;
|
||||
}
|
||||
if (markScratchInUse(scratch)) {
|
||||
return HS_SCRATCH_IN_USE;
|
||||
}
|
||||
|
||||
scratch->magic = 0;
|
||||
assert(scratch->scratch_alloc);
|
||||
DEBUG_PRINTF("scratch %p is really at %p : freeing\n", scratch,
|
||||
|
@@ -140,6 +140,7 @@ struct match_deduper {
|
||||
*/
|
||||
struct ALIGN_CL_DIRECTIVE hs_scratch {
|
||||
u32 magic;
|
||||
u8 in_use; /**< non-zero when being used by an API call. */
|
||||
char *scratch_alloc; /* user allocated scratch object */
|
||||
u32 queueCount;
|
||||
u32 bStateSize; /**< sizeof block mode states */
|
||||
@@ -198,6 +199,34 @@ char can_stop_matching(const struct hs_scratch *scratch) {
|
||||
return scratch->core_info.status & (STATUS_TERMINATED | STATUS_EXHAUSTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mark scratch as in use.
|
||||
*
|
||||
* Returns non-zero if it was already in use, zero otherwise.
|
||||
*/
|
||||
static really_inline
|
||||
char markScratchInUse(struct hs_scratch *scratch) {
|
||||
DEBUG_PRINTF("marking scratch as in use\n");
|
||||
assert(scratch && scratch->magic == SCRATCH_MAGIC);
|
||||
if (scratch->in_use) {
|
||||
DEBUG_PRINTF("scratch already in use!\n");
|
||||
return 1;
|
||||
}
|
||||
scratch->in_use = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mark scratch as no longer in use.
|
||||
*/
|
||||
static really_inline
|
||||
void unmarkScratchInUse(struct hs_scratch *scratch) {
|
||||
DEBUG_PRINTF("marking scratch as not in use\n");
|
||||
assert(scratch && scratch->magic == SCRATCH_MAGIC);
|
||||
assert(scratch->in_use == 1);
|
||||
scratch->in_use = 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user