Commit b4d4414a authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Intermediate step - with 4K sectors, better threads handling

parent 6be06d67
Loading
Loading
Loading
Loading
+38 −9
Original line number Diff line number Diff line
@@ -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
@@ -1668,14 +1676,19 @@ int listener_loop(camogm_state *state)
#endif
		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);
}
+16 −6
Original line number Diff line number Diff line
@@ -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 */