Index: tools/ev.c =================================================================== --- tools/ev.c (revision 757) +++ tools/ev.c (working copy) @@ -107,7 +107,7 @@ break; case FXT_TRACE_USER_RAW32: case FXT_TRACE_USER_RAW64: - evs->raw.end_data =evs->cur_pos + evs->fxt->infos.page_size; + evs->raw.end_data = evs->block.start + evs->block.ondisk.size; evs->raw.start_data=evs->cur_pos; break; } Index: tools/fut_record.c =================================================================== --- tools/fut_record.c (revision 757) +++ tools/fut_record.c (working copy) @@ -181,6 +181,7 @@ #endif static unsigned long trash_buffer[8]; +extern int allow_fut_flush; unsigned long* fut_getstampedbuffer(unsigned long code, int size) @@ -194,10 +195,27 @@ prev_slot, next_slot)); if (tbx_unlikely(next_slot > fut_last_slot)) { - fut_active=0; - /* Pourquoi on restaure ici ? Pas de race condition possible ? */ - fut_next_slot=prev_slot; - return trash_buffer; + if(allow_fut_flush) { + /* flush the buffer to disk and events */ + /* todo: race condition here ? */ + + fut_active=0; + /* todo: add this kind of event */ + //FUT_DO_PROBE0(FUT_START_FLUSH_CODE); + fut_next_slot = prev_slot; + fut_flush(NULL); + fut_active=1; + /* todo: add this kind of event */ + //FUT_DO_PROBE0(FUT_STOP_FLUSH_CODE); + + return fut_getstampedbuffer(code, size); + } else { + /* stop recording events */ + fut_active=0; + /* Pourquoi on restaure ici ? Pas de race condition possible ? */ + fut_next_slot = prev_slot; + return trash_buffer; + } } fxt_trace_user_raw_t *rec=(fxt_trace_user_raw_t *)prev_slot; Index: tools/fut_setup.c =================================================================== --- tools/fut_setup.c (revision 757) +++ tools/fut_setup.c (working copy) @@ -67,6 +67,37 @@ /* number of contiguous allocated bytes pointed to by bufptr */ static unsigned int nallocated = 0; +/* filename of the output trace */ +static char *fut_filename = NULL; +/* file descriptor of the output trace */ +static int fut_fd = 0; + +/* if !=0, activate the recording of thread id */ +int record_tid_activated = 0; + +/* if !=0, activate automatic buffer dumping: when the buffer is full, it is dumped to disk. + * This permits to record trace larger than the buffer, but this may kill the performance + */ +int allow_fut_flush = 0; + +static int already_flushed = 0; + +void fut_set_filename(char* filename) +{ + if(fut_filename) { + if(already_flushed) + fprintf(stderr, "Warning: change output file name to %s, but some events have been saved in file %s\n", + filename, fut_filename); + free(fut_filename); + } + asprintf(&fut_filename, "%s", filename); +} + +static void __fut_reset_pointers() +{ + fut_next_slot = (unsigned long *)bufptr; +} + void dumptime( time_t *the_time, clock_t *the_jiffies) { struct tms cur_time; @@ -79,8 +110,6 @@ } -int record_tid_activated = 0; - /* activate the recording of thread id */ void fut_enable_tid_logging() { @@ -93,6 +122,21 @@ record_tid_activated = 0; } +/* activate automatic buffer dumping: when the buffer is full, it is dumped to disk. + * This permits to record trace larger than the buffer, but this may kill the performance + */ +void enable_fut_flush() +{ + allow_fut_flush = 1; +} + +/* disactivate automatic buffer dumping + */ +void disable_fut_flush() +{ + allow_fut_flush = 0; +} + /* called once to set up tracing. includes mallocing the buffer to hold the trace. returns number of bytes allocated if all ok, else a negative error code. @@ -132,7 +176,7 @@ * size(long), so that there could be some memory that is never * actually initialized. This also avoids page faults while tracing. */ memset(bufptr, 0, nbytes); - + fut_last_slot = (unsigned long *)(bufptr + nbytes); /* touch all pages so they get loaded */ @@ -205,7 +249,6 @@ return old_active; } - /* called once when completely done with buffer. returns previous value of active if all ok, else a negative error code. */ @@ -213,7 +256,6 @@ { unsigned int old_active = fut_active; - fut_active = 0; if( bufptr != NULL ) {/* previous allocation region was not released, do it now */ @@ -293,43 +335,90 @@ return local_nlongs; } -int fut_endup( char *filename ) - { - int n, nlongs=0, fd; - long size; - unsigned long *copy=NULL; +int fut_flush( char* filename ) +{ - /* stop all futher tracing */ - fut_active = 0; + int n, nlongs=0; + long size; + unsigned long *copy=NULL; - dumptime(&fut_infos->stop_time,&fut_infos->stop_jiffies); + /* stop all futher tracing */ + fut_active = 0; - if( (n = fut_getbuffer(&nlongs, ©)) < 0 ) - return n; + dumptime(&fut_infos->stop_time,&fut_infos->stop_jiffies); - size = nlongs * sizeof(long); + if( (n = fut_getbuffer(&nlongs, ©)) < 0 ) + return n; - if( filename == NULL ) - filename = DEFAULT_TRACE_FILE; + size = nlongs * sizeof(long); - if( (fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0 ) - return fd; + if(!fut_fd) { - fut_infos->page_size = size; - fxt_fdwrite(fut,fd); + /* First time fut_flush is called. Open the output file and write headers */ + if( fut_filename == NULL ) + fut_filename = filename ; - fxt_fdevents_start(fut, fd, FXT_TRACE_USER_RAW); - //if( write(fd, (void *)&size, sizeof(size)) < sizeof(size) ) - // perror("write buffer's size"); - - if( write(fd, (void *)copy, size) < 0 ) - perror("write buffer"); - fxt_fdevents_stop(fut, fd); + if( fut_filename == NULL ) + fut_filename = DEFAULT_TRACE_FILE; - if( close(fd) < 0 ) - perror(filename); + /* we can't open the file using the O_NONBLOCK option since after a call to write + * we are going to modify the buffer. If O_NONBLOCK is set, modifying the buffer while + * the OS is writting it may corrupt the output trace. + */ - //fut_done(); // Removed by Raymond + /* todo: implement a pipeline + * see Alexandre DENIS. "A High Performance Superpipeline Protocol for InfiniBand" in + * Proceedings of the 17th International Euro-Par Conference for instance + */ + if( (fut_fd = open(fut_filename, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0 ) + return fut_fd; - return nlongs; + already_flushed = 1; + /* write header */ + fxt_fdwrite(fut, fut_fd); + + /* begin a block of events */ + fxt_fdevents_start(fut, fut_fd, FXT_TRACE_USER_RAW); + } + + if( write(fut_fd, (void *)copy, size) < 0 ) { + perror("write buffer"); + } + + fut_infos->page_size = size; + + off_t end; + if( (end=lseek(fut_fd,0,SEEK_CUR)) < 0 ) { + perror("getting block end seek"); + exit(EXIT_FAILURE); + } + + __fut_reset_pointers(); + fut_active = 1; + + return nlongs; +} + +int fut_endup( char *filename ) + { + + /* stop all futher tracing */ + fut_active = 0; + + /* dump the buffer to disk */ + int nlongs = fut_flush(filename); + if(nlongs < 0) + return nlongs; + + /* end a block of events */ + fxt_fdevents_stop(fut, fut_fd); + + if( close(fut_fd) < 0 ) + perror(fut_filename); + + __fut_reset_pointers(); + //fut_done(); // Removed by Raymond + fut_active = 1; + + return nlongs; }