Blame psm_utils.h

Packit 961e70
/*
Packit 961e70
Packit 961e70
  This file is provided under a dual BSD/GPLv2 license.  When using or
Packit 961e70
  redistributing this file, you may do so under either license.
Packit 961e70
Packit 961e70
  GPL LICENSE SUMMARY
Packit 961e70
Packit 961e70
  Copyright(c) 2015 Intel Corporation.
Packit 961e70
Packit 961e70
  This program is free software; you can redistribute it and/or modify
Packit 961e70
  it under the terms of version 2 of the GNU General Public License as
Packit 961e70
  published by the Free Software Foundation.
Packit 961e70
Packit 961e70
  This program is distributed in the hope that it will be useful, but
Packit 961e70
  WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 961e70
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 961e70
  General Public License for more details.
Packit 961e70
Packit 961e70
  Contact Information:
Packit 961e70
  Intel Corporation, www.intel.com
Packit 961e70
Packit 961e70
  BSD LICENSE
Packit 961e70
Packit 961e70
  Copyright(c) 2015 Intel Corporation.
Packit 961e70
Packit 961e70
  Redistribution and use in source and binary forms, with or without
Packit 961e70
  modification, are permitted provided that the following conditions
Packit 961e70
  are met:
Packit 961e70
Packit 961e70
    * Redistributions of source code must retain the above copyright
Packit 961e70
      notice, this list of conditions and the following disclaimer.
Packit 961e70
    * Redistributions in binary form must reproduce the above copyright
Packit 961e70
      notice, this list of conditions and the following disclaimer in
Packit 961e70
      the documentation and/or other materials provided with the
Packit 961e70
      distribution.
Packit 961e70
    * Neither the name of Intel Corporation nor the names of its
Packit 961e70
      contributors may be used to endorse or promote products derived
Packit 961e70
      from this software without specific prior written permission.
Packit 961e70
Packit 961e70
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 961e70
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 961e70
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 961e70
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 961e70
  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 961e70
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 961e70
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 961e70
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 961e70
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 961e70
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 961e70
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 961e70
Packit 961e70
*/
Packit 961e70
Packit 961e70
#ifndef _PSMI_IN_USER_H
Packit 961e70
#error psm_utils.h not meant to be included directly, include psm_user.h instead
Packit 961e70
#endif
Packit 961e70
Packit 961e70
#ifndef _PSMI_UTILS_H
Packit 961e70
#define _PSMI_UTILS_H
Packit 961e70
Packit 961e70
#include <arpa/inet.h>		/* ipv4addr */
Packit 961e70
#include <stdlib.h>		/* malloc/free */
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Endpoint 'id' hash table, with iterator interface
Packit 961e70
 */
Packit 961e70
struct psmi_epid_table {
Packit 961e70
	struct psmi_epid_tabentry *table;
Packit 961e70
	int tabsize;
Packit 961e70
	int tabsize_used;
Packit 961e70
	pthread_mutex_t tablock;
Packit 961e70
};
Packit 961e70
/*
Packit 961e70
 * Endpoint address hash table
Packit 961e70
 */
Packit 961e70
struct psmi_epid_tabentry {
Packit 961e70
	void *entry;
Packit 961e70
	uint64_t key;
Packit 961e70
	psm2_ep_t ep;
Packit 961e70
	psm2_epid_t epid;
Packit 961e70
};
Packit 961e70
Packit 961e70
extern struct psmi_epid_table psmi_epid_table;
Packit 961e70
#define EPADDR_DELETED	((void *)-1)	/* tag used to mark deleted entries */
Packit 961e70
Packit 961e70
psm2_error_t psmi_epid_init();
Packit 961e70
psm2_error_t psmi_epid_fini();
Packit 961e70
void *psmi_epid_lookup(psm2_ep_t ep, psm2_epid_t epid);
Packit 961e70
void *psmi_epid_remove(psm2_ep_t ep, psm2_epid_t epid);
Packit Service 7ed5cc
void psmi_epid_remove_all(psm2_ep_t ep);
Packit 961e70
psm2_error_t psmi_epid_add(psm2_ep_t ep, psm2_epid_t epid, void *entry);
Packit 961e70
#define PSMI_EP_HOSTNAME    ((psm2_ep_t) -1)	/* Special endpoint handle we use
Packit 961e70
						 * to register hostnames */
