예제 #1
0
파일: param.c 프로젝트: Aerovinci/Firmware
/** lock the parameter store for read access */
static void
param_lock_reader(void)
{
	do {} while (px4_sem_wait(&reader_lock_holders_lock) != 0);

	++reader_lock_holders;

	if (reader_lock_holders == 1) {
		// the first reader takes the lock, the next ones are allowed to just continue
		do {} while (px4_sem_wait(&param_sem) != 0);
	}

	px4_sem_post(&reader_lock_holders_lock);
}
예제 #2
0
static int
enqueue_work_item_and_wait_for_result(work_q_item_t *item)
{
	/* put the work item at the end of the work queue */
	lock_queue(&g_work_q);
	sq_addlast(&item->link, &(g_work_q.q));

	/* Adjust the queue size and potentially the maximum queue size */
	if (++g_work_q.size > g_work_q.max_size) {
		g_work_q.max_size = g_work_q.size;
	}

	unlock_queue(&g_work_q);

	/* tell the work thread that work is available */
	px4_sem_post(&g_work_queued_sema);

	/* wait for the result */
	px4_sem_wait(&item->wait_sem);

	int result = item->result;

	destroy_work_item(item);

	return result;
}
예제 #3
0
void
SyslinkMemory::sendAndWait()
{
	// TODO: Force the syslink thread to wake up
	_link->_queue.force(&msgbuf, sizeof(msgbuf));
	px4_sem_wait(&_link->memory_sem);
}
예제 #4
0
int test_dataman(int argc, char *argv[])
{
	int i, num_tasks = 4;
	char buffer[DM_MAX_DATA_SIZE];

	if (argc > 1) {
		num_tasks = atoi(argv[1]);
	}

	sems = (px4_sem_t *)malloc(num_tasks * sizeof(px4_sem_t));
	warnx("Running %d tasks", num_tasks);

	for (i = 0; i < num_tasks; i++) {
		int task;
		char a[16];
		sprintf(a, "%d", i);
		const char *av[2];
		av[0] = a;
		av[1] = 0;
		px4_sem_init(sems + i, 1, 0);
		/* sems use case is a signal */
		px4_sem_setprotocol(&sems, SEM_PRIO_NONE);

		/* start the task */
		if ((task = px4_task_spawn_cmd("dataman", SCHED_DEFAULT, SCHED_PRIORITY_MAX - 5, 2048, task_main, (void *)av)) <= 0) {
			warn("task start failed");
		}
	}

	for (i = 0; i < num_tasks; i++) {
		px4_sem_wait(sems + i);
		px4_sem_destroy(sems + i);
	}

	free(sems);
	dm_restart(DM_INIT_REASON_IN_FLIGHT);

	for (i = 0; i < NUM_MISSIONS_SUPPORTED; i++) {
		if (dm_read(DM_KEY_WAYPOINTS_OFFBOARD_1, i, buffer, sizeof(buffer)) != 0) {
			break;
		}
	}

	if (i >= NUM_MISSIONS_SUPPORTED) {
		warnx("Restart in-flight failed");
		return -1;

	}

	dm_restart(DM_INIT_REASON_POWER_ON);

	for (i = 0; i < NUM_MISSIONS_SUPPORTED; i++) {
		if (dm_read(DM_KEY_WAYPOINTS_OFFBOARD_1, i, buffer, sizeof(buffer)) != 0) {
			warnx("Restart power-on failed");
			return -1;
		}
	}

	return 0;
}
예제 #5
0
파일: param.c 프로젝트: Aerovinci/Firmware
/** unlock the parameter store */
static void
param_unlock_reader(void)
{
	do {} while (px4_sem_wait(&reader_lock_holders_lock) != 0);

	--reader_lock_holders;

	if (reader_lock_holders == 0) {
		// the last reader releases the lock
		px4_sem_post(&param_sem);
	}

	px4_sem_post(&reader_lock_holders_lock);
}
예제 #6
0
__EXPORT void
dm_lock(dm_item_t item)
{
	/* Make sure data manager has been started and is not shutting down */
	if ((g_fd < 0) || g_task_should_exit) {
		return;
	}

	if (item >= DM_KEY_NUM_KEYS) {
		return;
	}

	if (g_item_locks[item]) {
		px4_sem_wait(g_item_locks[item]);
	}
}
예제 #7
0
static int
start(void)
{
	int task;

	px4_sem_init(&g_init_sema, 1, 0);

	/* start the worker thread with low priority for disk IO */
	if ((task = px4_task_spawn_cmd("dataman", SCHED_DEFAULT, SCHED_PRIORITY_DEFAULT - 10, 1200, task_main, NULL)) <= 0) {
		warn("task start failed");
		return -1;
	}

	/* wait for the thread to actually initialize */
	px4_sem_wait(&g_init_sema);
	px4_sem_destroy(&g_init_sema);

	return 0;
}
예제 #8
0
int UavcanNode::fw_server(eServerAction action)
{
	int rv = -EAGAIN;

	switch (action) {
	case Start:
	case Stop:
	case CheckFW:
		if (_fw_server_action == None) {
			_fw_server_action = action;
			px4_sem_wait(&_server_command_sem);
			rv = _fw_server_status;
		}

		break;

	default:
		rv = -EINVAL;
		break;
	}

	return rv;
}
예제 #9
0
파일: param.c 프로젝트: Aerovinci/Firmware
/** lock the parameter store for write access */
static void
param_lock_writer(void)
{
	do {} while (px4_sem_wait(&param_sem) != 0);
}
예제 #10
0
파일: param.c 프로젝트: Aerovinci/Firmware
int
param_export(int fd, bool only_unsaved)
{
	perf_begin(param_export_perf);

	struct param_wbuf_s *s = NULL;
	int	result = -1;

	struct bson_encoder_s encoder;

	int shutdown_lock_ret = px4_shutdown_lock();

	if (shutdown_lock_ret) {
		PX4_ERR("px4_shutdown_lock() failed (%i)", shutdown_lock_ret);
	}

	// take the file lock
	do {} while (px4_sem_wait(&param_sem_save) != 0);

	param_lock_reader();

	uint8_t bson_buffer[256];
	bson_encoder_init_buf_file(&encoder, fd, &bson_buffer, sizeof(bson_buffer));

	/* no modified parameters -> we are done */
	if (param_values == NULL) {
		result = 0;
		goto out;
	}

	while ((s = (struct param_wbuf_s *)utarray_next(param_values, s)) != NULL) {
		/*
		 * If we are only saving values changed since last save, and this
		 * one hasn't, then skip it
		 */
		if (only_unsaved && !s->unsaved) {
			continue;
		}

		s->unsaved = false;

		const char *name = param_name(s->param);
		const size_t size = param_size(s->param);

		/* append the appropriate BSON type object */
		switch (param_type(s->param)) {

		case PARAM_TYPE_INT32: {
				const int32_t i = s->val.i;

				debug("exporting: %s (%d) size: %d val: %d", name, s->param, size, i);

				if (bson_encoder_append_int(&encoder, name, i)) {
					PX4_ERR("BSON append failed for '%s'", name);
					goto out;
				}
			}
			break;

		case PARAM_TYPE_FLOAT: {
				const float f = s->val.f;

				debug("exporting: %s (%d) size: %d val: %.3f", name, s->param, size, (double)f);

				if (bson_encoder_append_double(&encoder, name, f)) {
					PX4_ERR("BSON append failed for '%s'", name);
					goto out;
				}
			}
			break;

		case PARAM_TYPE_STRUCT ... PARAM_TYPE_STRUCT_MAX: {
				const void *value_ptr = param_get_value_ptr(s->param);

				/* lock as short as possible */
				if (bson_encoder_append_binary(&encoder,
							       name,
							       BSON_BIN_BINARY,
							       size,
							       value_ptr)) {

					PX4_ERR("BSON append failed for '%s'", name);
					goto out;
				}
			}
			break;

		default:
			PX4_ERR("unrecognized parameter type");
			goto out;
		}
	}

	result = 0;

out:

	if (result == 0) {
		if (bson_encoder_fini(&encoder) != PX4_OK) {
			PX4_ERR("bson encoder finish failed");
		}
	}

	param_unlock_reader();

	px4_sem_post(&param_sem_save);

	if (shutdown_lock_ret == 0) {
		px4_shutdown_unlock();
	}

	perf_end(param_export_perf);

	return result;
}
예제 #11
0
	void		lock() { do {} while (px4_sem_wait(&_lock) != 0); }
