-SUBDIRS=contract synchobj cbroker resmng resalloc
+SUBDIRS=contract synchobj sharedobj cbroker resmng resalloc
ifneq ($(QTDIR),)
SUBDIRS += frm_gui
typedef long frsh_signal_t;
typedef long frsh_signal_info_t;
+typedef struct frsh_memory_area_data {
+ long size;
+ long area;
+} frsh_memory_area_data_t;
+
+typedef struct frsh_memory_areas {
+ long size;
+ frsh_memory_area_data_t memory_areas[255];
+} frsh_memory_areas_t;
+
+typedef struct frsh_csect {
+ long op_kind;
+ long obj_handle;
+ fosa_rel_time_t wcet;
+ fosa_rel_time_t blocking;
+ long op;
+ frsh_memory_areas_t areas;
+ frsh_memory_areas_t storage;
+} frsh_csect_t;
+
+typedef struct frsh_csects_group {
+ long size;
+ frsh_csect_t csects[255];
+} frsh_csects_group_t;
+
module fres {
native container_ptr;
// frsh_signal_info_t deadline_miss_siginfo;
};
+ /// Critical sections (for shared objects)
+ struct csects {
+ frsh_csects_group_t sections;
+ };
+
/// Spare capacity
struct spare_capacity {
frsh_granularity_t granularity;
);
}
+int fres_block_csects_to_string(char *dest, size_t size, enum fres_block_type type,
+ const void *block_data)
+{
+ const fres_block_csects *c = block_data;
+
+ return snprintf(dest, size, "Coming Soon...\n");
+}
+
static const desc_default(label);
static const desc_default(resource);
static const desc_default(basic);
static const desc_default(timing_reqs);
+static const desc_default(csects);
static const struct fres_block_desc desc_spare_capacity = {
.size = sizeof(fres_block_spare_capacity),
[FRES_BLOCK_RESOURCE] = &desc_default_resource,
[FRES_BLOCK_BASIC] = &desc_default_basic,
[FRES_BLOCK_TIMING_REQS] = &desc_default_timing_reqs,
+ [FRES_BLOCK_CSECTS] = &desc_default_csects,
};
/**
FRES_BLOCK_RESOURCE,
FRES_BLOCK_BASIC,
FRES_BLOCK_TIMING_REQS,
+ FRES_BLOCK_CSECTS,
FRES_BLOCK_SPARE_CAPACITY,
FRES_BLOCK_DUMMY_SCHED, /**< See resources/dummy/res_dummy_idl.idl */
FRES_BLOCK_CLUSTER_TREE_TRAFFIC, /**< resources/cluster_tree/cluster_tree_idl.idl */
FRES_CONTAINER_ACCESSOR(RESOURCE, resource)
FRES_CONTAINER_ACCESSOR(BASIC, basic)
FRES_CONTAINER_ACCESSOR(TIMING_REQS, timing_reqs)
+FRES_CONTAINER_ACCESSOR(CSECTS, csects)
FRES_CONTAINER_ACCESSOR(SPARE_CAPACITY, spare_capacity)
int
FRES_CONTRACT_ACCESSOR(resource)
FRES_CONTRACT_ACCESSOR(basic)
FRES_CONTRACT_ACCESSOR(timing_reqs)
+FRES_CONTRACT_ACCESSOR(csects)
FRES_CONTRACT_ACCESSOR(spare_capacity)
#ifdef __cplusplus
#define _frsh_granularity_t_defined 1
#define _frsh_signal_t_defined 1
#define _frsh_signal_info_t_defined 1
+#define _frsh_memory_area_data_t_defined 1
+#define _frsh_memory_areas_t_defined 1
+#define _frsh_csect_t_defined 1
+#define _frsh_csects_group_t_defined 1
#define frsh_resource_type_t_serialize(codec, val) CORBA_unsigned_long_serialize(codec, val)
#define frsh_resource_type_t_deserialize(codec, val) CORBA_unsigned_long_deserialize(codec, val)
#define frsh_signal_info_t_serialize(x,y) CORBA_long_serialize((x),(y))
#define frsh_signal_info_t_deserialize(x,y) CORBA_long_deserialize((x),(y))
+static inline CORBA_boolean
+frsh_memory_area_data_t_serialize
+ (FORB_CDR_Codec *codec,
+ const frsh_memory_area_data_t *m)
+{
+ CORBA_long size, area;
+ size = m->size;
+ area = (CORBA_long) 0; //m->area;
+ if (!CORBA_long_serialize(codec, &size)) return CORBA_FALSE;
+ if (!CORBA_long_serialize(codec, &area)) return CORBA_FALSE;
+ return CORBA_TRUE;
+}
+
+static inline CORBA_boolean
+frsh_memory_area_data_t_deserialize
+ (FORB_CDR_Codec *codec,
+ frsh_memory_area_data_t *m)
+{
+ CORBA_long size, area;
+ if (!CORBA_long_deserialize(codec, &size)) return CORBA_FALSE;
+ if (!CORBA_long_deserialize(codec, &area)) return CORBA_FALSE;
+ m->size = size;
+ m->area = (void*) NULL; //area;
+ return CORBA_TRUE;
+}
+
+static inline CORBA_boolean
+frsh_memory_areas_t_serialize
+ (FORB_CDR_Codec *codec,
+ const frsh_memory_areas_t *a)
+{
+ CORBA_long i, size;
+ CORBA_boolean ret;
+ size = a->size;
+ if (!CORBA_long_serialize(codec, &size)) return CORBA_FALSE;
+ for (i = 0; i < FRSH_MAX_N_MEMORY_AREAS; i++) {
+ ret = frsh_memory_area_data_t_serialize(codec, &a->memory_areas[i]);
+ if (ret == CORBA_FALSE) return ret;
+ }
+ return CORBA_TRUE;
+}
+
+static inline CORBA_boolean
+frsh_memory_areas_t_deserialize
+ (FORB_CDR_Codec *codec,
+ frsh_memory_areas_t *a)
+{
+ CORBA_long i, size;
+ CORBA_boolean ret;
+ if (!CORBA_long_deserialize(codec, &size)) return CORBA_FALSE;
+ for (i = 0; i < FRSH_MAX_N_MEMORY_AREAS; i++) {
+ ret = frsh_memory_area_data_t_deserialize(codec, &a->memory_areas[i]);
+ if (ret == CORBA_FALSE) return ret;
+ }
+ a->size = size;
+ return CORBA_TRUE;
+}
+
+static inline CORBA_boolean
+frsh_csect_t_serialize
+ (FORB_CDR_Codec *codec,
+ const frsh_csect_t *c)
+{
+ return CORBA_TRUE;
+}
+
+static inline CORBA_boolean
+frsh_csect_t_deserialize
+ (FORB_CDR_Codec *codec,
+ frsh_csect_t *c)
+{
+ return CORBA_TRUE;
+}
+
+static inline CORBA_boolean
+frsh_csects_group_t_serialize
+ (FORB_CDR_Codec *codec,
+ const frsh_csects_group_t *g)
+{
+ return CORBA_TRUE;
+}
+
+static inline CORBA_boolean
+frsh_csects_group_t_deserialize
+ (FORB_CDR_Codec *codec,
+ frsh_csects_group_t *g)
+{
+ return CORBA_TRUE;
+}
+
#endif
--- /dev/null
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+ @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
--- /dev/null
+shared_LIBRARIES = sharedobj
+
+sharedobj_SOURCES = fres_sharedobj.c
+sharedobj_CLIENT_IDL = fres_sharedobj_idl.idl
+
+#fres_sharedobj_idl_IDLFLAGS = --include=fres_contract_ser.h
+#fres_blocks_IDLFLAGS = --include=idl_native.h
+
+include_HEADERS = fres_sharedobj.h
+
+include_GEN_HEADERS = fres_sharedobj_idl.h
+
+SUBDIRS=tests
--- /dev/null
+/**
+ * @file fres_sharedobj.c
+ * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ *
+ * @brief Implementation of shared objects functions.
+ *
+ *
+ */
+#include <frsh_forb.h>
+#include <fres_sharedobj.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/**
+ * Allocates new fres_sharedobj structure. Use fres_sharedobj_destroy to
+ * deallocate the shared object.
+ *
+ * @return The new object on succes, NULL on error.
+ */
+struct fres_sharedobj* fres_sharedobj_new(const char *label, int kind)
+{
+ struct fres_sharedobj *s;
+ char shm_path[108];
+ int shm_fd;
+
+ snprintf(shm_path, sizeof(shm_path), "/tmp/shared.%s", label);
+
+ shm_fd = shm_open(shm_path, O_CREAT|O_EXCL|O_RDWR, S_IRWXU|S_IRWXG);
+ if (shm_fd < 0) goto err;
+
+ s = mmap(NULL, sizeof(*s),
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ shm_fd, 0);
+ if (s == MAP_FAILED) goto unlink_err;
+
+ memcpy(s->label, label, sizeof(s->label));
+ memcpy(s->path, shm_path, sizeof(shm_path));
+ fosa_mutex_init(&s->mutex, 0);
+ s->kind = kind;
+
+ return s;
+
+unlink_err:
+ shm_unlink(shm_path);
+err:
+ return NULL;
+}
+
+struct fres_sharedobj* fres_sharedobj_get_path(const char *sharedobj_path)
+{
+ struct fres_sharedobj *s = NULL;
+ int shm_fd;
+
+ shm_fd = shm_open(sharedobj_path, O_RDWR, S_IRWXU|S_IRWXG);
+ if (shm_fd < 0) goto out;
+
+ s = mmap(NULL, sizeof(*s),
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ shm_fd, 0);
+ if (s == MAP_FAILED) goto out;
+
+out:
+ return s;
+}
+
+struct fres_sharedobj* fres_sharedobj_get_label(const char *label)
+{
+ struct fres_sharedobj *s = NULL;
+ char shm_path[108];
+ int shm_fd;
+
+ snprintf(shm_path, sizeof(shm_path), "/tmp/sync.%s", s->label);
+
+ shm_fd = shm_open(shm_path, O_RDWR, S_IRWXU|S_IRWXG);
+ if (shm_fd < 0) goto out;
+
+ s = mmap(NULL, sizeof(*s),
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ shm_fd, 0);
+ if (s == MAP_FAILED) goto out;
+
+out:
+ return s;
+}
+
+int fres_sharedobj_destroy(struct fres_sharedobj *s)
+{
+ int ret = 0;
+
+ if (!s) return EINVAL;
+
+ /* Since now no new task can mmap the object. */
+ ret = shm_unlink(s->path);
+ if (ret) goto out;
+
+ ret = munmap((void*) s, sizeof(*s));
+ if (ret) goto out;
+
+out:
+ return ret;
+}
+
+int
+fres_sharedobj_to_string(char *dest,
+ size_t size,
+ const struct fres_sharedobj *s)
+{
+ int ret;
+
+ if (!s) return 0;
+
+ ret = snprintf(dest, size, "label: %s\n"
+ "path: %s\n"
+ "kind: %d\n",
+ s->label, s->path, s->kind);
+
+ return ret;
+}
+
+void
+fres_sharedobj_print(char *prefix, const struct fres_sharedobj *s)
+{
+ char sharedobj[1000];
+
+ fres_sharedobj_to_string(sharedobj, sizeof(sharedobj)-1, s);
+ sharedobj[sizeof(sharedobj)-1] = 0;
+ printf("%s %s", prefix, sharedobj);
+}
+
--- /dev/null
+/**
+ * @file fres_sharedobj.h
+ * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ *
+ * @brief Declaration of synchronization object type and functions.
+ *
+ *
+ */
+#ifndef FRES_SHAREDOBJ_H
+#define FRES_SHAREDOBJ_H
+
+#include <ul_gavl.h>
+#include <forb/server_id.h>
+#include <fres_sharedobj_idl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Synchronization object data type.
+ *
+ */
+struct fres_sharedobj {
+ char path[108]; /**< Filesystem path of the POSIX semaphore. */
+
+ fosa_mutex_t mutex; /**< POSIX mutex implementing the object. */
+ fosa_timer_id_t wcet_timer; /** WCET enforcing timer. */
+ fosa_long_jump_context_t context; /** Jump context (for overruns). */
+
+ char label[65]; /**< Shared object label. */
+ int kind; /**< Shared object kind. */
+};
+
+static inline int fres_sharedobj_id_cmp(const fres_sharedobj_id_t *a,
+ const fres_sharedobj_id_t *b)
+{
+ return forb_server_id_cmp((forb_server_id*)a,
+ (forb_server_id*)b);
+}
+
+static inline char *fres_sharedobj_id_to_string(char *dest,
+ const fres_sharedobj_id_t *id,
+ size_t n)
+{
+ return forb_server_id_to_string(dest, (forb_server_id*)id, n);
+}
+
+struct fres_sharedobj *fres_sharedobj_new(const char *label, int kind);
+struct fres_sharedobj* fres_sharedobj_get_path(const char sharedobj_path[]);
+struct fres_sharedobj* fres_sharedobj_get_label(const char sharedobj_label[]);
+int fres_sharedobj_destroy(struct fres_sharedobj *sharedobj);
+
+void
+fres_sharedobj_print(char *prefix, const struct fres_sharedobj *c);
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif
+
--- /dev/null
+/**
+ * @file fres_synchobj_idl.idl
+ * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ *
+ * @brief Definitions of data types and constants for
+ FRESCOR synchronization objects.
+ *
+ */
+
+#ifndef _SHAREDOBJ_IDL
+#define _SHAREDOBJ_IDL
+module fres {
+ module sharedobj {
+ /// Pointer to the contract type
+ native ptr;
+
+ /// Globaly unique contract ID
+ struct id_t {
+ char byte[8];
+ };
+
+ };
+};
+
+#endif
+
--- /dev/null
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+ @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
--- /dev/null
+test_PROGRAMS:=$(basename $(notdir $(wildcard $(SOURCES_DIR)/*.c)))
+
+$(foreach t,$(test_PROGRAMS),\
+$(eval $(t)_SOURCES = $(t).c)\
+$(eval $(t)_LIBS = fosa m contract rt forb ulut)\
+)
SUBDIRS = tests
shared_LIBRARIES = frsh
-frsh_SOURCES = frsh_contract.c frsh_vres.c frsh_synchobj.c frsh_distributed.c frsh_core.c frsh_error.c frsh_thread.c
+frsh_SOURCES = frsh_contract.c frsh_vres.c frsh_synchobj.c frsh_distributed.c frsh_core.c frsh_error.c frsh_thread.c frsh_sharedobj.c
include_HEADERS = frsh_opaque_types.h frsh_forb.h
-frsh_LIBS = fna fcb_client forb contract synchobj fra ulut fosa $(allocator-libs-y)
+frsh_LIBS = fna fcb_client forb contract synchobj sharedobj fra ulut fosa $(allocator-libs-y)
config_include_HEADERS = frsh_resources.h
frsh_resources_DEFINES = CONFIG_RESOURCE_DUMMY \
#define FRSH_SYNCHOBJ_HANDLE_T_OPAQUE struct fres_synchobj *
-typedef int FRSH_SHAREDOBJ_HANDLE_T_OPAQUE;
+#define FRSH_SHAREDOBJ_HANDLE_T_OPAQUE struct fres_sharedobj *
typedef unsigned int FRSH_GROUP_ID_T_OPAQUE;
*
*
*/
+#include <fres_contract.h>
+#include <fres_contract_idl.h>
+#include <frsh_error.h>
+#include <fres_blocks.h>
#include <frsh_core.h>
-/* #include <fres_sharedobj.h> */
+#include <fres_sharedobj.h>
int frsh_sharedobj_init
(const char *obj_label,
frsh_sharedobj_handle_t *obj_handle,
frsh_mutex_t *mutex)
{
- return FRSH_ERR_NOT_IMPLEMENTED;
+ if (!obj_handle)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ /* In this implementation external mutex is not supported, *
+ * use frsh_sharedobj_get_mutex instead. */
+ if (mutex)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ *obj_handle = fres_sharedobj_new(obj_label, obj_kind);
+ if (!(*obj_handle)) goto err;
+
+ return 0;
+err:
+ return errno;
+}
+
+int frsh_sharedobj_get_handle
+ (char *obj_label,
+ frsh_sharedobj_handle_t *obj_handle)
+{
+ if (!obj_label || !obj_handle)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ *obj_handle = fres_sharedobj_get_label(obj_label);
+ if (!(*obj_handle)) goto err;
+
+ return 0;
+err:
+ return errno;
+}
+
+int frsh_sharedobj_get_mutex
+ (frsh_sharedobj_handle_t obj_handle,
+ frsh_mutex_t **mutex)
+{
+ if (!obj_handle || !mutex)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ *mutex = &obj_handle->mutex;
+
+ return 0;
+}
+
+int frsh_sharedobj_get_obj_kind
+ (frsh_sharedobj_handle_t obj_handle,
+ frsh_sharedobj_kind_t *obj_kind)
+{
+ if (!obj_handle || !obj_kind)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ *obj_kind = obj_handle->kind;
+
+ return 0;
}
int frsh_sharedobj_remove(frsh_sharedobj_handle_t obj_handle)
{
- return FRSH_ERR_NOT_IMPLEMENTED;
+ if (!obj_handle)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ return fres_sharedobj_destroy(obj_handle);
+}
+
+/* Critical Sections. */
+
+int frsh_csect_init
+ (frsh_sharedobj_handle_t obj_handle,
+ frsh_rel_time_t wcet,
+ frsh_csect_t *csect)
+{
+ if (!obj_handle || !csect)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ csect->op_kind = FRSH_CSOK_UNCHECKED;
+ csect->obj_handle = obj_handle;
+ csect->wcet = wcet;
+ csect->blocking = wcet;
+ csect->op = NULL;
+ csect->areas.size = 0;
+ csect->storage.size = 0;
+
+ return 0;
+}
+
+int frsh_csect_get_sharedobj_handle
+ (const frsh_csect_t *csect,
+ frsh_sharedobj_handle_t *obj_handle)
+{
+ if (!obj_handle || !csect)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ *obj_handle = csect->obj_handle;
+
+ return 0;
+}
+
+int frsh_csect_get_wcet
+ (const frsh_csect_t *csect,
+ frsh_rel_time_t *wcet)
+{
+ if (!csect || !wcet)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ *wcet = csect->wcet;
+
+ return 0;
+}
+
+int frsh_csect_get_blocking_time
+ (const frsh_csect_t *csect,
+ fosa_rel_time_t *blocking)
+{
+ if (!csect || !blocking)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ *blocking = csect->blocking;
+
+ return 0;
+}
+
+int frsh_csect_get_op_kind
+ (const frsh_csect_t *csect,
+ frsh_csect_op_kind_t *op_kind)
+{
+ if (!csect || !op_kind)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ *op_kind = csect->op_kind;
+
+ return 0;
+}
+
+int frsh_csect_get_read_op
+ (const frsh_csect_t *csect,
+ frsh_csect_op_t *op)
+{
+ if (!csect ||
+ !op ||
+ csect->op_kind != FRSH_CSOK_READ)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ *op = csect->op;
+
+ return 0;
+}
+
+int frsh_csect_get_write_op
+ (const frsh_csect_t *csect,
+ frsh_csect_op_t *op,
+ frsh_memory_areas_t *areas)
+{
+ int i;
+
+ if (!csect ||
+ !op ||
+ !areas ||
+ csect->op_kind != FRSH_CSOK_WRITE)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ *op = csect->op;
+ areas->size = csect->areas.size;
+
+ for (i = 0; i < areas->size; i++)
+ areas->memory_areas[i] = csect->areas.memory_areas[i];
+
+ return 0;
+}
+
+int frsh_csect_register_read_op
+ (frsh_csect_t *csect,
+ frsh_csect_op_t op)
+{
+ if (!csect || !op)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ csect->op_kind = FRSH_CSOK_READ;
+ csect->op = op;
+
+ /* Account for protection overheads: NOT IMPLEMENTED! */
+ /* csect->blocking = fosa_rel_time_add(csect->wcet, ); */
+ csect->blocking = csect->wcet;
+
+ return 0;
+}
+
+int frsh_csect_register_write_op
+ (frsh_csect_t *csect,
+ frsh_csect_op_t op,
+ const frsh_memory_areas_t *areas)
+{
+ int i, j;
+
+ if (!csect || !op)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ if (areas->size <= 0 || areas->size > FRSH_MAX_N_MEMORY_AREAS)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ /* TODO:
+ * Check for the shared object associated with this
+ * critical section not to be UNPROTECTED;
+ */
+
+ csect->storage.size = areas->size;
+ csect->areas.size = areas->size;
+ csect->op_kind = FRSH_CSOK_WRITE;
+ csect->op = op;
+
+ for (i = 0; i< areas->size; i++) {
+ csect->areas.memory_areas[i] =
+ areas->memory_areas[i];
+
+ csect->storage.memory_areas[i].size =
+ areas->memory_areas[i].size;
+
+ /*
+ * TODO:
+ * Who is going to free() these mallocs? Maybe something
+ * like frsh_csect_destroy is needed and missing?
+ */
+ csect->storage.memory_areas[i].area =
+ malloc(areas->memory_areas[i].size);
+ if (!csect->storage.memory_areas[i].area)
+ goto free_err;
+ }
+
+ /* Account for protection and rollback overheads: NOT IMPLEMENTED! */
+ /* csect->blocking = fosa_rel_time_add(csect->wcet, ); */
+ csect->blocking = csect->wcet;
+
+ return 0;
+free_err:
+ for (j = i; j >= 0; j--)
+ free(csect->storage.memory_areas[j].area);
+
+ return FOSA_ENOMEM;
+}
+
+/**
+ * Type that contains the information necessary to implement
+ * time-protection in shared resources.
+ */
+typedef struct {
+ fosa_timer_id_t timer_id;
+ fosa_long_jump_context_t context;
+} frsh_sr_protection_t;
+
+int frsh_csect_invoke
+ (const frsh_csect_t *csect,
+ const void *input_arg,
+ void *output_arg)
+{
+ int i, jumped, ret = 0;
+ fosa_signal_t signal;
+ fosa_signal_info_t siginfo;
+ fosa_clock_id_t clockid;
+ frsh_sharedobj_handle_t obj_handle;
+ fosa_mutex_t *obj_mutex;
+
+ if (!csect) {
+ ret = FRSH_ERR_BAD_ARGUMENT;
+ goto out;
+ }
+
+ obj_handle = csect->obj_handle;
+
+ ret = frsh_sharedobj_get_mutex(obj_handle, &obj_mutex);
+ if (ret) goto out;
+ ret = fosa_mutex_lock(obj_mutex);
+ if (ret) goto out;
+
+ siginfo.sival_ptr = (void*) (&(obj_handle->context));
+ ret = fosa_long_jump_install_handler(&signal, NULL);
+ if (ret) goto out_unlock;
+
+ /* Prepare the WCET timer. */
+ ret = fosa_thread_get_cputime_clock(fosa_thread_self() ,&clockid);
+ if (ret) goto out_unlock;
+ ret = fosa_timer_create_with_receiver(clockid,
+ signal,
+ siginfo,
+ &obj_handle->wcet_timer,
+ fosa_thread_self());
+ if (ret) goto out_unlock;
+ ret = fosa_rel_timer_arm(obj_handle->wcet_timer, &csect->wcet);
+ if (ret) goto out_disarm;
+
+ /* Backup memory areas. */
+ if (csect->op_kind == FRSH_CSOK_WRITE) {
+ for (i = 0; i < csect->areas.size; i++)
+ if (!memcpy(csect->storage.memory_areas[i].area,
+ csect->areas.memory_areas[i].area,
+ csect->areas.memory_areas[i].size)) {
+ ret = errno;
+ goto out_disarm;
+ }
+ }
+
+ ret = fosa_long_jump_save_context(&obj_handle->context);
+ if (ret) goto out_disarm;
+ ret = fosa_long_jump_was_performed(&obj_handle->context, &jumped);
+ if (ret) goto out_disarm;
+
+ if (!jumped) {
+ /* Invoke the operation. */
+ csect->op(input_arg,output_arg);
+
+ /* Leave the critical section normally. */
+ goto out_disarm;
+ }
+
+ ret = FRSH_ERR_BUDGET_EXPIRED;
+
+ /* Restore backed-up memory areas. */
+ if (csect->op_kind == FRSH_CSOK_WRITE) {
+ for (i = 0; i < csect->areas.size; i++)
+ if (!memcpy(csect->areas.memory_areas[i].area,
+ csect->storage.memory_areas[i].area,
+ csect->areas.memory_areas[i].size)) {
+ ret = errno;
+ goto out_unlock;
+ }
+ }
+
+out_disarm:
+ fosa_timer_disarm(obj_handle->wcet_timer, NULL);
+ fosa_timer_delete(obj_handle->wcet_timer);
+out_unlock:
+ fosa_mutex_unlock(obj_mutex);
+out:
+ return ret;
+}
+
+/* Contract Parameters. */
+
+int frsh_contract_set_csects
+ (frsh_contract_t *contract,
+ const frsh_csects_group_t *critical_sections)
+{
+ fres_block_csects *c;
+ int i, ret;
+
+ if (!contract || !*contract || !critical_sections)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ if (critical_sections->size < 0 ||
+ critical_sections->size > FRSH_MAX_N_CRITICAL_SECTIONS)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ c = malloc(sizeof(*c));
+ if (!c) return FOSA_ENOMEM;
+
+ c->sections.size = critical_sections->size;
+ for (i = 0; i < critical_sections->size; i++)
+ c->sections.csects[i] = critical_sections->csects[i];
+
+ fres_contract_del_csects(*contract);
+ ret = fres_contract_add_csects(*contract, c);
+
+ if (ret) {
+ free(c);
+ return errno;
+ }
+
+ return 0;
+}
+
+int frsh_contract_get_csects
+ (const frsh_contract_t *contract,
+ frsh_csects_group_t *critical_sections)
+{
+ fres_block_csects *c;
+ int i;
+
+ if (!contract || !*contract || !critical_sections)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ c = fres_contract_get_csects(*contract);
+
+ critical_sections->size = c->sections.size;
+ for (i = 0; i < c->sections.size; i++)
+ critical_sections->csects[i] = c->sections.csects[i];
+
+ return 0;
}