* It can also happen if this is a buffer we never got. */
return -EIO;
} else {
- if(atomic_read(<t_buf->full) == 1) {
+ if(atomic_inc_return(<t_buf->writer_futex) <= 0) {
+ atomic_set(<t_buf->writer_futex, 1);
/* tell the client that buffer is now unfull */
- ret = futex((unsigned long)<t_buf->full,
+ ret = futex((unsigned long)<t_buf->writer_futex,
FUTEX_WAKE, 1, 0, 0, 0);
if(ret != 1) {
dbg_printf("LTT warning : race condition : writer not waiting or too many writers\n");
}
- atomic_set(<t_buf->full, 0);
}
}
}
{
struct sigaction act;
int ret;
- int fd_fac;
- int fd_cpu;
+ int fd_process;
char outfile_name[PATH_MAX];
char identifier_name[PATH_MAX];
}
snprintf(identifier_name, PATH_MAX-1, "%lu.%lu.%llu",
traced_tid, traced_pid, get_cycles());
- snprintf(outfile_name, PATH_MAX-1, "facilities-%s", identifier_name);
- fd_fac = creat(outfile_name, 0644);
-
- snprintf(outfile_name, PATH_MAX-1, "cpu-%s", identifier_name);
- fd_cpu = creat(outfile_name, 0644);
-
+ snprintf(outfile_name, PATH_MAX-1, "process-%s", identifier_name);
+#ifndef LTT_NULL_OUTPUT_TEST
+ fd_process = creat(outfile_name, 0644);
+#else
+ /* NULL test */
+ ret = symlink("/dev/null", outfile_name);
+ if(ret < 0) {
+ perror("error in symlink");
+ }
+ fd_process = open(outfile_name, O_WRONLY);
+ if(fd_process < 0) {
+ perror("Error in open");
+ }
+#endif //LTT_NULL_OUTPUT_TEST
while(1) {
pause();
dbg_printf("LTT Doing a buffer switch read. pid is : %lu\n", getpid());
do {
- ret = read_subbuffer(&shared_trace_info->channel.cpu, fd_cpu);
- } while(ret == 0);
-
- do {
- ret = read_subbuffer(&shared_trace_info->channel.facilities, fd_fac);
+ ret = read_subbuffer(&shared_trace_info->channel.process, fd_process);
} while(ret == 0);
}
/* Buffer force switch (flush). Using FLUSH instead of ACTIVE because we know
* there is no writer. */
- flush_buffer(&shared_trace_info->channel.cpu, FORCE_FLUSH);
+ flush_buffer(&shared_trace_info->channel.process, FORCE_FLUSH);
do {
- ret = read_subbuffer(&shared_trace_info->channel.cpu, fd_cpu);
+ ret = read_subbuffer(&shared_trace_info->channel.process, fd_process);
} while(ret == 0);
- flush_buffer(&shared_trace_info->channel.facilities, FORCE_FLUSH);
- do {
- ret = read_subbuffer(&shared_trace_info->channel.facilities, fd_fac);
- } while(ret == 0);
-
- close(fd_fac);
- close(fd_cpu);
+ close(fd_process);
munmap(shared_trace_info, sizeof(*shared_trace_info));
shared_trace_info->filter=0;
shared_trace_info->daemon_id=0;
shared_trace_info->nesting=0;
- memset(&shared_trace_info->channel.facilities, 0,
- sizeof(shared_trace_info->channel.facilities));
- memset(&shared_trace_info->channel.cpu, 0,
- sizeof(shared_trace_info->channel.cpu));
+ memset(&shared_trace_info->channel.process, 0,
+ sizeof(shared_trace_info->channel.process));
/* Tricky semaphore : is in a shared memory space, so it's ok for a fast
* mutex (futex). */
- atomic_set(&shared_trace_info->channel.facilities.full, 0);
- shared_trace_info->channel.facilities.alloc_size = LTT_BUF_SIZE_FACILITIES;
- shared_trace_info->channel.facilities.subbuf_size = LTT_SUBBUF_SIZE_FACILITIES;
- shared_trace_info->channel.facilities.start =
- shared_trace_info->channel.facilities_buf;
- ltt_buffer_begin_callback(&shared_trace_info->channel.facilities,
- ltt_get_timestamp(), 0);
-
- atomic_set(&shared_trace_info->channel.cpu.full, 0);
- shared_trace_info->channel.cpu.alloc_size = LTT_BUF_SIZE_CPU;
- shared_trace_info->channel.cpu.subbuf_size = LTT_SUBBUF_SIZE_CPU;
- shared_trace_info->channel.cpu.start = shared_trace_info->channel.cpu_buf;
- ltt_buffer_begin_callback(&shared_trace_info->channel.cpu,
+ atomic_set(&shared_trace_info->channel.process.writer_futex, LTT_N_SUBBUFS);
+ shared_trace_info->channel.process.alloc_size = LTT_BUF_SIZE_PROCESS;
+ shared_trace_info->channel.process.subbuf_size = LTT_SUBBUF_SIZE_PROCESS;
+ shared_trace_info->channel.process.start =
+ shared_trace_info->channel.process_buf;
+ ltt_buffer_begin_callback(&shared_trace_info->channel.process,
ltt_get_timestamp(), 0);
shared_trace_info->init = 1;
/* Child */
role = LTT_ROLE_READER;
sid = setsid();
- ret = nice(1);
- if(ret < 0) {
- perror("Error in nice");
- }
+ //Not a good idea to renice, unless futex wait eventually implement
+ //priority inheritence.
+ //ret = nice(1);
+ //if(ret < 0) {
+ // perror("Error in nice");
+ //}
if(sid < 0) {
perror("Error setting sid");
}
#define LTT_N_SUBBUFS 2
#endif //LTT_N_SUBBUFS
-#ifndef LTT_SUBBUF_SIZE_CPU
-#define LTT_SUBBUF_SIZE_CPU 1048576
+#ifndef LTT_SUBBUF_SIZE_PROCESS
+#define LTT_SUBBUF_SIZE_PROCESS 1048576
#endif //LTT_BUF_SIZE_CPU
-#define LTT_BUF_SIZE_CPU (LTT_SUBBUF_SIZE_CPU * LTT_N_SUBBUFS)
-
-#ifndef LTT_SUBBUF_SIZE_FACILITIES
-#define LTT_SUBBUF_SIZE_FACILITIES 4096
-#endif //LTT_BUF_SIZE_FACILITIES
-
-#define LTT_BUF_SIZE_FACILITIES (LTT_SUBBUF_SIZE_FACILITIES * LTT_N_SUBBUFS)
+#define LTT_BUF_SIZE_PROCESS (LTT_SUBBUF_SIZE_PROCESS * LTT_N_SUBBUFS)
#ifndef LTT_USERTRACE_ROOT
#define LTT_USERTRACE_ROOT "/tmp/ltt-usertrace"
atomic_t events_lost;
atomic_t corrupted_subbuffers;
- atomic_t full; /* futex on which the writer waits : 1 : full */
+ atomic_t writer_futex; /* futex on which the writer waits */
unsigned int alloc_size;
unsigned int subbuf_size;
};
pid_t daemon_id;
int nesting;
struct {
- struct ltt_buf facilities;
- struct ltt_buf cpu;
- char facilities_buf[LTT_BUF_SIZE_FACILITIES] __attribute__ ((aligned (8)));
- char cpu_buf[LTT_BUF_SIZE_CPU] __attribute__ ((aligned (8)));
+ struct ltt_buf process;
+ char process_buf[LTT_BUF_SIZE_PROCESS] __attribute__ ((aligned (8)));
} channel;
};
ltt_get_index_from_facility(ltt_facility_t fID,
uint8_t eID)
{
- return GET_CHANNEL_INDEX(cpu);
+ return GET_CHANNEL_INDEX(process);
}
ltt_buf)]);
if(reserve_commit_diff == 0) {
/* Next buffer not corrupted. */
- if((SUBBUF_TRUNC(offset_begin, ltt_buf)
- - SUBBUF_TRUNC(atomic_read(<t_buf->consumed), ltt_buf))
- >= ltt_buf->alloc_size) {
- /* We block until the reader unblocks us */
- atomic_set(<t_buf->full, 1);
- /* We block until the reader tells us to wake up.
- Signals will simply cause this loop to restart.
- */
- do {
- ret = futex((unsigned long)<t_buf->full, FUTEX_WAIT, 1, 0, 0, 0);
- } while(ret != 0 && ret != EWOULDBLOCK);
+ //if((SUBBUF_TRUNC(offset_begin, ltt_buf)
+ // - SUBBUF_TRUNC(atomic_read(<t_buf->consumed), ltt_buf))
+ // >= ltt_buf->alloc_size) {
+ if(atomic_dec_return(<t_buf->writer_futex) >= 0) {
+ /* non contended */
+ } else {
+ /* We block until the reader unblocks us */
+ atomic_set(<t_buf->writer_futex, -1);
+ /* We block until the reader tells us to wake up.
+ Signals will simply cause this loop to restart.
+ */
+ do {
+ ret = futex((unsigned long)<t_buf->writer_futex,
+ FUTEX_WAIT, -1, 0, 0, 0);
+ } while(ret != 0 && ret != EWOULDBLOCK);
+ }
/* go on with the write */
- } else {
- /* next buffer not corrupted, we are either in overwrite mode or
- * the buffer is not full. It's safe to write in this new subbuffer.*/
- }
+ //} else {
+ // /* next buffer not corrupted, we are either in overwrite mode or
+ // * the buffer is not full. It's safe to write in this new subbuffer.*/
+ //}
} else {
/* Next subbuffer corrupted. Force pushing reader even in normal
* mode. It's safe to write in this new subbuffer. */