예제 #12
0
static int
task_main(int argc, char *argv[])
{
	work_q_item_t *work;

	/* Initialize global variables */
	g_key_offsets[0] = 0;

	for (unsigned i = 0; i < (DM_KEY_NUM_KEYS - 1); i++) {
		g_key_offsets[i + 1] = g_key_offsets[i] + (g_per_item_max_index[i] * k_sector_size);
	}

	unsigned max_offset = g_key_offsets[DM_KEY_NUM_KEYS - 1] + (g_per_item_max_index[DM_KEY_NUM_KEYS - 1] * k_sector_size);

	for (unsigned i = 0; i < dm_number_of_funcs; i++) {
		g_func_counts[i] = 0;
	}

	/* Initialize the item type locks, for now only DM_KEY_MISSION_STATE supports locking */
	px4_sem_init(&g_sys_state_mutex, 1, 1); /* Initially unlocked */

	for (unsigned i = 0; i < DM_KEY_NUM_KEYS; i++) {
		g_item_locks[i] = NULL;
	}

	g_item_locks[DM_KEY_MISSION_STATE] = &g_sys_state_mutex;

	g_task_should_exit = false;

	init_q(&g_work_q);
	init_q(&g_free_q);

	px4_sem_init(&g_work_queued_sema, 1, 0);

	/* See if the data manage file exists and is a multiple of the sector size */
	g_task_fd = open(k_data_manager_device_path, O_RDONLY | O_BINARY);

	if (g_task_fd >= 0) {

#ifndef __PX4_POSIX
		// XXX on Mac OS and Linux the file is not a multiple of the sector sizes
		// this might need further inspection.

		/* File exists, check its size */
		int file_size = lseek(g_task_fd, 0, SEEK_END);

		if ((file_size % k_sector_size) != 0) {
			PX4_WARN("Incompatible data manager file %s, resetting it", k_data_manager_device_path);
			PX4_WARN("Size: %u, sector size: %d", file_size, k_sector_size);
			close(g_task_fd);
			unlink(k_data_manager_device_path);
		}

#else
		close(g_task_fd);
#endif

	}

	/* Open or create the data manager file */
	g_task_fd = open(k_data_manager_device_path, O_RDWR | O_CREAT | O_BINARY, PX4_O_MODE_666);

	if (g_task_fd < 0) {
		PX4_WARN("Could not open data manager file %s", k_data_manager_device_path);
		px4_sem_post(&g_init_sema); /* Don't want to hang startup */
		return -1;
	}

	if ((unsigned)lseek(g_task_fd, max_offset, SEEK_SET) != max_offset) {
		close(g_task_fd);
		PX4_WARN("Could not seek data manager file %s", k_data_manager_device_path);
		px4_sem_post(&g_init_sema); /* Don't want to hang startup */
		return -1;
	}

	fsync(g_task_fd);

	/* see if we need to erase any items based on restart type */
	int sys_restart_val;

	const char *restart_type_str = "Unkown restart";

	if (param_get(param_find("SYS_RESTART_TYPE"), &sys_restart_val) == OK) {
		if (sys_restart_val == DM_INIT_REASON_POWER_ON) {
			restart_type_str = "Power on restart";
			_restart(DM_INIT_REASON_POWER_ON);

		} else if (sys_restart_val == DM_INIT_REASON_IN_FLIGHT) {
			restart_type_str = "In flight restart";
			_restart(DM_INIT_REASON_IN_FLIGHT);
		}
	}

	/* We use two file descriptors, one for the caller context and one for the worker thread */
	/* They are actually the same but we need to some way to reject caller request while the */
	/* worker thread is shutting down but still processing requests */
	g_fd = g_task_fd;

	PX4_INFO("%s, data manager file '%s' size is %d bytes",
		 restart_type_str, k_data_manager_device_path, max_offset);

	/* Tell startup that the worker thread has completed its initialization */
	px4_sem_post(&g_init_sema);

	/* Start the endless loop, waiting for then processing work requests */
	while (true) {

		/* do we need to exit ??? */
		if ((g_task_should_exit) && (g_fd >= 0)) {
			/* Close the file handle to stop further queuing */
			g_fd = -1;
		}

		if (!g_task_should_exit) {
			/* wait for work */
			px4_sem_wait(&g_work_queued_sema);
		}

		/* Empty the work queue */
		while ((work = dequeue_work_item())) {

			/* handle each work item with the appropriate handler */
			switch (work->func) {
			case dm_write_func:
				g_func_counts[dm_write_func]++;
				work->result =
					_write(work->write_params.item, work->write_params.index, work->write_params.persistence, work->write_params.buf,
					       work->write_params.count);
				break;

			case dm_read_func:
				g_func_counts[dm_read_func]++;
				work->result =
					_read(work->read_params.item, work->read_params.index, work->read_params.buf, work->read_params.count);
				break;

			case dm_clear_func:
				g_func_counts[dm_clear_func]++;
				work->result = _clear(work->clear_params.item);
				break;

			case dm_restart_func:
				g_func_counts[dm_restart_func]++;
				work->result = _restart(work->restart_params.reason);
				break;

			default: /* should never happen */
				work->result = -1;
				break;
			}

			/* Inform the caller that work is done */
			px4_sem_post(&work->wait_sem);
		}

		/* time to go???? */
		if ((g_task_should_exit) && (g_fd < 0)) {
			break;
		}
	}

	close(g_task_fd);
	g_task_fd = -1;

	/* The work queue is now empty, empty the free queue */
	for (;;) {
		if ((work = (work_q_item_t *)sq_remfirst(&(g_free_q.q))) == NULL) {
			break;
		}

		if (work->first) {
			free(work);
		}
	}

	destroy_q(&g_work_q);
	destroy_q(&g_free_q);
	px4_sem_destroy(&g_work_queued_sema);
	px4_sem_destroy(&g_sys_state_mutex);

	return 0;
}
예제 #13
0
static inline void
lock_queue(work_q_t *q)
{
	px4_sem_wait(&(q->mutex));	/* Acquire the queue lock */
}
예제 #14
0
int test_dataman(int argc, char *argv[])
{
	int i = 0;
	unsigned num_tasks = 4;
	char buffer[DM_MAX_DATA_SIZE];

	if (argc > 1) {
		num_tasks = atoi(argv[1]);
	}

	sems = (px4_sem_t *)malloc(num_tasks * sizeof(px4_sem_t));
	task_returned_error = (bool *)calloc(num_tasks, sizeof(bool));
	PX4_INFO("Running %d tasks", num_tasks);

	for (i = 0; i < num_tasks; i++) {
		int task;

		char a[16];
		snprintf(a, 16, "%d", i);

		char *av[] = {"tests_dataman", a, NULL};

		px4_sem_init(sems + i, 1, 0);
		/* sems use case is a signal */
		px4_sem_setprotocol(sems, SEM_PRIO_NONE);

		/* start the task */
		if ((task = px4_task_spawn_cmd("dataman", SCHED_DEFAULT, SCHED_PRIORITY_MAX - 5, 2048, task_main, av)) <= 0) {
			PX4_ERR("task start failed");
		}
	}

	for (i = 0; i < num_tasks; i++) {
		px4_sem_wait(sems + i);
		px4_sem_destroy(sems + i);
	}

	free(sems);

	bool got_error = false;

	for (i = 0; i < num_tasks; i++) {
		if (task_returned_error[i]) {
			got_error = true;
			break;
		}
	}

	free(task_returned_error);

	if (got_error) {
		return -1;
	}

	dm_restart(DM_INIT_REASON_IN_FLIGHT);

	for (i = 0; i < NUM_MISSIONS_TEST; i++) {
		if (dm_read(DM_KEY_WAYPOINTS_OFFBOARD_1, i, buffer, sizeof(buffer)) != 0) {
			break;
		}
	}

	if (i >= NUM_MISSIONS_TEST) {
		PX4_ERR("Restart in-flight failed");
		return -1;

	}

	dm_restart(DM_INIT_REASON_POWER_ON);

	for (i = 0; i < NUM_MISSIONS_TEST; i++) {
		if (dm_read(DM_KEY_WAYPOINTS_OFFBOARD_1, i, buffer, sizeof(buffer)) != 0) {
			PX4_ERR("Restart power-on failed");
			return -1;
		}
	}

	return 0;
}
예제 #15
0
static void hrt_lock(void)
{
	px4_sem_wait(&_hrt_lock);
}