Changeset 1360
- Timestamp:
- Jul 30, 2004, 4:28:29 PM (22 years ago)
- Location:
- trunk/psLib
- Files:
-
- 7 edited
-
src/collections/psVector.c (modified) (5 diffs)
-
src/mathtypes/psVector.c (modified) (5 diffs)
-
src/sys/psMemory.c (modified) (12 diffs)
-
src/sys/psType.h (modified) (4 diffs)
-
src/sysUtils/psMemory.c (modified) (12 diffs)
-
src/sysUtils/psType.h (modified) (4 diffs)
-
test/psTest.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/collections/psVector.c
r1305 r1360 1 1 /** @file psVector.c 2 *3 * @brief Contains support for basic vector types4 *5 * This file defines the basic type for a vector struct and functions useful6 * in manupulating vectors.7 *8 * @author Ross Harman, MHPCC9 *10 * @version $Revision: 1.16$ $Name: not supported by cvs2svn $11 * @date $Date: 2004-07-28 00:06:13$12 *13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii14 */2 * 3 * @brief Contains support for basic vector types 4 * 5 * This file defines the basic type for a vector struct and functions useful 6 * in manupulating vectors. 7 * 8 * @author Ross Harman, MHPCC 9 * 10 * @version $Revision: 1.17 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2004-07-31 02:28:10 $ 12 * 13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 14 */ 15 15 16 16 /******************************************************************************/ … … 54 54 /* FUNCTION IMPLEMENTATION - LOCAL */ 55 55 /*****************************************************************************/ 56 static void vectorFree( psVector *restrict psVec);56 static void vectorFree( psVector *restrict psVec ); 57 57 58 58 /*****************************************************************************/ 59 59 /* FUNCTION IMPLEMENTATION - PUBLIC */ 60 60 /*****************************************************************************/ 61 psVector* psVectorAlloc( unsigned int nalloc, psElemType elemType)62 { 63 psVector * psVec = NULL;61 psVector* psVectorAlloc( unsigned int nalloc, psElemType elemType ) 62 { 63 psVector * psVec = NULL; 64 64 int elementSize = 0; 65 65 66 66 // Invalid nalloc 67 if (nalloc < 1) {68 psError(__func__, "Invalid value for nalloc. nalloc: %d\n", nalloc);69 return NULL;70 }71 72 elementSize = PSELEMTYPE_SIZEOF( elemType);73 67 if ( nalloc < 1 ) { 68 psError( __func__, "Invalid value for nalloc. nalloc: %d\n", nalloc ); 69 return NULL; 70 } 71 72 elementSize = PSELEMTYPE_SIZEOF( elemType ); 73 74 74 // Create vector struct 75 psVec = ( psVector *)psAlloc(sizeof(psVector));76 p_psMemSetDeallocator( psVec,(psFreeFcn)vectorFree);77 75 psVec = ( psVector * ) psAlloc( sizeof( psVector ) ); 76 p_psMemSetDeallocator( psVec, ( psFreeFcn ) vectorFree ); 77 78 78 psVec->type.dimen = PS_DIMEN_VECTOR; 79 79 psVec->type.type = elemType; 80 80 psVec->nalloc = nalloc; 81 81 psVec->n = nalloc; 82 82 83 83 // Create vector data array 84 psVec->data.V = psAlloc( nalloc*elementSize);85 84 psVec->data.V = psAlloc( nalloc * elementSize ); 85 86 86 return psVec; 87 87 } 88 88 89 psVector *psVectorRealloc( unsigned int nalloc, psVector *restrict in)89 psVector *psVectorRealloc( unsigned int nalloc, psVector *restrict in ) 90 90 { 91 91 int elementSize = 0; 92 92 psElemType elemType; 93 93 94 94 // Invalid nalloc 95 if (nalloc < 1) {96 psError(__func__, "Invalid value for realloc (%d)\n", nalloc);97 return NULL;98 }99 100 if (in == NULL) {101 psError(__func__, "Null input vector\n");102 return NULL;103 } else if(in->nalloc != nalloc) { // No need to realloc to same size104 elemType = in->type.type;105 elementSize = PSELEMTYPE_SIZEOF(elemType);106 if(nalloc < in->n) {107 in->n = nalloc;108 }109 110 // Realloc after decrementation to avoid accessing freed array elements111 in->data.V = psRealloc(in->data.V,nalloc*elementSize);112 in->nalloc = nalloc;113 }114 95 if ( nalloc < 1 ) { 96 psError( __func__, "Invalid value for realloc (%d)\n", nalloc ); 97 return NULL; 98 } 99 100 if ( in == NULL ) { 101 psError( __func__, "Null input vector\n" ); 102 return NULL; 103 } else if ( in->nalloc != nalloc ) { // No need to realloc to same size 104 elemType = in->type.type; 105 elementSize = PSELEMTYPE_SIZEOF( elemType ); 106 if ( nalloc < in->n ) { 107 in->n = nalloc; 108 } 109 110 // Realloc after decrementation to avoid accessing freed array elements 111 in->data.V = psRealloc( in->data.V, nalloc * elementSize ); 112 in->nalloc = nalloc; 113 } 114 115 115 return in; 116 116 } 117 117 118 psVector *psVectorRecycle( psVector *restrict in, psElemType type, unsigned int nalloc)118 psVector *psVectorRecycle( psVector *restrict in, psElemType type, unsigned int nalloc ) 119 119 { 120 120 psElemType elemType; 121 122 if ( in == NULL) {123 return psVectorAlloc(nalloc, type);124 }125 121 122 if ( in == NULL ) { 123 return psVectorAlloc( nalloc, type ); 124 } 125 126 126 elemType = in->type.type; 127 128 if ( in->nalloc == nalloc && elemType == type) {129 // it is proper size/type already130 return in;131 }132 127 128 if ( in->nalloc == nalloc && elemType == type ) { 129 // it is proper size/type already 130 return in; 131 } 132 133 133 // Invalid nalloc 134 if(nalloc < 1) { 135 psError(__func__, "Invalid value for nalloc (%d)\n", nalloc); 136 psFree(in); 137 return NULL; 138 } 139 140 141 in->data.V = psRealloc(in->data.V,nalloc*PSELEMTYPE_SIZEOF(type)); 142 143 in->n = 0; 134 if ( nalloc < 1 ) { 135 psError( __func__, "Invalid value for nalloc (%d)\n", nalloc ); 136 psFree( in ); 137 return NULL; 138 } 139 140 141 in->data.V = psRealloc( in->data.V, nalloc * PSELEMTYPE_SIZEOF( type ) ); 142 144 143 in->type.type = type; 145 144 in->nalloc = nalloc; 146 145 in->n = nalloc; 146 147 147 return in; 148 148 } 149 149 150 psVector *psVectorSort( psVector *restrict outVector, const psVector *restrict inVector)150 psVector *psVectorSort( psVector *restrict outVector, const psVector *restrict inVector ) 151 151 { 152 152 int inN = 0; … … 156 156 void *outVec = NULL; 157 157 psElemType inType = 0; 158 159 if (inVector == NULL) {160 psError(__func__, " : Line %d - Null input vector\n", __LINE__);161 return outVector;162 }163 158 159 if ( inVector == NULL ) { 160 psError( __func__, " : Line %d - Null input vector\n", __LINE__ ); 161 return outVector; 162 } 163 164 164 inType = inVector->type.type; 165 165 inN = inVector->n; 166 166 inVec = inVector->data.V; 167 elSize = PSELEMTYPE_SIZEOF( inType);168 169 if (outVector == NULL) {170 outVector = psVectorAlloc(inN, inType);171 outVector->n = inVector->n;172 }173 167 elSize = PSELEMTYPE_SIZEOF( inType ); 168 169 if ( outVector == NULL ) { 170 outVector = psVectorAlloc( inN, inType ); 171 outVector->n = inVector->n; 172 } 173 174 174 outN = outVector->n; 175 175 outVec = outVector->data.V; 176 177 if (inN != outN) {178 psError(__func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n", __LINE__,179 inN, outN);180 return outVector;181 }182 183 if (inType != outVector->type.type) {184 psError(__func__, " : Line %d - Input and output vectors are not same type: in=%d out=%d\n", __LINE__,185 inType, outVector->type.type);186 return outVector;187 }188 189 if (inN == 0) {190 psError(__func__, " : Line %d - No elements in use for input vector\n", __LINE__);191 return outVector;192 }193 194 if (outN == 0) {195 psError(__func__, " : Line %d - No elements in use for output vector\n", __LINE__);196 return outVector;197 }198 176 177 if ( inN != outN ) { 178 psError( __func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n", __LINE__, 179 inN, outN ); 180 return outVector; 181 } 182 183 if ( inType != outVector->type.type ) { 184 psError( __func__, " : Line %d - Input and output vectors are not same type: in=%d out=%d\n", __LINE__, 185 inType, outVector->type.type ); 186 return outVector; 187 } 188 189 if ( inN == 0 ) { 190 psError( __func__, " : Line %d - No elements in use for input vector\n", __LINE__ ); 191 return outVector; 192 } 193 194 if ( outN == 0 ) { 195 psError( __func__, " : Line %d - No elements in use for output vector\n", __LINE__ ); 196 return outVector; 197 } 198 199 199 // Copy input vector values into output vector 200 memcpy( outVec, inVec, elSize*outN);201 200 memcpy( outVec, inVec, elSize * outN ); 201 202 202 // Sort output vector 203 switch (inType) {204 case PS_TYPE_U8:205 qsort(outVec, inN, elSize, psCompareU8);206 break;207 case PS_TYPE_U16:208 qsort(outVec, inN, elSize, psCompareU16);209 break;210 case PS_TYPE_U32:211 qsort(outVec, inN, elSize, psCompareU32);212 break;213 case PS_TYPE_U64:214 qsort(outVec, inN, elSize, psCompareU64);215 break;216 case PS_TYPE_S8:217 qsort(outVec, inN, elSize, psCompareS8);218 break;219 case PS_TYPE_S16:220 qsort(outVec, inN, elSize, psCompareS16);221 break;222 case PS_TYPE_S32:223 qsort(outVec, inN, elSize, psCompareS32);224 break;225 case PS_TYPE_S64:226 qsort(outVec, inN, elSize, psCompareS64);227 break;228 case PS_TYPE_F32:229 qsort(outVec, inN, elSize, psCompareF32);230 break;231 case PS_TYPE_F64:232 qsort(outVec, inN, elSize, psCompareF64);233 break;234 default:235 psError(__func__, " : Line %d - Invalid psType\n", __LINE__);236 }237 203 switch ( inType ) { 204 case PS_TYPE_U8: 205 qsort( outVec, inN, elSize, psCompareU8 ); 206 break; 207 case PS_TYPE_U16: 208 qsort( outVec, inN, elSize, psCompareU16 ); 209 break; 210 case PS_TYPE_U32: 211 qsort( outVec, inN, elSize, psCompareU32 ); 212 break; 213 case PS_TYPE_U64: 214 qsort( outVec, inN, elSize, psCompareU64 ); 215 break; 216 case PS_TYPE_S8: 217 qsort( outVec, inN, elSize, psCompareS8 ); 218 break; 219 case PS_TYPE_S16: 220 qsort( outVec, inN, elSize, psCompareS16 ); 221 break; 222 case PS_TYPE_S32: 223 qsort( outVec, inN, elSize, psCompareS32 ); 224 break; 225 case PS_TYPE_S64: 226 qsort( outVec, inN, elSize, psCompareS64 ); 227 break; 228 case PS_TYPE_F32: 229 qsort( outVec, inN, elSize, psCompareF32 ); 230 break; 231 case PS_TYPE_F64: 232 qsort( outVec, inN, elSize, psCompareF64 ); 233 break; 234 default: 235 psError( __func__, " : Line %d - Invalid psType\n", __LINE__ ); 236 } 237 238 238 return outVector; 239 239 } … … 241 241 #define SORT_INDICES(TYPE) \ 242 242 for(i=0; i<inN; i++) { \ 243 for(j=0; j<inN; j++) { \244 diff = fabs((double)tmpVector->data.TYPE[i] - inVec[j]); \245 if(diff < FLT_EPSILON) { \246 outVec[i] = j; \247 break; \248 } \249 } \250 }251 252 psVector *psVectorSortIndex( psVector *restrict outVector, const psVector *restrict inVector)243 for(j=0; j<inN; j++) { \ 244 diff = fabs((double)tmpVector->data.TYPE[i] - inVec[j]); \ 245 if(diff < FLT_EPSILON) { \ 246 outVec[i] = j; \ 247 break; \ 248 } \ 249 } \ 250 } 251 252 psVector *psVectorSortIndex( psVector *restrict outVector, const psVector *restrict inVector ) 253 253 { 254 254 int inN = 0; … … 261 261 psVector *tmpVector = NULL; 262 262 psElemType inType = 0; 263 264 if (inVector == NULL) {265 psError(__func__, " : Line %d - Null input vector\n", __LINE__);266 return outVector;267 }268 263 264 if ( inVector == NULL ) { 265 psError( __func__, " : Line %d - Null input vector\n", __LINE__ ); 266 return outVector; 267 } 268 269 269 inN = inVector->n; 270 270 inVec = inVector->data.V; 271 271 inType = inVector->type.type; 272 273 if (outVector == NULL) {274 outVector = psVectorAlloc(inN, PS_TYPE_U32);275 outVector->n = inN;276 }277 272 273 if ( outVector == NULL ) { 274 outVector = psVectorAlloc( inN, PS_TYPE_U32 ); 275 outVector->n = inN; 276 } 277 278 278 outN = outVector->n; 279 279 outVec = outVector->data.V; 280 281 if (inN != outN) {282 psError(__func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n",283 __LINE__, inN, outN);284 return outVector;285 }286 287 if (outVector->type.type != PS_TYPE_U32) {288 psError(__func__, " : Line %d - Output vector is not of type U32: out=%d\n",289 __LINE__, outVector->type.type);290 return outVector;291 }292 293 tmpVector = psVectorAlloc( inN, inType);280 281 if ( inN != outN ) { 282 psError( __func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n", 283 __LINE__, inN, outN ); 284 return outVector; 285 } 286 287 if ( outVector->type.type != PS_TYPE_U32 ) { 288 psError( __func__, " : Line %d - Output vector is not of type U32: out=%d\n", 289 __LINE__, outVector->type.type ); 290 return outVector; 291 } 292 293 tmpVector = psVectorAlloc( inN, inType ); 294 294 tmpVector->n = inN; 295 tmpVector = psVectorSort( tmpVector, inVector);296 295 tmpVector = psVectorSort( tmpVector, inVector ); 296 297 297 // Sort output vector 298 switch (inType) {299 case PS_TYPE_U8:300 SORT_INDICES(U8);301 break;302 case PS_TYPE_U16:303 SORT_INDICES(U16);304 break;305 case PS_TYPE_U32:306 SORT_INDICES(U32);307 break;308 case PS_TYPE_U64:309 SORT_INDICES(U64);310 break;311 case PS_TYPE_S8:312 SORT_INDICES(S8);313 break;314 case PS_TYPE_S16:315 SORT_INDICES(S16);316 break;317 case PS_TYPE_S32:318 SORT_INDICES(S32);319 break;320 case PS_TYPE_S64:321 SORT_INDICES(S64);322 break;323 case PS_TYPE_F32:324 SORT_INDICES(F32);325 break;326 case PS_TYPE_F64:327 SORT_INDICES(F64);328 break;329 default:330 psError(__func__, " : Line %d - Invalid psType\n", __LINE__);331 }332 298 switch ( inType ) { 299 case PS_TYPE_U8: 300 SORT_INDICES( U8 ); 301 break; 302 case PS_TYPE_U16: 303 SORT_INDICES( U16 ); 304 break; 305 case PS_TYPE_U32: 306 SORT_INDICES( U32 ); 307 break; 308 case PS_TYPE_U64: 309 SORT_INDICES( U64 ); 310 break; 311 case PS_TYPE_S8: 312 SORT_INDICES( S8 ); 313 break; 314 case PS_TYPE_S16: 315 SORT_INDICES( S16 ); 316 break; 317 case PS_TYPE_S32: 318 SORT_INDICES( S32 ); 319 break; 320 case PS_TYPE_S64: 321 SORT_INDICES( S64 ); 322 break; 323 case PS_TYPE_F32: 324 SORT_INDICES( F32 ); 325 break; 326 case PS_TYPE_F64: 327 SORT_INDICES( F64 ); 328 break; 329 default: 330 psError( __func__, " : Line %d - Invalid psType\n", __LINE__ ); 331 } 332 333 333 // Free temp memory 334 psFree( tmpVector);335 334 psFree( tmpVector ); 335 336 336 return outVector; 337 337 } 338 338 339 static void vectorFree( psVector *restrict psVec)340 { 341 if ( psVec == NULL) {342 return;343 }344 345 psFree( psVec->data.V);346 } 339 static void vectorFree( psVector *restrict psVec ) 340 { 341 if ( psVec == NULL ) { 342 return ; 343 } 344 345 psFree( psVec->data.V ); 346 } -
trunk/psLib/src/mathtypes/psVector.c
r1305 r1360 1 1 /** @file psVector.c 2 *3 * @brief Contains support for basic vector types4 *5 * This file defines the basic type for a vector struct and functions useful6 * in manupulating vectors.7 *8 * @author Ross Harman, MHPCC9 *10 * @version $Revision: 1.16$ $Name: not supported by cvs2svn $11 * @date $Date: 2004-07-28 00:06:13$12 *13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii14 */2 * 3 * @brief Contains support for basic vector types 4 * 5 * This file defines the basic type for a vector struct and functions useful 6 * in manupulating vectors. 7 * 8 * @author Ross Harman, MHPCC 9 * 10 * @version $Revision: 1.17 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2004-07-31 02:28:10 $ 12 * 13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 14 */ 15 15 16 16 /******************************************************************************/ … … 54 54 /* FUNCTION IMPLEMENTATION - LOCAL */ 55 55 /*****************************************************************************/ 56 static void vectorFree( psVector *restrict psVec);56 static void vectorFree( psVector *restrict psVec ); 57 57 58 58 /*****************************************************************************/ 59 59 /* FUNCTION IMPLEMENTATION - PUBLIC */ 60 60 /*****************************************************************************/ 61 psVector* psVectorAlloc( unsigned int nalloc, psElemType elemType)62 { 63 psVector * psVec = NULL;61 psVector* psVectorAlloc( unsigned int nalloc, psElemType elemType ) 62 { 63 psVector * psVec = NULL; 64 64 int elementSize = 0; 65 65 66 66 // Invalid nalloc 67 if (nalloc < 1) {68 psError(__func__, "Invalid value for nalloc. nalloc: %d\n", nalloc);69 return NULL;70 }71 72 elementSize = PSELEMTYPE_SIZEOF( elemType);73 67 if ( nalloc < 1 ) { 68 psError( __func__, "Invalid value for nalloc. nalloc: %d\n", nalloc ); 69 return NULL; 70 } 71 72 elementSize = PSELEMTYPE_SIZEOF( elemType ); 73 74 74 // Create vector struct 75 psVec = ( psVector *)psAlloc(sizeof(psVector));76 p_psMemSetDeallocator( psVec,(psFreeFcn)vectorFree);77 75 psVec = ( psVector * ) psAlloc( sizeof( psVector ) ); 76 p_psMemSetDeallocator( psVec, ( psFreeFcn ) vectorFree ); 77 78 78 psVec->type.dimen = PS_DIMEN_VECTOR; 79 79 psVec->type.type = elemType; 80 80 psVec->nalloc = nalloc; 81 81 psVec->n = nalloc; 82 82 83 83 // Create vector data array 84 psVec->data.V = psAlloc( nalloc*elementSize);85 84 psVec->data.V = psAlloc( nalloc * elementSize ); 85 86 86 return psVec; 87 87 } 88 88 89 psVector *psVectorRealloc( unsigned int nalloc, psVector *restrict in)89 psVector *psVectorRealloc( unsigned int nalloc, psVector *restrict in ) 90 90 { 91 91 int elementSize = 0; 92 92 psElemType elemType; 93 93 94 94 // Invalid nalloc 95 if (nalloc < 1) {96 psError(__func__, "Invalid value for realloc (%d)\n", nalloc);97 return NULL;98 }99 100 if (in == NULL) {101 psError(__func__, "Null input vector\n");102 return NULL;103 } else if(in->nalloc != nalloc) { // No need to realloc to same size104 elemType = in->type.type;105 elementSize = PSELEMTYPE_SIZEOF(elemType);106 if(nalloc < in->n) {107 in->n = nalloc;108 }109 110 // Realloc after decrementation to avoid accessing freed array elements111 in->data.V = psRealloc(in->data.V,nalloc*elementSize);112 in->nalloc = nalloc;113 }114 95 if ( nalloc < 1 ) { 96 psError( __func__, "Invalid value for realloc (%d)\n", nalloc ); 97 return NULL; 98 } 99 100 if ( in == NULL ) { 101 psError( __func__, "Null input vector\n" ); 102 return NULL; 103 } else if ( in->nalloc != nalloc ) { // No need to realloc to same size 104 elemType = in->type.type; 105 elementSize = PSELEMTYPE_SIZEOF( elemType ); 106 if ( nalloc < in->n ) { 107 in->n = nalloc; 108 } 109 110 // Realloc after decrementation to avoid accessing freed array elements 111 in->data.V = psRealloc( in->data.V, nalloc * elementSize ); 112 in->nalloc = nalloc; 113 } 114 115 115 return in; 116 116 } 117 117 118 psVector *psVectorRecycle( psVector *restrict in, psElemType type, unsigned int nalloc)118 psVector *psVectorRecycle( psVector *restrict in, psElemType type, unsigned int nalloc ) 119 119 { 120 120 psElemType elemType; 121 122 if ( in == NULL) {123 return psVectorAlloc(nalloc, type);124 }125 121 122 if ( in == NULL ) { 123 return psVectorAlloc( nalloc, type ); 124 } 125 126 126 elemType = in->type.type; 127 128 if ( in->nalloc == nalloc && elemType == type) {129 // it is proper size/type already130 return in;131 }132 127 128 if ( in->nalloc == nalloc && elemType == type ) { 129 // it is proper size/type already 130 return in; 131 } 132 133 133 // Invalid nalloc 134 if(nalloc < 1) { 135 psError(__func__, "Invalid value for nalloc (%d)\n", nalloc); 136 psFree(in); 137 return NULL; 138 } 139 140 141 in->data.V = psRealloc(in->data.V,nalloc*PSELEMTYPE_SIZEOF(type)); 142 143 in->n = 0; 134 if ( nalloc < 1 ) { 135 psError( __func__, "Invalid value for nalloc (%d)\n", nalloc ); 136 psFree( in ); 137 return NULL; 138 } 139 140 141 in->data.V = psRealloc( in->data.V, nalloc * PSELEMTYPE_SIZEOF( type ) ); 142 144 143 in->type.type = type; 145 144 in->nalloc = nalloc; 146 145 in->n = nalloc; 146 147 147 return in; 148 148 } 149 149 150 psVector *psVectorSort( psVector *restrict outVector, const psVector *restrict inVector)150 psVector *psVectorSort( psVector *restrict outVector, const psVector *restrict inVector ) 151 151 { 152 152 int inN = 0; … … 156 156 void *outVec = NULL; 157 157 psElemType inType = 0; 158 159 if (inVector == NULL) {160 psError(__func__, " : Line %d - Null input vector\n", __LINE__);161 return outVector;162 }163 158 159 if ( inVector == NULL ) { 160 psError( __func__, " : Line %d - Null input vector\n", __LINE__ ); 161 return outVector; 162 } 163 164 164 inType = inVector->type.type; 165 165 inN = inVector->n; 166 166 inVec = inVector->data.V; 167 elSize = PSELEMTYPE_SIZEOF( inType);168 169 if (outVector == NULL) {170 outVector = psVectorAlloc(inN, inType);171 outVector->n = inVector->n;172 }173 167 elSize = PSELEMTYPE_SIZEOF( inType ); 168 169 if ( outVector == NULL ) { 170 outVector = psVectorAlloc( inN, inType ); 171 outVector->n = inVector->n; 172 } 173 174 174 outN = outVector->n; 175 175 outVec = outVector->data.V; 176 177 if (inN != outN) {178 psError(__func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n", __LINE__,179 inN, outN);180 return outVector;181 }182 183 if (inType != outVector->type.type) {184 psError(__func__, " : Line %d - Input and output vectors are not same type: in=%d out=%d\n", __LINE__,185 inType, outVector->type.type);186 return outVector;187 }188 189 if (inN == 0) {190 psError(__func__, " : Line %d - No elements in use for input vector\n", __LINE__);191 return outVector;192 }193 194 if (outN == 0) {195 psError(__func__, " : Line %d - No elements in use for output vector\n", __LINE__);196 return outVector;197 }198 176 177 if ( inN != outN ) { 178 psError( __func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n", __LINE__, 179 inN, outN ); 180 return outVector; 181 } 182 183 if ( inType != outVector->type.type ) { 184 psError( __func__, " : Line %d - Input and output vectors are not same type: in=%d out=%d\n", __LINE__, 185 inType, outVector->type.type ); 186 return outVector; 187 } 188 189 if ( inN == 0 ) { 190 psError( __func__, " : Line %d - No elements in use for input vector\n", __LINE__ ); 191 return outVector; 192 } 193 194 if ( outN == 0 ) { 195 psError( __func__, " : Line %d - No elements in use for output vector\n", __LINE__ ); 196 return outVector; 197 } 198 199 199 // Copy input vector values into output vector 200 memcpy( outVec, inVec, elSize*outN);201 200 memcpy( outVec, inVec, elSize * outN ); 201 202 202 // Sort output vector 203 switch (inType) {204 case PS_TYPE_U8:205 qsort(outVec, inN, elSize, psCompareU8);206 break;207 case PS_TYPE_U16:208 qsort(outVec, inN, elSize, psCompareU16);209 break;210 case PS_TYPE_U32:211 qsort(outVec, inN, elSize, psCompareU32);212 break;213 case PS_TYPE_U64:214 qsort(outVec, inN, elSize, psCompareU64);215 break;216 case PS_TYPE_S8:217 qsort(outVec, inN, elSize, psCompareS8);218 break;219 case PS_TYPE_S16:220 qsort(outVec, inN, elSize, psCompareS16);221 break;222 case PS_TYPE_S32:223 qsort(outVec, inN, elSize, psCompareS32);224 break;225 case PS_TYPE_S64:226 qsort(outVec, inN, elSize, psCompareS64);227 break;228 case PS_TYPE_F32:229 qsort(outVec, inN, elSize, psCompareF32);230 break;231 case PS_TYPE_F64:232 qsort(outVec, inN, elSize, psCompareF64);233 break;234 default:235 psError(__func__, " : Line %d - Invalid psType\n", __LINE__);236 }237 203 switch ( inType ) { 204 case PS_TYPE_U8: 205 qsort( outVec, inN, elSize, psCompareU8 ); 206 break; 207 case PS_TYPE_U16: 208 qsort( outVec, inN, elSize, psCompareU16 ); 209 break; 210 case PS_TYPE_U32: 211 qsort( outVec, inN, elSize, psCompareU32 ); 212 break; 213 case PS_TYPE_U64: 214 qsort( outVec, inN, elSize, psCompareU64 ); 215 break; 216 case PS_TYPE_S8: 217 qsort( outVec, inN, elSize, psCompareS8 ); 218 break; 219 case PS_TYPE_S16: 220 qsort( outVec, inN, elSize, psCompareS16 ); 221 break; 222 case PS_TYPE_S32: 223 qsort( outVec, inN, elSize, psCompareS32 ); 224 break; 225 case PS_TYPE_S64: 226 qsort( outVec, inN, elSize, psCompareS64 ); 227 break; 228 case PS_TYPE_F32: 229 qsort( outVec, inN, elSize, psCompareF32 ); 230 break; 231 case PS_TYPE_F64: 232 qsort( outVec, inN, elSize, psCompareF64 ); 233 break; 234 default: 235 psError( __func__, " : Line %d - Invalid psType\n", __LINE__ ); 236 } 237 238 238 return outVector; 239 239 } … … 241 241 #define SORT_INDICES(TYPE) \ 242 242 for(i=0; i<inN; i++) { \ 243 for(j=0; j<inN; j++) { \244 diff = fabs((double)tmpVector->data.TYPE[i] - inVec[j]); \245 if(diff < FLT_EPSILON) { \246 outVec[i] = j; \247 break; \248 } \249 } \250 }251 252 psVector *psVectorSortIndex( psVector *restrict outVector, const psVector *restrict inVector)243 for(j=0; j<inN; j++) { \ 244 diff = fabs((double)tmpVector->data.TYPE[i] - inVec[j]); \ 245 if(diff < FLT_EPSILON) { \ 246 outVec[i] = j; \ 247 break; \ 248 } \ 249 } \ 250 } 251 252 psVector *psVectorSortIndex( psVector *restrict outVector, const psVector *restrict inVector ) 253 253 { 254 254 int inN = 0; … … 261 261 psVector *tmpVector = NULL; 262 262 psElemType inType = 0; 263 264 if (inVector == NULL) {265 psError(__func__, " : Line %d - Null input vector\n", __LINE__);266 return outVector;267 }268 263 264 if ( inVector == NULL ) { 265 psError( __func__, " : Line %d - Null input vector\n", __LINE__ ); 266 return outVector; 267 } 268 269 269 inN = inVector->n; 270 270 inVec = inVector->data.V; 271 271 inType = inVector->type.type; 272 273 if (outVector == NULL) {274 outVector = psVectorAlloc(inN, PS_TYPE_U32);275 outVector->n = inN;276 }277 272 273 if ( outVector == NULL ) { 274 outVector = psVectorAlloc( inN, PS_TYPE_U32 ); 275 outVector->n = inN; 276 } 277 278 278 outN = outVector->n; 279 279 outVec = outVector->data.V; 280 281 if (inN != outN) {282 psError(__func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n",283 __LINE__, inN, outN);284 return outVector;285 }286 287 if (outVector->type.type != PS_TYPE_U32) {288 psError(__func__, " : Line %d - Output vector is not of type U32: out=%d\n",289 __LINE__, outVector->type.type);290 return outVector;291 }292 293 tmpVector = psVectorAlloc( inN, inType);280 281 if ( inN != outN ) { 282 psError( __func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n", 283 __LINE__, inN, outN ); 284 return outVector; 285 } 286 287 if ( outVector->type.type != PS_TYPE_U32 ) { 288 psError( __func__, " : Line %d - Output vector is not of type U32: out=%d\n", 289 __LINE__, outVector->type.type ); 290 return outVector; 291 } 292 293 tmpVector = psVectorAlloc( inN, inType ); 294 294 tmpVector->n = inN; 295 tmpVector = psVectorSort( tmpVector, inVector);296 295 tmpVector = psVectorSort( tmpVector, inVector ); 296 297 297 // Sort output vector 298 switch (inType) {299 case PS_TYPE_U8:300 SORT_INDICES(U8);301 break;302 case PS_TYPE_U16:303 SORT_INDICES(U16);304 break;305 case PS_TYPE_U32:306 SORT_INDICES(U32);307 break;308 case PS_TYPE_U64:309 SORT_INDICES(U64);310 break;311 case PS_TYPE_S8:312 SORT_INDICES(S8);313 break;314 case PS_TYPE_S16:315 SORT_INDICES(S16);316 break;317 case PS_TYPE_S32:318 SORT_INDICES(S32);319 break;320 case PS_TYPE_S64:321 SORT_INDICES(S64);322 break;323 case PS_TYPE_F32:324 SORT_INDICES(F32);325 break;326 case PS_TYPE_F64:327 SORT_INDICES(F64);328 break;329 default:330 psError(__func__, " : Line %d - Invalid psType\n", __LINE__);331 }332 298 switch ( inType ) { 299 case PS_TYPE_U8: 300 SORT_INDICES( U8 ); 301 break; 302 case PS_TYPE_U16: 303 SORT_INDICES( U16 ); 304 break; 305 case PS_TYPE_U32: 306 SORT_INDICES( U32 ); 307 break; 308 case PS_TYPE_U64: 309 SORT_INDICES( U64 ); 310 break; 311 case PS_TYPE_S8: 312 SORT_INDICES( S8 ); 313 break; 314 case PS_TYPE_S16: 315 SORT_INDICES( S16 ); 316 break; 317 case PS_TYPE_S32: 318 SORT_INDICES( S32 ); 319 break; 320 case PS_TYPE_S64: 321 SORT_INDICES( S64 ); 322 break; 323 case PS_TYPE_F32: 324 SORT_INDICES( F32 ); 325 break; 326 case PS_TYPE_F64: 327 SORT_INDICES( F64 ); 328 break; 329 default: 330 psError( __func__, " : Line %d - Invalid psType\n", __LINE__ ); 331 } 332 333 333 // Free temp memory 334 psFree( tmpVector);335 334 psFree( tmpVector ); 335 336 336 return outVector; 337 337 } 338 338 339 static void vectorFree( psVector *restrict psVec)340 { 341 if ( psVec == NULL) {342 return;343 }344 345 psFree( psVec->data.V);346 } 339 static void vectorFree( psVector *restrict psVec ) 340 { 341 if ( psVec == NULL ) { 342 return ; 343 } 344 345 psFree( psVec->data.V ); 346 } -
trunk/psLib/src/sys/psMemory.c
r1240 r1360 1 1 /** @file psMemory.c 2 *3 * @brief Contains the definitions for the memory management system4 *5 * psMemory.h has additional information and documentation of the routines found in this file.6 *7 * @author Robert DeSonia, MHPCC8 * @author Robert Lupton, Princeton University9 *10 * @version $Revision: 1.29$ $Name: not supported by cvs2svn $11 * @date $Date: 2004-07-19 20:45:53$12 *13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii14 */2 * 3 * @brief Contains the definitions for the memory management system 4 * 5 * psMemory.h has additional information and documentation of the routines found in this file. 6 * 7 * @author Robert DeSonia, MHPCC 8 * @author Robert Lupton, Princeton University 9 * 10 * @version $Revision: 1.30 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2004-07-31 02:28:10 $ 12 * 13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 14 */ 15 15 16 16 #define PS_ALLOW_MALLOC // we're allowed to call malloc() … … 30 30 #define P_PS_LARGE_BLOCK_SIZE 65536 // size where under, we try to recycle 31 31 32 static int checkMemBlock( const psMemBlock *m, const char* funcName);32 static int checkMemBlock( const psMemBlock *m, const char* funcName ); 33 33 static psMemBlock *lastMemBlockAllocated = NULL; 34 34 static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER; … … 38 38 39 39 static int recycleBins = 13; 40 static int recycleBinSize[14] = {8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,P_PS_LARGE_BLOCK_SIZE}; 40 static int recycleBinSize[ 14 ] = 41 { 42 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, P_PS_LARGE_BLOCK_SIZE 43 }; 41 44 // N.B. recycleBinSize should be terminated by P_PS_LARGE_BLOCK_SIZE (simplifies search loops) 42 static psMemBlock* recycleMemBlockList[13] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; 43 45 static psMemBlock* recycleMemBlockList[ 13 ] = 46 { 47 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 48 }; 49 44 50 #ifdef PS_MEM_DEBUG 45 51 static psMemBlock* deadBlockList; // a place to put dead memBlocks in debug mode. … … 53 59 * Default memExhausted callback. 54 60 */ 55 static void *memExhaustedCallbackDefault( size_t size)56 { 57 void * ptr = NULL;58 59 pthread_mutex_lock( &recycleMemBlockListMutex);60 int level =recycleBins-1;61 while ( level >= 0 && ptr == NULL) {62 while (recycleMemBlockList[level] != NULL && ptr == NULL) {63 psMemBlock* old = recycleMemBlockList[level];64 recycleMemBlockList[level] = recycleMemBlockList[level]->nextBlock;65 free(old);66 ptr = malloc(size);67 }68 level--;69 }70 pthread_mutex_unlock( &recycleMemBlockListMutex);71 61 static void *memExhaustedCallbackDefault( size_t size ) 62 { 63 void * ptr = NULL; 64 65 pthread_mutex_lock( &recycleMemBlockListMutex ); 66 int level = recycleBins - 1; 67 while ( level >= 0 && ptr == NULL ) { 68 while ( recycleMemBlockList[ level ] != NULL && ptr == NULL ) { 69 psMemBlock * old = recycleMemBlockList[ level ]; 70 recycleMemBlockList[ level ] = recycleMemBlockList[ level ] ->nextBlock; 71 free( old ); 72 ptr = malloc( size ); 73 } 74 level--; 75 } 76 pthread_mutex_unlock( &recycleMemBlockListMutex ); 77 72 78 return ptr; 73 79 } … … 75 81 static psMemExhaustedCallback memExhaustedCallback = memExhaustedCallbackDefault; 76 82 77 psMemExhaustedCallback psMemExhaustedCallbackSet( psMemExhaustedCallback func)83 psMemExhaustedCallback psMemExhaustedCallbackSet( psMemExhaustedCallback func ) 78 84 { 79 85 psMemExhaustedCallback old = memExhaustedCallback; 80 81 if ( func != NULL) {82 memExhaustedCallback = func;83 } else {84 memExhaustedCallback = memExhaustedCallbackDefault;85 }86 86 87 if ( func != NULL ) { 88 memExhaustedCallback = func; 89 } else { 90 memExhaustedCallback = memExhaustedCallbackDefault; 91 } 92 87 93 return old; 88 94 } 89 95 90 static void memProblemCallbackDefault( const psMemBlock *ptr,91 const char *file, int lineno)92 { 93 if ( ptr->refCounter < 1) {94 psError(__func__,95 "Block %ld allocated at %s:%d freed more than once at %s:%d\n",96 ptr->id, ptr->file, ptr->lineno, file, lineno);97 }98 99 if ( lineno > 0) {100 psAbort(__func__, "Detected a problem in the memory system at %s:%d", file, lineno);101 }96 static void memProblemCallbackDefault( const psMemBlock *ptr, 97 const char *file, int lineno ) 98 { 99 if ( ptr->refCounter < 1 ) { 100 psError( __func__, 101 "Block %ld allocated at %s:%d freed more than once at %s:%d\n", 102 ptr->id, ptr->file, ptr->lineno, file, lineno ); 103 } 104 105 if ( lineno > 0 ) { 106 psAbort( __func__, "Detected a problem in the memory system at %s:%d", file, lineno ); 107 } 102 108 } 103 109 static psMemProblemCallback memProblemCallback = memProblemCallbackDefault; 104 110 105 psMemProblemCallback psMemProblemCallbackSet( psMemProblemCallback func)111 psMemProblemCallback psMemProblemCallbackSet( psMemProblemCallback func ) 106 112 { 107 113 psMemProblemCallback old = memProblemCallback; 108 109 if ( func != NULL) {110 memProblemCallback = func;111 } else {112 memProblemCallback = memProblemCallbackDefault;113 }114 114 115 if ( func != NULL ) { 116 memProblemCallback = func; 117 } else { 118 memProblemCallback = memProblemCallbackDefault; 119 } 120 115 121 return old; 116 122 } … … 123 129 psMemoryId p_psMemFreeID = 0; // notify user this block is freed 124 130 125 psMemoryId psMemAllocateCallbackSetID( psMemoryId id)131 psMemoryId psMemAllocateCallbackSetID( psMemoryId id ) 126 132 { 127 133 psMemoryId old = p_psMemAllocateID; 128 134 p_psMemAllocateID = id; 129 135 130 136 return old; 131 137 } 132 138 133 psMemoryId psMemFreeCallbackSetID( psMemoryId id)139 psMemoryId psMemFreeCallbackSetID( psMemoryId id ) 134 140 { 135 141 psMemoryId old = p_psMemFreeID; 136 142 p_psMemFreeID = id; 137 143 138 144 return old; 139 145 } … … 145 151 * isn't resignalled) 146 152 */ 147 static psMemoryId memAllocateCallbackDefault( const psMemBlock *ptr)153 static psMemoryId memAllocateCallbackDefault( const psMemBlock *ptr ) 148 154 { 149 155 static psMemoryId incr = 0; // "p_psMemAllocateID += incr" 150 156 151 157 return incr; 152 158 } 153 159 154 static psMemoryId memFreeCallbackDefault( const psMemBlock *ptr)160 static psMemoryId memFreeCallbackDefault( const psMemBlock *ptr ) 155 161 { 156 162 static psMemoryId incr = 0; // "p_psMemFreeID += incr" 157 163 158 164 return incr; 159 165 } … … 165 171 static psMemFreeCallback memFreeCallback = memFreeCallbackDefault; 166 172 167 psMemAllocateCallback psMemAllocateCallbackSet( psMemAllocateCallback func)173 psMemAllocateCallback psMemAllocateCallbackSet( psMemAllocateCallback func ) 168 174 { 169 175 psMemFreeCallback old = memAllocateCallback; 170 171 if ( func != NULL) {172 memAllocateCallback =func;173 } else {174 memAllocateCallback = memAllocateCallbackDefault;175 }176 176 177 if ( func != NULL ) { 178 memAllocateCallback = func; 179 } else { 180 memAllocateCallback = memAllocateCallbackDefault; 181 } 182 177 183 return old; 178 184 } 179 185 180 psMemFreeCallback psMemFreeCallbackSet( psMemFreeCallback func)186 psMemFreeCallback psMemFreeCallbackSet( psMemFreeCallback func ) 181 187 { 182 188 psMemFreeCallback old = memFreeCallback; 183 184 if ( func != NULL) {185 memFreeCallback = func;186 } else {187 memFreeCallback = memFreeCallbackDefault;188 }189 189 190 if ( func != NULL ) { 191 memFreeCallback = func; 192 } else { 193 memFreeCallback = memFreeCallbackDefault; 194 } 195 190 196 return old; 191 197 } … … 194 200 * Return memory ID counter for next block to be allocated 195 201 */ 196 psMemoryId psMemGetId( void)202 psMemoryId psMemGetId( void ) 197 203 { 198 204 psMemoryId id; 199 pthread_mutex_lock( &memIdMutex);205 pthread_mutex_lock( &memIdMutex ); 200 206 id = memid + 1; 201 pthread_mutex_unlock( &memIdMutex);202 207 pthread_mutex_unlock( &memIdMutex ); 208 203 209 return id; 204 210 } … … 210 216 */ 211 217 212 static int checkMemBlock( const psMemBlock *m, const char* funcName)218 static int checkMemBlock( const psMemBlock *m, const char* funcName ) 213 219 { 214 220 // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked, 215 221 // we shouldn't call such things as p_psAlloc/p_psFree here. 216 217 if ( m == NULL) {218 psError(funcName,"Memory Corruption: NULL memory block found.");219 return 1;220 }221 222 if ( m->refCounter == 0) {223 // using an unreferenced block of memory, are you?224 psError(__func__,"Memory Corruption: memory block %ld was freed but still used.",225 m->id);226 return 1;227 }228 229 if ( m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC) {230 psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer underflow)",231 m->id);232 return 1;233 }234 if ( *(void**)((int8_t*)(m+1)+m->userMemorySize) != P_PS_MEMMAGIC) {235 psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)",236 m->id);237 return 1;238 }239 222 223 if ( m == NULL ) { 224 psError( funcName, "Memory Corruption: NULL memory block found." ); 225 return 1; 226 } 227 228 if ( m->refCounter == 0 ) { 229 // using an unreferenced block of memory, are you? 230 psError( __func__, "Memory Corruption: memory block %ld was freed but still used.", 231 m->id ); 232 return 1; 233 } 234 235 if ( m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC ) { 236 psError( funcName, "Memory Corruption: memory block %ld is corrupted (buffer underflow)", 237 m->id ); 238 return 1; 239 } 240 if ( *( void** ) ( ( int8_t* ) ( m + 1 ) + m->userMemorySize ) != P_PS_MEMMAGIC ) { 241 psError( funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)", 242 m->id ); 243 return 1; 244 } 245 240 246 return 0; 241 247 } 242 248 243 int psMemCheckCorruption( bool abort_on_error)249 int psMemCheckCorruption( bool abort_on_error ) 244 250 { 245 251 int nbad = 0; // number of bad blocks 246 252 247 253 // get exclusive access to the memBlock list to avoid it changing on us while we use it. 248 pthread_mutex_lock( &memBlockListMutex);249 250 for ( psMemBlock* iter=lastMemBlockAllocated; iter != NULL; iter=iter->nextBlock) {251 if (checkMemBlock(iter, __func__)) {252 nbad++;253 254 memProblemCallback(iter, __func__, __LINE__);255 256 if (abort_on_error) {257 // release the lock on the memblock list258 pthread_mutex_unlock(&memBlockListMutex);259 psAbort(__func__, "Detected memory corruption");260 return nbad;261 }262 }263 }264 254 pthread_mutex_lock( &memBlockListMutex ); 255 256 for ( psMemBlock * iter = lastMemBlockAllocated; iter != NULL; iter = iter->nextBlock ) { 257 if ( checkMemBlock( iter, __func__ ) ) { 258 nbad++; 259 260 memProblemCallback( iter, __func__, __LINE__ ); 261 262 if ( abort_on_error ) { 263 // release the lock on the memblock list 264 pthread_mutex_unlock( &memBlockListMutex ); 265 psAbort( __func__, "Detected memory corruption" ); 266 return nbad; 267 } 268 } 269 } 270 265 271 // release the lock on the memblock list 266 pthread_mutex_unlock( &memBlockListMutex);272 pthread_mutex_unlock( &memBlockListMutex ); 267 273 return nbad; 268 274 } 269 275 270 void *p_psAlloc( size_t size, const char *file, int lineno)271 { 272 273 psMemBlock * ptr = NULL;274 276 void *p_psAlloc( size_t size, const char *file, int lineno ) 277 { 278 279 psMemBlock * ptr = NULL; 280 275 281 // memory is of the size I want to bother recycling? 276 if ( size < P_PS_LARGE_BLOCK_SIZE) {277 // find the bin we need.278 int level = 0;279 while (size > recycleBinSize[level]) {280 level++;281 }282 // Are we in one of the bins283 if (level<recycleBins) {284 285 size = recycleBinSize[level]; // round-up size to next sized bin.286 287 pthread_mutex_lock(&recycleMemBlockListMutex);288 289 if (recycleMemBlockList[level] != NULL) {290 ptr = recycleMemBlockList[level];291 recycleMemBlockList[level] = ptr->nextBlock;292 if (recycleMemBlockList[level] != NULL) {293 recycleMemBlockList[level]->previousBlock = NULL;294 }295 size = ptr->userMemorySize;296 }297 298 pthread_mutex_unlock(&recycleMemBlockListMutex);299 }300 }301 302 if ( ptr == NULL) {303 ptr = malloc(sizeof(psMemBlock) + size + sizeof(void*));304 305 if (ptr == NULL) {306 ptr = memExhaustedCallback(size);307 if (ptr == NULL) {308 psAbort(__func__, "Failed to allocate %u bytes at %s:%d",309 size, file, lineno);310 }311 }312 313 ptr->startblock = P_PS_MEMMAGIC;314 ptr->endblock = P_PS_MEMMAGIC;315 ptr->userMemorySize = size;316 pthread_mutex_init(&ptr->refCounterMutex, NULL);317 }318 282 if ( size < P_PS_LARGE_BLOCK_SIZE ) { 283 // find the bin we need. 284 int level = 0; 285 while ( size > recycleBinSize[ level ] ) { 286 level++; 287 } 288 // Are we in one of the bins 289 if ( level < recycleBins ) { 290 291 size = recycleBinSize[ level ]; // round-up size to next sized bin. 292 293 pthread_mutex_lock( &recycleMemBlockListMutex ); 294 295 if ( recycleMemBlockList[ level ] != NULL ) { 296 ptr = recycleMemBlockList[ level ]; 297 recycleMemBlockList[ level ] = ptr->nextBlock; 298 if ( recycleMemBlockList[ level ] != NULL ) { 299 recycleMemBlockList[ level ] ->previousBlock = NULL; 300 } 301 size = ptr->userMemorySize; 302 } 303 304 pthread_mutex_unlock( &recycleMemBlockListMutex ); 305 } 306 } 307 308 if ( ptr == NULL ) { 309 ptr = malloc( sizeof( psMemBlock ) + size + sizeof( void* ) ); 310 311 if ( ptr == NULL ) { 312 ptr = memExhaustedCallback( size ); 313 if ( ptr == NULL ) { 314 psAbort( __func__, "Failed to allocate %u bytes at %s:%d", 315 size, file, lineno ); 316 } 317 } 318 319 ptr->startblock = P_PS_MEMMAGIC; 320 ptr->endblock = P_PS_MEMMAGIC; 321 ptr->userMemorySize = size; 322 pthread_mutex_init( &ptr->refCounterMutex, NULL ); 323 } 324 319 325 // increment the memory id safely. 320 pthread_mutex_lock( &memBlockListMutex);321 *( psMemoryId*)&ptr->id = ++memid;322 pthread_mutex_unlock( &memBlockListMutex);323 326 pthread_mutex_lock( &memBlockListMutex ); 327 *( psMemoryId* ) & ptr->id = ++memid; 328 pthread_mutex_unlock( &memBlockListMutex ); 329 324 330 ptr->file = file; 325 331 ptr->freeFcn = NULL; 326 *( unsigned int*)&ptr->lineno = lineno;327 *( void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;332 *( unsigned int* ) & ptr->lineno = lineno; 333 *( void** ) ( ( int8_t* ) ( ptr + 1 ) + size ) = P_PS_MEMMAGIC; 328 334 ptr->previousBlock = NULL; 329 335 330 336 ptr->refCounter = 1; // one user so far 331 337 332 338 // need exclusive access of the memory block list now... 333 pthread_mutex_lock( &memBlockListMutex);334 339 pthread_mutex_lock( &memBlockListMutex ); 340 335 341 // insert the new block to the front of the memBlock linked-list 336 342 ptr->nextBlock = lastMemBlockAllocated; 337 if ( ptr->nextBlock != NULL) {338 ptr->nextBlock->previousBlock = ptr;339 }343 if ( ptr->nextBlock != NULL ) { 344 ptr->nextBlock->previousBlock = ptr; 345 } 340 346 lastMemBlockAllocated = ptr; 341 342 pthread_mutex_unlock( &memBlockListMutex);343 347 348 pthread_mutex_unlock( &memBlockListMutex ); 349 344 350 // Did the user ask to be informed about this allocation? 345 if ( ptr->id == p_psMemAllocateID) {346 p_psMemAllocateID += memAllocateCallback(ptr);347 }348 351 if ( ptr->id == p_psMemAllocateID ) { 352 p_psMemAllocateID += memAllocateCallback( ptr ); 353 } 354 349 355 // And return the user the memory that they allocated 350 356 return ptr + 1; // user memory 351 357 } 352 358 353 void *p_psRealloc( void *vptr, size_t size, const char *file, int lineno)354 { 355 if ( vptr == NULL) {356 return p_psAlloc(size, file, lineno);357 } else {358 psMemBlock *ptr = ((psMemBlock *)vptr) - 1;359 bool isBlockLast = false;360 361 if (checkMemBlock(ptr, __func__) != 0) {362 memProblemCallback(ptr, file, lineno);363 psAbort(file,"Realloc detected a memory corruption (id %ld @ %s:%d).",364 ptr->id,ptr->file,ptr->lineno);365 }366 367 pthread_mutex_lock(&memBlockListMutex);368 369 isBlockLast = (ptr == lastMemBlockAllocated);370 371 ptr = (psMemBlock*)realloc(ptr, sizeof(psMemBlock) + size + sizeof(void*));372 373 if (ptr == NULL) {374 psAbort(__func__, "Failed to reallocate %ld bytes at %s:%d",375 size, file, lineno);376 }377 378 ptr->userMemorySize = size;379 *(void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;380 381 if (isBlockLast) {382 lastMemBlockAllocated = ptr;383 }384 385 // the block location may have changed, so fix the linked list addresses.386 if (ptr->nextBlock != NULL) {387 ptr->nextBlock->previousBlock = ptr;388 }389 if (ptr->previousBlock != NULL) {390 ptr->previousBlock->nextBlock = ptr;391 }392 393 pthread_mutex_unlock(&memBlockListMutex);394 395 // Did the user ask to be informed about this allocation?396 if (ptr->id == p_psMemAllocateID) {397 p_psMemAllocateID += memAllocateCallback(ptr);398 }399 400 return ptr + 1; // usr memory401 }402 } 403 404 void p_psFree( void *vptr, const char *file, int lineno)405 { 406 ( void)p_psMemDecrRefCounter(vptr,file,lineno); // this handles the free, if required.359 void *p_psRealloc( void *vptr, size_t size, const char *file, int lineno ) 360 { 361 if ( vptr == NULL ) { 362 return p_psAlloc( size, file, lineno ); 363 } else { 364 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 365 bool isBlockLast = false; 366 367 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 368 memProblemCallback( ptr, file, lineno ); 369 psAbort( file, "Realloc detected a memory corruption (id %ld @ %s:%d).", 370 ptr->id, ptr->file, ptr->lineno ); 371 } 372 373 pthread_mutex_lock( &memBlockListMutex ); 374 375 isBlockLast = ( ptr == lastMemBlockAllocated ); 376 377 ptr = ( psMemBlock* ) realloc( ptr, sizeof( psMemBlock ) + size + sizeof( void* ) ); 378 379 if ( ptr == NULL ) { 380 psAbort( __func__, "Failed to reallocate %ld bytes at %s:%d", 381 size, file, lineno ); 382 } 383 384 ptr->userMemorySize = size; 385 *( void** ) ( ( int8_t* ) ( ptr + 1 ) + size ) = P_PS_MEMMAGIC; 386 387 if ( isBlockLast ) { 388 lastMemBlockAllocated = ptr; 389 } 390 391 // the block location may have changed, so fix the linked list addresses. 392 if ( ptr->nextBlock != NULL ) { 393 ptr->nextBlock->previousBlock = ptr; 394 } 395 if ( ptr->previousBlock != NULL ) { 396 ptr->previousBlock->nextBlock = ptr; 397 } 398 399 pthread_mutex_unlock( &memBlockListMutex ); 400 401 // Did the user ask to be informed about this allocation? 402 if ( ptr->id == p_psMemAllocateID ) { 403 p_psMemAllocateID += memAllocateCallback( ptr ); 404 } 405 406 return ptr + 1; // usr memory 407 } 408 } 409 410 void p_psFree( void *vptr, const char *file, int lineno ) 411 { 412 ( void ) p_psMemDecrRefCounter( vptr, file, lineno ); // this handles the free, if required. 407 413 } 408 414 … … 410 416 * Check for memory leaks. 411 417 */ 412 int psMemCheckLeaks( psMemoryId id0,psMemBlock ***arr,FILE *fd)418 int psMemCheckLeaks( psMemoryId id0, psMemBlock ***arr, FILE *fd ) 413 419 { 414 420 int nleak = 0; 415 421 int j = 0; 416 422 psMemBlock* topBlock = lastMemBlockAllocated; 417 418 pthread_mutex_lock( &memBlockListMutex);419 420 for ( psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) {421 if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) {422 nleak++;423 424 if (fd != NULL) {425 if (nleak == 1) {426 fprintf(fd, " %20s:line ID\n", "file");427 }428 429 fprintf(fd, " %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id);430 }431 }432 }433 434 pthread_mutex_unlock( &memBlockListMutex);435 436 if ( nleak == 0 || arr == NULL) {437 return nleak;438 }439 440 *arr = p_psAlloc( nleak*sizeof(psMemBlock), __FILE__, __LINE__);441 pthread_mutex_lock( &memBlockListMutex);442 443 for ( psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) {444 if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) {445 (*arr)[j++] = iter;446 if (j == nleak) { // found them all447 break;448 }449 }450 }451 452 pthread_mutex_unlock( &memBlockListMutex);453 423 424 pthread_mutex_lock( &memBlockListMutex ); 425 426 for ( psMemBlock * iter = topBlock; iter != NULL; iter = iter->nextBlock ) { 427 if ( ( psMemGetRefCounter( iter + 1 ) > 0 ) && ( iter->id >= id0 ) ) { 428 nleak++; 429 430 if ( fd != NULL ) { 431 if ( nleak == 1 ) { 432 fprintf( fd, " %20s:line ID\n", "file" ); 433 } 434 435 fprintf( fd, " %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id ); 436 } 437 } 438 } 439 440 pthread_mutex_unlock( &memBlockListMutex ); 441 442 if ( nleak == 0 || arr == NULL ) { 443 return nleak; 444 } 445 446 *arr = p_psAlloc( nleak * sizeof( psMemBlock ), __FILE__, __LINE__ ); 447 pthread_mutex_lock( &memBlockListMutex ); 448 449 for ( psMemBlock * iter = topBlock; iter != NULL; iter = iter->nextBlock ) { 450 if ( ( psMemGetRefCounter( iter + 1 ) > 0 ) && ( iter->id >= id0 ) ) { 451 ( *arr ) [ j++ ] = iter; 452 if ( j == nleak ) { // found them all 453 break; 454 } 455 } 456 } 457 458 pthread_mutex_unlock( &memBlockListMutex ); 459 454 460 return nleak; 455 461 } … … 457 463 /* 458 464 * Reference counting APIs 459 */ 465 */ 460 466 // return refCounter 461 psReferenceCount psMemGetRefCounter( void *vptr)462 { 463 psMemBlock * ptr;467 psReferenceCount psMemGetRefCounter( void *vptr ) 468 { 469 psMemBlock * ptr; 464 470 unsigned int refCount; 465 466 if ( vptr == NULL) {467 return 0;468 }469 470 ptr = ( (psMemBlock *)vptr) - 1;471 472 if ( checkMemBlock(ptr, __func__) != 0) {473 memProblemCallback(ptr, __func__, __LINE__);474 }475 476 pthread_mutex_lock( &ptr->refCounterMutex);471 472 if ( vptr == NULL ) { 473 return 0; 474 } 475 476 ptr = ( ( psMemBlock * ) vptr ) - 1; 477 478 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 479 memProblemCallback( ptr, __func__, __LINE__ ); 480 } 481 482 pthread_mutex_lock( &ptr->refCounterMutex ); 477 483 refCount = ptr->refCounter; 478 pthread_mutex_unlock( &ptr->refCounterMutex);479 484 pthread_mutex_unlock( &ptr->refCounterMutex ); 485 480 486 return refCount; 481 487 } 482 488 // increment and return refCounter 483 void* p_psMemIncrRefCounter( void *vptr, const char *file, int lineno)484 { 485 psMemBlock * ptr;486 487 if ( vptr == NULL) {488 return vptr;489 }490 491 ptr = ( (psMemBlock *)vptr) - 1;492 493 if ( checkMemBlock(ptr, __func__)) {494 memProblemCallback(ptr, file,lineno);495 }496 497 pthread_mutex_lock( &ptr->refCounterMutex);489 void* p_psMemIncrRefCounter( void *vptr, const char *file, int lineno ) 490 { 491 psMemBlock * ptr; 492 493 if ( vptr == NULL ) { 494 return vptr; 495 } 496 497 ptr = ( ( psMemBlock * ) vptr ) - 1; 498 499 if ( checkMemBlock( ptr, __func__ ) ) { 500 memProblemCallback( ptr, file, lineno ); 501 } 502 503 pthread_mutex_lock( &ptr->refCounterMutex ); 498 504 ptr->refCounter++; 499 pthread_mutex_unlock( &ptr->refCounterMutex);500 505 pthread_mutex_unlock( &ptr->refCounterMutex ); 506 501 507 return vptr; 502 508 } 503 509 504 510 // decrement and return refCounter 505 void* p_psMemDecrRefCounter(void *vptr,const char *file, int lineno) 506 { 507 if (vptr == NULL) { 508 return NULL; 509 } 510 511 psMemBlock *ptr = ((psMemBlock *)vptr) - 1; 512 513 if (checkMemBlock(ptr, __func__) != 0) { 514 memProblemCallback(ptr, file, lineno); 515 return NULL; 516 } 517 518 pthread_mutex_lock(&ptr->refCounterMutex); 519 520 if (ptr->refCounter > 1) { 521 /// XXX - Probably should have another mutex here. 522 ptr->refCounter--; // multiple references, just decrement the count. 523 pthread_mutex_unlock(&ptr->refCounterMutex); 524 525 } else { 526 pthread_mutex_unlock(&ptr->refCounterMutex); 527 528 // Did the user ask to be informed about this deallocation? 529 if (ptr->id == p_psMemFreeID) { 530 p_psMemFreeID += memFreeCallback(ptr); 531 } 532 533 if (ptr->freeFcn != NULL) { 534 ptr->freeFcn(vptr); 535 } 536 537 pthread_mutex_lock(&memBlockListMutex); 538 539 // cut the memBlock out of the memBlock list 540 if (ptr->nextBlock != NULL) { 541 ptr->nextBlock->previousBlock = ptr->previousBlock; 542 } 543 if (ptr->previousBlock != NULL) { 544 ptr->previousBlock->nextBlock = ptr->nextBlock; 545 } 546 if (lastMemBlockAllocated == ptr) { 547 lastMemBlockAllocated = ptr->nextBlock; 548 } 549 550 pthread_mutex_unlock(&memBlockListMutex); 551 552 553 // do we need to recycle? 554 if (ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE) { 555 556 int level = 1; 557 while (ptr->userMemorySize >= recycleBinSize[level]) { 558 level++; 559 } 560 level--; 561 562 ptr->refCounter = 0; 563 ptr->previousBlock = NULL; 564 565 pthread_mutex_lock(&recycleMemBlockListMutex); 566 ptr->nextBlock = recycleMemBlockList[level]; 567 if (recycleMemBlockList[level] != NULL) { 568 recycleMemBlockList[level]->previousBlock = ptr; 569 } 570 recycleMemBlockList[level] = ptr; 571 pthread_mutex_unlock(&recycleMemBlockListMutex); 572 511 void* p_psMemDecrRefCounter( void *vptr, const char *file, int lineno ) 512 { 513 if ( vptr == NULL ) { 514 return NULL; 515 } 516 517 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 518 519 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 520 memProblemCallback( ptr, file, lineno ); 521 return NULL; 522 } 523 524 pthread_mutex_lock( &ptr->refCounterMutex ); 525 526 if ( ptr->refCounter > 1 ) { 527 /// XXX - Probably should have another mutex here. 528 ptr->refCounter--; // multiple references, just decrement the count. 529 pthread_mutex_unlock( &ptr->refCounterMutex ); 530 573 531 } else { 574 // memory is larger than I want to recycle. 575 #ifdef PS_MEM_DEBUG 576 (void)p_psRealloc(vptr,0,file,lineno); 577 ptr->previousBlock = NULL; 578 ptr->nextBlock = deadBlockList; 579 if (deadBlockList != NULL) { 580 deadBlockList->previous = ptr; 581 } 582 deadBlockList = ptr; 583 #else 584 585 pthread_mutex_destroy(&ptr->refCounterMutex); 586 free(ptr); 587 #endif 588 589 } 590 591 592 pthread_mutex_destroy(&ptr->refCounterMutex); 593 594 595 vptr = NULL; // since we freed it, make sure we return NULL. 596 } 597 532 pthread_mutex_unlock( &ptr->refCounterMutex ); 533 534 // Did the user ask to be informed about this deallocation? 535 if ( ptr->id == p_psMemFreeID ) { 536 p_psMemFreeID += memFreeCallback( ptr ); 537 } 538 539 if ( ptr->freeFcn != NULL ) { 540 ptr->freeFcn( vptr ); 541 } 542 543 pthread_mutex_lock( &memBlockListMutex ); 544 545 // cut the memBlock out of the memBlock list 546 if ( ptr->nextBlock != NULL ) { 547 ptr->nextBlock->previousBlock = ptr->previousBlock; 548 } 549 if ( ptr->previousBlock != NULL ) { 550 ptr->previousBlock->nextBlock = ptr->nextBlock; 551 } 552 if ( lastMemBlockAllocated == ptr ) { 553 lastMemBlockAllocated = ptr->nextBlock; 554 } 555 556 pthread_mutex_unlock( &memBlockListMutex ); 557 558 559 // do we need to recycle? 560 if ( ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE ) { 561 562 int level = 1; 563 while ( ptr->userMemorySize >= recycleBinSize[ level ] ) { 564 level++; 565 } 566 level--; 567 568 ptr->refCounter = 0; 569 ptr->previousBlock = NULL; 570 571 pthread_mutex_lock( &recycleMemBlockListMutex ); 572 ptr->nextBlock = recycleMemBlockList[ level ]; 573 if ( recycleMemBlockList[ level ] != NULL ) { 574 recycleMemBlockList[ level ] ->previousBlock = ptr; 575 } 576 recycleMemBlockList[ level ] = ptr; 577 pthread_mutex_unlock( &recycleMemBlockListMutex ); 578 579 } else { 580 // memory is larger than I want to recycle. 581 #ifdef PS_MEM_DEBUG 582 ( void ) p_psRealloc( vptr, 0, file, lineno ); 583 ptr->previousBlock = NULL; 584 ptr->nextBlock = deadBlockList; 585 if ( deadBlockList != NULL ) { 586 deadBlockList->previous = ptr; 587 } 588 deadBlockList = ptr; 589 #else 590 591 pthread_mutex_destroy( &ptr->refCounterMutex ); 592 free( ptr ); 593 #endif 594 595 } 596 597 vptr = NULL; // since we freed it, make sure we return NULL. 598 } 599 598 600 return vptr; 599 601 } 600 602 601 void p_psMemSetDeallocator( void* vptr, psFreeFcn freeFcn)602 { 603 if ( vptr == NULL) {604 return;605 }606 607 psMemBlock *ptr = ( (psMemBlock *)vptr) - 1;608 609 if ( checkMemBlock(ptr, __func__) != 0) {610 memProblemCallback(ptr, __func__, __LINE__);611 }612 603 void p_psMemSetDeallocator( void* vptr, psFreeFcn freeFcn ) 604 { 605 if ( vptr == NULL ) { 606 return ; 607 } 608 609 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 610 611 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 612 memProblemCallback( ptr, __func__, __LINE__ ); 613 } 614 613 615 ptr->freeFcn = freeFcn; 614 615 } 616 psFreeFcn p_psMemGetDeallocator( void* vptr)617 { 618 if ( vptr == NULL) {619 return NULL;620 }621 622 psMemBlock *ptr = ( (psMemBlock *)vptr) - 1;623 624 if ( checkMemBlock(ptr, __func__) != 0) {625 memProblemCallback(ptr, __func__, __LINE__);626 }627 616 617 } 618 psFreeFcn p_psMemGetDeallocator( void* vptr ) 619 { 620 if ( vptr == NULL ) { 621 return NULL; 622 } 623 624 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 625 626 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 627 memProblemCallback( ptr, __func__, __LINE__ ); 628 } 629 628 630 return ptr->freeFcn; 629 631 } -
trunk/psLib/src/sys/psType.h
r1292 r1360 1 1 /** @file psType.h 2 *3 * @brief Contains support for basic types4 *5 * This file defines common datatypes used throughout psLib.6 *7 * @ingroup DataContainer8 *9 * @author Robert DeSonia, MHPCC10 * @author Ross Harman, MHPCC11 *12 * @version $Revision: 1.14$ $Name: not supported by cvs2svn $13 * @date $Date: 2004-07-24 02:00:21$14 *15 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii16 */2 * 3 * @brief Contains support for basic types 4 * 5 * This file defines common datatypes used throughout psLib. 6 * 7 * @ingroup DataContainer 8 * 9 * @author Robert DeSonia, MHPCC 10 * @author Ross Harman, MHPCC 11 * 12 * @version $Revision: 1.15 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2004-07-31 02:28:10 $ 14 * 15 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 16 */ 17 17 18 18 #ifndef PS_TYPE_H … … 37 37 */ 38 38 39 typedef uint8_t psU8; ///< 8-bit unsigned int40 typedef uint16_t psU16; ///< 16-bit unsigned int41 typedef uint32_t psU32; ///< 32-bit unsigned int42 typedef uint64_t psU64; ///< 64-bit unsigned int43 typedef int8_t psS8; ///< 8-bit signed int44 typedef int16_t psS16; ///< 16-bit signed int45 typedef int32_t psS32; ///< 32-bit signed int46 typedef int64_t psS64; ///< 64-bit signed int47 typedef float psF32; ///< 32-bit floating point48 typedef double psF64; ///< 64-bit floating point49 typedef complex float psC32; ///< complex with 32-bit floating point Real and Imagary numbers50 typedef complex double psC64; ///< complex with 64-bit floating point Real and Imagary numbers51 typedef void* psPTR; ///< void pointer39 typedef uint8_t psU8; ///< 8-bit unsigned int 40 typedef uint16_t psU16; ///< 16-bit unsigned int 41 typedef uint32_t psU32; ///< 32-bit unsigned int 42 typedef uint64_t psU64; ///< 64-bit unsigned int 43 typedef int8_t psS8; ///< 8-bit signed int 44 typedef int16_t psS16; ///< 16-bit signed int 45 typedef int32_t psS32; ///< 32-bit signed int 46 typedef int64_t psS64; ///< 64-bit signed int 47 typedef float psF32; ///< 32-bit floating point 48 typedef double psF64; ///< 64-bit floating point 49 typedef complex float psC32; ///< complex with 32-bit floating point Real and Imagary numbers 50 typedef complex double psC64; ///< complex with 64-bit floating point Real and Imagary numbers 51 typedef void* psPTR; ///< void pointer 52 52 53 53 54 54 typedef enum { 55 PS_TYPE_S8 = 0x0101,///< Character.56 PS_TYPE_S16 = 0x0102,///< Short integer.57 PS_TYPE_S32 = 0x0104,///< Integer.58 PS_TYPE_S64 = 0x0108,///< Long integer.59 PS_TYPE_U8 = 0x0301,///< Unsigned character.60 PS_TYPE_U16 = 0x0302,///< Unsigned short integer.61 PS_TYPE_U32 = 0x0304,///< Unsigned integer.62 PS_TYPE_U64 = 0x0308,///< Unsigned long integer.63 PS_TYPE_F32 = 0x0404,///< Single-precision Floating point.64 PS_TYPE_F64 = 0x0408,///< Double-precision floating point.65 PS_TYPE_C32 = 0x0808,///< Complex numbers consisting of single-precision floating point.66 PS_TYPE_C64 = 0x0810,///< Complex numbers consisting of double-precision floating point.67 PS_TYPE_PTR = 0x0000 ///< Something else that's not supported for arithmetic.55 PS_TYPE_S8 = 0x0101, ///< Character. 56 PS_TYPE_S16 = 0x0102, ///< Short integer. 57 PS_TYPE_S32 = 0x0104, ///< Integer. 58 PS_TYPE_S64 = 0x0108, ///< Long integer. 59 PS_TYPE_U8 = 0x0301, ///< Unsigned character. 60 PS_TYPE_U16 = 0x0302, ///< Unsigned short integer. 61 PS_TYPE_U32 = 0x0304, ///< Unsigned integer. 62 PS_TYPE_U64 = 0x0308, ///< Unsigned long integer. 63 PS_TYPE_F32 = 0x0404, ///< Single-precision Floating point. 64 PS_TYPE_F64 = 0x0408, ///< Double-precision floating point. 65 PS_TYPE_C32 = 0x0808, ///< Complex numbers consisting of single-precision floating point. 66 PS_TYPE_C64 = 0x0810, ///< Complex numbers consisting of double-precision floating point. 67 PS_TYPE_PTR = 0x0000 ///< Something else that's not supported for arithmetic. 68 68 } psElemType; 69 69 70 70 #define PS_TYPE_MASK PS_TYPE_U8 ///< the psElemType to use for mask image 71 #define PS_TYPE_MASK_DATA U8 ///< the data member to use for mask image 71 72 #define PS_TYPE_MASK_NAME "psU8" 72 73 typedef psU8 psMaskType; ///< the C datatype for a mask image … … 127 128 */ 128 129 typedef enum { 129 PS_DIMEN_SCALAR, ///< Scalar.130 PS_DIMEN_VECTOR, ///< Vector.131 PS_DIMEN_TRANSV, ///< Transposed vector.132 PS_DIMEN_IMAGE, ///< Image.130 PS_DIMEN_SCALAR, ///< Scalar. 131 PS_DIMEN_VECTOR, ///< Vector. 132 PS_DIMEN_TRANSV, ///< Transposed vector. 133 PS_DIMEN_IMAGE, ///< Image. 133 134 PS_DIMEN_OTHER ///< Something else that's not supported for arithmetic. 134 135 } psDimen; … … 141 142 */ 142 143 typedef struct 143 {144 psElemType type; ///< Primitive type.145 psDimen dimen; ///< Dimensionality.146 }144 { 145 psElemType type; ///< Primitive type. 146 psDimen dimen; ///< Dimensionality. 147 } 147 148 psType; 148 149 -
trunk/psLib/src/sysUtils/psMemory.c
r1240 r1360 1 1 /** @file psMemory.c 2 *3 * @brief Contains the definitions for the memory management system4 *5 * psMemory.h has additional information and documentation of the routines found in this file.6 *7 * @author Robert DeSonia, MHPCC8 * @author Robert Lupton, Princeton University9 *10 * @version $Revision: 1.29$ $Name: not supported by cvs2svn $11 * @date $Date: 2004-07-19 20:45:53$12 *13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii14 */2 * 3 * @brief Contains the definitions for the memory management system 4 * 5 * psMemory.h has additional information and documentation of the routines found in this file. 6 * 7 * @author Robert DeSonia, MHPCC 8 * @author Robert Lupton, Princeton University 9 * 10 * @version $Revision: 1.30 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2004-07-31 02:28:10 $ 12 * 13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 14 */ 15 15 16 16 #define PS_ALLOW_MALLOC // we're allowed to call malloc() … … 30 30 #define P_PS_LARGE_BLOCK_SIZE 65536 // size where under, we try to recycle 31 31 32 static int checkMemBlock( const psMemBlock *m, const char* funcName);32 static int checkMemBlock( const psMemBlock *m, const char* funcName ); 33 33 static psMemBlock *lastMemBlockAllocated = NULL; 34 34 static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER; … … 38 38 39 39 static int recycleBins = 13; 40 static int recycleBinSize[14] = {8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,P_PS_LARGE_BLOCK_SIZE}; 40 static int recycleBinSize[ 14 ] = 41 { 42 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, P_PS_LARGE_BLOCK_SIZE 43 }; 41 44 // N.B. recycleBinSize should be terminated by P_PS_LARGE_BLOCK_SIZE (simplifies search loops) 42 static psMemBlock* recycleMemBlockList[13] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; 43 45 static psMemBlock* recycleMemBlockList[ 13 ] = 46 { 47 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 48 }; 49 44 50 #ifdef PS_MEM_DEBUG 45 51 static psMemBlock* deadBlockList; // a place to put dead memBlocks in debug mode. … … 53 59 * Default memExhausted callback. 54 60 */ 55 static void *memExhaustedCallbackDefault( size_t size)56 { 57 void * ptr = NULL;58 59 pthread_mutex_lock( &recycleMemBlockListMutex);60 int level =recycleBins-1;61 while ( level >= 0 && ptr == NULL) {62 while (recycleMemBlockList[level] != NULL && ptr == NULL) {63 psMemBlock* old = recycleMemBlockList[level];64 recycleMemBlockList[level] = recycleMemBlockList[level]->nextBlock;65 free(old);66 ptr = malloc(size);67 }68 level--;69 }70 pthread_mutex_unlock( &recycleMemBlockListMutex);71 61 static void *memExhaustedCallbackDefault( size_t size ) 62 { 63 void * ptr = NULL; 64 65 pthread_mutex_lock( &recycleMemBlockListMutex ); 66 int level = recycleBins - 1; 67 while ( level >= 0 && ptr == NULL ) { 68 while ( recycleMemBlockList[ level ] != NULL && ptr == NULL ) { 69 psMemBlock * old = recycleMemBlockList[ level ]; 70 recycleMemBlockList[ level ] = recycleMemBlockList[ level ] ->nextBlock; 71 free( old ); 72 ptr = malloc( size ); 73 } 74 level--; 75 } 76 pthread_mutex_unlock( &recycleMemBlockListMutex ); 77 72 78 return ptr; 73 79 } … … 75 81 static psMemExhaustedCallback memExhaustedCallback = memExhaustedCallbackDefault; 76 82 77 psMemExhaustedCallback psMemExhaustedCallbackSet( psMemExhaustedCallback func)83 psMemExhaustedCallback psMemExhaustedCallbackSet( psMemExhaustedCallback func ) 78 84 { 79 85 psMemExhaustedCallback old = memExhaustedCallback; 80 81 if ( func != NULL) {82 memExhaustedCallback = func;83 } else {84 memExhaustedCallback = memExhaustedCallbackDefault;85 }86 86 87 if ( func != NULL ) { 88 memExhaustedCallback = func; 89 } else { 90 memExhaustedCallback = memExhaustedCallbackDefault; 91 } 92 87 93 return old; 88 94 } 89 95 90 static void memProblemCallbackDefault( const psMemBlock *ptr,91 const char *file, int lineno)92 { 93 if ( ptr->refCounter < 1) {94 psError(__func__,95 "Block %ld allocated at %s:%d freed more than once at %s:%d\n",96 ptr->id, ptr->file, ptr->lineno, file, lineno);97 }98 99 if ( lineno > 0) {100 psAbort(__func__, "Detected a problem in the memory system at %s:%d", file, lineno);101 }96 static void memProblemCallbackDefault( const psMemBlock *ptr, 97 const char *file, int lineno ) 98 { 99 if ( ptr->refCounter < 1 ) { 100 psError( __func__, 101 "Block %ld allocated at %s:%d freed more than once at %s:%d\n", 102 ptr->id, ptr->file, ptr->lineno, file, lineno ); 103 } 104 105 if ( lineno > 0 ) { 106 psAbort( __func__, "Detected a problem in the memory system at %s:%d", file, lineno ); 107 } 102 108 } 103 109 static psMemProblemCallback memProblemCallback = memProblemCallbackDefault; 104 110 105 psMemProblemCallback psMemProblemCallbackSet( psMemProblemCallback func)111 psMemProblemCallback psMemProblemCallbackSet( psMemProblemCallback func ) 106 112 { 107 113 psMemProblemCallback old = memProblemCallback; 108 109 if ( func != NULL) {110 memProblemCallback = func;111 } else {112 memProblemCallback = memProblemCallbackDefault;113 }114 114 115 if ( func != NULL ) { 116 memProblemCallback = func; 117 } else { 118 memProblemCallback = memProblemCallbackDefault; 119 } 120 115 121 return old; 116 122 } … … 123 129 psMemoryId p_psMemFreeID = 0; // notify user this block is freed 124 130 125 psMemoryId psMemAllocateCallbackSetID( psMemoryId id)131 psMemoryId psMemAllocateCallbackSetID( psMemoryId id ) 126 132 { 127 133 psMemoryId old = p_psMemAllocateID; 128 134 p_psMemAllocateID = id; 129 135 130 136 return old; 131 137 } 132 138 133 psMemoryId psMemFreeCallbackSetID( psMemoryId id)139 psMemoryId psMemFreeCallbackSetID( psMemoryId id ) 134 140 { 135 141 psMemoryId old = p_psMemFreeID; 136 142 p_psMemFreeID = id; 137 143 138 144 return old; 139 145 } … … 145 151 * isn't resignalled) 146 152 */ 147 static psMemoryId memAllocateCallbackDefault( const psMemBlock *ptr)153 static psMemoryId memAllocateCallbackDefault( const psMemBlock *ptr ) 148 154 { 149 155 static psMemoryId incr = 0; // "p_psMemAllocateID += incr" 150 156 151 157 return incr; 152 158 } 153 159 154 static psMemoryId memFreeCallbackDefault( const psMemBlock *ptr)160 static psMemoryId memFreeCallbackDefault( const psMemBlock *ptr ) 155 161 { 156 162 static psMemoryId incr = 0; // "p_psMemFreeID += incr" 157 163 158 164 return incr; 159 165 } … … 165 171 static psMemFreeCallback memFreeCallback = memFreeCallbackDefault; 166 172 167 psMemAllocateCallback psMemAllocateCallbackSet( psMemAllocateCallback func)173 psMemAllocateCallback psMemAllocateCallbackSet( psMemAllocateCallback func ) 168 174 { 169 175 psMemFreeCallback old = memAllocateCallback; 170 171 if ( func != NULL) {172 memAllocateCallback =func;173 } else {174 memAllocateCallback = memAllocateCallbackDefault;175 }176 176 177 if ( func != NULL ) { 178 memAllocateCallback = func; 179 } else { 180 memAllocateCallback = memAllocateCallbackDefault; 181 } 182 177 183 return old; 178 184 } 179 185 180 psMemFreeCallback psMemFreeCallbackSet( psMemFreeCallback func)186 psMemFreeCallback psMemFreeCallbackSet( psMemFreeCallback func ) 181 187 { 182 188 psMemFreeCallback old = memFreeCallback; 183 184 if ( func != NULL) {185 memFreeCallback = func;186 } else {187 memFreeCallback = memFreeCallbackDefault;188 }189 189 190 if ( func != NULL ) { 191 memFreeCallback = func; 192 } else { 193 memFreeCallback = memFreeCallbackDefault; 194 } 195 190 196 return old; 191 197 } … … 194 200 * Return memory ID counter for next block to be allocated 195 201 */ 196 psMemoryId psMemGetId( void)202 psMemoryId psMemGetId( void ) 197 203 { 198 204 psMemoryId id; 199 pthread_mutex_lock( &memIdMutex);205 pthread_mutex_lock( &memIdMutex ); 200 206 id = memid + 1; 201 pthread_mutex_unlock( &memIdMutex);202 207 pthread_mutex_unlock( &memIdMutex ); 208 203 209 return id; 204 210 } … … 210 216 */ 211 217 212 static int checkMemBlock( const psMemBlock *m, const char* funcName)218 static int checkMemBlock( const psMemBlock *m, const char* funcName ) 213 219 { 214 220 // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked, 215 221 // we shouldn't call such things as p_psAlloc/p_psFree here. 216 217 if ( m == NULL) {218 psError(funcName,"Memory Corruption: NULL memory block found.");219 return 1;220 }221 222 if ( m->refCounter == 0) {223 // using an unreferenced block of memory, are you?224 psError(__func__,"Memory Corruption: memory block %ld was freed but still used.",225 m->id);226 return 1;227 }228 229 if ( m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC) {230 psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer underflow)",231 m->id);232 return 1;233 }234 if ( *(void**)((int8_t*)(m+1)+m->userMemorySize) != P_PS_MEMMAGIC) {235 psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)",236 m->id);237 return 1;238 }239 222 223 if ( m == NULL ) { 224 psError( funcName, "Memory Corruption: NULL memory block found." ); 225 return 1; 226 } 227 228 if ( m->refCounter == 0 ) { 229 // using an unreferenced block of memory, are you? 230 psError( __func__, "Memory Corruption: memory block %ld was freed but still used.", 231 m->id ); 232 return 1; 233 } 234 235 if ( m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC ) { 236 psError( funcName, "Memory Corruption: memory block %ld is corrupted (buffer underflow)", 237 m->id ); 238 return 1; 239 } 240 if ( *( void** ) ( ( int8_t* ) ( m + 1 ) + m->userMemorySize ) != P_PS_MEMMAGIC ) { 241 psError( funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)", 242 m->id ); 243 return 1; 244 } 245 240 246 return 0; 241 247 } 242 248 243 int psMemCheckCorruption( bool abort_on_error)249 int psMemCheckCorruption( bool abort_on_error ) 244 250 { 245 251 int nbad = 0; // number of bad blocks 246 252 247 253 // get exclusive access to the memBlock list to avoid it changing on us while we use it. 248 pthread_mutex_lock( &memBlockListMutex);249 250 for ( psMemBlock* iter=lastMemBlockAllocated; iter != NULL; iter=iter->nextBlock) {251 if (checkMemBlock(iter, __func__)) {252 nbad++;253 254 memProblemCallback(iter, __func__, __LINE__);255 256 if (abort_on_error) {257 // release the lock on the memblock list258 pthread_mutex_unlock(&memBlockListMutex);259 psAbort(__func__, "Detected memory corruption");260 return nbad;261 }262 }263 }264 254 pthread_mutex_lock( &memBlockListMutex ); 255 256 for ( psMemBlock * iter = lastMemBlockAllocated; iter != NULL; iter = iter->nextBlock ) { 257 if ( checkMemBlock( iter, __func__ ) ) { 258 nbad++; 259 260 memProblemCallback( iter, __func__, __LINE__ ); 261 262 if ( abort_on_error ) { 263 // release the lock on the memblock list 264 pthread_mutex_unlock( &memBlockListMutex ); 265 psAbort( __func__, "Detected memory corruption" ); 266 return nbad; 267 } 268 } 269 } 270 265 271 // release the lock on the memblock list 266 pthread_mutex_unlock( &memBlockListMutex);272 pthread_mutex_unlock( &memBlockListMutex ); 267 273 return nbad; 268 274 } 269 275 270 void *p_psAlloc( size_t size, const char *file, int lineno)271 { 272 273 psMemBlock * ptr = NULL;274 276 void *p_psAlloc( size_t size, const char *file, int lineno ) 277 { 278 279 psMemBlock * ptr = NULL; 280 275 281 // memory is of the size I want to bother recycling? 276 if ( size < P_PS_LARGE_BLOCK_SIZE) {277 // find the bin we need.278 int level = 0;279 while (size > recycleBinSize[level]) {280 level++;281 }282 // Are we in one of the bins283 if (level<recycleBins) {284 285 size = recycleBinSize[level]; // round-up size to next sized bin.286 287 pthread_mutex_lock(&recycleMemBlockListMutex);288 289 if (recycleMemBlockList[level] != NULL) {290 ptr = recycleMemBlockList[level];291 recycleMemBlockList[level] = ptr->nextBlock;292 if (recycleMemBlockList[level] != NULL) {293 recycleMemBlockList[level]->previousBlock = NULL;294 }295 size = ptr->userMemorySize;296 }297 298 pthread_mutex_unlock(&recycleMemBlockListMutex);299 }300 }301 302 if ( ptr == NULL) {303 ptr = malloc(sizeof(psMemBlock) + size + sizeof(void*));304 305 if (ptr == NULL) {306 ptr = memExhaustedCallback(size);307 if (ptr == NULL) {308 psAbort(__func__, "Failed to allocate %u bytes at %s:%d",309 size, file, lineno);310 }311 }312 313 ptr->startblock = P_PS_MEMMAGIC;314 ptr->endblock = P_PS_MEMMAGIC;315 ptr->userMemorySize = size;316 pthread_mutex_init(&ptr->refCounterMutex, NULL);317 }318 282 if ( size < P_PS_LARGE_BLOCK_SIZE ) { 283 // find the bin we need. 284 int level = 0; 285 while ( size > recycleBinSize[ level ] ) { 286 level++; 287 } 288 // Are we in one of the bins 289 if ( level < recycleBins ) { 290 291 size = recycleBinSize[ level ]; // round-up size to next sized bin. 292 293 pthread_mutex_lock( &recycleMemBlockListMutex ); 294 295 if ( recycleMemBlockList[ level ] != NULL ) { 296 ptr = recycleMemBlockList[ level ]; 297 recycleMemBlockList[ level ] = ptr->nextBlock; 298 if ( recycleMemBlockList[ level ] != NULL ) { 299 recycleMemBlockList[ level ] ->previousBlock = NULL; 300 } 301 size = ptr->userMemorySize; 302 } 303 304 pthread_mutex_unlock( &recycleMemBlockListMutex ); 305 } 306 } 307 308 if ( ptr == NULL ) { 309 ptr = malloc( sizeof( psMemBlock ) + size + sizeof( void* ) ); 310 311 if ( ptr == NULL ) { 312 ptr = memExhaustedCallback( size ); 313 if ( ptr == NULL ) { 314 psAbort( __func__, "Failed to allocate %u bytes at %s:%d", 315 size, file, lineno ); 316 } 317 } 318 319 ptr->startblock = P_PS_MEMMAGIC; 320 ptr->endblock = P_PS_MEMMAGIC; 321 ptr->userMemorySize = size; 322 pthread_mutex_init( &ptr->refCounterMutex, NULL ); 323 } 324 319 325 // increment the memory id safely. 320 pthread_mutex_lock( &memBlockListMutex);321 *( psMemoryId*)&ptr->id = ++memid;322 pthread_mutex_unlock( &memBlockListMutex);323 326 pthread_mutex_lock( &memBlockListMutex ); 327 *( psMemoryId* ) & ptr->id = ++memid; 328 pthread_mutex_unlock( &memBlockListMutex ); 329 324 330 ptr->file = file; 325 331 ptr->freeFcn = NULL; 326 *( unsigned int*)&ptr->lineno = lineno;327 *( void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;332 *( unsigned int* ) & ptr->lineno = lineno; 333 *( void** ) ( ( int8_t* ) ( ptr + 1 ) + size ) = P_PS_MEMMAGIC; 328 334 ptr->previousBlock = NULL; 329 335 330 336 ptr->refCounter = 1; // one user so far 331 337 332 338 // need exclusive access of the memory block list now... 333 pthread_mutex_lock( &memBlockListMutex);334 339 pthread_mutex_lock( &memBlockListMutex ); 340 335 341 // insert the new block to the front of the memBlock linked-list 336 342 ptr->nextBlock = lastMemBlockAllocated; 337 if ( ptr->nextBlock != NULL) {338 ptr->nextBlock->previousBlock = ptr;339 }343 if ( ptr->nextBlock != NULL ) { 344 ptr->nextBlock->previousBlock = ptr; 345 } 340 346 lastMemBlockAllocated = ptr; 341 342 pthread_mutex_unlock( &memBlockListMutex);343 347 348 pthread_mutex_unlock( &memBlockListMutex ); 349 344 350 // Did the user ask to be informed about this allocation? 345 if ( ptr->id == p_psMemAllocateID) {346 p_psMemAllocateID += memAllocateCallback(ptr);347 }348 351 if ( ptr->id == p_psMemAllocateID ) { 352 p_psMemAllocateID += memAllocateCallback( ptr ); 353 } 354 349 355 // And return the user the memory that they allocated 350 356 return ptr + 1; // user memory 351 357 } 352 358 353 void *p_psRealloc( void *vptr, size_t size, const char *file, int lineno)354 { 355 if ( vptr == NULL) {356 return p_psAlloc(size, file, lineno);357 } else {358 psMemBlock *ptr = ((psMemBlock *)vptr) - 1;359 bool isBlockLast = false;360 361 if (checkMemBlock(ptr, __func__) != 0) {362 memProblemCallback(ptr, file, lineno);363 psAbort(file,"Realloc detected a memory corruption (id %ld @ %s:%d).",364 ptr->id,ptr->file,ptr->lineno);365 }366 367 pthread_mutex_lock(&memBlockListMutex);368 369 isBlockLast = (ptr == lastMemBlockAllocated);370 371 ptr = (psMemBlock*)realloc(ptr, sizeof(psMemBlock) + size + sizeof(void*));372 373 if (ptr == NULL) {374 psAbort(__func__, "Failed to reallocate %ld bytes at %s:%d",375 size, file, lineno);376 }377 378 ptr->userMemorySize = size;379 *(void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;380 381 if (isBlockLast) {382 lastMemBlockAllocated = ptr;383 }384 385 // the block location may have changed, so fix the linked list addresses.386 if (ptr->nextBlock != NULL) {387 ptr->nextBlock->previousBlock = ptr;388 }389 if (ptr->previousBlock != NULL) {390 ptr->previousBlock->nextBlock = ptr;391 }392 393 pthread_mutex_unlock(&memBlockListMutex);394 395 // Did the user ask to be informed about this allocation?396 if (ptr->id == p_psMemAllocateID) {397 p_psMemAllocateID += memAllocateCallback(ptr);398 }399 400 return ptr + 1; // usr memory401 }402 } 403 404 void p_psFree( void *vptr, const char *file, int lineno)405 { 406 ( void)p_psMemDecrRefCounter(vptr,file,lineno); // this handles the free, if required.359 void *p_psRealloc( void *vptr, size_t size, const char *file, int lineno ) 360 { 361 if ( vptr == NULL ) { 362 return p_psAlloc( size, file, lineno ); 363 } else { 364 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 365 bool isBlockLast = false; 366 367 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 368 memProblemCallback( ptr, file, lineno ); 369 psAbort( file, "Realloc detected a memory corruption (id %ld @ %s:%d).", 370 ptr->id, ptr->file, ptr->lineno ); 371 } 372 373 pthread_mutex_lock( &memBlockListMutex ); 374 375 isBlockLast = ( ptr == lastMemBlockAllocated ); 376 377 ptr = ( psMemBlock* ) realloc( ptr, sizeof( psMemBlock ) + size + sizeof( void* ) ); 378 379 if ( ptr == NULL ) { 380 psAbort( __func__, "Failed to reallocate %ld bytes at %s:%d", 381 size, file, lineno ); 382 } 383 384 ptr->userMemorySize = size; 385 *( void** ) ( ( int8_t* ) ( ptr + 1 ) + size ) = P_PS_MEMMAGIC; 386 387 if ( isBlockLast ) { 388 lastMemBlockAllocated = ptr; 389 } 390 391 // the block location may have changed, so fix the linked list addresses. 392 if ( ptr->nextBlock != NULL ) { 393 ptr->nextBlock->previousBlock = ptr; 394 } 395 if ( ptr->previousBlock != NULL ) { 396 ptr->previousBlock->nextBlock = ptr; 397 } 398 399 pthread_mutex_unlock( &memBlockListMutex ); 400 401 // Did the user ask to be informed about this allocation? 402 if ( ptr->id == p_psMemAllocateID ) { 403 p_psMemAllocateID += memAllocateCallback( ptr ); 404 } 405 406 return ptr + 1; // usr memory 407 } 408 } 409 410 void p_psFree( void *vptr, const char *file, int lineno ) 411 { 412 ( void ) p_psMemDecrRefCounter( vptr, file, lineno ); // this handles the free, if required. 407 413 } 408 414 … … 410 416 * Check for memory leaks. 411 417 */ 412 int psMemCheckLeaks( psMemoryId id0,psMemBlock ***arr,FILE *fd)418 int psMemCheckLeaks( psMemoryId id0, psMemBlock ***arr, FILE *fd ) 413 419 { 414 420 int nleak = 0; 415 421 int j = 0; 416 422 psMemBlock* topBlock = lastMemBlockAllocated; 417 418 pthread_mutex_lock( &memBlockListMutex);419 420 for ( psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) {421 if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) {422 nleak++;423 424 if (fd != NULL) {425 if (nleak == 1) {426 fprintf(fd, " %20s:line ID\n", "file");427 }428 429 fprintf(fd, " %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id);430 }431 }432 }433 434 pthread_mutex_unlock( &memBlockListMutex);435 436 if ( nleak == 0 || arr == NULL) {437 return nleak;438 }439 440 *arr = p_psAlloc( nleak*sizeof(psMemBlock), __FILE__, __LINE__);441 pthread_mutex_lock( &memBlockListMutex);442 443 for ( psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) {444 if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) {445 (*arr)[j++] = iter;446 if (j == nleak) { // found them all447 break;448 }449 }450 }451 452 pthread_mutex_unlock( &memBlockListMutex);453 423 424 pthread_mutex_lock( &memBlockListMutex ); 425 426 for ( psMemBlock * iter = topBlock; iter != NULL; iter = iter->nextBlock ) { 427 if ( ( psMemGetRefCounter( iter + 1 ) > 0 ) && ( iter->id >= id0 ) ) { 428 nleak++; 429 430 if ( fd != NULL ) { 431 if ( nleak == 1 ) { 432 fprintf( fd, " %20s:line ID\n", "file" ); 433 } 434 435 fprintf( fd, " %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id ); 436 } 437 } 438 } 439 440 pthread_mutex_unlock( &memBlockListMutex ); 441 442 if ( nleak == 0 || arr == NULL ) { 443 return nleak; 444 } 445 446 *arr = p_psAlloc( nleak * sizeof( psMemBlock ), __FILE__, __LINE__ ); 447 pthread_mutex_lock( &memBlockListMutex ); 448 449 for ( psMemBlock * iter = topBlock; iter != NULL; iter = iter->nextBlock ) { 450 if ( ( psMemGetRefCounter( iter + 1 ) > 0 ) && ( iter->id >= id0 ) ) { 451 ( *arr ) [ j++ ] = iter; 452 if ( j == nleak ) { // found them all 453 break; 454 } 455 } 456 } 457 458 pthread_mutex_unlock( &memBlockListMutex ); 459 454 460 return nleak; 455 461 } … … 457 463 /* 458 464 * Reference counting APIs 459 */ 465 */ 460 466 // return refCounter 461 psReferenceCount psMemGetRefCounter( void *vptr)462 { 463 psMemBlock * ptr;467 psReferenceCount psMemGetRefCounter( void *vptr ) 468 { 469 psMemBlock * ptr; 464 470 unsigned int refCount; 465 466 if ( vptr == NULL) {467 return 0;468 }469 470 ptr = ( (psMemBlock *)vptr) - 1;471 472 if ( checkMemBlock(ptr, __func__) != 0) {473 memProblemCallback(ptr, __func__, __LINE__);474 }475 476 pthread_mutex_lock( &ptr->refCounterMutex);471 472 if ( vptr == NULL ) { 473 return 0; 474 } 475 476 ptr = ( ( psMemBlock * ) vptr ) - 1; 477 478 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 479 memProblemCallback( ptr, __func__, __LINE__ ); 480 } 481 482 pthread_mutex_lock( &ptr->refCounterMutex ); 477 483 refCount = ptr->refCounter; 478 pthread_mutex_unlock( &ptr->refCounterMutex);479 484 pthread_mutex_unlock( &ptr->refCounterMutex ); 485 480 486 return refCount; 481 487 } 482 488 // increment and return refCounter 483 void* p_psMemIncrRefCounter( void *vptr, const char *file, int lineno)484 { 485 psMemBlock * ptr;486 487 if ( vptr == NULL) {488 return vptr;489 }490 491 ptr = ( (psMemBlock *)vptr) - 1;492 493 if ( checkMemBlock(ptr, __func__)) {494 memProblemCallback(ptr, file,lineno);495 }496 497 pthread_mutex_lock( &ptr->refCounterMutex);489 void* p_psMemIncrRefCounter( void *vptr, const char *file, int lineno ) 490 { 491 psMemBlock * ptr; 492 493 if ( vptr == NULL ) { 494 return vptr; 495 } 496 497 ptr = ( ( psMemBlock * ) vptr ) - 1; 498 499 if ( checkMemBlock( ptr, __func__ ) ) { 500 memProblemCallback( ptr, file, lineno ); 501 } 502 503 pthread_mutex_lock( &ptr->refCounterMutex ); 498 504 ptr->refCounter++; 499 pthread_mutex_unlock( &ptr->refCounterMutex);500 505 pthread_mutex_unlock( &ptr->refCounterMutex ); 506 501 507 return vptr; 502 508 } 503 509 504 510 // decrement and return refCounter 505 void* p_psMemDecrRefCounter(void *vptr,const char *file, int lineno) 506 { 507 if (vptr == NULL) { 508 return NULL; 509 } 510 511 psMemBlock *ptr = ((psMemBlock *)vptr) - 1; 512 513 if (checkMemBlock(ptr, __func__) != 0) { 514 memProblemCallback(ptr, file, lineno); 515 return NULL; 516 } 517 518 pthread_mutex_lock(&ptr->refCounterMutex); 519 520 if (ptr->refCounter > 1) { 521 /// XXX - Probably should have another mutex here. 522 ptr->refCounter--; // multiple references, just decrement the count. 523 pthread_mutex_unlock(&ptr->refCounterMutex); 524 525 } else { 526 pthread_mutex_unlock(&ptr->refCounterMutex); 527 528 // Did the user ask to be informed about this deallocation? 529 if (ptr->id == p_psMemFreeID) { 530 p_psMemFreeID += memFreeCallback(ptr); 531 } 532 533 if (ptr->freeFcn != NULL) { 534 ptr->freeFcn(vptr); 535 } 536 537 pthread_mutex_lock(&memBlockListMutex); 538 539 // cut the memBlock out of the memBlock list 540 if (ptr->nextBlock != NULL) { 541 ptr->nextBlock->previousBlock = ptr->previousBlock; 542 } 543 if (ptr->previousBlock != NULL) { 544 ptr->previousBlock->nextBlock = ptr->nextBlock; 545 } 546 if (lastMemBlockAllocated == ptr) { 547 lastMemBlockAllocated = ptr->nextBlock; 548 } 549 550 pthread_mutex_unlock(&memBlockListMutex); 551 552 553 // do we need to recycle? 554 if (ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE) { 555 556 int level = 1; 557 while (ptr->userMemorySize >= recycleBinSize[level]) { 558 level++; 559 } 560 level--; 561 562 ptr->refCounter = 0; 563 ptr->previousBlock = NULL; 564 565 pthread_mutex_lock(&recycleMemBlockListMutex); 566 ptr->nextBlock = recycleMemBlockList[level]; 567 if (recycleMemBlockList[level] != NULL) { 568 recycleMemBlockList[level]->previousBlock = ptr; 569 } 570 recycleMemBlockList[level] = ptr; 571 pthread_mutex_unlock(&recycleMemBlockListMutex); 572 511 void* p_psMemDecrRefCounter( void *vptr, const char *file, int lineno ) 512 { 513 if ( vptr == NULL ) { 514 return NULL; 515 } 516 517 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 518 519 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 520 memProblemCallback( ptr, file, lineno ); 521 return NULL; 522 } 523 524 pthread_mutex_lock( &ptr->refCounterMutex ); 525 526 if ( ptr->refCounter > 1 ) { 527 /// XXX - Probably should have another mutex here. 528 ptr->refCounter--; // multiple references, just decrement the count. 529 pthread_mutex_unlock( &ptr->refCounterMutex ); 530 573 531 } else { 574 // memory is larger than I want to recycle. 575 #ifdef PS_MEM_DEBUG 576 (void)p_psRealloc(vptr,0,file,lineno); 577 ptr->previousBlock = NULL; 578 ptr->nextBlock = deadBlockList; 579 if (deadBlockList != NULL) { 580 deadBlockList->previous = ptr; 581 } 582 deadBlockList = ptr; 583 #else 584 585 pthread_mutex_destroy(&ptr->refCounterMutex); 586 free(ptr); 587 #endif 588 589 } 590 591 592 pthread_mutex_destroy(&ptr->refCounterMutex); 593 594 595 vptr = NULL; // since we freed it, make sure we return NULL. 596 } 597 532 pthread_mutex_unlock( &ptr->refCounterMutex ); 533 534 // Did the user ask to be informed about this deallocation? 535 if ( ptr->id == p_psMemFreeID ) { 536 p_psMemFreeID += memFreeCallback( ptr ); 537 } 538 539 if ( ptr->freeFcn != NULL ) { 540 ptr->freeFcn( vptr ); 541 } 542 543 pthread_mutex_lock( &memBlockListMutex ); 544 545 // cut the memBlock out of the memBlock list 546 if ( ptr->nextBlock != NULL ) { 547 ptr->nextBlock->previousBlock = ptr->previousBlock; 548 } 549 if ( ptr->previousBlock != NULL ) { 550 ptr->previousBlock->nextBlock = ptr->nextBlock; 551 } 552 if ( lastMemBlockAllocated == ptr ) { 553 lastMemBlockAllocated = ptr->nextBlock; 554 } 555 556 pthread_mutex_unlock( &memBlockListMutex ); 557 558 559 // do we need to recycle? 560 if ( ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE ) { 561 562 int level = 1; 563 while ( ptr->userMemorySize >= recycleBinSize[ level ] ) { 564 level++; 565 } 566 level--; 567 568 ptr->refCounter = 0; 569 ptr->previousBlock = NULL; 570 571 pthread_mutex_lock( &recycleMemBlockListMutex ); 572 ptr->nextBlock = recycleMemBlockList[ level ]; 573 if ( recycleMemBlockList[ level ] != NULL ) { 574 recycleMemBlockList[ level ] ->previousBlock = ptr; 575 } 576 recycleMemBlockList[ level ] = ptr; 577 pthread_mutex_unlock( &recycleMemBlockListMutex ); 578 579 } else { 580 // memory is larger than I want to recycle. 581 #ifdef PS_MEM_DEBUG 582 ( void ) p_psRealloc( vptr, 0, file, lineno ); 583 ptr->previousBlock = NULL; 584 ptr->nextBlock = deadBlockList; 585 if ( deadBlockList != NULL ) { 586 deadBlockList->previous = ptr; 587 } 588 deadBlockList = ptr; 589 #else 590 591 pthread_mutex_destroy( &ptr->refCounterMutex ); 592 free( ptr ); 593 #endif 594 595 } 596 597 vptr = NULL; // since we freed it, make sure we return NULL. 598 } 599 598 600 return vptr; 599 601 } 600 602 601 void p_psMemSetDeallocator( void* vptr, psFreeFcn freeFcn)602 { 603 if ( vptr == NULL) {604 return;605 }606 607 psMemBlock *ptr = ( (psMemBlock *)vptr) - 1;608 609 if ( checkMemBlock(ptr, __func__) != 0) {610 memProblemCallback(ptr, __func__, __LINE__);611 }612 603 void p_psMemSetDeallocator( void* vptr, psFreeFcn freeFcn ) 604 { 605 if ( vptr == NULL ) { 606 return ; 607 } 608 609 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 610 611 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 612 memProblemCallback( ptr, __func__, __LINE__ ); 613 } 614 613 615 ptr->freeFcn = freeFcn; 614 615 } 616 psFreeFcn p_psMemGetDeallocator( void* vptr)617 { 618 if ( vptr == NULL) {619 return NULL;620 }621 622 psMemBlock *ptr = ( (psMemBlock *)vptr) - 1;623 624 if ( checkMemBlock(ptr, __func__) != 0) {625 memProblemCallback(ptr, __func__, __LINE__);626 }627 616 617 } 618 psFreeFcn p_psMemGetDeallocator( void* vptr ) 619 { 620 if ( vptr == NULL ) { 621 return NULL; 622 } 623 624 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 625 626 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 627 memProblemCallback( ptr, __func__, __LINE__ ); 628 } 629 628 630 return ptr->freeFcn; 629 631 } -
trunk/psLib/src/sysUtils/psType.h
r1292 r1360 1 1 /** @file psType.h 2 *3 * @brief Contains support for basic types4 *5 * This file defines common datatypes used throughout psLib.6 *7 * @ingroup DataContainer8 *9 * @author Robert DeSonia, MHPCC10 * @author Ross Harman, MHPCC11 *12 * @version $Revision: 1.14$ $Name: not supported by cvs2svn $13 * @date $Date: 2004-07-24 02:00:21$14 *15 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii16 */2 * 3 * @brief Contains support for basic types 4 * 5 * This file defines common datatypes used throughout psLib. 6 * 7 * @ingroup DataContainer 8 * 9 * @author Robert DeSonia, MHPCC 10 * @author Ross Harman, MHPCC 11 * 12 * @version $Revision: 1.15 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2004-07-31 02:28:10 $ 14 * 15 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 16 */ 17 17 18 18 #ifndef PS_TYPE_H … … 37 37 */ 38 38 39 typedef uint8_t psU8; ///< 8-bit unsigned int40 typedef uint16_t psU16; ///< 16-bit unsigned int41 typedef uint32_t psU32; ///< 32-bit unsigned int42 typedef uint64_t psU64; ///< 64-bit unsigned int43 typedef int8_t psS8; ///< 8-bit signed int44 typedef int16_t psS16; ///< 16-bit signed int45 typedef int32_t psS32; ///< 32-bit signed int46 typedef int64_t psS64; ///< 64-bit signed int47 typedef float psF32; ///< 32-bit floating point48 typedef double psF64; ///< 64-bit floating point49 typedef complex float psC32; ///< complex with 32-bit floating point Real and Imagary numbers50 typedef complex double psC64; ///< complex with 64-bit floating point Real and Imagary numbers51 typedef void* psPTR; ///< void pointer39 typedef uint8_t psU8; ///< 8-bit unsigned int 40 typedef uint16_t psU16; ///< 16-bit unsigned int 41 typedef uint32_t psU32; ///< 32-bit unsigned int 42 typedef uint64_t psU64; ///< 64-bit unsigned int 43 typedef int8_t psS8; ///< 8-bit signed int 44 typedef int16_t psS16; ///< 16-bit signed int 45 typedef int32_t psS32; ///< 32-bit signed int 46 typedef int64_t psS64; ///< 64-bit signed int 47 typedef float psF32; ///< 32-bit floating point 48 typedef double psF64; ///< 64-bit floating point 49 typedef complex float psC32; ///< complex with 32-bit floating point Real and Imagary numbers 50 typedef complex double psC64; ///< complex with 64-bit floating point Real and Imagary numbers 51 typedef void* psPTR; ///< void pointer 52 52 53 53 54 54 typedef enum { 55 PS_TYPE_S8 = 0x0101,///< Character.56 PS_TYPE_S16 = 0x0102,///< Short integer.57 PS_TYPE_S32 = 0x0104,///< Integer.58 PS_TYPE_S64 = 0x0108,///< Long integer.59 PS_TYPE_U8 = 0x0301,///< Unsigned character.60 PS_TYPE_U16 = 0x0302,///< Unsigned short integer.61 PS_TYPE_U32 = 0x0304,///< Unsigned integer.62 PS_TYPE_U64 = 0x0308,///< Unsigned long integer.63 PS_TYPE_F32 = 0x0404,///< Single-precision Floating point.64 PS_TYPE_F64 = 0x0408,///< Double-precision floating point.65 PS_TYPE_C32 = 0x0808,///< Complex numbers consisting of single-precision floating point.66 PS_TYPE_C64 = 0x0810,///< Complex numbers consisting of double-precision floating point.67 PS_TYPE_PTR = 0x0000 ///< Something else that's not supported for arithmetic.55 PS_TYPE_S8 = 0x0101, ///< Character. 56 PS_TYPE_S16 = 0x0102, ///< Short integer. 57 PS_TYPE_S32 = 0x0104, ///< Integer. 58 PS_TYPE_S64 = 0x0108, ///< Long integer. 59 PS_TYPE_U8 = 0x0301, ///< Unsigned character. 60 PS_TYPE_U16 = 0x0302, ///< Unsigned short integer. 61 PS_TYPE_U32 = 0x0304, ///< Unsigned integer. 62 PS_TYPE_U64 = 0x0308, ///< Unsigned long integer. 63 PS_TYPE_F32 = 0x0404, ///< Single-precision Floating point. 64 PS_TYPE_F64 = 0x0408, ///< Double-precision floating point. 65 PS_TYPE_C32 = 0x0808, ///< Complex numbers consisting of single-precision floating point. 66 PS_TYPE_C64 = 0x0810, ///< Complex numbers consisting of double-precision floating point. 67 PS_TYPE_PTR = 0x0000 ///< Something else that's not supported for arithmetic. 68 68 } psElemType; 69 69 70 70 #define PS_TYPE_MASK PS_TYPE_U8 ///< the psElemType to use for mask image 71 #define PS_TYPE_MASK_DATA U8 ///< the data member to use for mask image 71 72 #define PS_TYPE_MASK_NAME "psU8" 72 73 typedef psU8 psMaskType; ///< the C datatype for a mask image … … 127 128 */ 128 129 typedef enum { 129 PS_DIMEN_SCALAR, ///< Scalar.130 PS_DIMEN_VECTOR, ///< Vector.131 PS_DIMEN_TRANSV, ///< Transposed vector.132 PS_DIMEN_IMAGE, ///< Image.130 PS_DIMEN_SCALAR, ///< Scalar. 131 PS_DIMEN_VECTOR, ///< Vector. 132 PS_DIMEN_TRANSV, ///< Transposed vector. 133 PS_DIMEN_IMAGE, ///< Image. 133 134 PS_DIMEN_OTHER ///< Something else that's not supported for arithmetic. 134 135 } psDimen; … … 141 142 */ 142 143 typedef struct 143 {144 psElemType type; ///< Primitive type.145 psDimen dimen; ///< Dimensionality.146 }144 { 145 psElemType type; ///< Primitive type. 146 psDimen dimen; ///< Dimensionality. 147 } 147 148 psType; 148 149 -
trunk/psLib/test/psTest.c
r1193 r1360 27 27 #define HEADER_BOTTOM "\\**********************************************************************************/\n\n" 28 28 29 bool p_runTestSuite( FILE *fp, const char* testPointFile, const char* packageName,30 testDescription tests[], int argc, char * const argv[])29 bool p_runTestSuite( FILE *fp, const char* testPointFile, const char* packageName, 30 testDescription tests[], int argc, char * const argv[] ) 31 31 { 32 32 bool success = true; … … 37 37 int n; 38 38 extern char *optarg; 39 40 if (argc > 0) { 41 while ( (c=getopt(argc,argv,"lhn:dt:")) != -1) { 42 switch (c) { 43 case 'h': 44 printf("Usage: %s [-l] [-d] [-h] [-n=Testpoint#] [-t=TestpointName]\n" 45 " where:\n" 46 " -l : lists the testpoints contained in this test driver executable\n" 47 " -d : turns on debugger-friendly mode (no forking, aborts/signals are not handled)\n" 48 " -h : prints this help\n" 49 " -n : specifies a particular testpoint by number to run\n" 50 " -t : specifies a particular testpoint by name to run\n" 51 " (if no -l, -n or -t options are given, all testpoints are run)\n", 52 argv[0]); 53 runAll = false; 54 break; 55 case 'd': 56 useFork = false; 57 break; 58 case 'l': 59 printf("Test Driver: %s\n",testPointFile); 60 printf("Package Name: %s\n",packageName); 61 printf("Testpoints:\n"); 62 runAll = false; 63 for (int index=0; tests[index].fcn != NULL; index++) { 64 printf(" %6d - %s \n",tests[index].testPointNumber, 65 tests[index].testPointName); 66 } 67 printf("\n"); 68 break; 69 case 't': 70 runAll = false; 71 for (int index=0; tests[index].fcn != NULL; index++) { 72 if (strcmp(optarg,tests[index].testPointName) == 0) { 73 success = p_runTest(fp, 74 testPointFile, 75 packageName, 76 tests[index].testPointName, 77 tests[index].fcn, 78 tests[index].expectedReturn, 79 useFork) && success; 80 } 81 } 82 break; 83 case 'n': 84 runAll = false; 85 if (sscanf(optarg,"%i",&n) != 1) { 86 psError(__func__,"Failed to parse the testpoint number (%s).", 87 optarg); 88 break; 89 } 90 found = false; 91 for (int index=0; tests[index].fcn != NULL; index++) { 92 if (n==tests[index].testPointNumber) { 93 found = true; 94 success = p_runTest(fp, 95 testPointFile, 96 packageName, 97 tests[index].testPointName, 98 tests[index].fcn, 99 tests[index].expectedReturn, 100 useFork) && success; 101 } 102 } 103 if (! found) { 104 psError(__func__,"The specified testpoint number (%d) doesn't exist in this test driver.", 105 n); 106 break; 107 } 108 break; 109 case '?': 110 psError(__func__,"Option %s is not recognized and is ignored.",optarg); 111 break; 112 } 113 } 114 } 115 116 if (runAll) { 117 for (int index=0; tests[index].fcn != NULL; index++) { 118 if (! tests[index].isDuplicateEntry) { 119 success = p_runTest(fp, 120 testPointFile, 121 packageName, 122 tests[index].testPointName, 123 tests[index].fcn, 124 tests[index].expectedReturn, 125 useFork) && success; 126 } 127 } 128 } 39 40 if ( argc > 0 ) { 41 while ( ( c = getopt( argc, argv, "lhn:dt:" ) ) != -1 ) { 42 switch ( c ) { 43 case 'h': 44 printf( "Usage: %s [-l] [-d] [-h] [-n=Testpoint#] [-t=TestpointName]\n" 45 " where:\n" 46 " -l : lists the testpoints contained in this test driver executable\n" 47 " -d : turns on debugger-friendly mode (no forking, aborts/signals are not handled)\n" 48 " -h : prints this help\n" 49 " -n : specifies a particular testpoint by number to run\n" 50 " -t : specifies a particular testpoint by name to run\n" 51 " (if no -l, -n or -t options are given, all testpoints are run)\n", 52 argv[ 0 ] ); 53 runAll = false; 54 break; 55 case 'd': 56 useFork = false; 57 break; 58 case 'l': 59 printf( "Test Driver: %s\n", testPointFile ); 60 printf( "Package Name: %s\n", packageName ); 61 printf( "Testpoints:\n" ); 62 runAll = false; 63 for ( int index = 0; tests[ index ].fcn != NULL; index++ ) { 64 printf( " %6d - %s \n", tests[ index ].testPointNumber, 65 tests[ index ].testPointName ); 66 } 67 printf( "\n" ); 68 break; 69 case 't': 70 runAll = false; 71 for ( int index = 0; tests[ index ].fcn != NULL; index++ ) { 72 if ( strcmp( optarg, tests[ index ].testPointName ) == 0 ) { 73 success = p_runTest( fp, 74 testPointFile, 75 packageName, 76 tests[ index ].testPointName, 77 tests[ index ].fcn, 78 tests[ index ].expectedReturn, 79 useFork ) && success; 80 } 81 } 82 break; 83 case 'n': 84 runAll = false; 85 if ( sscanf( optarg, "%i", &n ) != 1 ) { 86 psError( __func__, "Failed to parse the testpoint number (%s).", 87 optarg ); 88 break; 89 } 90 found = false; 91 for ( int index = 0; tests[ index ].fcn != NULL; index++ ) { 92 if ( n == tests[ index ].testPointNumber ) { 93 found = true; 94 success = p_runTest( fp, 95 testPointFile, 96 packageName, 97 tests[ index ].testPointName, 98 tests[ index ].fcn, 99 tests[ index ].expectedReturn, 100 useFork ) && success; 101 } 102 } 103 if ( ! found ) { 104 psError( __func__, "The specified testpoint number (%d) doesn't exist in this test driver.", 105 n ); 106 break; 107 } 108 break; 109 case '?': 110 psError( __func__, "Option %s is not recognized and is ignored.", optarg ); 111 break; 112 } 113 } 114 } 115 116 if ( runAll ) { 117 for ( int index = 0; tests[ index ].fcn != NULL; index++ ) { 118 if ( ! tests[ index ].isDuplicateEntry ) { 119 success = p_runTest( fp, 120 testPointFile, 121 packageName, 122 tests[ index ].testPointName, 123 tests[ index ].fcn, 124 tests[ index ].expectedReturn, 125 useFork ) && success; 126 } 127 } 128 } 129 130 if ( ! success ) { 131 psError( testPointFile, "One or more tests failed" ); 132 } 133 129 134 return success; 130 135 } 131 136 132 bool p_runTest( FILE *fp, const char* testPointFile, const char* packageName, const char* testPointName,133 testFcn fcn, int expectedReturn, bool useFork)137 bool p_runTest( FILE *fp, const char* testPointFile, const char* packageName, const char* testPointName, 138 testFcn fcn, int expectedReturn, bool useFork ) 134 139 { 135 140 int childReturn = 0; 136 141 pid_t child; 137 138 p_printPositiveTestHeader(fp,testPointFile,packageName,testPointName); 139 140 if (useFork) { 141 child = fork(); 142 if (child == 0) { // I am the child process, run the test 142 143 p_printPositiveTestHeader( fp, testPointFile, packageName, testPointName ); 144 145 if ( useFork ) { 146 child = fork(); 147 if ( child == 0 ) { // I am the child process, run the test 148 int currentId = psMemGetId(); 149 int retVal = fcn(); 150 if ( retVal == 0 ) { // only bother checking memory if test executed to end. 151 if ( psMemCheckLeaks( currentId, NULL, stderr ) != 0 ) { 152 psError( __func__, "Memory Leaks Detected" ); 153 retVal = 64; 154 } 155 psMemCheckCorruption( 1 ); 156 } 157 exit( retVal ); 158 } else if ( child < 0 ) { 159 fprintf( fp, "Couldn't fork a process to run a negative test (%s|%s)", 160 packageName, testPointName ); 161 abort(); 162 } 163 164 waitpid( child, &childReturn, 0 ); 165 if ( WIFSIGNALED( childReturn ) ) { 166 childReturn = -WTERMSIG( childReturn ); 167 } else { 168 childReturn = WEXITSTATUS( childReturn ); 169 } 170 } else { 143 171 int currentId = psMemGetId(); 144 int retVal = fcn(); 145 if (retVal == 0) { // only bother checking memory if test executed to end. 146 if (psMemCheckLeaks(currentId,NULL,stderr) != 0) { 147 psError(__func__,"Memory Leaks Detected"); 148 retVal = 64; 149 } 150 psMemCheckCorruption(1); 151 } 152 exit(retVal); 153 } else if (child < 0) { 154 fprintf(fp,"Couldn't fork a process to run a negative test (%s|%s)", 155 packageName, testPointName); 156 abort(); 157 } 158 159 waitpid(child,&childReturn,0); 160 if (WIFSIGNALED(childReturn)) { 161 childReturn = -WTERMSIG(childReturn); 172 childReturn = fcn(); 173 if ( childReturn == 0 ) { // only bother checking memory if test executed to end. 174 if ( psMemCheckLeaks( currentId, NULL, stderr ) != 0 ) { 175 psError( __func__, "Memory Leaks Detected" ); 176 childReturn = 64; 177 } 178 psMemCheckCorruption( 1 ); 179 } 180 } 181 182 183 if ( childReturn != expectedReturn ) { 184 fprintf( fp, "Return value mismatch: expected %d, got %d", 185 expectedReturn, childReturn ); 186 } 187 188 p_printFooter( fp, testPointFile, packageName, testPointName, 189 ( childReturn == expectedReturn ) ); 190 191 return ( childReturn == expectedReturn ); 192 } 193 194 void p_printPositiveTestHeader( FILE *fp, 195 const char* testPointFile, 196 const char* packageName, 197 const char* testPointName ) 198 { 199 char TP[ 80 ]; 200 201 snprintf( TP, 80, "%s{%s}", packageName, testPointName ); 202 203 fprintf( fp, HEADER_TOP ); 204 fprintf( fp, HEADER_LINE_STRING, "TestFile", testPointFile ); 205 fprintf( fp, HEADER_LINE_STRING, "TestPoint", TP ); 206 fprintf( fp, HEADER_LINE_STRING, "TestType", "Positive" ); 207 fprintf( fp, HEADER_BOTTOM ); 208 } 209 210 void p_printNegativeTestHeader( FILE *fp, 211 const char* testPointFile, 212 const char* packageName, 213 const char* testPointName, 214 const char* expectedError, 215 int exitValue ) 216 { 217 char TP[ 80 ]; 218 219 snprintf( TP, 80, "%s{%s}", packageName, testPointName ); 220 221 fprintf( fp, HEADER_TOP ); 222 fprintf( fp, HEADER_LINE_STRING, "TestFile", testPointFile ); 223 fprintf( fp, HEADER_LINE_STRING, "TestPoint", TP ); 224 fprintf( fp, HEADER_LINE_STRING, "TestType", "Negative" ); 225 fprintf( fp, HEADER_LINE_STRING, "ExpectedErrorText", expectedError ); 226 fprintf( fp, HEADER_LINE_INT, "ExpectedStatusValue", exitValue ); 227 fprintf( fp, HEADER_BOTTOM ); 228 } 229 230 231 void p_printFooter( FILE *fp, 232 const char* testPointFile, 233 const char* packageName, 234 const char* testPointName, 235 bool success ) 236 { 237 if ( success ) { 238 fprintf( fp, "\n---> TESTPOINT PASSED (%s{%s} | %s)\n\n", packageName, testPointName, testPointFile ); 162 239 } else { 163 childReturn = WEXITSTATUS(childReturn); 164 } 165 } else { 166 int currentId = psMemGetId(); 167 childReturn = fcn(); 168 if (childReturn == 0) { // only bother checking memory if test executed to end. 169 if (psMemCheckLeaks(currentId,NULL,stderr) != 0) { 170 psError(__func__,"Memory Leaks Detected"); 171 childReturn = 64; 172 } 173 psMemCheckCorruption(1); 174 } 175 } 176 177 178 if (childReturn != expectedReturn) { 179 fprintf(fp,"Return value mismatch: expected %d, got %d", 180 expectedReturn,childReturn); 181 } 182 183 p_printFooter(fp,testPointFile,packageName,testPointName, 184 (childReturn==expectedReturn)); 185 186 return (childReturn==expectedReturn); 187 } 188 189 void p_printPositiveTestHeader(FILE *fp, 190 const char* testPointFile, 191 const char* packageName, 192 const char* testPointName) 193 { 194 char TP[80]; 195 196 snprintf(TP,80,"%s{%s}",packageName,testPointName); 197 198 fprintf(fp, HEADER_TOP); 199 fprintf(fp, HEADER_LINE_STRING, "TestFile", testPointFile); 200 fprintf(fp, HEADER_LINE_STRING, "TestPoint", TP); 201 fprintf(fp, HEADER_LINE_STRING, "TestType","Positive"); 202 fprintf(fp, HEADER_BOTTOM); 203 } 204 205 void p_printNegativeTestHeader(FILE *fp, 206 const char* testPointFile, 207 const char* packageName, 208 const char* testPointName, 209 const char* expectedError, 210 int exitValue) 211 { 212 char TP[80]; 213 214 snprintf(TP,80,"%s{%s}",packageName,testPointName); 215 216 fprintf(fp, HEADER_TOP); 217 fprintf(fp, HEADER_LINE_STRING, "TestFile", testPointFile); 218 fprintf(fp, HEADER_LINE_STRING, "TestPoint", TP); 219 fprintf(fp, HEADER_LINE_STRING,"TestType","Negative"); 220 fprintf(fp, HEADER_LINE_STRING,"ExpectedErrorText",expectedError); 221 fprintf(fp, HEADER_LINE_INT,"ExpectedStatusValue",exitValue); 222 fprintf(fp, HEADER_BOTTOM); 223 } 224 225 226 void p_printFooter(FILE *fp, 227 const char* testPointFile, 228 const char* packageName, 229 const char* testPointName, 230 bool success) 231 { 232 if (success) { 233 fprintf(fp, "\n---> TESTPOINT PASSED (%s{%s} | %s)\n\n", packageName,testPointName, testPointFile); 234 } else { 235 fprintf(fp, "\n---> TESTPOINT FAILED (%s{%s} | %s)\n\n", packageName,testPointName,testPointFile); 236 } 237 } 240 fprintf( fp, "\n---> TESTPOINT FAILED (%s{%s} | %s)\n\n", packageName, testPointName, testPointFile ); 241 } 242 }
Note:
See TracChangeset
for help on using the changeset viewer.
