Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
  2#ifndef __LIBPERF_INTERNAL_RC_CHECK_H
  3#define __LIBPERF_INTERNAL_RC_CHECK_H
  4
  5#include <stdlib.h>
  6#include <linux/zalloc.h>
  7
  8/*
  9 * Enable reference count checking implicitly with leak checking, which is
 10 * integrated into address sanitizer.
 11 */
 12#if defined(__SANITIZE_ADDRESS__) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
 13#define REFCNT_CHECKING 1
 14#elif defined(__has_feature)
 15#if __has_feature(address_sanitizer) || __has_feature(leak_sanitizer)
 16#define REFCNT_CHECKING 1
 17#endif
 18#endif
 19
 20/*
 21 * Shared reference count checking macros.
 22 *
 23 * Reference count checking is an approach to sanitizing the use of reference
 24 * counted structs. It leverages address and leak sanitizers to make sure gets
 25 * are paired with a put. Reference count checking adds a malloc-ed layer of
 26 * indirection on a get, and frees it on a put. A missed put will be reported as
 27 * a memory leak. A double put will be reported as a double free. Accessing
 28 * after a put will cause a use-after-free and/or a segfault.
 29 */
 30
 31#ifndef REFCNT_CHECKING
 32/* Replaces "struct foo" so that the pointer may be interposed. */
 33#define DECLARE_RC_STRUCT(struct_name)		\
 34	struct struct_name
 35
 36/* Declare a reference counted struct variable. */
 37#define RC_STRUCT(struct_name) struct struct_name
 38
 39/*
 40 * Interpose the indirection. Result will hold the indirection and object is the
 41 * reference counted struct.
 42 */
 43#define ADD_RC_CHK(result, object) (result = object, object)
 44
 45/* Strip the indirection layer. */
 46#define RC_CHK_ACCESS(object) object
 47
 48/* Frees the object and the indirection layer. */
 49#define RC_CHK_FREE(object) free(object)
 50
 51/* A get operation adding the indirection layer. */
 52#define RC_CHK_GET(result, object) ADD_RC_CHK(result, object)
 53
 54/* A put operation removing the indirection layer. */
 55#define RC_CHK_PUT(object) {}
 56
 57/* Pointer equality when the indirection may or may not be there. */
 58#define RC_CHK_EQUAL(object1, object2) (object1 == object2)
 59
 60#else
 61
 62/* Replaces "struct foo" so that the pointer may be interposed. */
 63#define DECLARE_RC_STRUCT(struct_name)			\
 64	struct original_##struct_name;			\
 65	struct struct_name {				\
 66		struct original_##struct_name *orig;	\
 67	};						\
 68	struct original_##struct_name
 69
 70/* Declare a reference counted struct variable. */
 71#define RC_STRUCT(struct_name) struct original_##struct_name
 72
 73/*
 74 * Interpose the indirection. Result will hold the indirection and object is the
 75 * reference counted struct.
 76 */
 77#define ADD_RC_CHK(result, object)					\
 78	(								\
 79		object ? (result = malloc(sizeof(*result)),		\
 80			result ? (result->orig = object, result)	\
 81			: (result = NULL, NULL))			\
 82		: (result = NULL, NULL)					\
 83		)
 84
 85/* Strip the indirection layer. */
 86#define RC_CHK_ACCESS(object) object->orig
 87
 88/* Frees the object and the indirection layer. */
 89#define RC_CHK_FREE(object)			\
 90	do {					\
 91		zfree(&object->orig);		\
 92		free(object);			\
 93	} while(0)
 94
 95/* A get operation adding the indirection layer. */
 96#define RC_CHK_GET(result, object) ADD_RC_CHK(result, (object ? object->orig : NULL))
 97
 98/* A put operation removing the indirection layer. */
 99#define RC_CHK_PUT(object)			\
100	do {					\
101		if (object) {			\
102			object->orig = NULL;	\
103			free(object);		\
104		}				\
105	} while(0)
106
107/* Pointer equality when the indirection may or may not be there. */
108#define RC_CHK_EQUAL(object1, object2) (object1 == object2 || \
109		(object1 && object2 && object1->orig == object2->orig))
110
111#endif
112
113#endif /* __LIBPERF_INTERNAL_RC_CHECK_H */