Commit 1ab4818a authored by Mikhail Karpenko's avatar Mikhail Karpenko
Browse files

Start reading thread right after program start

Program state can be changed from both threads now and
'state->prog_state' modification is protected with mutex
parent eb13c40a
Loading
Loading
Loading
Loading
+27 −40
Original line number Diff line number Diff line
@@ -215,6 +215,7 @@ void camogm_init(camogm_state *state, char *pipe_name)
	state->exif = DEFAULT_EXIF;
	state->frame_lengths = NULL;

	// reading thread has not been started yet, mutex lock is not necessary
	state->prog_state = STATE_STOPPED;

	// kml stuff
@@ -312,7 +313,9 @@ int camogm_start(camogm_state *state)
	}
	state->max_frames =       state->set_max_frames;
	state->frames_per_chunk = state->set_frames_per_chunk;
	pthread_mutex_lock(&state->mutex);
	state->prog_state = STATE_STARTING;
	pthread_mutex_unlock(&state->mutex);
	FOR_EACH_PORT(int, chn) {
		//! Check/set circbuf read pointer
		D3(fprintf(debug_file, "1: state->cirbuf_rp=0x%x\n", state->cirbuf_rp[chn]));
@@ -453,7 +456,9 @@ int camogm_start(camogm_state *state)
	}
	if (state->kml_enable) rslt = camogm_start_kml(state);  // will turn on state->kml_used if it can
	if (rslt) return rslt;
	pthread_mutex_lock(&state->mutex);
	state->prog_state = STATE_RUNNING;
	pthread_mutex_unlock(&state->mutex);
	D1(fprintf(debug_file, "Started OK\n"));
	return 0;
}
@@ -656,7 +661,9 @@ int camogm_stop(camogm_state *state)
		if (state->prog_state != STATE_STARTING) {
			D2(fprintf(debug_file, "Recording was not running, nothing to stop\n"));
		} else {
			pthread_mutex_lock(&state->mutex);
			state->prog_state = STATE_STOPPED;
			pthread_mutex_unlock(&state->mutex);
			D1(fprintf(debug_file, "Dropping attempt to start\n"));
		}
		return 0;
@@ -675,7 +682,9 @@ int camogm_stop(camogm_state *state)
	state->vf = NULL;
	if (rslt) return rslt;
	state->last = 1;
	pthread_mutex_lock(&state->mutex);
	state->prog_state = STATE_STOPPED;
	pthread_mutex_unlock(&state->mutex);
	return 0;
}

@@ -1331,20 +1340,14 @@ int parse_cmd(camogm_state *state, FILE* npipe)
			state->rawdev.rawdev_path[0] = '\0';
		}
		return 28;
	} else if (strcmp(cmd, "rawdev_read") == 0) {
		if (state->rawdev_op && state->prog_state == STATE_STOPPED) {
			state->prog_state = STATE_READING;
		} else {
			D0(fprintf(debug_file, "Unable to switch state to 'reading' from current state. Check settings.\n"));
		}
		return 29;
	} else if (strcmp(cmd, "rawdev_stop") == 0) {
		if (state->prog_state == STATE_READING) {
	} else if (strcmp(cmd, "reader_stop") == 0) {
		if (state->prog_state == STATE_READING &&
				state->rawdev.thread_state == STATE_RUNNING) {
			state->rawdev.thread_state = STATE_CANCEL;
		} else {
			D0(fprintf(debug_file, "Reading thread is not running, nothing to stop\n"));
		}
		return 30;
		return 29;
	}

	return -1;
@@ -1380,7 +1383,6 @@ void clean_up(camogm_state *state)
 */
int listener_loop(camogm_state *state)
{
	void *tret;
	FILE *cmd_file;
	int rslt, ret, cmd, f_ok;
	int fp0, fp1;
@@ -1495,35 +1497,9 @@ int listener_loop(camogm_state *state)
			} // switch camogm_start()
			if ((rslt != 0) && (rslt != CAMOGM_TOO_EARLY) && (rslt != CAMOGM_FRAME_NOT_READY) && (rslt != CAMOGM_FRAME_CHANGED) ) state->last_error_code = rslt;
		} else if (state->prog_state == STATE_READING) {
			if (state->rawdev.thread_state == STATE_RUNNING) {
				if (state->rawdev.thread_finished == true) {
					state->rawdev.thread_state = STATE_STOPPED;
					state->rawdev.thread_finished = false;
					state->prog_state = STATE_STOPPED;
					pthread_join(state->rawdev.tid, &tret);
					if ((int)tret != 0 && (int)tret != (int)PTHREAD_CANCELED) {
						D0(fprintf(debug_file, "Reading thread returned error %d\n", (int)tret));
					} else {
						D3(fprintf(debug_file, "Reading thread stopped\n"));
					}
				} else {
			usleep(COMMAND_LOOP_DELAY);
				}
			} else if (state->rawdev.thread_state == STATE_STOPPED) {
				state->rawdev.thread_state = STATE_RUNNING;
				state->rawdev.thread_finished = false;
//				if (pthread_create(&state->rawdev.tid, NULL, build_index, state) != 0) {
				if (pthread_create(&state->rawdev.tid, NULL, reader, state) != 0) {
					state->prog_state = STATE_STOPPED;
					state->rawdev.thread_state = STATE_STOPPED;
					D0(fprintf(debug_file, "%s:line %d: Can not start new thread, disk index is not built\n", __FILE__, __LINE__));
				}
			} else if (state->rawdev.thread_state == STATE_CANCEL) {
				// cancel reading thread and return to running state waiting for the thread to terminate
				state->rawdev.thread_state = STATE_RUNNING;
				pthread_cancel(state->rawdev.tid);
			}
		} else {                            // not running, not starting
			state->rawdev.thread_state = STATE_RUNNING;
			usleep(COMMAND_LOOP_DELAY);     // make it longer but interruptible by signals?
		}
	} // while (process)
