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