Packit 961e70
#define PSMI_EP_CROSSTALK   ((psm2_ep_t) -2)	/* Second special endpoint handle
Packit 961e70
						 * to log which nodes we've seen
Packit 961e70
						 * crosstalk from */
Packit 961e70
struct psmi_eptab_iterator {
Packit 961e70
	int i;			/* last index looked up */
Packit 961e70
	psm2_ep_t ep;
Packit 961e70
};
Packit 961e70
void psmi_epid_itor_init(struct psmi_eptab_iterator *itor, psm2_ep_t ep);
Packit 961e70
void *psmi_epid_itor_next(struct psmi_eptab_iterator *itor);
Packit 961e70
void psmi_epid_itor_fini(struct psmi_eptab_iterator *itor);
Packit 961e70
Packit 961e70
uint64_t psmi_epid_version(psm2_epid_t epid);
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Hostname manipulation
Packit 961e70
 */
Packit 961e70
char *psmi_gethostname(void);
Packit 961e70
const char *psmi_epaddr_get_hostname(psm2_epid_t epid);
Packit 961e70
const char *psmi_epaddr_get_name(psm2_epid_t epid);
Packit 961e70
psm2_error_t psmi_epid_set_hostname(uint64_t nid, const char *hostname,
Packit 961e70
				   int overwrite);
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Memory allocation, use macros only.
Packit 961e70
 *
Packit 961e70
 * In all calls, ep can be a specific endpoint (valid psm2_ep_t) or PSMI_EP_NONE
Packit 961e70
 * if no endpoint is available.
Packit 961e70
 *
Packit 961e70
 *   psmi_malloc_usable_size(void *ptr)
Packit 961e70
 *   psmi_malloc(ep, memtype, size)
Packit 961e70
 *   psmi_realloc(ep, memtype, ptr, newsize)
Packit 961e70
 *   psmi_memalign(ep, memtype, alignment, size)
Packit 961e70
 *   psmi_calloc(ep, memtype, elemsz, numelems)
Packit 961e70
 *   psmi_strdup(ep, memtype, ptr)
Packit 961e70
 *   psmi_free(ptr)
Packit 961e70
 *
Packit 961e70
 */
Packit 961e70
typedef enum psmi_memtype {
Packit 961e70
	TOTAL = 0,		/* Logged automatically by malloc/calloc */
Packit 961e70
	UNDEFINED,		/* For tracking "other types" of allocations */
Packit 961e70
	PER_PEER_ENDPOINT,	/* For tracking "per peer" allocations */
Packit 961e70
	NETWORK_BUFFERS,	/* For tracking network buffers */
Packit 961e70
	DESCRIPTORS,		/* For tracking send/recv descriptors */
Packit 961e70
	UNEXPECTED_BUFFERS,	/* For tracking unexpected recv buffers */
Packit 961e70
	STATS,			/* For tracking stats-related allocs */
Packit 961e70
} psmi_memtype_t;
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * We track allocation stats.
Packit 961e70
 */
Packit 961e70
struct psmi_stats_malloc {
Packit 961e70
	int64_t m_all_total;
Packit 961e70
	int64_t m_all_max;
Packit 961e70
	int64_t m_perpeer_total;
Packit 961e70
	int64_t m_perpeer_max;
Packit 961e70
	int64_t m_netbufs_total;
Packit 961e70
	int64_t m_netbufs_max;
Packit 961e70
	int64_t m_descriptors_total;
Packit 961e70
	int64_t m_descriptors_max;
Packit 961e70
	int64_t m_unexpbufs_total;
Packit 961e70
	int64_t m_unexpbufs_max;
Packit 961e70
	int64_t m_undefined_total;
Packit 961e70
	int64_t m_undefined_max;
Packit 961e70
	int64_t m_stats_total;
Packit 961e70
	int64_t m_stats_max;
Packit 961e70
};
Packit 961e70
Packit 961e70
extern struct psmi_stats_malloc psmi_stats_memory;
Packit 961e70
Packit 961e70
void *psmi_malloc_internal(psm2_ep_t ep, psmi_memtype_t mt, size_t sz,
Packit 961e70
			   const char *curloc);
Packit 961e70
void *psmi_realloc_internal(psm2_ep_t ep, psmi_memtype_t mt, void *ptr,
Packit 961e70
			    size_t newSz, const char *curloc);
Packit 961e70
void *psmi_memalign_internal(psm2_ep_t ep, psmi_memtype_t mt, size_t alignment,
Packit 961e70
			     size_t sz, const char *curloc);