@@ -1683,7 +1659,7 @@ int open_files(camogm_state *state)
		}
		framePars[port] = frameParsAll[port]->framePars;
		aglobalPars[port] = frameParsAll[port]->globalPars;
#endif /* DESABLE_CODE */
#endif /* DISABLE_CODE */
	}

	return ret;
@@ -1718,9 +1694,20 @@ int main(int argc, char *argv[])
	}

	camogm_init(&sstate, argv[1]);
	if (pthread_mutex_init(&sstate.mutex, NULL) != 0) {
		perror("Unable to initialize mutex\n");
		return EXIT_FAILURE;
	}
	ret = open_files(&sstate);
	if (ret < 0)
		return ret;
	if (pthread_create(&sstate.rawdev.tid, NULL, reader, &sstate) != 0 ||
			pthread_detach(sstate.rawdev.tid) != 0) {
		D0(fprintf(debug_file, "%s:line %d: Can not start reading thread in detached state\n", __FILE__, __LINE__));
		clean_up(&sstate);
		return EXIT_FAILURE;
	}
	sstate.rawdev.thread_state = STATE_RUNNING;

	ret = listener_loop(&sstate);

+3 −3
Original line number Diff line number Diff line
@@ -107,8 +107,7 @@ typedef struct {
	volatile uint64_t curr_pos_r;
	uint64_t file_start;
	pthread_t tid;
	int thread_state;
	volatile bool thread_finished;
	volatile int thread_state;
} rawdev_buffer;

/**
@@ -137,7 +136,8 @@ typedef struct {
	int frame_period[SENSOR_PORTS];                         ///< in microseconds (1/10 of what is needed for the Ogm header)
	int width;                                              ///< image width
	int height;                                             ///< image height
	int prog_state;                                         ///< program state flag, can be one of #state_flags
	volatile int prog_state;                                ///< program state flag, can be one of #state_flags
	pthread_mutex_t mutex;                                  ///< mutex for @e prog_state variable; all modifications to the variable must be using this mutex
	int last_error_code;
	ogg_stream_state os;
	ogg_page og;
+16 −5
Original line number Diff line number Diff line
@@ -942,10 +942,19 @@ void *reader(void *arg)
		fd = accept(sockfd, NULL, 0);
		if (fd == -1)
			continue;
		if (state->prog_state == STATE_STOPPED && state->rawdev_op) {
			pthread_mutex_lock(&state->mutex);
			state->prog_state = STATE_READING;
			pthread_mutex_unlock(&state->mutex);
		} else {
			close(fd);
			D0(fprintf(debug_file, "Can not change state of the program, check settings\n"));
			continue;
		}
		cmd_len = read(fd, cmd_buff, sizeof(cmd_buff) - 1);
		cmd_ptr = cmd_buff;
		trim_command(cmd_ptr, cmd_len);
		while ((cmd = parse_command(&cmd_ptr)) != -2) {
		while ((cmd = parse_command(&cmd_ptr)) != -2 && state->rawdev.thread_state != STATE_CANCEL) {
			if (cmd >= 0)
				D6(fprintf(debug_file, "Got command '%s', number %d\n", cmd_list[cmd], cmd));
			switch (cmd) {
@@ -984,7 +993,7 @@ void *reader(void *arg)
				mm_file_size = rawdev->mmap_default_size - rawdev->start_pos;
				send_fnum(fd, disk_chunks);
				close(fd);
				while (disk_chunks > 0 && transfer) {
				while (disk_chunks > 0 && transfer && state->rawdev.thread_state != STATE_CANCEL) {
					fd = accept(sockfd, NULL, 0);
					if (mmap_disk(rawdev, &mmap_range) == 0) {
						send_buffer(fd, &rawdev->disk_mmap[mm_file_start], mm_file_size);
@@ -1041,7 +1050,7 @@ void *reader(void *arg)
					cross_boundary_indx = NULL;
					file_cntr = 0;
					transfer = true;
					while (file_cntr < index_dir.size && disk_indx != NULL) {
					while (file_cntr < index_dir.size && disk_indx != NULL && state->rawdev.thread_state != STATE_CANCEL) {
						if (is_in_range(&mmap_range, disk_indx) && rawdev->disk_mmap != NULL) {
							fd = accept(sockfd, NULL, 0);
							mm_file_start = disk_indx->f_offset - rawdev->mmap_offset;
@@ -1090,6 +1099,9 @@ void *reader(void *arg)
		}
		if (fstat(fd, &stat_buff) != EBADF)
			close(fd);
		pthread_mutex_lock(&state->mutex);
		state->prog_state = STATE_STOPPED;
		pthread_mutex_unlock(&state->mutex);
		usleep(COMMAND_LOOP_DELAY);
	}
	pthread_cleanup_pop(0);
@@ -1114,7 +1126,6 @@ static inline void exit_thread(void *arg)
		close(*s->sockfd_const);
	if (fstat(*s->sockfd_temp, &buff) != EBADF)
		close(*s->sockfd_temp);
	s->state->rawdev.thread_finished = true;
}

/**
@@ -1171,7 +1182,7 @@ void build_index(camogm_state *state, struct disk_idir *idir)
	zero_cross = 0;
	search_state = SEARCH_SKIP;
	idir_result = 0;
	while (process) {
	while (process && state->rawdev.thread_state != STATE_CANCEL) {
		rd = read(state->rawdev.rawdev_fd, buff, sizeof(buff));
		err = errno;
		if ((rd > 0) && (dev_curr_pos + rd > state->rawdev.end_pos)) {