• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_USB_NEW_DELETE_H__
18 #define ANDROID_USB_NEW_DELETE_H__
19 /** \file
20   This file consists implementations of our 'new' and 'delete' operators
21 */
22 
23 #include "android_usb_pool_tags.h"
24 
25 /** \brief Checks if given pool type is one of NonPaged pool kinds.
26 
27   All numeric values for all NonPaged pool types are even numbers while all
28   numeric values for all PagedPool types are odd numbers (see definition of
29   POOL_TYPE enum). So this routine utilizes this to see whether given pool
30   type is one of NonPaged pool kinds. This routine can be called at any IRQL.
31   @param pool_type[in] Pool type
32   @return True if pool type is one of NonPaged pool types, false otherwise
33 */
IsPoolNonPaged(POOL_TYPE pool_type)34 __forceinline bool IsPoolNonPaged(POOL_TYPE pool_type) {
35   return (0 == (pool_type & 0x1));
36 }
37 
38 /** @name Operators new and delete
39 
40   In Kernel Mode development each memory allocation must specify type of the
41   pool from which memory should be allocated, usualy PagedPool or NonPagedPool.
42   Because of that "traditional" operator 'new' that takes only one parameter
43   (memory size) is not good so we modify that operator by adding two more
44   parameters: pool type and memory tag (last one is optional but highly
45   encouraged). To prevent from mistakes, traditional operator 'new' is also
46   defined. It will allocate requested number of bytes from NonPagedPool with
47   default memory tag but it will always assert on checked (debug) builds.
48   Since there is no infrastructure for C++ exceptions in Kernel Mode we are
49   not using them to report memory allocation error. So, on failure operators
50   'new' are returning NULL instead of throwing an exception.
51 */
52 ///@{
53 
54 /** \brief Main operator new
55 
56   This is the main operator new that allocates specified number of bytes from
57   the specified pool and assigns a custom tag to the allocated memory.
58   Inherits IRQL restrictions for ExAllocatePoolWithTag (see the DDK doc).
59   @param size[in] Number of bytes to allocate.
60   @param pool_type[in] Type of the pool to allocate from.
61   @param pool_tag[in] A tag to attach to the allocated memory. Since utilities
62          that display tags use their ASCII representations it's advisable to
63          use tag values that are ASCII symbols, f.i. 'ATag'. Note that due to
64          inversion of bytes in stored ULONG value, to read 'ATag' in the tag
65          displaying utility, the actual value passed to operator 'new' must be
66          'gaTA'
67   @return Pointer to allocated memory on success, NULL on error.
68 */
new(size_t size,POOL_TYPE pool_type,ULONG pool_tag)69 __forceinline void* __cdecl operator new(size_t size,
70                                          POOL_TYPE pool_type,
71                                          ULONG pool_tag) {
72   ASSERT((pool_type < MaxPoolType) && (0 != size));
73   // Enforce IRQL restriction check.
74   ASSERT(IsPoolNonPaged(pool_type) || (KeGetCurrentIrql() < DISPATCH_LEVEL));
75   return size ? ExAllocatePoolWithTag(pool_type,
76                                       static_cast<ULONG>(size),
77                                       pool_tag) :
78                 NULL;
79 }
80 
81 /** \brief
82   Short operator new that attaches a default tag to the allocated memory.
83 
84   This version of operator new allocates specified number of bytes from the
85   specified pool and assigns a default tag (GANDR_POOL_TAG_DEFAULT) to the
86   allocated memory. Inherits IRQL restrictions for ExAllocatePoolWithTag.
87   @param size[in] Number of bytes to allocate.
88   @param pool_type[in] Type of the pool to allocate from.
89   @return Pointer to allocated memory on success, NULL on error.
90 */
new(size_t size,POOL_TYPE pool_type)91 __forceinline void* __cdecl operator new(size_t size, POOL_TYPE pool_type) {
92   ASSERT((pool_type < MaxPoolType) && (0 != size));
93   // Enforce IRQL restriction check.
94   ASSERT(IsPoolNonPaged(pool_type) || (KeGetCurrentIrql() < DISPATCH_LEVEL));
95   return size ? ExAllocatePoolWithTag(pool_type,
96                                       static_cast<ULONG>(size),
97                                       GANDR_POOL_TAG_DEFAULT) :
98                 NULL;
99 }
100 
101 /** \brief Traditional operator new that should never be used.
102 
103   Using of this version of operator 'new' is prohibited in Kernel Mode
104   development. For the sake of safety it is implemented though to allocate
105   requested number of bytes from the NonPagedPool and attach default tag
106   to the allocated memory. It will assert on checked (debug) builds.
107   Inherits IRQL restrictions for ExAllocatePoolWithTag.
108   @param size[in] Number of bytes to allocate.
109   @return Pointer to memory allocated from NonPagedPool on success or NULL on
110           error.
111 */
new(size_t size)112 __forceinline void* __cdecl operator new(size_t size) {
113   ASSERTMSG("\n!!! Using of operator new(size_t size) is detected!\n"
114     "This is illegal in our driver C++ development environment to use "
115     "this version of operator 'new'. Please switch to\n"
116     "new(size_t size, POOL_TYPE pool_type) or "
117     "new(size_t size, POOL_TYPE pool_type, ULONG pool_tag) ASAP!!!\n",
118     false);
119   ASSERT(0 != size);
120   return size ? ExAllocatePoolWithTag(NonPagedPool,
121                                       static_cast<ULONG>(size),
122                                       GANDR_POOL_TAG_DEFAULT) :
123                 NULL;
124 }
125 
126 /** \brief Operator delete.
127 
128   Frees memory allocated by 'new' operator.
129   @param pointer[in] Memory to free. If this parameter is NULL operator does
130          nothing but asserts on checked build. Inherits IRQL restrictions
131          for ExFreePool.
132 */
delete(void * pointer)133 __forceinline void __cdecl operator delete(void* pointer) {
134   ASSERT(NULL != pointer);
135   if (NULL != pointer)
136     ExFreePool(pointer);
137 }
138 
139 /** \brief Operator delete for arrays.
140 
141   Frees memory allocated by 'new' operator.
142   @param pointer[in] Memory to free. If this parameter is NULL operator does
143          nothing but asserts on checked build. Inherits IRQL restrictions
144          for ExFreePool.
145 */
146 __forceinline void __cdecl operator delete[](void* pointer) {
147   ASSERT(NULL != pointer);
148   if (NULL != pointer)
149     ExFreePool(pointer);
150 }
151 
152 ///@}
153 
154 #endif  // ANDROID_USB_NEW_DELETE_H__
155