Files
open-gpu-kernel-modules/src/nvidia/inc/kernel/core/locks.h
Andy Ritger 758b4ee818 525.53
2022-11-10 08:39:33 -08:00

196 lines
7.1 KiB
C

/*
* SPDX-FileCopyrightText: Copyright (c) 1993-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef LOCKS_H
#define LOCKS_H
#include "core/core.h"
#include "os/os.h"
// Forward declarations
typedef struct OBJSYS OBJSYS;
typedef enum
{
GPU_LOCK_GRP_SUBDEVICE, // locks will be taken for subdevice only
GPU_LOCK_GRP_DEVICE, // locks will be taken for device only
GPU_LOCK_GRP_MASK, // locks will be taken for devices specified by the mask
GPU_LOCK_GRP_ALL // locks will be taken for all devices
} GPU_LOCK_GRP_ID;
typedef NvU32 GPU_MASK;
//
// This structure is used to trace lock acquire/release activity.
// The calling IP is stored in a circular array.
//
#define MAX_TRACE_LOCK_CALLS 32
typedef enum
{
lockTraceEmpty,
lockTraceAcquire,
lockTraceRelease,
lockTraceAlloc,
lockTraceFree
} LOCK_TRACE_TYPE;
typedef struct
{
LOCK_TRACE_TYPE type;
union {
GPU_MASK gpuMask; // For GPU locks
NvU32 lockModule; // For API lock
NvU32 value;
} data32;
union {
NvU16 gpuInst; // For GPU locks
NvU16 lockFlags; // For API lock
NvU16 value;
} data16;
NvBool bHighIrql;
NvU8 priority;
NvU64 callerRA;
NvU64 threadId;
NvU64 timestamp;
} LOCK_TRACE_ENTRY;
typedef struct
{
LOCK_TRACE_ENTRY entries[MAX_TRACE_LOCK_CALLS];
NvU32 index;
} LOCK_TRACE_INFO;
#define INSERT_LOCK_TRACE(plti, ra, t, d16, d32, ti, irql, pr, ts) \
{ \
(plti)->entries[(plti)->index].callerRA = (NvUPtr)ra; \
(plti)->entries[(plti)->index].type = t; \
(plti)->entries[(plti)->index].data16.value = d16; \
(plti)->entries[(plti)->index].data32.value = d32; \
(plti)->entries[(plti)->index].threadId = ti; \
(plti)->entries[(plti)->index].timestamp = ts; \
(plti)->entries[(plti)->index].bHighIrql = irql; \
(plti)->entries[(plti)->index].priority = pr; \
(plti)->index = ((plti)->index + 1) % MAX_TRACE_LOCK_CALLS; \
}
//
// Callers specify this value when they to lock all possible GPUs.
//
#define GPUS_LOCK_ALL (0xFFFFFFFF)
//
// Flags for rmGpusLock[Acquire,Release] operations.
//
// default no flags
#define GPUS_LOCK_FLAGS_NONE (0x00000000)
// conditional acquire; if lock is already held then return error
#define GPU_LOCK_FLAGS_COND_ACQUIRE NVBIT(0)
// acquire the lock in read (shared) mode, if applicable
#define GPU_LOCK_FLAGS_READ NVBIT(1)
// Attempt acquire even if it potentially violates the locking order
// But do not block in a way that could cause a deadlock
#define GPU_LOCK_FLAGS_SAFE_LOCK_UPGRADE NVBIT(2)
//
// RM Lock Related Functions
//
NV_STATUS rmLocksAlloc(OBJSYS *);
void rmLocksFree(OBJSYS *);
NV_STATUS rmLocksAcquireAll(NvU32 module);
void rmLocksReleaseAll(void);
NV_STATUS workItemLocksAcquire(NvU32 gpuInstance, NvU32 flags, NvU32 *pReleaseLocks, NvU32 *pGpuMask);
void workItemLocksRelease(NvU32 releaseLocks, NvU32 gpuMask);
//
// Thread priority boosting and throttling:
// Used to temporarily increase the priority of a thread on Windows platforms
// in order to prevent starvation from the scheduler.
//
void threadPriorityStateAlloc(void);
void threadPriorityStateFree(void);
//! Temporarily boost the priority of the current thread
void threadPriorityBoost(NvU64* pBoostPriority, NvU64 *pOriginalPriority);
//! Gradually lower the priority of the current thread if it is boosted and sufficient time has elapsed
void threadPriorityThrottle(void);
//! Restore the original priority of the current thread if it is boosted
void threadPriorityRestore(void);
NV_STATUS rmGpuGroupLockGetMask(NvU32 gpuInst, GPU_LOCK_GRP_ID gpuGrpId, GPU_MASK* pGpuMask);
//
// Defines for rmGpuLockSetOwner operation.
//
#define GPUS_LOCK_OWNER_PENDING_DPC_REFRESH (OS_THREAD_HANDLE)(-1)
NV_STATUS rmGpuLockInfoInit(void);
void rmGpuLockInfoDestroy(void);
NV_STATUS rmGpuLockAlloc(NvU32);
void rmGpuLockFree(NvU32);
NV_STATUS rmGpuLocksAcquire(NvU32, NvU32);
NvU32 rmGpuLocksRelease(NvU32, OBJGPU *);
void rmGpuLocksFreeze(GPU_MASK);
void rmGpuLocksUnfreeze(GPU_MASK);
NV_STATUS rmGpuLockHide(NvU32);
void rmGpuLockShow(NvU32);
NvBool rmGpuLockIsOwner(void);
NvU32 rmGpuLocksGetOwnedMask(void);
NvBool rmGpuLockIsHidden(OBJGPU *);
NV_STATUS rmGpuLockSetOwner(OS_THREAD_HANDLE);
NV_STATUS rmGpuGroupLockAcquire(NvU32, GPU_LOCK_GRP_ID, NvU32, NvU32, GPU_MASK *);
NV_STATUS rmGpuGroupLockRelease(GPU_MASK, NvU32);
NvBool rmGpuGroupLockIsOwner(NvU32, GPU_LOCK_GRP_ID, GPU_MASK*);
NvBool rmDeviceGpuLockIsOwner(NvU32);
NV_STATUS rmDeviceGpuLockSetOwner(OBJGPU *, OS_THREAD_HANDLE);
NV_STATUS rmDeviceGpuLocksAcquire(OBJGPU *, NvU32, NvU32);
NvU32 rmDeviceGpuLocksRelease(OBJGPU *, NvU32, OBJGPU *);
NV_STATUS rmIntrMaskLockAlloc(NvU32 gpuInst);
void rmIntrMaskLockFree(NvU32 gpuInst);
/// @note The return value is always zero, not the actual IRQL
NvU64 rmIntrMaskLockAcquire(OBJGPU *pGpu);
void rmIntrMaskLockRelease(OBJGPU *pGpu, NvU64 oldIrql);
// wrappers for handling lock-related NV_ASSERT_OR_RETURNs
#define LOCK_ASSERT_AND_RETURN(cond) NV_ASSERT_OR_ELSE_STR((cond), #cond, return NV_ERR_INVALID_LOCK_STATE)
#define IRQL_ASSERT_AND_RETURN(cond) NV_ASSERT_OR_ELSE_STR((cond), #cond, return NV_ERR_INVALID_IRQ_LEVEL)
#define LOCK_ASSERT_AND_RETURN_BOOL(cond, bRet) NV_ASSERT_OR_ELSE_STR((cond), #cond, return (bRet))
#define LOCK_METER_OP(f,l,t,d0,d1,d2)
#define LOCK_METER_DATA(t,d0,d1,d2)
#define rmInitLockMetering()
#define rmDestroyLockMetering()
#include "rmapi/rmapi.h"
#define API_LOCK_FLAGS_NONE RMAPI_LOCK_FLAGS_NONE
#define API_LOCK_FLAGS_COND_ACQUIRE RMAPI_LOCK_FLAGS_COND_ACQUIRE
#endif // LOCKS_H