summaryrefslogtreecommitdiffstats
path: root/mysys/my_likely.c
diff options
context:
space:
mode:
Diffstat (limited to 'mysys/my_likely.c')
-rw-r--r--mysys/my_likely.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/mysys/my_likely.c b/mysys/my_likely.c
new file mode 100644
index 00000000..2ae587be
--- /dev/null
+++ b/mysys/my_likely.c
@@ -0,0 +1,172 @@
+/* Copyright (c) 2018, MariaDB Corporation Ab.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/*
+ Checks that my_likely/my_unlikely is correctly used
+
+ Note that we can't use mysql_mutex or my_malloc here as these
+ uses likely() macros and the likely_mutex would be used twice
+*/
+
+#include "mysys_priv.h"
+#include <hash.h>
+#include <m_ctype.h>
+
+#ifndef CHECK_UNLIKEY
+my_bool likely_inited= 0;
+
+typedef struct st_likely_entry
+{
+ const char *key;
+ size_t key_length;
+ uint line;
+ ulonglong ok,fail;
+} LIKELY_ENTRY;
+
+static uchar *get_likely_key(LIKELY_ENTRY *part, size_t *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length= part->key_length;
+ return (uchar*) part->key;
+}
+
+pthread_mutex_t likely_mutex;
+HASH likely_hash;
+
+void init_my_likely()
+{
+ /* Allocate big enough to avoid malloc calls */
+ my_hash_init2(PSI_NOT_INSTRUMENTED, &likely_hash, 10000, &my_charset_bin,
+ 1024, 0, 0, (my_hash_get_key) get_likely_key, 0, free,
+ HASH_UNIQUE);
+ likely_inited= 1;
+ pthread_mutex_init(&likely_mutex, MY_MUTEX_INIT_FAST);
+}
+
+static int likely_cmp(LIKELY_ENTRY **a, LIKELY_ENTRY **b)
+{
+ int cmp;
+ if ((cmp= strcmp((*a)->key, (*b)->key)))
+ return cmp;
+ return (int) ((*a)->line - (*b)->line);
+}
+
+
+void end_my_likely(FILE *out)
+{
+ uint i;
+ FILE *likely_file;
+ my_bool do_close= 0;
+ LIKELY_ENTRY **sort_ptr= 0;
+
+ likely_inited= 0;
+
+ if (!(likely_file= out))
+ {
+ char name[80];
+ sprintf(name, "/tmp/unlikely-%lu.out", (ulong) getpid());
+ if ((likely_file= my_fopen(name, O_TRUNC | O_WRONLY, MYF(MY_WME))))
+ do_close= 1;
+ else
+ likely_file= stderr;
+ }
+ fflush(likely_file);
+ fputs("Wrong likely/unlikely usage:\n", likely_file);
+ if (!(sort_ptr= (LIKELY_ENTRY**)
+ malloc(sizeof(LIKELY_ENTRY*) *likely_hash.records)))
+ {
+ fprintf(stderr, "ERROR: Out of memory in end_my_likely\n");
+ goto err;
+ }
+
+ for (i=0 ; i < likely_hash.records ; i++)
+ sort_ptr[i]= (LIKELY_ENTRY *) my_hash_element(&likely_hash, i);
+
+ my_qsort(sort_ptr, likely_hash.records, sizeof(LIKELY_ENTRY*),
+ (qsort_cmp) likely_cmp);
+
+ for (i=0 ; i < likely_hash.records ; i++)
+ {
+ LIKELY_ENTRY *entry= sort_ptr[i];
+ if (entry->fail > entry->ok)
+ fprintf(likely_file,
+ "%50s line: %6u ok: %8lld fail: %8lld\n",
+ entry->key, entry->line, entry->ok, entry->fail);
+ }
+ fputs("\n", likely_file);
+ fflush(likely_file);
+err:
+ free((void*) sort_ptr);
+ if (do_close)
+ my_fclose(likely_file, MYF(MY_WME));
+ pthread_mutex_destroy(&likely_mutex);
+ my_hash_free(&likely_hash);
+}
+
+
+static LIKELY_ENTRY *my_likely_find(const char *file_name, uint line)
+{
+ char key[80], *pos;
+ LIKELY_ENTRY *entry;
+ size_t length;
+
+ if (!likely_inited)
+ return 0;
+
+ pos= strnmov(key, file_name, sizeof(key)-4);
+ int3store(pos+1, line);
+ length= (size_t) (pos-key)+4;
+
+ pthread_mutex_lock(&likely_mutex);
+ if (!(entry= (LIKELY_ENTRY*) my_hash_search(&likely_hash, (uchar*) key,
+ length)))
+ {
+ if (!(entry= (LIKELY_ENTRY *) malloc(sizeof(*entry) + length)))
+ return 0;
+ entry->key= (char*) (entry+1);
+ memcpy((void*) entry->key, key, length);
+ entry->key_length= length;
+ entry->line= line;
+ entry->ok= entry->fail= 0;
+
+ if (my_hash_insert(&likely_hash, (void*) entry))
+ {
+ pthread_mutex_unlock(&likely_mutex);
+ free(entry);
+ return 0;
+ }
+ }
+ pthread_mutex_unlock(&likely_mutex);
+ return entry;
+}
+
+
+int my_likely_ok(const char *file_name, uint line)
+{
+ LIKELY_ENTRY *entry= my_likely_find(file_name, line);
+ if (entry)
+ entry->ok++;
+ return 0;
+}
+
+
+int my_likely_fail(const char *file_name, uint line)
+{
+ LIKELY_ENTRY *entry= my_likely_find(file_name, line);
+ if (entry)
+ entry->fail++;
+ return 0;
+}
+#endif /* CHECK_UNLIKEY */