Packit 961e70
void *psmi_calloc_internal(psm2_ep_t ep, psmi_memtype_t mt, size_t num,
Packit 961e70
			   size_t sz, const char *curloc);
Packit 961e70
void *psmi_strdup_internal(psm2_ep_t ep, const char *string, const char *curloc);
Packit 961e70
Packit 961e70
void MOCKABLE(psmi_free_internal)(void *ptr, const char *curLoc);
Packit 961e70
MOCK_DCL_EPILOGUE(psmi_free_internal);
Packit 961e70
Packit 961e70
size_t psmi_malloc_usable_size_internal(void *ptr, const char *curLoc);
Packit 961e70
Packit 961e70
#ifdef PSM_HEAP_DEBUG
Packit 961e70
/* During heap debug code, we can sprinkle function calls:
Packit 961e70
   psmi_heapdebug_val_heapallocs(), that will examine all of the heap allocations
Packit 961e70
   to ensure integrity. */
Packit 961e70
void _psmi_heapdebug_val_heapallocs(const char *curloc);
Packit 961e70
Packit 961e70
#define psmi_heapdebug_val_heapallocs() _psmi_heapdebug_val_heapallocs(PSMI_CURLOC)
Packit 961e70
Packit Service 7ed5cc
/* Finialize the heapdebug functionality after tear down of the psm
Packit Service 7ed5cc
   session when you are certain that all heap allocations have been
Packit Service 7ed5cc
   freed. psmi_heapdebug_finalize() will emit all of the extant
Packit Service 7ed5cc
   heap allocations and abort if there are any.  This is to aid
Packit Service 7ed5cc
   in debug of heap leaks. */
Packit Service 7ed5cc
void psmi_heapdebug_finalize(void);
Packit Service 7ed5cc
Packit 961e70
#else
Packit 961e70
Packit 961e70
#define psmi_heapdebug_val_heapallocs() /* nothing */
Packit Service 7ed5cc
#define psmi_heapdebug_finalize() /* nothing */
Packit 961e70
Packit 961e70
#endif
Packit 961e70
Packit 961e70
#define psmi_strdup(ep, string) psmi_strdup_internal(ep, string, PSMI_CURLOC)
Packit 961e70
#define psmi_calloc(ep, mt, nelem, elemsz) \
Packit 961e70
	psmi_calloc_internal(ep, mt, nelem, elemsz, PSMI_CURLOC)
Packit 961e70
#define psmi_malloc(ep, mt, sz) psmi_malloc_internal(ep, mt, sz, PSMI_CURLOC)
Packit 961e70
#define psmi_realloc(ep, mt, ptr, nsz) psmi_realloc_internal(ep, mt, ptr, nsz, PSMI_CURLOC)
Packit 961e70
#define psmi_memalign(ep, mt, al, sz) \
Packit 961e70
	psmi_memalign_internal(ep, mt, al, sz, PSMI_CURLOC)
Packit 961e70
#define psmi_free(ptr)	psmi_free_internal(ptr, PSMI_CURLOC)
Packit 961e70
#define psmi_malloc_usable_size(ptr) psmi_malloc_usable_size_internal(ptr, PSMI_CURLOC)
Packit 961e70
#ifndef PSM_IS_TEST
Packit 961e70
#define malloc(sz)        _use_psmi_malloc_instead_of_plain_malloc
Packit 961e70
#define realloc(ptr,nsz)  _use_psmi_realloc_instead_of_plain_realloc
Packit 961e70
#define memalign(algn,sz) _use_psmi_memalign_instead_of_plain_memalign
Packit 961e70
#define calloc(sz, nelm)  _use_psmi_calloc_instead_of_plain_calloc
Packit 961e70
#ifdef strdup
Packit 961e70
#undef strdup
Packit 961e70
#endif
Packit 961e70
#define strdup(ptr)             _use_psmi_strdup_instead_of_plain_strdup
Packit 961e70
#define free(ptr)               _use_psmi_free_instead_of_plain_free
Packit 961e70
#define malloc_usable_size(ptr) _use_psmi_malloc_usable_size_instead_of_plain_malloc_usable_size
Packit 961e70
#endif /* PSM_IS_TEST */
Packit 961e70
Packit 961e70
void psmi_log_memstats(psmi_memtype_t type, int64_t nbytes);
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Parsing int parameters set in string tuples.
Packit 961e70
 */
