Dummy scheduler is provided as an example of how to write schedulers.
}
/* Create VRes */
- ret = fres_resource_scheduler_create_vres(rs->rs, contracts_sched->_buffer[0], ev);
+ ret = fres_resource_scheduler_create_vreses(rs->rs, contracts_sched, ev);
if (CORBA_sequence_get_release(contracts_sched)) forb_free(contracts_sched->_buffer);
forb_free(contracts_sched);
if (forb_exception_occured(ev)) {
(forb_server_id*)b);
}
+static inline char *fres_contract_id_to_string(char *dest,
+ const fres_contract_id_t *id,
+ size_t n)
+{
+ return forb_server_id_to_string(dest, (forb_server_id*)id, n);
+}
+
struct fres_contract *fres_contract_new(void);
void fres_contract_destroy(struct fres_contract *contract);
struct fres_contract *fres_contract_duplicate(struct fres_contract *src);
}
-GAVL_CUST_NODE_INT_DEC(fres_sa_scenario_contract /* cust_prefix */,
- struct fres_sa_scenario /* cust_root_t */,
- struct fres_sa_contract /* cust_item_t */,
- fres_contract_id_t /* cust_key_t */,
- contracts /* cust_root_node */,
- node /* cust_item_node */,
- contract->id /* cust_item_key */,
- fres_contract_id_cmp /* cust_cmp_fnc */)
-
GAVL_CUST_NODE_INT_IMP(fres_sa_scenario_contract /* cust_prefix */,
struct fres_sa_scenario /* cust_root_t */,
struct fres_sa_contract /* cust_item_t */,
contracts /* cust_root_node */,
node /* cust_item_node */,
contract->id /* cust_item_key */,
- fres_contract_id_cmp /* cust_cmp_fnc */)
+ fres_contract_id_cmp /* cust_cmp_fnc */);
struct fres_sa_scenario *
fres_sa_scenario_new(void)
void *priv;
};
+/**
+ * @warning Do not manipulate the tree direcly through this macros,
+ * instead use fres_sa_scenario_add_contract(),
+ * fres_sa_scenario_del_contract() and
+ * fres_sa_scenario_find_contract().
+ */
+
+GAVL_CUST_NODE_INT_DEC(fres_sa_scenario_contract /* cust_prefix */,
+ struct fres_sa_scenario /* cust_root_t */,
+ struct fres_sa_contract /* cust_item_t */,
+ fres_contract_id_t /* cust_key_t */,
+ contracts /* cust_root_node */,
+ node /* cust_item_node */,
+ contract->id /* cust_item_key */,
+ fres_contract_id_cmp /* cust_cmp_fnc */);
+
+
+/**
+ * Expands to for-cycle for traversing all contracts in a
+ * scenario. The actual contract is stored in @a contract variable.
+ *
+ */
+#define fres_sa_scenario_for_each_contract(scenario, contract) \
+ gavl_cust_for_each(fres_sa_scenario_contract, scenario, contract)
+
+
struct fres_sa_contract *
fres_sa_contract_new(void);
*
* @return
*/
-int frm_generic_run(forb_orb orb, frm_adm_test_fnc_t admission_test, void *priv)
+int frm_register_and_run(forb_orb orb, const struct fres_res_manager *res_manager)
{
fres_contract_broker fcb;
fres_resource_manager frm;
int ret;
memset(&frm_data, 0, sizeof(frm_data));
- frm_data.admission_test = admission_test;
- frm_data.priv = priv;
+ frm_data.admission_test = res_manager->admission_test;
+ frm_data.priv = res_manager->priv;
fcb = forb_resolve_reference(orb, fres_contract_broker_reg_name);
if (!fcb) {
if (ret) goto err_executor;
/* Register resource manager */
- fres_contract_broker_register_manager(fcb, FRSH_RT_PROCESSOR, 0,
- frm, &env);
- if (forb_exception_occured(&env)) {
+ ret = fres_contract_broker_register_manager(fcb,
+ res_manager->res_type,
+ res_manager->res_id,
+ frm, &env);
+ if (forb_exception_occured(&env) || ret != 0) {
goto err_executor;
}
*/
typedef bool (*frm_adm_test_fnc_t)(struct fres_sa_scenario *scenario, void *priv);
-int frm_generic_run(forb_orb orb, frm_adm_test_fnc_t admission_test, void *priv);
+struct fres_res_manager {
+ frsh_resource_type_t res_type;
+ frsh_resource_id_t res_id;
+ frm_adm_test_fnc_t admission_test;
+ void *priv;
+};
+
+int frm_register_and_run(forb_orb orb,
+ const struct fres_res_manager *res_manager);
#endif
shared_LIBRARIES += frs
+frs_SOURCES = frs_generic.c
frs_SERVER_IDL = frs.idl
include_GEN_HEADERS += frs.h
+include_HEADERS = frs_generic.h
lib_LIBRARIES += frs_client
frs_client_CLIENT_IDL = frs.idl
module fres {
interface resource_scheduler {
- long create_vres(in fres::contract::ptr contract);
- long change_vres(in fres::contract::id_t id, in fres::contract::ptr contract);
- long cancel_vres(in fres::contract::id_t id);
+ long create_vreses(in contract::ptr_seq contracts);
+ long cancel_vreses(in contract::id_seq ids);
+
+ /**
+ * This function is intended to perform a mode change
+ * acoording to a mode change protocol. Its semantic
+ * will be defined later.
+ *
+ * @param contracts
+ *
+ * @return
+ */
+ long change_vreses(in contract::ptr_seq contracts);
};
};
--- /dev/null
+/**
+ * @file frs_generic.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date Thu Oct 23 15:26:19 2008
+ *
+ * @brief FORB interface of FRES Resource Scheduler
+ *
+ *
+ */
+#include <forb.h>
+#include <frs.h>
+#include <fcb.h>
+#include <ul_log.h>
+#include "frs_generic.h"
+
+UL_LOG_CUST(ulogd_frs);
+ul_log_domain_t ulogd_frs = {UL_LOGL_MSG, "frs"};
+
+/**
+ * Global "registry" of all virtual resources in one application.
+ */
+struct fres_vreses fres_vreses;
+
+GAVL_CUST_NODE_INT_IMP(fres_vreses_nolock /* cust_prefix */,
+ struct fres_vreses /* cust_root_t */,
+ struct fres_vres /* cust_item_t */,
+ fres_contract_id_t /* cust_key_t */,
+ vreses /* cust_root_node */,
+ node /* cust_item_node */,
+ contract->id /* cust_item_key */,
+ fres_contract_id_cmp /* cust_cmp_fnc */);
+
+static int
+fres_vreses_insert(struct fres_vreses *root, struct fres_vres *vres)
+{
+ int ret;
+ fosa_mutex_lock(&root->mutex);
+ ret = fres_vreses_nolock_insert(root, vres);
+ fosa_mutex_unlock(&root->mutex);
+ return ret;
+}
+
+static int
+fres_vreses_delete(struct fres_vreses *root, struct fres_vres *vres)
+{
+ int ret;
+ fosa_mutex_lock(&root->mutex);
+ ret = fres_vreses_nolock_delete(root, vres);
+ fosa_mutex_unlock(&root->mutex);
+ return ret;
+}
+
+static struct fres_vres *
+fres_vreses_find(struct fres_vreses *root, fres_contract_id_t *id)
+{
+ struct fres_vres *ret;
+ fosa_mutex_lock(&root->mutex);
+ ret = fres_vreses_nolock_find(root, id);
+ fosa_mutex_unlock(&root->mutex);
+ return ret;
+}
+
+
+#define save_errno(cmd) do { int _e = errno; cmd; errno = _e; } while(0)
+
+CORBA_long create_vreses(fres_resource_scheduler obj,
+ const fres_contract_ptr_seq* contracts,
+ CORBA_Environment *ev)
+{
+ int ret, i;
+ struct fres_scheduler *sch = forb_instance_data(obj);
+
+ for (i=0; i<contracts->_length; i++) {
+ struct fres_contract *contract;
+ struct fres_vres *vres;
+ contract = fres_contract_duplicate(contracts->_buffer[i]);
+ if (!contracts) {
+ ret = -1;
+ goto err;
+ }
+ vres = malloc(sizeof(*vres));
+ if (!vres) {
+ fres_contract_destroy(contract);
+ ret = -1;
+ goto err;
+ }
+ memset(vres, 0, sizeof(*vres));
+ vres->contract = contract;
+ vres->scheduler = sch;
+
+ /* Create the real VRes */
+ ret = sch->create_vres(vres, sch->priv);
+ if (ret) {
+ free(vres);
+ fres_contract_destroy(contract);
+ goto err;
+ }
+
+ /* Store the vres in registry */
+ fres_vreses_insert(&fres_vreses, vres);
+ }
+ return 0;
+err:
+ /* FIXME: Release memory of already created VReses in case of
+ * error. */
+ return ret;
+}
+
+CORBA_long cancel_vreses(fres_resource_scheduler obj,
+ const fres_contract_id_seq* ids,
+ CORBA_Environment *ev)
+{
+ int ret, i;
+ struct fres_scheduler *sch = forb_instance_data(obj);
+
+ for (i=0; i < ids->_length; i++) {
+ struct fres_vres *vres;
+ fres_contract_id_t *id = &ids->_buffer[i];
+
+ vres = fres_vreses_find(&fres_vreses, id);
+ if (!vres) goto err;
+
+ ret = sch->cancel_vres(vres, sch->priv);
+ if (ret != 0) goto err;
+
+ fres_vreses_delete(&fres_vreses, vres);
+
+ fres_contract_destroy(vres->contract);
+ free(vres);
+ }
+ return 0;
+err:
+ return -1;
+}
+
+CORBA_long change_vreses(fres_resource_scheduler obj,
+ const fres_contract_ptr_seq* contracts,
+ CORBA_Environment *ev)
+{
+ /* Mode change protocol is currently not implemented. */
+ return -1;
+}
+
+static const struct forb_fres_resource_scheduler_impl frs_impl = {
+ .create_vreses = create_vreses,
+ .cancel_vreses = cancel_vreses,
+ .change_vreses = change_vreses
+};
+
+/**
+ * Registeres the scheduler with contract broker.
+ *
+ * @param orb
+ * @param fcb
+ *
+ * @param executor Executor which will execute requests for this fres
+ * scheduler.
+ *
+ * @param scheduler
+ *
+ * @return Zero on success, -1 on error.
+ */
+int frs_register(forb_orb orb,
+ fres_contract_broker fcb,
+ forb_executor_t *executor,
+ struct fres_scheduler *scheduler)
+{
+ int ret;
+ fres_resource_scheduler frs;
+ struct forb_env env;
+
+
+ frs = forb_fres_resource_scheduler_new(orb, &frs_impl, scheduler);
+ if (!frs) {
+ save_errno(ul_logerr("forb_fres_resource_manager_new error"));
+ goto err;
+ }
+
+ /* Prepare executor before we register the resource scheduler
+ * with contract broker */
+ ret = forb_executor_register_object(executor, frs);
+ if (ret) goto err_release;
+
+ /* Register resource scheduler */
+ ret = fres_contract_broker_register_scheduler(fcb,
+ scheduler->res_type,
+ scheduler->res_id,
+ frs, &env);
+ if (forb_exception_occured(&env) || ret != 0) {
+ goto err_release;
+ }
+ return 0;
+err_release:
+ save_errno(forb_object_release(frs));
+err:
+ return -1;
+}
+
+/**
+ * Returns pointer to VRes, which corresponds to the contract with the
+ * given id.
+ *
+ * @param id
+ *
+ * @return Pointer to VRes, or NULL in the VRes doesn't exist.
+ */
+fres_vres_t *frs_get_vres(fres_contract_id_t *id)
+{
+ return fres_vreses_find(&fres_vreses, id);
+}
--- /dev/null
+#ifndef FRS_GENERIC_H
+#define FRS_GENERIC_H
+#include <fcb.h>
+#include <frs.h>
+#include <fres_contract.h>
+#include <ul_gavlcust.h>
+#include <fosa.h>
+#include <forb/executor.h>
+#include <fres_contract_idl.h>
+
+struct fres_scheduler;
+
+typedef struct fres_vres {
+ struct fres_contract *contract;
+ struct fres_scheduler *scheduler;
+ void *priv; /**< Resource scheduler private data */
+ gavl_node_t node;
+} fres_vres_t;
+
+/** Registry of all virtual resources in an application. */
+struct fres_vreses {
+ fosa_mutex_t mutex; /**< Mutex for manipulation with vreses tree. If all schedulers are executed from one executor, locking can be avoided. */
+ gavl_cust_root_field_t vreses; /**< Container of all virtual resources */
+};
+
+GAVL_CUST_NODE_INT_DEC(fres_vreses_nolock /* cust_prefix */,
+ struct fres_vreses /* cust_root_t */,
+ struct fres_vres /* cust_item_t */,
+ fres_contract_id_t /* cust_key_t */,
+ vreses /* cust_root_node */,
+ node /* cust_item_node */,
+ contract->id /* cust_item_key */,
+ fres_contract_id_cmp /* cust_cmp_fnc */)
+
+extern struct fres_vreses fres_vreses;
+
+
+/**
+ * Structure describing FRES scheduler. It is used as a parameter to
+ * frs_register(), which registeres this scheduler with contract
+ * broker and provides FORB interface to this scheduler.
+ *
+ */
+struct fres_scheduler {
+ frsh_resource_type_t res_type;
+ frsh_resource_id_t res_id;
+ int (*create_vres)(fres_vres_t *vres, void *priv);
+ int (*cancel_vres)(fres_vres_t *vres, void *priv);
+ int (*change_vres)(fres_vres_t *vres, void *priv);
+ void *priv;
+};
+
+int frs_register(forb_orb orb,
+ fres_contract_broker fcb,
+ forb_executor_t *executor,
+ struct fres_scheduler *scheduler);
+
+fres_vres_t *frs_get_vres(fres_contract_id_t *id);
+
+#endif
bin_PROGRAMS = frm_dummy
-shared_LIBRARIES = frs_dummy
-
frm_dummy_SOURCES = frm_dummy.c
frm_dummy_LIBS = frm forb contract fosa rt ulut fcb_client
+shared_LIBRARIES = frs_dummy
frs_dummy_SOURCES = frs_dummy.c
frs_dummy_LIBS = frs
#include <fres_sa_scenario.h>
#include <stdbool.h>
#include <ul_log.h>
-
-UL_LOG_CUST(ulogd_frm_dummy);
-ul_log_domain_t ulogd_frm_dummy = {UL_LOGL_MSG, "frm_dummy"};
+#include "res_dummy.h"
+#include <stdio.h>
struct dummy_data {
int some_data;
{
bool schedulable;
struct dummy_data *data = priv;
+ struct fres_sa_contract *c;
- ul_logmsg("Admission test");
+ printf("Admission test:\n");
data->some_data++;
+
+ fres_sa_scenario_for_each_contract(scenario, c) {
+ fres_block_basic *basic;
+ char id[40];
+ fres_contract_id_to_string(id, &c->contract->id, sizeof(id));
+ basic = fres_contract_get_basic(c->contract);
+
+ printf(" processing: id=%s, period=%ld ms, budget=%ld ms\n",
+ id,
+ fosa_rel_time_to_msec(basic->period),
+ fosa_rel_time_to_msec(basic->budget));
+
+ }
schedulable = scenario->num_contracts <= 3;
+ printf("=> %s\n", schedulable?"schedulable":"not schedulable");
return schedulable;
}
+struct dummy_data dummy_data;
+
+static const struct fres_res_manager frm = {
+ .res_type = DUMMY_RESOURCE_TYPE,
+ .res_id = DUMMY_RESOURCE_ID,
+ .admission_test = admission_test,
+ .priv = &dummy_data
+};
+
int main(int argc, char *argv[])
{
forb_orb orb;
- struct dummy_data dummy_data;
int ret;
orb = forb_init(&argc, &argv, "frm_dummy");
if (!orb) error(1, errno, "forb_init");
- ret = frm_generic_run(orb, admission_test, &dummy_data);
+ ret = frm_register_and_run(orb, &frm);
if (ret != 0) {
error(1, errno, "frm_generic_run");
-#include <frs.h>
+#include <ul_log.h>
+#include <frs_generic.h>
+#include "res_dummy.h"
+#include <stdio.h>
+
+
+UL_LOG_CUST(ulogd_frs_dummy);
+ul_log_domain_t ulogd_frs_dummy = {UL_LOGL_MSG, "frs_dummy"};
+
+int create_vres(fres_vres_t *vres, void *priv)
+{
+ int *my_data = priv;
+ fres_block_basic *basic;
+ char id[40];
+
+ (*my_data)++;
+
+ fres_contract_id_to_string(id, &vres->contract->id, sizeof(id));
+ basic = fres_contract_get_basic(vres->contract);
+ printf("Creating VRes #%d (id=%s, period=%ld ms, budget=%ld ms)\n",
+ *my_data, id,
+ fosa_rel_time_to_msec(basic->period),
+ fosa_rel_time_to_msec(basic->budget));
+ return 0;
+}
+int cancel_vres(fres_vres_t *vres, void *priv)
+{
+ int *my_data = priv;
+ fres_block_basic *basic;
+ char id[40];
+
+ fres_contract_id_to_string(id, &vres->contract->id, sizeof(id));
+ basic = fres_contract_get_basic(vres->contract);
+ printf("Creating VRes #%d (id=%s, period=%ld ms, budget=%ld ms)\n",
+ *my_data, id,
+ fosa_rel_time_to_msec(basic->period),
+ fosa_rel_time_to_msec(basic->budget));
+
+ (*my_data)--;
+ return 0;
+}
+
+int change_vres(fres_vres_t *vres, void *priv)
+{
+ return 0;
+}
+
+
+
+static int my_data;
+
+static struct fres_scheduler dummy_scheduler = {
+ .res_type = DUMMY_RESOURCE_TYPE,
+ .res_id = DUMMY_RESOURCE_ID,
+ .create_vres = create_vres,
+ .cancel_vres = cancel_vres,
+ .change_vres = change_vres,
+ .priv = &my_data
+};
+
+int frs_dummy_init(forb_orb orb, fres_contract_broker fcb, forb_executor_t *executor)
+{
+ return frs_register(orb, fcb, executor, &dummy_scheduler);
+}
--- /dev/null
+#ifndef RES_DUMMY_H
+#define RES_DUMMY_H
+
+#define DUMMY_RESOURCE_TYPE FRSH_RT_PROCESSOR
+#define DUMMY_RESOURCE_ID 0
+
+#endif