Blame external/opae-test/framework/mock/test_fpgad/monitor_thread.c

Packit 534379
// Copyright(c) 2018-2019, Intel Corporation
Packit 534379
//
Packit 534379
// Redistribution  and  use  in source  and  binary  forms,  with  or  without
Packit 534379
// modification, are permitted provided that the following conditions are met:
Packit 534379
//
Packit 534379
// * Redistributions of  source code  must retain the  above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer.
Packit 534379
// * Redistributions in binary form must reproduce the above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer in the documentation
Packit 534379
//   and/or other materials provided with the distribution.
Packit 534379
// * Neither the name  of Intel Corporation  nor the names of its contributors
Packit 534379
//   may be used to  endorse or promote  products derived  from this  software
Packit 534379
//   without specific prior written permission.
Packit 534379
//
Packit 534379
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 534379
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,  BUT NOT LIMITED TO,  THE
Packit 534379
// IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 534379
// ARE DISCLAIMED.  IN NO EVENT  SHALL THE COPYRIGHT OWNER  OR CONTRIBUTORS BE
Packit 534379
// LIABLE  FOR  ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
Packit 534379
// CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT LIMITED  TO,  PROCUREMENT  OF
Packit 534379
// SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
Packit 534379
// INTERRUPTION)  HOWEVER CAUSED  AND ON ANY THEORY  OF LIABILITY,  WHETHER IN
Packit 534379
// CONTRACT,  STRICT LIABILITY,  OR TORT  (INCLUDING NEGLIGENCE  OR OTHERWISE)
Packit 534379
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
Packit 534379
// POSSIBILITY OF SUCH DAMAGE.
Packit 534379
Packit 534379
#ifdef HAVE_CONFIG_H
Packit 534379
#include <config.h>
Packit 534379
#endif // HAVE_CONFIG_H
Packit 534379
Packit 534379
#include <dlfcn.h>
Packit 534379
#include "monitored_device.h"
Packit 534379
#include "monitor_thread.h"
Packit 534379
#include "event_dispatcher_thread.h"
Packit 534379
Packit 534379
#include "logging.h"
Packit 534379
Packit 534379
#ifdef LOG
Packit 534379
#undef LOG
Packit 534379
#endif
Packit 534379
#define LOG(format, ...) \
Packit 534379
log_printf("monitor_thread: " format, ##__VA_ARGS__)
Packit 534379
Packit 534379
monitor_thread_config monitor_config = {
Packit 534379
	.global = &global_config,
Packit 534379
	.sched_policy = SCHED_RR,
Packit 534379
	.sched_priority = 20,
Packit 534379
};
Packit 534379
Packit 534379
STATIC pthread_mutex_t mon_list_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
Packit 534379
STATIC fpgad_monitored_device *monitored_device_list;
Packit 534379
Packit 534379
STATIC void mon_queue_response(fpgad_detection_status status,
Packit 534379
			       fpgad_respond_event_t response,
Packit 534379
			       fpgad_monitored_device *d,
Packit 534379
			       void *response_context)
Packit 534379
{
Packit 534379
	if (status == FPGAD_STATUS_DETECTED_HIGH) {
Packit 534379
Packit 534379
		if (evt_queue_response_high(response,
Packit 534379
					    d,
Packit 534379
					    response_context)) {
Packit 534379
			pthread_yield();
Packit 534379
		} else {
Packit 534379
			LOG("high priority event queue is full. Dropping!\n");
Packit 534379
		}
Packit 534379
Packit 534379
	} else if (status == FPGAD_STATUS_DETECTED) {
Packit 534379
Packit 534379
		if (evt_queue_response(response,
Packit 534379
				       d,
Packit 534379
				       response_context)) {
Packit 534379
			pthread_yield();
Packit 534379
		} else {
Packit 534379
			LOG("event queue is full. Dropping!\n");
Packit 534379
		}
Packit 534379
Packit 534379
	}
Packit 534379
}
Packit 534379
Packit 534379
STATIC void mon_monitor(fpgad_monitored_device *d)
Packit 534379
{
Packit 534379
	unsigned i;
Packit 534379
Packit 534379
	if (!d->detections)
Packit 534379
		return;
Packit 534379
Packit 534379
	for (i = 0 ; d->detections[i] ; ++i) {
Packit 534379
		fpgad_detection_status result;
Packit 534379
		fpgad_detect_event_t detect =
Packit 534379
			d->detections[i];
Packit 534379
		void *detect_context =
Packit 534379
			d->detection_contexts ?
Packit 534379
			d->detection_contexts[i] : NULL;
Packit 534379
Packit 534379
		result = detect(d, detect_context);
Packit 534379
Packit 534379
		if (result != FPGAD_STATUS_NOT_DETECTED && d->responses) {
Packit 534379
			fpgad_respond_event_t response =
Packit 534379
				d->responses[i];
Packit 534379
			void *response_context =
Packit 534379
				d->response_contexts ?
Packit 534379
				d->response_contexts[i] : NULL;
Packit 534379
Packit 534379
			if (response) {
Packit 534379
				mon_queue_response(result,
Packit 534379
						   response,
Packit 534379
						   d,
Packit 534379
						   response_context);
Packit 534379
			}
Packit 534379
		}
Packit 534379
	}
Packit 534379
}
Packit 534379
Packit 534379
STATIC volatile bool mon_is_ready = false;
Packit 534379
Packit 534379
bool monitor_is_ready(void)
Packit 534379
{
Packit 534379
	return mon_is_ready;
Packit 534379
}
Packit 534379
Packit 534379
void *monitor_thread(void *thread_context)
Packit 534379
{
Packit 534379
	monitor_thread_config *c = (monitor_thread_config *)thread_context;
Packit 534379
	struct sched_param sched_param;
Packit 534379
	int policy = 0;
Packit 534379
	int res;
Packit 534379
	//errno_t err;
Packit 534379
	int err;
Packit 534379
	fpgad_monitored_device *d;
Packit 534379
Packit 534379
	LOG("starting\n");
Packit 534379
Packit 534379
	res = pthread_getschedparam(pthread_self(), &policy, &sched_param);
Packit 534379
	if (res) {
Packit 534379
		LOG("error getting scheduler params: %s\n", strerror(res));
Packit 534379
	} else {
Packit 534379
		policy = c->sched_policy;
Packit 534379
		sched_param.sched_priority = c->sched_priority;
Packit 534379
Packit 534379
		res = pthread_setschedparam(pthread_self(),
Packit 534379
					    policy,
Packit 534379
					    &sched_param);
Packit 534379
		if (res) {
Packit 534379
			LOG("error setting scheduler params"
Packit 534379
			    " (got root?): %s\n", strerror(res));
Packit 534379
		}
Packit 534379
	}
Packit 534379
Packit 534379
	mon_is_ready = true;
Packit 534379
Packit 534379
	while (c->global->running) {
Packit 534379
		fpgad_mutex_lock(err, &mon_list_lock);
Packit 534379
Packit 534379
		for (d = monitored_device_list ; d ; d = d->next) {
Packit 534379
			mon_monitor(d);
Packit 534379
		}
Packit 534379
Packit 534379
		fpgad_mutex_unlock(err, &mon_list_lock);
Packit 534379
Packit 534379
		usleep(c->global->poll_interval_usec);
Packit 534379
	}
Packit 534379
Packit 534379
	while (evt_dispatcher_is_ready()) {
Packit 534379
		// Wait for the event dispatcher to complete
Packit 534379
		// before we destroy the monitored devices.
Packit 534379
		usleep(c->global->poll_interval_usec);
Packit 534379
	}
Packit 534379
Packit 534379
	mon_destroy(c->global);
Packit 534379
	mon_is_ready = false;
Packit 534379
Packit 534379
	LOG("exiting\n");
Packit 534379
	return NULL;
Packit 534379
}
Packit 534379
Packit 534379
void mon_monitor_device(fpgad_monitored_device *d)
Packit 534379
{
Packit 534379
	//errno_t err;
Packit 534379
	int err;
Packit 534379
	fpgad_monitored_device *trav;
Packit 534379
Packit 534379
	fpgad_mutex_lock(err, &mon_list_lock);
Packit 534379
Packit 534379
	d->next = NULL;
Packit 534379
Packit 534379
	if (!monitored_device_list) {
Packit 534379
		monitored_device_list = d;
Packit 534379
		goto out_unlock;
Packit 534379
	}
Packit 534379
Packit 534379
	for (trav = monitored_device_list ;
Packit 534379
		trav->next ;
Packit 534379
			trav = trav->next)
Packit 534379
		/* find the end of the list */ ;
Packit 534379
Packit 534379
	trav->next = d;
Packit 534379
Packit 534379
out_unlock:
Packit 534379
	fpgad_mutex_unlock(err, &mon_list_lock);
Packit 534379
}
Packit 534379
Packit 534379
void mon_destroy(struct fpgad_config *c)
Packit 534379
{
Packit 534379
	unsigned i;
Packit 534379
	//errno_t err;
Packit 534379
	int err;
Packit 534379
	fpgad_monitored_device *d;
Packit 534379
Packit 534379
	fpgad_mutex_lock(err, &mon_list_lock);
Packit 534379
Packit 534379
	for (d = monitored_device_list ; d ; ) {
Packit 534379
		fpgad_monitored_device *trash = d;
Packit 534379
		fpgad_plugin_destroy_t destroy;
Packit 534379
Packit 534379
		d = d->next;
Packit 534379
Packit 534379
		if (trash->type == FPGAD_PLUGIN_TYPE_THREAD) {
Packit 534379
Packit 534379
			if (trash->thread_stop_fn) {
Packit 534379
				trash->thread_stop_fn();
Packit 534379
			} else {
Packit 534379
				LOG("Thread plugin \"%s\" has"
Packit 534379
				    " no thread_stop_fn\n",
Packit 534379
				    trash->supported->library_path);
Packit 534379
				pthread_cancel(trash->thread);
Packit 534379
			}
Packit 534379
Packit 534379
			pthread_join(trash->thread, NULL);
Packit 534379
		}
Packit 534379
Packit 534379
		destroy = (fpgad_plugin_destroy_t)
Packit 534379
			dlsym(trash->supported->dl_handle,
Packit 534379
				FPGAD_PLUGIN_DESTROY);
Packit 534379
Packit 534379
		if (destroy) {
Packit 534379
			destroy(trash);
Packit 534379
		} else {
Packit 534379
			LOG("warning - no destructor for \"%s\"\n",
Packit 534379
				trash->supported->library_path);
Packit 534379
		}
Packit 534379
Packit 534379
		if (trash->token)
Packit 534379
			fpgaDestroyToken(&trash->token);
Packit 534379
Packit 534379
		free(trash);
Packit 534379
	}
Packit 534379
	monitored_device_list = NULL;
Packit 534379
Packit 534379
	if (c->supported_devices) {
Packit 534379
Packit 534379
		for (i = 0 ; c->supported_devices[i].library_path ; ++i) {
Packit 534379
			fpgad_supported_device *d = &c->supported_devices[i];
Packit 534379
Packit 534379
			if (d->flags & FPGAD_DEV_LOADED) {
Packit 534379
				dlclose(d->dl_handle);
Packit 534379
			}
Packit 534379
Packit 534379
			d->flags = 0;
Packit 534379
			d->dl_handle = NULL;
Packit 534379
		}
Packit 534379
Packit 534379
	}
Packit 534379
Packit 534379
	fpgad_mutex_unlock(err, &mon_list_lock);
Packit 534379
}