Packit 961e70
int psmi_parse_str_tuples(const char *str, int ntup, int *vals);
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Resource Limiting based on PSM memory mode.
Packit 961e70
 */
Packit 961e70
#define PSMI_MEMMODE_NORMAL  0
Packit 961e70
#define PSMI_MEMMODE_MINIMAL 1
Packit 961e70
#define PSMI_MEMMODE_LARGE   2
Packit 961e70
#define PSMI_MEMMODE_NUM     3
Packit 961e70
Packit 961e70
struct psmi_rlimit_mpool {
Packit 961e70
	const char *env;
Packit 961e70
	const char *descr;
Packit 961e70
	int env_level;
Packit 961e70
	uint32_t minval;
Packit 961e70
	uint32_t maxval;
Packit 961e70
	struct {
Packit 961e70
		uint32_t obj_chunk;
Packit 961e70
		uint32_t obj_max;
Packit 961e70
	} mode[PSMI_MEMMODE_NUM];
Packit 961e70
};
Packit 961e70
psm2_error_t psmi_parse_mpool_env(const psm2_mq_t mq, int level,
Packit 961e70
				 const struct psmi_rlimit_mpool *rlim,
Packit 961e70
				 uint32_t *valo, uint32_t *chunkszo);
Packit 961e70
int psmi_parse_memmode(void);
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Parsing environment variables
Packit 961e70
 */
Packit 961e70
Packit 961e70
union psmi_envvar_val {
Packit 961e70
	void *e_void;
Packit 961e70
	char *e_str;
Packit 961e70
	int e_int;
Packit 961e70
	unsigned int e_uint;
Packit 961e70
	long e_long;
Packit 961e70
	unsigned long e_ulong;
Packit 961e70
	unsigned long long e_ulonglong;
Packit 961e70
};
Packit 961e70
Packit 961e70
#define PSMI_ENVVAR_LEVEL_USER	         1
Packit 961e70
#define PSMI_ENVVAR_LEVEL_HIDDEN         2
Packit 961e70
#define PSMI_ENVVAR_LEVEL_NEVER_PRINT    4
Packit 961e70
Packit 961e70
#define PSMI_ENVVAR_TYPE_YESNO		0
Packit 961e70
#define PSMI_ENVVAR_TYPE_STR		1
Packit 961e70
#define PSMI_ENVVAR_TYPE_INT		2
Packit 961e70
#define PSMI_ENVVAR_TYPE_UINT		3
Packit 961e70
#define PSMI_ENVVAR_TYPE_UINT_FLAGS	4
Packit 961e70
#define PSMI_ENVVAR_TYPE_LONG		5
Packit 961e70
#define PSMI_ENVVAR_TYPE_ULONG		6
Packit 961e70
#define PSMI_ENVVAR_TYPE_ULONG_FLAGS	7
Packit 961e70
#define PSMI_ENVVAR_TYPE_ULONG_ULONG    8
Packit 961e70
Packit 961e70
#define PSMI_ENVVAR_VAL_YES ((union psmi_envvar_val) 1)
Packit 961e70
#define PSMI_ENVVAR_VAL_NO  ((union psmi_envvar_val) 0)
Packit 961e70
Packit 961e70
int
Packit 961e70
MOCKABLE(psmi_getenv)(const char *name, const char *descr, int level,
Packit 961e70
		int type, union psmi_envvar_val defval,
Packit 961e70
		union psmi_envvar_val *newval);
Packit 961e70
MOCK_DCL_EPILOGUE(psmi_getenv);
Packit 961e70
/*
Packit 961e70
 * Misc functionality
Packit 961e70
 */
Packit 961e70
uintptr_t psmi_getpagesize(void);
Packit 961e70
uint64_t psmi_cycles_left(uint64_t start_cycles, int64_t timeout_ns);
Packit 961e70
uint32_t psmi_get_ipv4addr();
Packit 961e70
void psmi_syslog(psm2_ep_t ep, int to_console, int level,
Packit 961e70
		 const char *format, ...);
Packit 961e70
void psmi_uuid_unparse(const psm2_uuid_t uuid, char *out);
Packit 961e70
int psmi_uuid_compare(const psm2_uuid_t uuA, const psm2_uuid_t uuB);
Packit 961e70
void *psmi_memcpyo(void *dst, const void *src, size_t n);
Packit 961e70
uint32_t psmi_crc(unsigned char *buf, int len);
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Internal CPUID detection
Packit 961e70
 */
