diff options
author | Carlo Marcelo Arenas Belón <carenas@gmail.com> | 2023-02-03 12:48:47 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-02-03 12:48:47 +0000 |
commit | 4d3b040b5846f60d5333621b38bce6434d43ea0e (patch) | |
tree | de956c6c378e57c9358a24b930af426a463df3b9 | |
parent | 9a79d0d04b66032c5ae2a7d02811b094a83ae5c0 (diff) | |
parent | 0470684f9e91f182e8ca4a6c85857789baee1ac6 (diff) | |
download | selinux-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.c | 108 | ||||
-rw-r--r-- | libselinux/src/selinux_internal.h | 4 |
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(®ex->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(®ex->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(®ex->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(®ex->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(®ex_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 |