aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlo Marcelo Arenas Belón <carenas@gmail.com>2023-02-03 12:48:47 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-02-03 12:48:47 +0000
commit4d3b040b5846f60d5333621b38bce6434d43ea0e (patch)
treede956c6c378e57c9358a24b930af426a463df3b9
parent9a79d0d04b66032c5ae2a7d02811b094a83ae5c0 (diff)
parent0470684f9e91f182e8ca4a6c85857789baee1ac6 (diff)
downloadselinux-4d3b040b5846f60d5333621b38bce6434d43ea0e.tar.gz
libselinux: improve performance with pcre matches am: 72806f3933 am: 0470684f9e
Original change: https://android-review.googlesource.com/c/platform/external/selinux/+/2411194 Change-Id: I20bcafd279e50e1354fb1e56d40c799ce26b9777 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--libselinux/src/regex.c108
-rw-r--r--libselinux/src/selinux_internal.h4
2 files changed, 64 insertions, 48 deletions
diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c
index 16df6790..54f24026 100644
--- a/libselinux/src/regex.c
+++ b/libselinux/src/regex.c
@@ -30,6 +30,11 @@
#endif
#ifdef USE_PCRE2
+static pthread_key_t match_data_key;
+static int match_data_key_initialized = -1;
+static pthread_mutex_t key_mutex = PTHREAD_MUTEX_INITIALIZER;
+static __thread char match_data_initialized;
+
char const *regex_arch_string(void)
{
static char arch_string_buffer[32];
@@ -60,14 +65,6 @@ char const *regex_arch_string(void)
struct regex_data {
pcre2_code *regex; /* compiled regular expression */
-#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
- /*
- * match data block required for the compiled
- * pattern in pcre2
- */
- pcre2_match_data *match_data;
-#endif
- pthread_mutex_t match_mutex;
};
int regex_prepare_data(struct regex_data **regex, char const *pattern_string,
@@ -86,13 +83,6 @@ int regex_prepare_data(struct regex_data **regex, char const *pattern_string,
goto err;
}
-#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
- (*regex)->match_data =
- pcre2_match_data_create_from_pattern((*regex)->regex, NULL);
- if (!(*regex)->match_data) {
- goto err;
- }
-#endif
return 0;
err:
@@ -142,13 +132,6 @@ int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex,
if (rc != 1)
goto err;
-#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
- (*regex)->match_data =
- pcre2_match_data_create_from_pattern((*regex)->regex, NULL);
- if (!(*regex)->match_data)
- goto err;
-#endif
-
*regex_compiled = true;
}
@@ -204,18 +187,32 @@ out:
return rc;
}
+static void __attribute__((destructor)) match_data_thread_free(void *key)
+{
+ void *value;
+ pcre2_match_data *match_data;
+
+ if (match_data_key_initialized <= 0 || !match_data_initialized)
+ return;
+
+ value = __selinux_getspecific(match_data_key);
+ match_data = value ? value : key;
+
+ pcre2_match_data_free(match_data);
+
+ __pthread_mutex_lock(&key_mutex);
+ if (--match_data_key_initialized == 1) {
+ __selinux_key_delete(match_data_key);
+ match_data_key_initialized = -1;
+ }
+ __pthread_mutex_unlock(&key_mutex);
+}
+
void regex_data_free(struct regex_data *regex)
{
if (regex) {
if (regex->regex)
pcre2_code_free(regex->regex);
-
-#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
- if (regex->match_data)
- pcre2_match_data_free(regex->match_data);
-#endif
-
- __pthread_mutex_destroy(&regex->match_mutex);
free(regex);
}
}
@@ -223,32 +220,40 @@ void regex_data_free(struct regex_data *regex)
int regex_match(struct regex_data *regex, char const *subject, int partial)
{
int rc;
- pcre2_match_data *match_data;
- __pthread_mutex_lock(&regex->match_mutex);
+ bool slow;
+ pcre2_match_data *match_data = NULL;
+
+ if (match_data_key_initialized > 0) {
+ if (match_data_initialized == 0) {
+ match_data = pcre2_match_data_create(1, NULL);
+ if (match_data) {
+ match_data_initialized = 1;
+ __selinux_setspecific(match_data_key,
+ match_data);
+ __pthread_mutex_lock(&key_mutex);
+ match_data_key_initialized++;
+ __pthread_mutex_unlock(&key_mutex);
+ }
+ } else
+ match_data = __selinux_getspecific(match_data_key);
+ }
-#ifdef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
- match_data = pcre2_match_data_create_from_pattern(
- regex->regex, NULL);
- if (match_data == NULL) {
- __pthread_mutex_unlock(&regex->match_mutex);
- return REGEX_ERROR;
+ slow = (match_data_key_initialized <= 0 || match_data == NULL);
+ if (slow) {
+ match_data = pcre2_match_data_create_from_pattern(regex->regex,
+ NULL);
+ if (!match_data)
+ return REGEX_ERROR;
}
-#else
- match_data = regex->match_data;
-#endif
rc = pcre2_match(
regex->regex, (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0,
partial ? PCRE2_PARTIAL_SOFT : 0, match_data, NULL);
-#ifdef AGGRESSIVE_FREE_AFTER_REGEX_MATCH
- // pcre2_match allocates heap and it won't be freed until
- // pcre2_match_data_free, resulting in heap overhead.
- pcre2_match_data_free(match_data);
-#endif
+ if (slow)
+ pcre2_match_data_free(match_data);
- __pthread_mutex_unlock(&regex->match_mutex);
- if (rc > 0)
+ if (rc >= 0)
return REGEX_MATCH;
switch (rc) {
case PCRE2_ERROR_PARTIAL:
@@ -290,7 +295,14 @@ struct regex_data *regex_data_create(void)
if (!regex_data)
return NULL;
- __pthread_mutex_init(&regex_data->match_mutex, NULL);
+ __pthread_mutex_lock(&key_mutex);
+ if (match_data_key_initialized < 0) {
+ match_data_key_initialized = !__selinux_key_create(
+ &match_data_key,
+ match_data_thread_free);
+ }
+ __pthread_mutex_unlock(&key_mutex);
+
return regex_data;
}
diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h
index 06f2c038..d1e6c50f 100644
--- a/libselinux/src/selinux_internal.h
+++ b/libselinux/src/selinux_internal.h
@@ -13,6 +13,7 @@ extern int selinux_page_size ;
#pragma weak pthread_key_create
#pragma weak pthread_key_delete
#pragma weak pthread_setspecific
+#pragma weak pthread_getspecific
/* Call handler iff the first call. */
#define __selinux_once(ONCE_CONTROL, INIT_FUNCTION) \
@@ -41,6 +42,9 @@ extern int selinux_page_size ;
pthread_setspecific(KEY, VALUE); \
} while (0)
+#define __selinux_getspecific(KEY) \
+ (pthread_getspecific != NULL ? pthread_getspecific(KEY) : NULL)
+
/* selabel_lookup() is only thread safe if we're compiled with pthreads */
#pragma weak pthread_mutex_init