]> rtime.felk.cvut.cz Git - frescor/frsh.git/commitdiff
Finished implementation of resource scheduler generic code
authorMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 23 Oct 2008 15:46:19 +0000 (17:46 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 23 Oct 2008 15:46:19 +0000 (17:46 +0200)
Dummy scheduler is provided as an example of how to write schedulers.

14 files changed:
fres/cbroker/fcb.c
fres/contract/fres_contract.h
fres/resmng/fres_sa_scenario.c
fres/resmng/fres_sa_scenario.h
fres/resmng/frm_generic.c
fres/resmng/frm_generic.h
fres/ressched/Makefile.omk
fres/ressched/frs.idl
fres/ressched/frs_generic.c [new file with mode: 0644]
fres/ressched/frs_generic.h [new file with mode: 0644]
resources/dummy/Makefile.omk
resources/dummy/frm_dummy.c
resources/dummy/frs_dummy.c
resources/dummy/res_dummy.h [new file with mode: 0644]

index ea11ce6649f264c6508343238630eb376a5b44f2..a36fe710efa73e3ac746ba47ba598bf0b9b883fa 100644 (file)
@@ -224,7 +224,7 @@ negotiate_contract(fres_contract_broker obj,
        }
 
        /* 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)) {
index a8b8abae476835ee8ffaa71ffb4d3c47b7db9823..116b1b72bc3b3029fa6427805cbc82951dc7daa5 100644 (file)
@@ -20,6 +20,13 @@ static inline int fres_contract_id_cmp(const fres_contract_id_t *a,
                                  (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);
index 9d79f5d677ff88b434830186261dc68fc8d996a4..45ae6c77116169f0eba139606503112e79d680f5 100644 (file)
@@ -50,15 +50,6 @@ err:
 }
 
 
-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 */,
@@ -66,7 +57,7 @@ GAVL_CUST_NODE_INT_IMP(fres_sa_scenario_contract /* cust_prefix */,
                       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)
index 950a0e3c63c9bfd11c65ec201da3cf9794980da5..5e853fa1553ce11904ef9ebfa798f439f1bf969f 100644 (file)
@@ -27,6 +27,32 @@ struct fres_sa_scenario {
        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);
 
index 1b7d3781d8ebd304e7ee64b4ec080391e298fb73..f6275416582e96f1bf9e483fa02b5f35f927e186 100644 (file)
@@ -111,7 +111,7 @@ static const struct forb_fres_resource_manager_impl frm_impl = {
  * 
  * @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;
@@ -121,8 +121,8 @@ int frm_generic_run(forb_orb orb, frm_adm_test_fnc_t admission_test, void *priv)
        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) {
@@ -145,9 +145,11 @@ int frm_generic_run(forb_orb orb, frm_adm_test_fnc_t admission_test, void *priv)
        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;
        }
 
index 809b3734d0e63eb252c0d9ddb0275d4bfce84d60..bea28028e272f4c7681103c07934412721f1fa2d 100644 (file)
  */
 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
index 530b7db8299e0afdbe52fecb817f6cad5213a6ff..9e18416129487a4aed4242cea081111eab9b2e57 100644 (file)
@@ -1,6 +1,8 @@
 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
index 8c3efe9d2223e2cfed7e5a4fc216868695f4664b..3a99d576c4aa128b404bab1a17b985a698e14cd5 100644 (file)
@@ -5,9 +5,19 @@
 
 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);
        };
 };
 
diff --git a/fres/ressched/frs_generic.c b/fres/ressched/frs_generic.c
new file mode 100644 (file)
index 0000000..9d30bff
--- /dev/null
@@ -0,0 +1,210 @@
+/**
+ * @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);
+}
diff --git a/fres/ressched/frs_generic.h b/fres/ressched/frs_generic.h
new file mode 100644 (file)
index 0000000..e62aba2
--- /dev/null
@@ -0,0 +1,60 @@
+#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
index 6c6431985475203c8787d9fc866dcb592b977246..58521c884c3b1e9dd980f924c778abc806af1cab 100644 (file)
@@ -1,8 +1,7 @@
 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
index 5fa17f2c71fcdb3ffaa26974e7751e3ff16bd8a6..5ea5fd56edb1da3c29489b01e5d1549aa2ee9156 100644 (file)
@@ -5,9 +5,8 @@
 #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;
@@ -18,25 +17,48 @@ bool admission_test(struct fres_sa_scenario *scenario, void *priv)
 {
        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");
index e1c37f3d746443aaf8505e98085c663bb175db14..a2a3a6b230a20413ebd0ebac7856003bd87b9d1e 100644 (file)
@@ -1 +1,64 @@
-#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);
+}
diff --git a/resources/dummy/res_dummy.h b/resources/dummy/res_dummy.h
new file mode 100644 (file)
index 0000000..a699d5a
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef RES_DUMMY_H
+#define RES_DUMMY_H
+
+#define DUMMY_RESOURCE_TYPE FRSH_RT_PROCESSOR
+#define DUMMY_RESOURCE_ID   0
+
+#endif