static void chapel_display_thread(qt_key_t addr, qthread_f f, void *arg, void *retloc, unsigned int thread_id, void *tls, void *callarg) { chpl_qthread_tls_t *rep = (chpl_qthread_tls_t *)tls; if (rep) { if ((rep->lock_lineno > 0) && rep->lock_filename) { fprintf(stderr, "Waiting at: %s:%zu (task %s:%zu)\n", chpl_lookupFilename(rep->lock_filename), rep->lock_lineno, chpl_lookupFilename(rep->chpl_data.task_filename), rep->chpl_data.task_lineno); } else if (rep->lock_lineno == 0 && rep->lock_filename) { fprintf(stderr, "Waiting for more work (line 0? file:%s) (task %s:%zu)\n", chpl_lookupFilename(rep->lock_filename), chpl_lookupFilename(rep->chpl_data.task_filename), rep->chpl_data.task_lineno); } else if (rep->lock_lineno == 0) { fprintf(stderr, "Waiting for dependencies (uninitialized task %s:%zu)\n", chpl_lookupFilename(rep->chpl_data.task_filename), rep->chpl_data.task_lineno); } fflush(stderr); } }
static int descCmp(const void* p1, const void* p2) { memTableEntry* m1 = *(memTableEntry**)p1; memTableEntry* m2 = *(memTableEntry**)p2; c_string m1Filename; c_string m2Filename; int val = strcmp(chpl_mem_descString(m1->description), chpl_mem_descString(m2->description)); if (val == 0 && m1->filename && m2->filename) { m1Filename = chpl_lookupFilename(m1->filename); m2Filename = chpl_lookupFilename(m2->filename); val = strcmp(m1Filename, m2Filename); } if (val == 0) val = (m1->lineno < m2->lineno) ? -1 : ((m1->lineno > m2->lineno) ? 1 : 0); return val; }
void chpl_warning(const char* message, int32_t lineno, int32_t filenameIdx) { const char* filename = NULL; // squash warnings if --quiet flag is used if (verbosity == 0) { return; } if (filenameIdx != 0) filename = chpl_lookupFilename(filenameIdx); chpl_warning_explicit(message, lineno, filename); }
void chpl_track_free(void* memAlloc, int32_t lineno, int32_t filename) { memTableEntry* memEntry = NULL; if (chpl_memTrack) { memTrack_lock(); memEntry = removeMemTableEntry(memAlloc); if (memEntry) { if (chpl_verbose_mem) { fprintf(memLogFile, "%" PRI_c_nodeid_t ": %s:%" PRId32 ": free %zuB of %s at %p\n", chpl_nodeID, (filename ? chpl_lookupFilename(filename) : "--"), lineno, memEntry->number * memEntry->size, chpl_mem_descString(memEntry->description), memAlloc); } sys_free(memEntry); } memTrack_unlock(); } else if (chpl_verbose_mem && !memEntry) { fprintf(memLogFile, "%" PRI_c_nodeid_t ": %s:%" PRId32 ": free at %p\n", chpl_nodeID, (filename ? chpl_lookupFilename(filename) : "--"), lineno, memAlloc); } }
void chpl_vdebug_log_put(void* addr, c_nodeid_t node, void* raddr, size_t size, int32_t typeIndex, int ln, int32_t fn) { if (chpl_vdebug) { struct timeval tv; chpl_taskID_t commTask = chpl_task_getId(); (void) gettimeofday (&tv, NULL); chpl_dprintf (chpl_vdebug_fd, "put: %lld.%06ld %d %d %lu 0x%lx 0x%lx %d %d %d %d %s\n", (long long) tv.tv_sec, (long) tv.tv_usec, chpl_nodeID, node, (unsigned long) commTask, (long) addr, (long) raddr, 1, typeIndex, (int)size, ln, chpl_lookupFilename(fn)); } }
void chpl_vdebug_log_get_strd(void* dstaddr, void* dststrides, c_nodeid_t srcnode_id, void* srcaddr, void* srcstrides, void* count, int32_t stridelevels, int32_t elemSize, int32_t typeIndex, int ln, int32_t fn) { if (chpl_vdebug) { struct timeval tv; chpl_taskID_t commTask = chpl_task_getId(); (void) gettimeofday (&tv, NULL); chpl_dprintf (chpl_vdebug_fd, "st_get: %lld.%06ld %d %ld %lu 0x%lx 0x%lx %d %d %d %s\n", (long long) tv.tv_sec, (long) tv.tv_usec, chpl_nodeID, (long) srcnode_id, (unsigned long) commTask, (long) dstaddr, (long) srcaddr, elemSize, typeIndex, ln, chpl_lookupFilename(fn)); // print out the srcstrides and dststrides and stridelevels? } }
void chpl_track_malloc(void* memAlloc, size_t number, size_t size, chpl_mem_descInt_t description, int32_t lineno, int32_t filename) { if (number * size > memThreshold) { if (chpl_memTrack && chpl_mem_descTrack(description)) { memTrack_lock(); addMemTableEntry(memAlloc, number, size, description, lineno, filename); memTrack_unlock(); } if (chpl_verbose_mem) { fprintf(memLogFile, "%" PRI_c_nodeid_t ": %s:%" PRId32 ": allocate %zuB of %s at %p\n", chpl_nodeID, (filename ? chpl_lookupFilename(filename) : "--"), lineno, number * size, chpl_mem_descString(description), memAlloc); } } }
void cb_task_create(const chpl_task_cb_info_t *info) { struct timeval tv; if (!chpl_vdebug) return; if (chpl_vdebug_fd >= 0) { chpl_taskID_t taskId = chpl_task_getId(); //printf ("taskCB: event: %d, node %d proc %s task id: %llu, new task id: %llu\n", // (int)info->event_kind, (int)info->nodeID, // (info->iu.full.is_executeOn ? "O" : "L"), taskId, info->iu.full.id); (void)gettimeofday(&tv, NULL); chpl_dprintf (chpl_vdebug_fd, "task: %lld.%06ld %lld %ld %lu %s %ld %s\n", (long long) tv.tv_sec, (long) tv.tv_usec, (long long) info->nodeID, (long int) info->iu.full.id, (unsigned long) taskId, (info->iu.full.is_executeOn ? "O" : "L"), (long int) info->iu.full.lineno, chpl_lookupFilename(info->iu.full.filename)); } }
// // Walk over the linked list of thread states and print the ones that // are blocked/waiting. This is used by both the deadlock reporting // and the ^C signal handler. // static void report_locked_threads(void) { lockReport_t* rep; fflush(stdout); rep = lockReportHead; while (rep != NULL) { if (rep->maybeLocked) { if (rep->lineno > 0 && rep->filename) fprintf(stderr, "Waiting at: %s:%d\n", chpl_lookupFilename(rep->filename), rep->lineno); else if (rep->lineno == 0 && rep->filename == CHPL_FILE_IDX_IDLE_TASK) fprintf(stderr, "Waiting for more work\n"); } rep = rep->next; } fflush(stdout); }
// // This signal handler prints an overall task report, containing // pending tasks and those that are running. // static void report_all_tasks(void) { task_pool_p pendingTask = task_pool_head; printf("Task report\n"); printf("--------------------------------\n"); // print out pending tasks printf("Pending tasks:\n"); while (pendingTask != NULL) { printf("- %s:%d\n", chpl_lookupFilename(pendingTask->filename), (int)pendingTask->lineno); pendingTask = pendingTask->next; } printf("\n"); // print out running tasks printf("Known tasks:\n"); chpldev_taskTable_print(); }
static void chpl_stack_unwind(void){ // This is just a prototype using libunwind unw_cursor_t cursor; unw_context_t uc; unw_word_t wordValue; char buffer[128]; unsigned int line; #ifdef __linux__ unw_proc_info_t info; // Get the exec path and name for the precise line printing char process_name[128]; line = readlink("/proc/self/exe", process_name, sizeof(process_name)); // It unlikely to happen but this means that the process name is too big // for our buffer. In this case, we truncate the name if(line == sizeof(process_name)) line = sizeof(process_name)-1; process_name[line] = '\0'; #endif // Check if we need to print the stack trace (default = yes) if(! chpl_get_rt_env_bool("UNWIND", true)) { return; } line = 0; unw_getcontext(&uc); unw_init_local(&cursor, &uc); if(chpl_sizeSymTable > 0) fprintf(stderr,"Stacktrace\n\n"); // This loop does the effective stack unwind, see libunwind documentation while (unw_step(&cursor) > 0) { unw_get_proc_name(&cursor, buffer, sizeof(buffer), &wordValue); // Since this stack trace is printed out a program exit, we do not believe // it is performance sensitive. Additionally, this initial implementation // favors simplicity over performance. // // If it becomes necessary to improve performance, this code could use be // faster using one of these two strategies: // 1) Use a hashtable or map to find entries in chpl_funSymTable, or // 2) Emit chpl_funSymTable in sorted order and use binary search on it for(int t = 0; t < chpl_sizeSymTable; t+=2 ){ if (!strcmp(chpl_funSymTable[t], buffer)){ #ifdef __linux__ // Maybe we can get a more precise line number unw_get_proc_info(&cursor, &info); line = chpl_unwind_getLineNum(process_name, (void *)(info.start_ip + wordValue)); // We wasn't able to obtain the line number, let's use the procedure // line number if(line == 0) line = chpl_filenumSymTable[t+1]; #else line = chpl_filenumSymTable[t+1]; #endif fprintf(stderr,"%s() at %s:%d\n", chpl_funSymTable[t+1], chpl_lookupFilename(chpl_filenumSymTable[t]), line); break; } } } }
void chpl_error(const char *message, int32_t lineno, int32_t filenameIdx) { const char *filename = NULL; if (filenameIdx != 0) filename= chpl_lookupFilename(filenameIdx); chpl_error_explicit(message, lineno, filename); }
static void printMemAllocs(chpl_mem_descInt_t description, int64_t threshold, int32_t lineno, int32_t filename) { const int numberWidth = 9; const int precision = sizeof(uintptr_t) * 2; const int addressWidth = precision+4; const int descWidth = 33; int filenameWidth = strlen("Allocated Memory (Bytes)"); int totalWidth; int filenameLength; memTableEntry* memEntry; c_string memEntryFilename; int n, i; char* loc; memTableEntry** table; if (!chpl_memTrack) { chpl_warning("invalid call to printMemAllocs(); rerun with --memTrack", lineno, filename); return; } n = 0; filenameWidth = strlen("Allocated Memory (Bytes)"); for (i = 0; i < hashSize; i++) { for (memEntry = memTable[i]; memEntry != NULL; memEntry = memEntry->nextInBucket) { size_t chunk = memEntry->number * memEntry->size; if (chunk < threshold) continue; if (description != -1 && memEntry->description != description) continue; n += 1; if (memEntry->filename) { memEntryFilename = chpl_lookupFilename(memEntry->filename); filenameLength = strlen(memEntryFilename); if (filenameLength > filenameWidth) filenameWidth = filenameLength; } } } totalWidth = filenameWidth+numberWidth*4+descWidth+20; for (i = 0; i < totalWidth; i++) fprintf(memLogFile, "="); fprintf(memLogFile, "\n"); fprintf(memLogFile, "%-*s%-*s%-*s%-*s%-*s%-*s\n", filenameWidth+numberWidth, "Allocated Memory (Bytes)", numberWidth, "Number", numberWidth, "Size", numberWidth, "Total", descWidth, "Description", 20, "Address"); for (i = 0; i < totalWidth; i++) fprintf(memLogFile, "="); fprintf(memLogFile, "\n"); table = (memTableEntry**)sys_malloc(n*sizeof(memTableEntry*)); if (!table) chpl_error("out of memory printing memory table", lineno, filename); n = 0; for (i = 0; i < hashSize; i++) { for (memEntry = memTable[i]; memEntry != NULL; memEntry = memEntry->nextInBucket) { size_t chunk = memEntry->number * memEntry->size; if (chunk < threshold) continue; if (description != -1 && memEntry->description != description) continue; table[n++] = memEntry; } } qsort(table, n, sizeof(memTableEntry*), descCmp); loc = (char*)sys_malloc((filenameWidth+numberWidth+1)*sizeof(char)); for (i = 0; i < n; i++) { memEntry = table[i]; if (memEntry->filename) { memEntryFilename = chpl_lookupFilename(memEntry->filename); sprintf(loc, "%s:%" PRId32, memEntryFilename, memEntry->lineno); } else { sprintf(loc, "--"); } fprintf(memLogFile, "%-*s%-*zu%-*zu%-*zu%-*s%#-*.*" PRIxPTR "\n", filenameWidth+numberWidth, loc, numberWidth, memEntry->number, numberWidth, memEntry->size, numberWidth, memEntry->size*memEntry->number, descWidth, chpl_mem_descString(memEntry->description), addressWidth, precision, (uintptr_t)memEntry->memAlloc); } for (i = 0; i < totalWidth; i++) fprintf(memLogFile, "="); fprintf(memLogFile, "\n"); putchar('\n'); sys_free(table); sys_free(loc); }