Main goal of memory allocation profiling patchset is to provide accounting that is cheap enough to run in production. To achieve that we inject counters using codetags at the allocation call sites to account every time allocation is made. This injection allows us to perform accounting efficiently because injected counters are immediately available as opposed to the alternative methods, such as using _RET_IP_, which would require counter lookup and appropriate locking that makes accounting much more expensive. This method requires all allocation functions to inject separate counters at their call sites so that their callers can be individually accounted. Counter injection is implemented by allocation hooks which should wrap all allocation functions. Inlined functions which perform allocations but do not use allocation hooks are directly charged for the allocations they perform. In most cases these functions are just specialized allocation wrappers used from multiple places to allocate objects of a specific type. It would be more useful to do the accounting at their call sites instead. Instrument these helpers to do accounting at the call site. Simple inlined allocation wrappers are converted directly into macros. More complex allocators or allocators with documentation are converted into _noprof versions and allocation hooks are added. This allows memory allocation profiling mechanism to charge allocations to the callers of these functions. Link: https://lkml.kernel.org/r/20240415020731.1152108-1-surenb@google.com Signed-off-by: Suren Baghdasaryan <surenb@google.com> Acked-by: Jan Kara <jack@suse.cz> [jbd2] Cc: Anna Schumaker <anna@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com> Cc: Christoph Lameter <cl@linux.com> Cc: David Rientjes <rientjes@google.com> Cc: David S. Miller <davem@davemloft.net> Cc: Dennis Zhou <dennis@kernel.org> Cc: Eric Dumazet <edumazet@google.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Jakub Sitnicki <jakub@cloudflare.com> Cc: Jiri Kosina <jikos@kernel.org> Cc: Joerg Roedel <joro@8bytes.org> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Kent Overstreet <kent.overstreet@linux.dev> Cc: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Paolo Abeni <pabeni@redhat.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: Tejun Heo <tj@kernel.org> Cc: Theodore Ts'o <tytso@mit.edu> Cc: Trond Myklebust <trond.myklebust@hammerspace.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Will Deacon <will@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
138 lines
3.2 KiB
C
138 lines
3.2 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
|
|
/******************************************************************************
|
|
*
|
|
* Name: aclinuxex.h - Extra OS specific defines, etc. for Linux
|
|
*
|
|
* Copyright (C) 2000 - 2023, Intel Corp.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifndef __ACLINUXEX_H__
|
|
#define __ACLINUXEX_H__
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#ifndef ACPI_USE_NATIVE_DIVIDE
|
|
|
|
#ifndef ACPI_DIV_64_BY_32
|
|
#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \
|
|
do { \
|
|
u64 (__n) = ((u64) n_hi) << 32 | (n_lo); \
|
|
(r32) = do_div ((__n), (d32)); \
|
|
(q32) = (u32) (__n); \
|
|
} while (0)
|
|
#endif
|
|
|
|
#ifndef ACPI_SHIFT_RIGHT_64
|
|
#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \
|
|
do { \
|
|
(n_lo) >>= 1; \
|
|
(n_lo) |= (((n_hi) & 1) << 31); \
|
|
(n_hi) >>= 1; \
|
|
} while (0)
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Overrides for in-kernel ACPICA
|
|
*/
|
|
acpi_status ACPI_INIT_FUNCTION acpi_os_initialize(void);
|
|
|
|
acpi_status acpi_os_terminate(void);
|
|
|
|
/*
|
|
* The irqs_disabled() check is for resume from RAM.
|
|
* Interrupts are off during resume, just like they are for boot.
|
|
* However, boot has (system_state != SYSTEM_RUNNING)
|
|
* to quiet __might_sleep() in kmalloc() and resume does not.
|
|
*/
|
|
#define acpi_os_allocate(_size) \
|
|
kmalloc(_size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL)
|
|
|
|
#define acpi_os_allocate_zeroed(_size) \
|
|
kzalloc(_size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL)
|
|
|
|
static inline void acpi_os_free(void *memory)
|
|
{
|
|
kfree(memory);
|
|
}
|
|
|
|
#define acpi_os_acquire_object(_cache) \
|
|
kmem_cache_zalloc(_cache, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL)
|
|
|
|
static inline acpi_thread_id acpi_os_get_thread_id(void)
|
|
{
|
|
return (acpi_thread_id) (unsigned long)current;
|
|
}
|
|
|
|
/*
|
|
* When lockdep is enabled, the spin_lock_init() macro stringifies it's
|
|
* argument and uses that as a name for the lock in debugging.
|
|
* By executing spin_lock_init() in a macro the key changes from "lock" for
|
|
* all locks to the name of the argument of acpi_os_create_lock(), which
|
|
* prevents lockdep from reporting false positives for ACPICA locks.
|
|
*/
|
|
#define acpi_os_create_lock(__handle) \
|
|
({ \
|
|
spinlock_t *lock = ACPI_ALLOCATE(sizeof(*lock)); \
|
|
if (lock) { \
|
|
*(__handle) = lock; \
|
|
spin_lock_init(*(__handle)); \
|
|
} \
|
|
lock ? AE_OK : AE_NO_MEMORY; \
|
|
})
|
|
|
|
|
|
#define acpi_os_create_raw_lock(__handle) \
|
|
({ \
|
|
raw_spinlock_t *lock = ACPI_ALLOCATE(sizeof(*lock)); \
|
|
if (lock) { \
|
|
*(__handle) = lock; \
|
|
raw_spin_lock_init(*(__handle)); \
|
|
} \
|
|
lock ? AE_OK : AE_NO_MEMORY; \
|
|
})
|
|
|
|
static inline acpi_cpu_flags acpi_os_acquire_raw_lock(acpi_raw_spinlock lockp)
|
|
{
|
|
acpi_cpu_flags flags;
|
|
|
|
raw_spin_lock_irqsave(lockp, flags);
|
|
return flags;
|
|
}
|
|
|
|
static inline void acpi_os_release_raw_lock(acpi_raw_spinlock lockp,
|
|
acpi_cpu_flags flags)
|
|
{
|
|
raw_spin_unlock_irqrestore(lockp, flags);
|
|
}
|
|
|
|
static inline void acpi_os_delete_raw_lock(acpi_raw_spinlock handle)
|
|
{
|
|
ACPI_FREE(handle);
|
|
}
|
|
|
|
static inline u8 acpi_os_readable(void *pointer, acpi_size length)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static inline acpi_status acpi_os_initialize_debugger(void)
|
|
{
|
|
return AE_OK;
|
|
}
|
|
|
|
static inline void acpi_os_terminate_debugger(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* OSL interfaces added by Linux
|
|
*/
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
#endif /* __ACLINUXEX_H__ */
|