/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_USB_NEW_DELETE_H__
#define ANDROID_USB_NEW_DELETE_H__
/** \file
This file consists implementations of our 'new' and 'delete' operators
*/
#include "android_usb_pool_tags.h"
/** \brief Checks if given pool type is one of NonPaged pool kinds.
All numeric values for all NonPaged pool types are even numbers while all
numeric values for all PagedPool types are odd numbers (see definition of
POOL_TYPE enum). So this routine utilizes this to see whether given pool
type is one of NonPaged pool kinds. This routine can be called at any IRQL.
@param pool_type[in] Pool type
@return True if pool type is one of NonPaged pool types, false otherwise
*/
__forceinline bool IsPoolNonPaged(POOL_TYPE pool_type) {
return (0 == (pool_type & 0x1));
}
/** @name Operators new and delete
In Kernel Mode development each memory allocation must specify type of the
pool from which memory should be allocated, usualy PagedPool or NonPagedPool.
Because of that "traditional" operator 'new' that takes only one parameter
(memory size) is not good so we modify that operator by adding two more
parameters: pool type and memory tag (last one is optional but highly
encouraged). To prevent from mistakes, traditional operator 'new' is also
defined. It will allocate requested number of bytes from NonPagedPool with
default memory tag but it will always assert on checked (debug) builds.
Since there is no infrastructure for C++ exceptions in Kernel Mode we are
not using them to report memory allocation error. So, on failure operators
'new' are returning NULL instead of throwing an exception.
*/
///@{
/** \brief Main operator new
This is the main operator new that allocates specified number of bytes from
the specified pool and assigns a custom tag to the allocated memory.
Inherits IRQL restrictions for ExAllocatePoolWithTag (see the DDK doc).
@param size[in] Number of bytes to allocate.
@param pool_type[in] Type of the pool to allocate from.
@param pool_tag[in] A tag to attach to the allocated memory. Since utilities
that display tags use their ASCII representations it's advisable to
use tag values that are ASCII symbols, f.i. 'ATag'. Note that due to
inversion of bytes in stored ULONG value, to read 'ATag' in the tag
displaying utility, the actual value passed to operator 'new' must be
'gaTA'
@return Pointer to allocated memory on success, NULL on error.
*/
__forceinline void* __cdecl operator new(size_t size,
POOL_TYPE pool_type,
ULONG pool_tag) {
ASSERT((pool_type < MaxPoolType) && (0 != size));
// Enforce IRQL restriction check.
ASSERT(IsPoolNonPaged(pool_type) || (KeGetCurrentIrql() < DISPATCH_LEVEL));
return size ? ExAllocatePoolWithTag(pool_type,
static_cast<ULONG>(size),
pool_tag) :
NULL;
}
/** \brief
Short operator new that attaches a default tag to the allocated memory.
This version of operator new allocates specified number of bytes from the
specified pool and assigns a default tag (GANDR_POOL_TAG_DEFAULT) to the
allocated memory. Inherits IRQL restrictions for ExAllocatePoolWithTag.
@param size[in] Number of bytes to allocate.
@param pool_type[in] Type of the pool to allocate from.
@return Pointer to allocated memory on success, NULL on error.
*/
__forceinline void* __cdecl operator new(size_t size, POOL_TYPE pool_type) {
ASSERT((pool_type < MaxPoolType) && (0 != size));
// Enforce IRQL restriction check.
ASSERT(IsPoolNonPaged(pool_type) || (KeGetCurrentIrql() < DISPATCH_LEVEL));
return size ? ExAllocatePoolWithTag(pool_type,
static_cast<ULONG>(size),
GANDR_POOL_TAG_DEFAULT) :
NULL;
}
/** \brief Traditional operator new that should never be used.
Using of this version of operator 'new' is prohibited in Kernel Mode
development. For the sake of safety it is implemented though to allocate
requested number of bytes from the NonPagedPool and attach default tag
to the allocated memory. It will assert on checked (debug) builds.
Inherits IRQL restrictions for ExAllocatePoolWithTag.
@param size[in] Number of bytes to allocate.
@return Pointer to memory allocated from NonPagedPool on success or NULL on
error.
*/
__forceinline void* __cdecl operator new(size_t size) {
ASSERTMSG("\n!!! Using of operator new(size_t size) is detected!\n"
"This is illegal in our driver C++ development environment to use "
"this version of operator 'new'. Please switch to\n"
"new(size_t size, POOL_TYPE pool_type) or "
"new(size_t size, POOL_TYPE pool_type, ULONG pool_tag) ASAP!!!\n",
false);
ASSERT(0 != size);
return size ? ExAllocatePoolWithTag(NonPagedPool,
static_cast<ULONG>(size),
GANDR_POOL_TAG_DEFAULT) :
NULL;
}
/** \brief Operator delete.
Frees memory allocated by 'new' operator.
@param pointer[in] Memory to free. If this parameter is NULL operator does
nothing but asserts on checked build. Inherits IRQL restrictions
for ExFreePool.
*/
__forceinline void __cdecl operator delete(void* pointer) {
ASSERT(NULL != pointer);
if (NULL != pointer)
ExFreePool(pointer);
}
/** \brief Operator delete for arrays.
Frees memory allocated by 'new' operator.
@param pointer[in] Memory to free. If this parameter is NULL operator does
nothing but asserts on checked build. Inherits IRQL restrictions
for ExFreePool.
*/
__forceinline void __cdecl operator delete[](void* pointer) {
ASSERT(NULL != pointer);
if (NULL != pointer)
ExFreePool(pointer);
}
///@}
#endif // ANDROID_USB_NEW_DELETE_H__