Commit b4d4414a authored by Andrey Filippov's avatar Andrey Filippov

Intermediate step - with 4K sectors, better threads handling

parent 6be06d67
......@@ -163,6 +163,7 @@ static int get_disk_range(const char *name, struct range *rng);
static int set_disk_range(const struct range *rng);
static void get_disk_info(camogm_state *state);
static struct timeval get_fpga_time(const int fd_fparsall, unsigned int port);
int open_files(camogm_state *state);
unsigned long getGPValue(unsigned int port, unsigned long GPNumber);
void setGValue(unsigned int port, unsigned long GNumber, unsigned long value);
......@@ -280,7 +281,12 @@ void camogm_init(camogm_state *state, char *pipe_name, uint16_t port_num)
state->rawdev.mmap_default_size = MMAP_CHUNK_SIZE;
state->sock_port = port_num;
state->writer_params.data_ready = false;
// state->writer_params.data_ready = false;
state->writer_params.chunk_page_prep = 0; // will prepare page 0
state->writer_params.chunk_page_write = 0; // will write page 0
state->writer_params.exit_thread = false;
state->writer_params.state = STATE_STOPPED;
......@@ -692,7 +698,7 @@ int sendImageFrame(camogm_state *state)
state->writer_params.segments = 1;
}
D3(fprintf(debug_file, "\tcirbuf_rp[%d] = 0x%x\t", port, state->cirbuf_rp[port]));
D3(fprintf(debug_file, "_12_"));
D3(fprintf(debug_file, "_12_\n"));
if (state->this_frame_params[port].color != COLORMODE_RAW) { // Tiff
state->packetchunks[state->chunk_index ].bytes = 2;
state->packetchunks[state->chunk_index++].chunk = (unsigned char*)trailer;
......@@ -701,6 +707,7 @@ int sendImageFrame(camogm_state *state)
dbg_show_packetchunks(state);
D6(fprintf(debug_file, "_12.5_ before CAMOGM_FORMAT_XXX @ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
switch (state->format) {
case CAMOGM_FORMAT_NONE: rslt = 0; break;
......@@ -741,14 +748,14 @@ int sendImageFrame(camogm_state *state)
// end_time.tv_sec, end_time.tv_usec,
// state->rawdev.last_jpeg_size));
// D6(fprintf(debug_file, "Write speed: %d MB/s\n", mbps));
D6(fprintf(debug_file, "Exit sendImageFrame() OK @ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
return 0;
}
static void dbg_show_packetchunks(camogm_state *state)
{
int i;
for (i = 0; i < FILE_CHUNKS_NUM; i++) {
for (i = 0; i < state->chunk_index; i++) {
D4(fprintf(debug_file, "packetchunk[%d]: ptr = %p, size = %d\n", i, state->packetchunks[i].chunk, state->packetchunks[i].bytes));
}
}
......@@ -1386,7 +1393,7 @@ int parse_cmd(camogm_state *state, FILE* npipe)
//skip empty commands
while (((cmd = getLineFromPipe(npipe))) && !cmd[0]) ;
if (!cmd) return 0; // nothing in the pipe
D2(fprintf(debug_file, "Got command: '%s'\n", cmd));
D2(fprintf(debug_file, "Got command: '%s' @ %06d -> ", cmd, get_fpga_usec(state->fd_fparmsall[0], 0)));
// Acknowledge received command by copying frame number to per-daemon parameter
// GLOBALPARS(state->port_num, G_DAEMON_ERR + lastDaemonBit[state->port_num]) = GLOBALPARS(state->port_num, G_THIS_FRAME);
......@@ -1655,6 +1662,7 @@ int listener_loop(camogm_state *state)
// enter main processing loop
while (process) {
D6(fprintf(debug_file, "--------------- Listener loop @ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
curr_port = select_port(state);
state->port_num = curr_port;
// look at command queue first
......@@ -1666,16 +1674,21 @@ int listener_loop(camogm_state *state)
}
if (pfd.revents & POLLIN){
#endif
cmd = parse_cmd(state, cmd_file);
if (cmd) {
cmd = parse_cmd(state, cmd_file);
if (cmd) {
D2(fprintf(debug_file, "DONE command @ %06d\n", get_fpga_usec(state->fd_fparmsall[0], 0)));
if (cmd < 0) D0(fprintf(debug_file, "Unrecognized command\n"));
#ifdef USE_POLL
}
#endif
} else if (state->prog_state == STATE_RUNNING) { // no commands in queue, started
continue;
// } else if (state->prog_state == STATE_RUNNING) { // no commands in queue, started
}
if (state->prog_state == STATE_RUNNING) { // no commands in queue, started
D6(fprintf(debug_file, "state->prog_state == STATE_RUNNING "));
rslt = -sendImageFrame(state);
D6(fprintf(debug_file, " ==> %d",rslt));
D6(fprintf(debug_file, " ==> %d @ %06d\n",rslt,get_fpga_usec(state->fd_fparmsall[0], 0)));
switch (rslt) {
case 0:
break; // frame sent OK, nothing to do (TODO: check file length/duration)
......@@ -1692,6 +1705,7 @@ int listener_loop(camogm_state *state)
D0(fprintf(debug_file, "%s:line %d got broken frame (%d) while waiting for ready. Before that fp0=0x%x\n", __FILE__, __LINE__, fp1, fp0));
rslt = CAMOGM_FRAME_BROKEN;
} else {
D6(fprintf(debug_file, "No compressed frame ready, skipped 1 frame sync for port %d @ %06d\n",curr_port,get_fpga_usec(state->fd_fparmsall[0], 0)));
break;
}
}
......@@ -1760,10 +1774,14 @@ int listener_loop(camogm_state *state)
// add port number to error code to facilitate debugging
state->last_error_code = rslt + 100 * state->port_num;
} else if (state->prog_state == STATE_READING) {
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY start for STATE_READING@ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
usleep(COMMAND_LOOP_DELAY);
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY end for STATE_READING@ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
} else { // not running, not starting
state->rawdev.thread_state = STATE_RUNNING;
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY start for STATE_RUNNING@ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
usleep(COMMAND_LOOP_DELAY); // make it longer but interruptible by signals?
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY end for STATE_RUNNING@ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
}
#ifdef USE_POLL
// } // if pfd.revents & POLLIN
......@@ -2265,3 +2283,14 @@ struct timeval get_fpga_time(const int fd_fparsall, unsigned int port)
return tv;
}
/**
* @brief Get current FPGA microseconds of time to use for timing of the code
* @return FPGA current microseconds
*/
inline int get_fpga_usec(const int fd_fparsall, unsigned int port)
{
lseek(fd_fparsall, LSEEK_GET_FPGA_TIME, SEEK_END);
// return (int) getGPValue(port, G_MICROSECONDS);
return (int) GLOBALPARS(port, G_MICROSECONDS);
}
......@@ -67,7 +67,9 @@
#define COMMAND_LOOP_DELAY 500000
/** @brief File can be split up to this number of chunks */
#define FILE_CHUNKS_NUM 8
/** @brief Number of chunk pages to overlap preparation with SSD raw write */
#define FILE_CHUNKS_PAGES 2
#define FILE_CHUNKS_TOTAL ((FILE_CHUNKS_NUM) * (FILE_CHUNKS_PAGES))
/**
* @enum state_flags
* @brief Program state flags
......@@ -145,25 +147,32 @@ struct writer_params {
pthread_mutex_t writer_mutex; ///< synchronization mutex for main and writing threads
pthread_cond_t writer_cond; ///< conditional variable indicating that writer thread can proceed with new frame
pthread_cond_t main_cond; ///< conditional variable indicating that main thread can update write pointers
bool data_ready; ///< flag indicating that new frame is ready for recording, access to this flag
///< must be protected with #writer_mutex. Set this flag in main thread and reset in
///< disk writing thread.
// bool data_ready; ///< flag indicating that new frame is ready for recording, access to this flag
// ///< must be protected with #writer_mutex. Set this flag in main thread and reset in
// ///< disk writing thread.
// ///< For overlapping disk raw writes with chunks preparation (should be atomic - use #writer_mutex)
int chunk_page_prep; ///< page of chunks being prepared. Incremented (mod) after data is prepared for raw write
int chunk_page_write; ///< page of chunks to write. Incremented (mod) after recording to disk
int last_ret_val; ///< error value return during last frame recording (if any occurred)
bool exit_thread; ///< flag indicating that the writing thread should terminate
int state; ///< the state of disk writing thread
int segments; ///< the number of segments in frame
struct iovec *data_chunks; ///< a set of vectors pointing to aligned frame data buffers
struct iovec was_CHUNK_REM; ///< extracting to a separate entity data_chunks[CHUNK_REM]
// struct iovec *was_CHUNK_COMMON; ///< extracting to a separate entity data_chunks[CHUNK_COMMON]
struct iovec prev_rem_vect; ///< vector pointing to the remainder of the previous frame
unsigned char *rem_buff; ///< buffer containing the unaligned remainder of the current frame
unsigned char *prev_rem_buff; ///< buffer containing the unaligned remainder of the previous frame
unsigned char *common_buff; ///< buffer for aligned JPEG header
// get rid of common_buff
// unsigned char *common_buff; ///< buffer for aligned JPEG header // make multiple?
unsigned char *common_buffs[FILE_CHUNKS_PAGES]; ///< buffer for aligned JPEG header // make multiple?
uint64_t lba_start; ///< disk starting LBA
uint64_t lba_current; ///< current write position in LBAs
uint64_t lba_end; ///< disk last LBA
time_t stat_update; ///< time when status file was updated
bool dummy_read; ///< inable dummy read cycle (debug feature)
bool dummy_read; ///< enable dummy read cycle (debug feature)
};
/**
* @struct camogm_state
......@@ -272,5 +281,6 @@ void setGValue(unsigned int port, unsigned long GNumber, unsigned long value);
int waitDaemonEnabled(unsigned int port, int daemonBit);
int isDaemonEnabled(unsigned int port, int daemonBit);
int is_fd_valid(int fd);
int get_fpga_usec(const int fd_fparsall, unsigned int port);
#endif /* _CAMOGM_H */
This diff is collapsed.
......@@ -22,8 +22,9 @@
#include <sys/types.h>
#include "camogm.h"
#define PHY_BLOCK_SIZE 512 ///< Physical disk block size
// TODO: Change PHY_BLOCK_SIZE to 4096 as it is 4096!
//#define PHY_BLOCK_SIZE 512 ///< Physical disk block size
#define PHY_BLOCK_SIZE 4096 ///< Physical disk block size
#define JPEG_MARKER_LEN 2 ///< The size in bytes of JPEG marker
#define JPEG_SIZE_LEN 2 ///< The size in bytes of JPEG marker length field
#define INCLUDE_REM 1 ///< Include REM buffer to total size calculation
......@@ -73,10 +74,10 @@ enum {
int init_align_buffers(camogm_state *state);
void deinit_align_buffers(camogm_state *state);
void align_frame(camogm_state *state);
void reset_chunks(struct iovec *vects, int all);
int update_lba(camogm_state *state);
int get_data_buffers(camogm_state *state, struct iovec *mapped, size_t all_sz);
int prep_last_block(camogm_state *state);
void reset_chunks(camogm_state *state, int all, int page);
//int update_lba(camogm_state *state);
int get_data_buffers(camogm_state *state, struct iovec *mapped, size_t mapped_sz, int page);
int prep_last_block(camogm_state *state, int page);
off64_t lba_to_offset(uint64_t lba);
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment