/*
* ctprof_utility.c
*
* Ctools Profiler Utility Implementation
*
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include "ctprof_utility.h"
static char * fifo_filename = "ctprof_fifo";
//static FILE * fp;
static int ctprof_pipe_fd;
static bool fifo_opened = false;
/* State definitions
* ready - ctprof_srv is ready for a signal
* recording - ctprof_srv is recording
* stopped - ctprof_srv has stopped recording
* Note - all messages are the same size in bytes.
*/
static const char msg_recording[] = "ctprof recording\n";
static const char msg_stopped[] = "ctprof stopped__\n";
static const char msg_ready[] = "ctprof ready____\n";
static char readbuf[sizeof(msg_recording)];
/* Note: This implementation uses named pipes for very
* simple ipc. This could be changed in the future to
* use sockets or some other ipc so check the requirements
* for the version of ctprof you are using
*/
static pid_t ctprof_srv_pid;
void ctprof_pipe_read(char * rd_buf_p, size_t rd_bytecnt)
{
while(rd_bytecnt > 0) {
size_t rc = read(ctprof_pipe_fd, rd_buf_p, rd_bytecnt);
if (( rc == -1) && (errno = EINTR)) {
continue;
}
rd_buf_p += rc;
rd_bytecnt -= rc;
}
}
int ctprof_pipe_open(void)
{
/* If fifo can't be opend then return -1 */
if (!fifo_opened) {
if (-1 == (ctprof_pipe_fd = open(fifo_filename, O_RDONLY))) {
return -1;
}
fifo_opened = true;
}
ctprof_pipe_read((char *)&ctprof_srv_pid, sizeof(pid_t));
}
void ctprof_pipe_close(void)
{
if (fifo_opened) {
close(ctprof_pipe_fd);
fifo_opened = false;
}
}
static pid_t ctprof_get_pid(void)
{
if (fifo_opened) {
return ctprof_srv_pid;
} else {
return -1;
}
}
ctprof_state_t ctprof_get_state(void)
{
/* If the fifo opened sucessfully, then fgets should block
* until data is avaiable.
*/
if (fifo_opened) {
ctprof_pipe_read(readbuf, sizeof(readbuf)-1);
if (0 == strcmp(readbuf, msg_recording)) {
return CTPROF_RECORDING;
}
if (0 == strcmp(readbuf, msg_stopped)) {
return CTPROF_STOPPED;
}
if (0 == strcmp(readbuf, msg_ready)) {
return CTPROF_READY;
}
}
return -1;
}
void ctprof_ready_wait()
{
ctprof_state_t ctprof_state;
do {
ctprof_state = ctprof_get_state();
if(ctprof_state == CTPROF_READY) {
break;
}
} while (1);
}
void ctprof_recording_wait()
{
ctprof_state_t ctprof_state;
do {
ctprof_state = ctprof_get_state();
if(ctprof_state == CTPROF_RECORDING) {
break;
}
} while (1);
}
void ctprof_stopped_wait()
{
ctprof_state_t ctprof_state;
do {
ctprof_state = ctprof_get_state();
if(ctprof_state == CTPROF_STOPPED) {
break;
}
} while (1);
}
/* Start recording with a signal*/
void ctprof_start_recording()
{
kill(ctprof_get_pid(), SIGUSR1);
}
/* End recording for this session*/
void ctprof_end_recording()
{
kill(ctprof_get_pid(), SIGUSR2);
}