mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 20:36:16 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			172 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 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];
 | 
						|
    snprintf(name, sizeof(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 */
 |