Commit e47f6596 authored by Éric Thiébaut's avatar Éric Thiébaut
Browse files

Reorganize object hierarchy and merge remote mirrors and their telemetry

parent 20dd01d6
......@@ -20,6 +20,22 @@
* Hitting Ctrl-C at a server terminal kills the server but never calls `atexit`
cleanup functions.
* Quitting a process does not release its locks. This is intended because
having a (write) lock means that the protected ressources are potentially in
an intermediate state and, obviously, releasing the lock automatically is a
bad idea because the state cannot be fixed. Perhaps, read-only locks can be
(and are?) released automatically? If locks are used to wait on a condition,
it is unlikely that the process dies in the middle (i.e., between acquiring
the lock and starting to wait).
* Perhaps it is a better idea to use r/w locks of the POSIX Threads Library
instead of my own implementation (whose motivation was to combine the of
exclusive lock, r/w lock and condition variable with one mutex and one
condition variable).
* See https://www.drdobbs.com/soft-real-time-programming-with-linux/184402031
for soft-real-time programming hints.
## Things to do
......
#include "tao-alpao.h"
#include "tao-generic.h"
#include "tao-mirrors-private.h"
#include "tao-mirrors.h"
#include "tao-shared-private.h"
#include <math.h>
#include <string.h>
// Private data needed for the cleanup callback.
static tao_remote_mirror* dm = NULL;
static tao_shared_mirror_data* dat = NULL;
static long* inds = NULL;
static uint8_t* msk = NULL;
static alpao_mirror* dev = NULL;
......@@ -22,9 +22,9 @@ static tao_status on_send(
// Copy requested commands as actual commands and send them (which also updates
// the actual commands).
double* act_cmds = TAO_REMOTE_MIRROR_ACT_CMDS(dm);
const double* req_cmds = TAO_REMOTE_MIRROR_REQ_CMDS(dm);
const double* refs = TAO_REMOTE_MIRROR_REFS(dm);
double* act_cmds = tao_remote_mirror_get_actual_commands(dm);
const double* req_cmds = tao_remote_mirror_get_requested_commands(dm);
const double* refs = tao_remote_mirror_get_reference(dm);
long nacts = dm->nacts;
for (long i = 0; i < nacts; ++i) {
act_cmds[i] = req_cmds[i];
......@@ -37,8 +37,8 @@ static tao_status on_reset(
tao_remote_mirror* dm,
void* ctx)
{
double* req_cmds = TAO_REMOTE_MIRROR_REQ_CMDS(dm);
long nacts = dm->nacts;
double* req_cmds = tao_remote_mirror_get_requested_commands(dm);
long nacts = tao_remote_mirror_get_nacts(dm);
for (long i = 0; i < nacts; ++i) {
req_cmds[i] = 0.0;
}
......@@ -49,19 +49,13 @@ static tao_status on_reset(
static void cleanup(void)
{
if (dm != NULL) {
if (dm->task != TAO_TASK_QUIT) {
dm->task = TAO_TASK_QUIT;
if (dm->base.task != TAO_TASK_QUIT) {
// FIXME: should lock
dm->base.task = TAO_TASK_QUIT;
}
tao_detach_remote_mirror(dm);
tao_remote_mirror_detach(dm);
dm = NULL;
}
if (dat != NULL) {
if (dat->running != false) {
dat->running = false;
}
tao_detach_shared_mirror_data(dat);
dat = NULL;
}
if (msk != NULL) {
tao_free(msk);
msk = NULL;
......@@ -242,17 +236,8 @@ int main(
return EXIT_FAILURE;
}
// Allocate the shared cyclic array of data-frames.
dat = tao_create_shared_mirror_data(ident, nbufs, nacts, perms);
if (dat == NULL) {
fprintf(stderr, "%s: failed to create shared mirror data\n",
progname);
tao_report_errors();
return EXIT_FAILURE;
}
// Allocate the remote mirror instance.
dm = tao_create_remote_mirror(dat, inds, dims[0], dims[1], perms);
dm = tao_remote_mirror_create(ident, nbufs, inds, dims[0], dims[1], perms);
if (dm == NULL) {
fprintf(stderr, "%s: failed to create remote mirror instance\n",
progname);
......@@ -268,7 +253,7 @@ int main(
.name = ident,
.debug = debug
};
tao_status status = tao_run_mirror_loop(dm, dat, &ops, dev);
tao_status status = tao_remote_mirror_run_loop(dm, &ops, NULL);
if (status != TAO_OK) {
tao_report_errors();
return EXIT_FAILURE;
......
......@@ -138,7 +138,7 @@ static void* run_worker(void* arg);
static tao_send_callback on_get_accesspoint;
static tao_send_callback on_get_bufferencoding;
static tao_send_callback on_get_buffers;
static tao_send_callback on_get_counter;
static tao_send_callback on_get_serial;
static tao_send_callback on_get_debuglevel;
static tao_send_callback on_get_drop;
static tao_send_callback on_get_exposuretime;
......@@ -165,7 +165,7 @@ static tao_server_command get_commands[] = {
{"accesspoint", on_get_accesspoint, NULL, NULL, NULL},
{"bufferencoding", on_get_bufferencoding, NULL, NULL, NULL},
{"buffers", on_get_buffers, NULL, NULL, NULL},
{"counter", on_get_counter, NULL, NULL, NULL},
{"serial", on_get_serial, NULL, NULL, NULL},
{"debuglevel", on_get_debuglevel, NULL, NULL, NULL},
{"drop", on_get_drop, NULL, NULL, NULL},
{"exposuretime", on_get_exposuretime, NULL, NULL, NULL},
......@@ -354,7 +354,7 @@ int main(
}
// Publish shmid of shared camera.
shmid = tao_get_shared_camera_shmid(shcam);
shmid = tao_shared_camera_get_shmid(shcam);
if (tao_config_write_long(group, shmid) != TAO_OK) {
fprintf(stderr, "%s: Failed to publish my shmid.\n", progname);
return EXIT_FAILURE;
......@@ -582,7 +582,7 @@ typedef void processor(
static void wrlock_shared_camera(
void)
{
if (tao_wrlock_shared_camera(shcam) != TAO_OK) {
if (tao_shared_camera_wrlock(shcam) != TAO_OK) {
tao_panic();
}
}
......@@ -590,7 +590,7 @@ static void wrlock_shared_camera(
static void rdlock_shared_camera(
void)
{
if (tao_rdlock_shared_camera(shcam) != TAO_OK) {
if (tao_shared_camera_rdlock(shcam) != TAO_OK) {
tao_panic();
}
}
......@@ -598,7 +598,7 @@ static void rdlock_shared_camera(
static void unlock_shared_camera(
void)
{
if (tao_unlock_shared_camera(shcam) != TAO_OK) {
if (tao_shared_camera_unlock(shcam) != TAO_OK) {
tao_panic();
}
}
......@@ -607,7 +607,7 @@ static void unlock_shared_camera(
static int try_rdlock_shared_camera(
void)
{
tao_status = tao_try_rdlock_shared_camera(shcam);
tao_status = tao_shared_camera_try_rdlock(shcam);
if (status == TAO_OK) {
return true;
}
......@@ -620,7 +620,7 @@ static int try_rdlock_shared_camera(
static int try_wrlock_shared_camera(
void)
{
tao_status = tao_try_wrlock_shared_camera(shcam);
tao_status = tao_shared_camera_try_wrlock(shcam);
if (status == TAO_OK) {
return true;
}
......@@ -633,7 +633,7 @@ static int try_wrlock_shared_camera(
static int timed_rdlock_shared_camera(
double secs)
{
tao_status = tao_timed_rdlock_shared_camera(shcam, secs);
tao_status = tao_shared_camera_timed_rdlock(shcam, secs);
if (status == TAO_OK) {
return true;
}
......@@ -646,7 +646,7 @@ static int timed_rdlock_shared_camera(
static int timed_wrlock_shared_camera(
double secs)
{
tao_status = tao_timed_wrlock_shared_camera(shcam, secs);
tao_status = tao_shared_camera_timed_wrlock(shcam, secs);
if (status == TAO_OK) {
return true;
}
......@@ -664,7 +664,7 @@ static int timed_wrlock_shared_camera(
static void lock_monitor(
void)
{
if (tao_lock_mutex(&monitor.mutex) != TAO_OK) {
if (tao_mutex_lock(&monitor.mutex) != TAO_OK) {
tao_panic();
}
}
......@@ -672,8 +672,8 @@ static void lock_monitor(
static void unlock_monitor(
void)
{
if (tao_signal_condition(&monitor.cond) != TAO_OK ||
tao_unlock_mutex(&monitor.mutex) != TAO_OK) {
if (tao_condition_signal(&monitor.cond) != TAO_OK ||
tao_mutex_unlock(&monitor.mutex) != TAO_OK) {
tao_panic();
}
}
......@@ -681,8 +681,8 @@ static void unlock_monitor(
static void wait_monitor(
void)
{
if (tao_signal_condition(&monitor.cond) != TAO_OK ||
tao_wait_condition(&monitor.cond, &monitor.mutex) != TAO_OK) {
if (tao_condition_signal(&monitor.cond) != TAO_OK ||
tao_condition_wait(&monitor.cond, &monitor.mutex) != TAO_OK) {
tao_panic();
}
}
......@@ -699,7 +699,7 @@ static tao_status process_frame(
const void* data = (unsigned char*)buf->data + buf->offset;
tao_shared_array* arr = tao_get_framegrabber_buffer(vfg);
tao_encoding arrenc;
switch (TAO_GET_SHARED_ARRAY_ELTYPE(arr)) {
switch (TAO_SHARED_ARRAY_ELTYPE(arr)) {
case TAO_UINT8:
case TAO_INT8:
arrenc = ANDOR_ENCODING_MONO8;
......@@ -723,10 +723,10 @@ static tao_status process_frame(
}
if (arrenc != ANDOR_ENCODING_UNKNOWN &&
TAO_GET_SHARED_ARRAY_NDIMS(arr) >= 2 &&
TAO_GET_SHARED_ARRAY_DIM(arr, 1) == width &&
TAO_GET_SHARED_ARRAY_DIM(arr, 2) == height) {
andor_convert_buffer(TAO_GET_SHARED_ARRAY_DATA(arr), arrenc,
TAO_SHARED_ARRAY_NDIMS(arr) >= 2 &&
TAO_SHARED_ARRAY_DIM(arr, 1) == width &&
TAO_SHARED_ARRAY_DIM(arr, 2) == height) {
andor_convert_buffer(TAO_SHARED_ARRAY_DATA(arr), arrenc,
data, bufenc, width, height, stride);
arr->ts[0] = buf->frame_start;
arr->ts[1] = buf->frame_end;
......@@ -822,10 +822,10 @@ static tao_status init_callback(
tao_server* srv,
void* ctx)
{
wrlock_shared_camera();
tao__set_shared_object_accesspoint(&shcam->base,
tao_get_server_accesspoint(srv));
unlock_shared_camera();
// FIXME: wrlock_shared_camera();
// FIXME: tao__set_shared_object_accesspoint(
// FIXME: &shcam->base, tao_get_server_accesspoint(srv));
// FIXME: unlock_shared_camera();
return TAO_OK;
}
......@@ -902,7 +902,7 @@ static tao_status on_get_accesspoint(
} \
return tao_set_reply_data_from_buffer(srv, bufptr, sizptr, false); \
}
GETTER(long long, "%lld", counter, counter)
GETTER(long long, "%lld", serial, serial)
GETTER(long, "%ld", lastshmid, lastframe)
GETTER(long, "%ld", nextshmid, nextframe)
GETTER(long, "%ld", sensorwidth, info.sensorwidth)
......@@ -1019,7 +1019,7 @@ static tao_status on_get_shmid(
send_usage(srv, argv[0], NULL);
return TAO_ERROR;
}
tao_shmid shmid = tao_get_shared_camera_shmid(shcam);
tao_shmid shmid = tao_shared_camera_get_shmid(shcam);
if (tao_print_to_server_buffer(srv, "%ld\n", (long)shmid) != TAO_OK) {
return TAO_ERROR;
}
......
......@@ -66,7 +66,6 @@ include_HEADERS = \
tao-locks.h \
tao-macros.h \
tao-mirrors.h \
tao-mirrors-private.h \
tao-options.h \
tao-preprocessing.h \
tao-servers.h \
......@@ -88,12 +87,12 @@ libtao_la_SOURCES = \
errors.c \
locks.c \
logmsg.c \
mirrors.c \
remote-mirrors.c \
options.c \
pixels.c \
semaphores.c \
sharedarrays.c \
sharedobjects.c \
shared-arrays.c \
shared-objects.c \
threadpools.c \
utils.c
libtao_la_LIBADD = $(OTHER_LIBS)
......@@ -110,7 +109,7 @@ libtao_xpa_la_SOURCES = servers.c
libtao_xpa_la_CPPFLAGS = $(XPA_DEFS)
libtao_xpa_la_LIBADD = $(XPA_LIBS) $(TAO_LIBS)
EXTRA_DIST = sharedgeneric.c intro.txt
EXTRA_DIST = shared-methods.c inline-funcs.h intro.txt
bin_PROGRAMS = \
tao-fake-mirror-server
......@@ -123,6 +122,7 @@ TESTS = \
test-basics \
test-encodings \
test-errors \
test-pthread \
test-search \
test-semaphores \
test-shared \
......@@ -148,6 +148,10 @@ test_errors_SOURCES = test-errors.c
test_errors_CPPFLAGS = -I$(srcdir)
test_errors_LDADD = $(TAO_LIBS)
test_pthread_SOURCES = test-pthread.c
test_pthread_CPPFLAGS = -I$(srcdir)
test_pthread_LDADD = $(TAO_LIBS)
test_search_SOURCES = test-search.c
test_search_CPPFLAGS =
test_search_LDADD =
......
......@@ -26,9 +26,6 @@
#define if_likely(expr) if TAO_LIKELY(expr)
#define if_unlikely(expr) if TAO_UNLIKELY(expr)
#define NEW_SHARED_OBJECT(type, owner, id, perms) \
((type*)tao_create_shared_object(owner, id, sizeof(type), perms))
//-----------------------------------------------------------------------------
// REGIONS OF INTEREST
......@@ -249,10 +246,10 @@ tao_camera* tao_create_camera(
return NULL;
}
memset((void*)cam, 0, size);
if (tao_initialize_mutex(&cam->mutex, false) != TAO_OK) {
if (tao_mutex_initialize(&cam->mutex, false) != TAO_OK) {
goto error1;
}
if (tao_initialize_condition(&cam->notify, false) != TAO_OK) {
if (tao_condition_initialize(&cam->notify, false) != TAO_OK) {
goto error2;
}
cam->ops = ops;
......@@ -365,21 +362,21 @@ void tao_notify_camera(
tao_status tao_wait_camera(
tao_camera* cam)
{
return tao_wait_condition(&cam->notify, &cam->mutex);
return tao_condition_wait(&cam->notify, &cam->mutex);
}
tao_status tao_abstimed_wait_camera(
tao_camera* cam,
const tao_time* abstime)
{
return tao_abstimed_wait_condition(&cam->notify, &cam->mutex, abstime);
return tao_condition_abstimed_wait(&cam->notify, &cam->mutex, abstime);
}
tao_status tao_timed_wait_camera(
tao_camera* cam,
double secs)
{
return tao_timed_wait_condition(&cam->notify, &cam->mutex, secs);
return tao_condition_timed_wait(&cam->notify, &cam->mutex, secs);
}
// This function may be called after an unsuccessful command to set the camera
......@@ -690,10 +687,10 @@ const tao_time* tao_get_camera_origin_of_time(
#define ENCODE(w) \
double tao_get_camera_elapsed_##w( \
const tao_camera* cam, \
const tao_time* t) \
const tao_camera* cam, \
const tao_time* t) \
{ \
tao_time dt; \
tao_time dt; \
if (t == NULL) { \
get_monotonic_time(&dt); \
t = &dt; \
......@@ -810,24 +807,24 @@ tao_status tao_destroy_framegrabber(
if (fg->camera != NULL) {
tao_shared_camera* cam = fg->camera;
fg->camera = NULL;
if (tao_detach_shared_camera(cam) != TAO_OK) {
if (tao_shared_camera_detach(cam) != TAO_OK) {
status = TAO_ERROR;
}
}
if (fg->locked != NULL) {
tao_shared_array* arr = fg->locked;
fg->locked = NULL;
if (tao_unlock_shared_array(arr) != TAO_OK) {
if (tao_shared_array_unlock(arr) != TAO_OK) {
status = TAO_ERROR;
}
}
if (fg->list != NULL) {
tao_shared_array** list = fg->list;
for (int i = 0; i < fg->length; ++i) {
for (int i = 0; i < fg->nbufs; ++i) {
tao_shared_array* arr = list[i];
list[i] = NULL;
if (arr != NULL &&
tao_detach_shared_array(arr) != TAO_OK) {
tao_shared_array_detach(arr) != TAO_OK) {
status = TAO_ERROR;
}
}
......@@ -839,48 +836,47 @@ tao_status tao_destroy_framegrabber(
return status;
}
// Methods to initialize `const` member in structure.
static inline void set_uint64(
const uint64_t* ptr,
int val)
{
*(uint64_t*)ptr = val;
}
tao_framegrabber* tao_create_framegrabber(
const char* owner,
int length,
unsigned perms)
int nbufs,
unsigned flags)
{
tao_framegrabber* fg;
tao_shared_camera* cam;
if (length < 2) {
long len = TAO_STRLEN(owner);
if (len < 1) {
tao_push_error(__func__, TAO_BAD_NAME);
return NULL;
}
if (nbufs < 2) {
tao_push_error(__func__, TAO_BAD_ARGUMENT);
return NULL;
}
fg = TAO_NEW(1, tao_framegrabber);
tao_framegrabber* fg = TAO_NEW(1, tao_framegrabber);
if (fg == NULL) {
return NULL;
}
fg->perms = perms;
fg->list = TAO_NEW(length, tao_shared_array*);
fg->flags = flags;
fg->list = TAO_NEW(nbufs, tao_shared_array*);
if (fg->list == NULL) {
tao_destroy_framegrabber(fg);
return NULL;
}
set_uint64(&fg->length, length);
fg->counter = 0;
cam = NEW_SHARED_OBJECT(tao_shared_camera,
owner, TAO_SHARED_CAMERA, perms);
tao_forced_store(&fg->nbufs, nbufs);
fg->serial = 0;
tao_shared_camera* cam = (tao_shared_camera*)tao_rwlocked_object_create(
TAO_SHARED_CAMERA, sizeof(tao_shared_camera), flags);
if (cam == NULL) {
tao_destroy_framegrabber(fg);
return NULL;
}
for (long i = 0; i < len; ++i) {
((char*)cam->owner)[i] = owner[i];
}
((char*)cam->owner)[len] = '\0';
fg->camera = cam;
initialize_camera_info(&cam->info);
set_uint64(&cam->length, length);
cam->counter = fg->counter;
tao_forced_store(&cam->nbufs, nbufs);
cam->serial = fg->serial;
cam->lastframe = TAO_BAD_SHMID;
cam->nextframe = TAO_BAD_SHMID;
return fg;
......@@ -900,21 +896,19 @@ tao_shared_array* tao_get_framegrabber_buffer(
static tao_shared_array* allocate_frame(
tao_shared_camera* cam,
unsigned perms)
unsigned flags)
{
tao_shared_array* arr;
if (cam->info.config.weighted == false) {
arr = tao_create_2d_shared_array(cam->base.owner,
cam->info.config.pixeltype,
arr = tao_shared_array_create_2d(cam->info.config.pixeltype,
cam->info.config.roi.width,
cam->info.config.roi.height,
perms);
flags);
} else {
arr = tao_create_3d_shared_array(cam->base.owner,
cam->info.config.pixeltype,
arr = tao_shared_array_create_3d(cam->info.config.pixeltype,
cam->info.config.roi.width,
cam->info.config.roi.height,
2, perms);
2, flags);
}
return arr;
}
......@@ -928,7 +922,7 @@ static inline int is_suitable(
const tao_shared_array* arr,
const tao_shared_camera* cam)
{
return (arr->base.shared.shmid != cam->lastframe &&
return (TAO_SHARED_ARRAY_SHMID(arr) != cam->lastframe &&
arr->eltype == cam->info.config.pixeltype &&
arr->dims[0] == cam->info.config.roi.width &&
arr->dims[1] == cam->info.config.roi.height &&
......@@ -942,14 +936,14 @@ static inline tao_shared_array* fetch_next_frame(
{
// Index and address of next frame.
tao_shared_camera* cam = fg->camera;
int index = fg->counter%fg->length;
int index = fg->serial%fg->nbufs;
tao_shared_array* arr = fg->list[index];
if (arr != NULL) {
bool drop = true;
if (is_suitable(arr, cam)) {
// Array is suitable to store next frame data, try to lock it for
// writing.
tao_status code = tao_try_wrlock_shared_array(arr);
tao_status code = tao_shared_array_try_wrlock(arr);
if (code == TAO_OK) {
// Shared array is now locked for writing.
drop = false;
......@@ -961,7 +955,7 @@ static inline tao_shared_array* fetch_next_frame(
if (drop == true) {
// Drop the shared array.
fg->list[index] = NULL;
if (tao_detach_shared_array(arr) != TAO_OK) {
if (tao_shared_array_detach(arr) != TAO_OK) {
return NULL;
}
arr = NULL;
......@@ -971,18 +965,18 @@ static inline tao_shared_array* fetch_next_frame(
// If no suitable spare array was available, allocate a new shared array to
// store the next frame data and lock it for writing.
if (arr == NULL) {
arr = allocate_frame(cam, fg->perms);
arr = allocate_frame(cam, fg->flags);
if (arr == NULL) {
return NULL;
}
fg->list[index] = arr;
if (tao_wrlock_shared_array(arr) != TAO_OK) {
if (tao_shared_array_wrlock(arr) != TAO_OK) {
return NULL;
}
}
// Update information and return shared array.
arr->counter = 0; // to indicate that this buffer is not valid
arr->serial = 0; // to indicate that this buffer is not valid
for (int i = 0; i < TAO_SHARED_ARRAY_TIMESTAMPS; ++i) {
arr->ts[i] = TAO_UNKNOWN_TIME;
}
......@@ -1003,7 +997,7 @@ tao_status tao_start_framegrabber_acquisition(
if (fg->locked == NULL) {
return TAO_ERROR;
}
fg->camera->nextframe = fg->locked->base.shared.shmid;
fg->camera->nextframe = fg->locked->base.base.shmid;
}
return TAO_OK;
}
......@@ -1021,7 +1015,7 @@ tao_status tao_stop_framegrabber_acquisition(
if (fg->locked != NULL) {
tao_shared_array* arr = fg->locked;
fg->locked = NULL;
if (tao_unlock_shared_array(arr) != TAO_OK) {
if (tao_shared_array_unlock(arr) != TAO_OK) {
return TAO_ERROR;
}
}
......@@ -1042,8 +1036,8 @@ tao_status tao_post_framegrabber_buffer(
if (fg->locked != NULL) {
tao_shared_array* arr = fg->locked;
fg->locked = NULL;
fg->counter += 1;
arr->counter = fg->counter;
fg->serial += 1;
arr->serial = fg->serial;
if (TAO_SHARED_ARRAY_TIMESTAMPS >= 4) {
tao_time t;
if (tao_get_monotonic_time(&t) == TAO_OK) {
......@@ -1052,11 +1046,11 @@ tao_status tao_post_framegrabber_buffer(
tao_report_errors();
}
}
if (tao_unlock_shared_array(arr) != TAO_OK) {
if (tao_shared_array_unlock(arr) != TAO_OK) {
return TAO_ERROR;
}
fg->camera->counter = fg->counter;
fg->camera->lastframe = arr->base.shared.shmid;
fg->camera->serial = fg->serial;
fg->camera->lastframe = arr->base.base.shmid;
}
// Fetch next acquisition frame buffer.
......@@ -1064,7 +1058,7 @@ tao_status tao_post_framegrabber_buffer(
if (fg->locked == NULL) {
return TAO_ERROR;
}
fg->camera->nextframe = fg->locked->base.shared.shmid;
fg->camera->nextframe = fg->locked->base.base.shmid;