Packit 961e70
#define CPUID_FAMILY_MASK       0x00000f00
Packit 961e70
#define CPUID_MODEL_MASK        0x000000f0
Packit 961e70
#define CPUID_EXMODEL_MASK      0x000f0000
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * CPUID return values
Packit 961e70
 */
Packit 961e70
#define CPUID_FAMILY_XEON       0x00000600
Packit 961e70
#define CPUID_MODEL_PHI_GEN2    87
Packit 961e70
#define CPUID_MODEL_PHI_GEN2M   133
Packit 961e70
/*
Packit 961e70
 * cpuid function 0, returns "GeniuneIntel" in EBX,ECX,EDX
Packit 961e70
 * due to Little Endian and Hex it is not so obvious
Packit 961e70
 */
Packit 961e70
#define CPUID_GENUINE_INTEL_EBX 0x756e6547 /* "uneG" - Little Endian "Genu" */
Packit 961e70
#define CPUID_GENUINE_INTEL_ECX 0x6c65746e /* "Ieni" - Little Endian "ineI" */
Packit 961e70
#define CPUID_GENUINE_INTEL_EDX 0x49656e69 /* "letn" - Little Endian "ntel" */
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * These values are internal only, not real register values
Packit 961e70
 */
Packit 961e70
#define CPUID_GENUINE_INTEL     0xf0000000
Packit 961e70
#define CPUID_MODEL_UNDEFINED   -1
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Global model so we can tune defaults better for specific cpu's
Packit 961e70
 */
Packit Service 7ed5cc
extern uint32_t psmi_cpu_model;
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Diagnostics, all in psm_diags.c
Packit 961e70
 */
Packit 961e70
int psmi_diags(void);
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Multiple Endpoints
Packit 961e70
 */
Packit 961e70
extern int psmi_multi_ep_enabled;
Packit 961e70
void psmi_multi_ep_init();
Packit 961e70
Packit Service 7ed5cc
#ifdef PSM_FI
Packit 961e70
/*
Packit 961e70
 * Fault injection
Packit 961e70
 */
Packit 961e70
struct psmi_faultinj_spec;
Packit 961e70
int psmi_faultinj_enabled;	/* use macro to test */
Packit 961e70
#if 1				/* possible to disable at compile time */
Packit 961e70
#define PSMI_FAULTINJ_ENABLED()	(!!psmi_faultinj_enabled)
Packit 961e70
#else
Packit 961e70
#define PSMI_FAULTINJ_ENABLED()	0
Packit 961e70
#endif
Packit 961e70
Packit 961e70
void psmi_faultinj_init();
Packit 961e70
void psmi_faultinj_fini();
Packit 961e70
struct psmi_faultinj_spec *psmi_faultinj_getspec(char *spec_name,
Packit 961e70
						 int num, int denom);
Packit 961e70
#define PSMI_FAULTINJ_STATIC_DECL(var, spec_name, num, denom)		\
Packit 961e70
	static struct psmi_faultinj_spec *var;			\
Packit 961e70
	if (PSMI_FAULTINJ_ENABLED() && (var) == NULL)			\
Packit 961e70
	    (var) = psmi_faultinj_getspec((spec_name), (num), (denom));
Packit 961e70
int psmi_faultinj_is_fault(struct psmi_faultinj_spec *spec);
Packit 961e70
Packit Service 7ed5cc
#endif /* #ifdef PSM_FI */
Packit 961e70
/*
Packit 961e70
 * PSM core component set/get options
Packit 961e70
 */
Packit 961e70
psm2_error_t psmi_core_setopt(const void *core_obj, int optname,
Packit 961e70
			     const void *optval, uint64_t optlen);
Packit 961e70
Packit 961e70
psm2_error_t psmi_core_getopt(const void *core_obj, int optname,
Packit 961e70
			     void *optval, uint64_t *optlen);
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * PSM AM component set/get options
Packit 961e70
 */
Packit 961e70
psm2_error_t psmi_am_setopt(const void *am_obj, int optname,
Packit 961e70
			   const void *optval, uint64_t optlen);
Packit 961e70
Packit 961e70
psm2_error_t psmi_am_getopt(const void *am_obj, int optname,
Packit 961e70
			   void *optval, uint64_t *optlen);
Packit 961e70
Packit 961e70
#endif /* _PSMI_UTILS_H */