📄 az_util.c
字号:
(int *) NULL);}/******************************************************************************//******************************************************************************//******************************************************************************/double *AZ_manage_memory(unsigned int input_size, int action, int type, char *name, int *status)/******************************************************************************* AZ_manage_memory() either frees memory that was previously allocated or returns a pointer to memory for future use (this pointer can be a newly allocated block or a block that was previously allocated). Author: Ray S. Tuminaro, SNL, 1422 ======= Return code: double *, pointer to allocated memory. ============ Parameter list: =============== input_size: integer variable. On input, size indicates the amount of memory that is needed (NOTE: ignored if action == AZ_CLEAR). action: On input, action indicates whether to allocate or free memory. = AZ_ALLOC: look for a chunk of memory (in the memory management list pointed to by 'head') that has already been allocated with a memory-type 'type', a size in bytes of 'size', and labelled with the string 'name'. If this memory is found return a pointer to this memory and set *status to AZ_OLD_ADDRESS. If this memory is not found allocate the memory, put it in the memory management list, return a pointer to this piece of memory, and set *status to AZ_NEW_ADDRESS. = AZ_REALLOC:look for a chunk of memory (in the memory management list pointed to by 'head') that has already been allocated with a memory-type 'type', and labelled with the string 'name'. Reallocate this item with size 'size' and change the size field. = AZ_CLEAR: free all memory associated with any chunk of memory that has the memory-type 'type'. = AZ_SELECTIVE_CLEAR: free all memory associated with any chunk ofmemory that has the memory-type 'type' and the memory-name 'name'. type: On input, a number associated with each piece of memory that is allocated. This number is used when checking to see if a requested piece of memory is already allocated. This number is also used when freeing up memory (see AZ_CLEAR). NOTE: Aztec uses the type AZ_SYS for temporary internal pieces of memory that can be deallocated after solving a linear system. name: On input, a character string associated with each piece of memory that is allocated. This string is used when checking to see if a requested piece of memory is already allocated. Additionally, this string is printed when AZ_manage_memory() fails to allocate memory. status: On output, *status = AZ_NEW_ADDRESS indicates that a new piece of memory has been allocated. *status = AZ_OLD_ADDRESS indicates that a pointer to a previously allocated chunk of memory is returned. NOTE: status is not used if action == AZ_CLEAR has been allocated.*******************************************************************************/{ /* local variables */ struct mem_ptr { char *name; double *address; int type; int size; char special; struct mem_ptr *next; }; long int size; static struct mem_ptr *head = NULL; struct mem_ptr *current, *temp,*prev, *thenext; int found = 0, i,j, n2, nn;int aligned_str_mem,aligned_j,aligned_size;double *dtmp; /**************************** execution begins ******************************/ size = (int) input_size; current = head; if (action == -43) { /* print the list */ while (current != NULL) { (void) printf("(%8d,%8d %ld) ==> %s\n", current->type, current->size, (long int) current->address, current->name); prev = current; current = current->next; } return (double *) 0; } else if (action == AZ_ALLOC) { if (size == 0) return (double *) 0; /* first look for entry */ while ( current != NULL) { if ( (current->size == size) && (current->type == type) && (strcmp(current->name,name) == 0) ) { found = 1; break; } prev = current; current = current->next; } if (found == 0) { /* * Put in a new entry if it has the type 0 we will put it at the front of * the list else put it at the end of the list This is done for efficiency * reasons as type = 0 is used a lot. */ j = strlen(name) + 1; aligned_str_mem = sizeof(struct mem_ptr); aligned_j = j; aligned_size = size; aligned_str_mem += (sizeof(double) - (aligned_str_mem%sizeof(double))); aligned_j += (sizeof(double) - (aligned_j%sizeof(double))); aligned_size += (sizeof(double) - (aligned_size%sizeof(double))); dtmp = (double *) AZ_allocate((unsigned int) (aligned_str_mem+aligned_j+ aligned_size) ); if (dtmp== NULL) { (void) fprintf(stderr, "Error: Not enough space to allocate\n"); (void) fprintf(stderr, " '%s' in memory_manage()\n", name); (void) fprintf(stderr, " Asked for %ld bytes. Perhaps\n", size); (void) fprintf(stderr, " a smaller problem should be run\n"); exit(-1); } temp = (struct mem_ptr *) &(dtmp[aligned_size/sizeof(double)]); temp->name = (char *) &(dtmp[(aligned_str_mem+aligned_size)/ sizeof(double)]); temp->address = dtmp; for (i = 0 ; i < j; i++ ) (temp->name)[i] = name[i]; temp->special = 'N'; temp->type = type; temp->size = size; /* put at the head of the list */ temp->next = head; head = temp; *status = AZ_NEW_ADDRESS; return temp->address; } else { *status = AZ_OLD_ADDRESS; return current->address; } } else if (action == AZ_CLEAR) { prev = NULL; while (current != NULL) { if (current->type == type) { if (prev == NULL) head = current->next; else prev->next = current->next; temp = current->next; AZ_free(current->address); current = temp; } else { prev = current; current = current->next; } } return (double *) 0; } else if (action == AZ_EVERYBODY_BUT_CLEAR) { prev = NULL; while (current != NULL) { if ( (current->type == type) && (strncmp(current->name,name,5) != 0) ) { if (prev == NULL) head = current->next; else prev->next = current->next; temp = current->next; AZ_free(current->address); current = temp; } else { prev = current; current = current->next; } } return (double *) 0; } else if (action == AZ_SUBSELECTIVE_CLEAR) { prev = NULL; while (current != NULL) { if ( (current->type == type) && (strncmp(current->name,name,5) == 0) ) { if (prev == NULL) head = current->next; else prev->next = current->next; temp = current->next; AZ_free(current->address); current = temp; } else { prev = current; current = current->next; } } return (double *) 0; } else if (action == AZ_SELECTIVE_CLEAR) { prev = NULL; while (current != NULL) { if ( (current->type == type) && (strcmp(current->name,name) == 0) ) { if (prev == NULL) head = current->next; else prev->next = current->next; temp = current->next; AZ_free(current->address); current = temp; } else { prev = current; current = current->next; } } return (double *) 0; } else if ( (action == AZ_REALLOC) || (action == AZ_SPEC_REALLOC)) { prev = NULL; /* first look for entry */ while ( current != NULL) { if ( (current->type == type) && (strcmp(current->name,name) == 0) ) { found = 1; break; } prev = current; current = current->next; } if (current == NULL) { (void) fprintf(stderr, "memory_management error: %s with type %d not", name, type); (void) fprintf(stderr, " found during reallocation\n"); exit(-1); } if ( (action == AZ_REALLOC) && (current->special != 'N')) { *status = AZ_SPECIAL; return(current->address); } else if (current->special != 'N') { *status = AZ_SPECIAL; } else *status = AZ_OLD_ADDRESS; if (current->size == size) return(current->address); j = strlen(name) + 1; aligned_str_mem = sizeof(struct mem_ptr); aligned_j = j; aligned_size = size; aligned_str_mem += (sizeof(double) - (aligned_str_mem%sizeof(double))); aligned_j += (sizeof(double) - (aligned_j%sizeof(double))); aligned_size += (sizeof(double) - (aligned_size%sizeof(double))); thenext = current->next; dtmp = current->address; dtmp = (double *) AZ_realloc((char *) dtmp,(unsigned int) aligned_str_mem+aligned_j+aligned_size); if (dtmp == NULL) { (void) fprintf(stderr, "Error:Not enough memory for '%s'\n", name); (void) fprintf(stderr, " Asked for %ld bytes. Perhaps\n", size); (void) fprintf(stderr, " a smaller problem should be run\n"); exit(-1); } temp = (struct mem_ptr *) &(dtmp[aligned_size/sizeof(double)]); temp->name = (char *) &(dtmp[(aligned_str_mem+aligned_size)/ sizeof(double)]); temp->address = dtmp; for (i = 0 ; i < j; i++ ) (temp->name)[i] = name[i]; temp->special = 'N'; if (action == AZ_SPEC_REALLOC) temp->special = 'S'; temp->type = type; temp->size = size; if (prev == NULL) head = temp; else prev->next = temp; temp->next = thenext; return temp->address; } else if (action == AZ_RESET_STRING) { prev = NULL; /* first look for entry */ n2 = strlen(name); while ( current != NULL) { nn = strlen(current->name); if ( (current->type == type) && (strncmp(current->name,name,(unsigned) nn) == 0) && (n2 < nn*2)) { found = 1; break; } prev = current; current = current->next; } if (current == NULL) { (void) fprintf(stderr, "memory_management error: %s with type %d not", name, type); (void) fprintf(stderr, " found while changing name\n"); exit(-1); } sprintf(current->name,"%s",&(name[nn])); *status = AZ_OLD_ADDRESS; } else if (action == AZ_EMPTY ) { if (current == NULL) *status = -1; else *status = 1; } else if (action == AZ_LOOKFOR_PRINT) { /* first look for entry */ printf("Looking in system for possible mismatches\n"); while ( current != NULL) { if (current->name[0] == 'P') { if (current->type != type) { printf("AZ_name/type does not match %d %d\n\n", current->type,type); return(NULL); } i = strcmp(current->name,name); if (i != 0) { printf("option keys do not match (%s) (%s)\n", current->name,name); nn = 1; while ( (current->name[nn] != ' ' )&&(nn < (int) strlen(current->name))) { if (current->name[nn] != name[nn]) break; nn++; } if ((current->name[nn] != ' ') || (name[nn] != ' ')) { sscanf(&(current->name[1]),"%d", &i); sscanf(&(name[1]),"%d", &j); printf("found context with different matrix size (%d vs. %d)\n", i,j); return(NULL); } i = (int) ( name[++nn] - '!'); j = (int) ( current->name[nn] - '!'); if (j != i) { printf("==> check overlapping and reordering choices\n"); return(NULL); } i = (int) ( name[++nn] - '!');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -