]> rtime.felk.cvut.cz Git - frescor/frsh.git/commitdiff
Merge branch 'master' of sojka@rtime.felk.cvut.cz:/var/git/frescor/frsh_forb
authorMichal Sojka <sojkam1@fel.cvut.cz>
Sat, 16 May 2009 19:55:29 +0000 (21:55 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Sat, 16 May 2009 19:55:29 +0000 (21:55 +0200)
83 files changed:
fres/cbroker/fcb.c
fres/contract/fres_blocks.idl
fres/contract/fres_container.c
fres/contract/fres_container.h
fres/contract/fres_contract.c
fres/contract/fres_contract.h
fres/resalloc/fra_generic.c
fres/resalloc/fra_generic.h
fres/resalloc/fra_registry.c
fres/resalloc/fres_vres.c
fres/resalloc/fres_vres.h
frsh_api/Makefile.omk
frsh_api/frsh_contract.c
frsh_api/frsh_core.c
frsh_api/frsh_feedback.c [new file with mode: 0644]
frsh_api/frsh_power.c [new file with mode: 0644]
frsh_api/frsh_spare_capacity.c
frsh_api/frsh_synchobj.c
frsh_api/frsh_thread.c
frsh_api/frsh_vres.c
frsh_api/tests/Makefile.omk
frsh_api/tests/spare_capacity.c [new file with mode: 0644]
resources/acpi_battery/Makefile [new file with mode: 0644]
resources/acpi_battery/Makefile.omk [new file with mode: 0644]
resources/acpi_battery/fra_acpi_battery.c [new file with mode: 0644]
resources/acpi_battery/fra_acpi_battery.h [new file with mode: 0644]
resources/acpi_battery/tests/Makefile [new file with mode: 0644]
resources/acpi_battery/tests/Makefile.omk [new file with mode: 0644]
resources/acpi_battery/tests/acpi_battery_test.c [new file with mode: 0644]
resources/acpi_battery/tests/config.omk [new file with mode: 0644]
resources/acpi_cpu/Makefile [new file with mode: 0644]
resources/acpi_cpu/Makefile.omk [new file with mode: 0644]
resources/acpi_cpu/fra_acpi_cpu.c [new file with mode: 0644]
resources/acpi_cpu/fra_acpi_cpu.h [new file with mode: 0644]
resources/acpi_cpu/tests/Makefile [new file with mode: 0644]
resources/acpi_cpu/tests/Makefile.omk [new file with mode: 0644]
resources/acpi_cpu/tests/acpi_cpu_test.c [new file with mode: 0644]
resources/acpi_cpu/tests/config.omk [new file with mode: 0644]
resources/acpi_lcd/Makefile [new file with mode: 0644]
resources/acpi_lcd/Makefile.omk [new file with mode: 0644]
resources/acpi_lcd/fra_acpi_lcd.c [new file with mode: 0644]
resources/acpi_lcd/fra_acpi_lcd.h [new file with mode: 0644]
resources/acpi_lcd/tests/Makefile [new file with mode: 0644]
resources/acpi_lcd/tests/Makefile.omk [new file with mode: 0644]
resources/acpi_lcd/tests/acpi_lcd_test.c [new file with mode: 0644]
resources/acpi_lcd/tests/config.omk [new file with mode: 0644]
resources/cluster_tree/frm_cluster_tree.c
resources/cpu_aquosa/lib/Makefile.omk
resources/cpu_aquosa/lib/aqcpu_fra.c
resources/cpu_aquosa/lib/aqcpu_res.h
resources/cpu_aquosa/lib/frsh_aqcpu.c [deleted file]
resources/cpu_aquosa/mngr/Makefile.omk
resources/cpu_aquosa/mngr/frm_aqcpu.c
resources/cpu_aquosa/tests/Makefile.omk
resources/cpu_aquosa/tests/aqcputest.c
resources/cpucg/lib/Makefile.omk
resources/cpucg/lib/cpucg_fra.c
resources/cpucg/lib/cpucg_res.h
resources/cpucg/lib/frsh_cpucg.c [deleted file]
resources/disk_bfq/Makefile [new file with mode: 0644]
resources/disk_bfq/Makefile.omk [new file with mode: 0644]
resources/disk_bfq/README [new file with mode: 0644]
resources/disk_bfq/lib/Makefile [new file with mode: 0644]
resources/disk_bfq/lib/Makefile.omk [new file with mode: 0644]
resources/disk_bfq/lib/disk_block.c [new file with mode: 0644]
resources/disk_bfq/lib/diskbfq_contract.c [new file with mode: 0644]
resources/disk_bfq/lib/diskbfq_contract.h [new file with mode: 0644]
resources/disk_bfq/lib/diskbfq_fra.c [new file with mode: 0644]
resources/disk_bfq/lib/diskbfq_res.h [new file with mode: 0644]
resources/disk_bfq/lib/res_disk.h [new file with mode: 0644]
resources/disk_bfq/lib/res_disk_idl.idl [new file with mode: 0644]
resources/disk_bfq/mngr/Makefile [new file with mode: 0644]
resources/disk_bfq/mngr/Makefile.omk [new file with mode: 0644]
resources/disk_bfq/mngr/diskbfq_mngr.c [new file with mode: 0644]
resources/disk_bfq/mngr/diskbfq_th.c [new file with mode: 0644]
resources/disk_bfq/mngr/diskbfq_th.h [new file with mode: 0644]
resources/disk_bfq/tests/Makefile [new file with mode: 0644]
resources/disk_bfq/tests/Makefile.omk [new file with mode: 0644]
resources/disk_bfq/tests/config.omk [new file with mode: 0644]
resources/disk_bfq/tests/diskbfq.c [new file with mode: 0644]
resources/dummy/frm_dummy.c
resources/fpga/frm_fpga.c
resources/item/frm_item.c

index 407f6303cbebb2e6200e986a7091ddd149e1504c..b9330859f26b8fb880dbb0293e373dabe921b323 100644 (file)
@@ -64,7 +64,7 @@
 #include <forb/server_id.h>
 #include <fres_contract.h>
 #include "fcb_config.h"
-
+#include <fosa_clocks_and_timers.h>
 #ifdef CONFIG_FCB_INET
 #include <forb/proto_inet.h>
 #endif
@@ -72,6 +72,8 @@
 UL_LOG_CUST(ulogd_fcb);
 ul_log_domain_t ulogd_fcb = {UL_LOGL_MSG, "fcb"};
 
+fosa_abs_time_t start_time;
+
 
 /**
  * Resource identification 
@@ -89,6 +91,7 @@ struct resource {
        struct res_key key;
        fres_resource_manager mng; /**< Object reference of the resource manager */
        gavl_cust_root_field_t allocators; /**< Registered allocators for this resource (from multiple applications/nodes) */
+       ul_list_head_t sc_contracts; /**< Negotiated contracts with spare capacity for this resource */
 };
 
 /**
@@ -102,8 +105,14 @@ struct res_alloc {
 
 struct fcb_contract {
        fres_contract_id_t id;
-       gavl_node_t node;
+       gavl_node_t node_fcb;
+       ul_list_node_t node_sc;
+       int next_sc_variant;
+       int reserved_sc_variant;
+       fosa_abs_time_t end_of_stability_period;
        struct fres_contract *user_contract;
+       struct fres_contract *reserved_contract;
+       struct fres_contract *to_be_reserved_contract;
 };
 
 /**
@@ -190,13 +199,20 @@ GAVL_CUST_NODE_INT_IMP(fcb_alloc        /* cust_prefix */,                \
                       app              /* cust_item_key */,            \
                       forb_server_id_cmp /* cust_cmp_fnc */);
 
+/* Container for contracts with spare capacity negotiated for a given resource */
+UL_LIST_CUST_DEC(sc_contracts        /* cust_prefix */,                        \
+                struct resource  /* cust_head_t */,                    \
+                struct fcb_contract /* cust_item_t */,                 \
+                sc_contracts   /* cust_head_field */,                  \
+                node_sc        /* cust_node_field */);
+
 /* Container for negotiated contracts */
 GAVL_CUST_NODE_INT_DEC(fcb_contract         /* cust_prefix */,         \
                       struct fcb           /* cust_root_t */,          \
                       struct fcb_contract  /* cust_item_t */,          \
                       fres_contract_id_t   /* cust_key_t */,           \
                       contracts            /* cust_root_node */,       \
-                      node                 /* cust_item_node */,       \
+                      node_fcb             /* cust_item_node */,       \
                       id                   /* cust_item_key */,        \
                       fres_contract_id_cmp /* cust_cmp_fnc */);
 
@@ -206,7 +222,7 @@ GAVL_CUST_NODE_INT_IMP(fcb_contract         /* cust_prefix */,              \
                       struct fcb_contract  /* cust_item_t */,          \
                       fres_contract_id_t   /* cust_key_t */,           \
                       contracts            /* cust_root_node */,       \
-                      node                 /* cust_item_node */,       \
+                      node_fcb             /* cust_item_node */,       \
                       id                   /* cust_item_key */,        \
                       fres_contract_id_cmp /* cust_cmp_fnc */);
 #else
@@ -259,7 +275,7 @@ check_single_resource(struct fcb *fcb, struct fres_contract *contracts[], int nu
 {
        struct resource *resource = NULL;
        unsigned i;
-       struct res_key key, key2;
+       struct res_key key, key2 = {-1,-1};
 
        for (i=0; i<num; i++) {
                if (!get_res_key(fcb, contracts[i], &key)) {
@@ -299,6 +315,7 @@ prepare_reservation_contracts(struct fcb *fcb, struct fres_contract *contracts[]
                struct fres_contract *c = contracts[i];
                
                if (fres_contract_id_is_empty(&c->id)) {
+                       /* Normal negotiation request */
                        forb_uuid_generate((forb_uuid_t *)&c->id);
                        continue;
                }
@@ -323,6 +340,47 @@ prepare_reservation_contracts(struct fcb *fcb, struct fres_contract *contracts[]
        return 0;
 }
 
+static int prepare_next_reservation_variant(struct fcb_contract *fc, fosa_abs_time_t now)
+{
+       fres_block_spare_capacity *s;
+       fres_contract_destroy(fc->to_be_reserved_contract);
+       fc->to_be_reserved_contract = fres_contract_duplicate(fc->user_contract);
+       if (!fc->to_be_reserved_contract)
+               return errno;
+       s = fres_contract_get_spare_capacity(fc->to_be_reserved_contract);
+       if (s) {
+               int variant;
+               variant = fosa_abs_time_smaller(fc->end_of_stability_period, now) ?
+                       fc->next_sc_variant :
+                       fc->reserved_sc_variant;
+               
+               fres_container_copy(fc->to_be_reserved_contract->container,
+                                   forb_sequence_elem(s->variants, variant));
+       }
+}
+
+static int
+rebalance_spare_capacity_and_reserve(struct fcb *fcb, struct resource *resource,
+                                    struct fcb_contract *fcb_contract[], int num)
+{
+       unsigned i;
+       fosa_abs_time_t now;
+       fosa_clock_get_time(CLOCK_REALTIME, &now);
+       for (i=0; i<num; i++) {
+               prepare_next_reservation_variant(fcb_contract[i], now);
+       }
+#if 0
+       do {
+               /* Reserve contract */
+               ret = fres_resource_manager_reserve_contracts(resource->mng, contracts, ev);
+               if (forb_exception_occurred(ev) || ret < 0) {
+                       return ret;
+               }
+       } while (ret != 0)
+#endif
+       return 0;
+}
+
 CORBA_long
 negotiate_contracts(fres_contract_broker obj,
                    const fres_contract_ptr_seq* contracts,
@@ -348,7 +406,7 @@ negotiate_contracts(fres_contract_broker obj,
        ret = prepare_reservation_contracts(fcb, contracts->_buffer, contracts->_length);
        if (ret)
                goto err;
-       
+
        forb_get_req_source(obj, &app);
        ra = fcb_alloc_find(resource, &app);
        if (!ra) {
@@ -363,6 +421,7 @@ negotiate_contracts(fres_contract_broker obj,
        /* Allocate all the needed memory before doing reservation. If
         * there is no enough memory, it has no sense to call resource
         * manager. */
+       /* TODO: Use FORB macros to allocate sequence */
        ids = malloc(sizeof(*ids));
        if (!ids) {
                ev->major = FORB_EX_NO_MEMORY;
@@ -389,6 +448,7 @@ negotiate_contracts(fres_contract_broker obj,
        memset(fcb_contracts, 0, sizeof(fcb_contracts[0])*contracts->_length);
 
        for (i=0; i<contracts->_length; i++) {
+               /* Allocate FCB contracts */
                struct fres_contract *c = contracts->_buffer[i];
                if (fres_contract_get_num_blocks(c) > 0) {
                        fcb_contracts[i] = fcb_contract_new(&c->id);
@@ -406,14 +466,18 @@ negotiate_contracts(fres_contract_broker obj,
 
        /* TODO: Optimize the following by introducing
         * reserve_and_commit FRM method. */
-       
+#if 1  
        /* Reserve contract */
        ret = fres_resource_manager_reserve_contracts(resource->mng, contracts, ev);
        if (forb_exception_occurred(ev) || ret < 0) {
                goto err_free_fcb_contracts;
        }
+#else
+       ret = rebalance_spare_capacity_and_reserve(fcb, resource, contracts->_buffer,
+                                                  fcb_contracts, contracts->_length);
+#endif
        if (ret == 1) {
-               ul_logmsg("Contract was not accepted\n");
+               ul_logmsg("Contract(s) was not accepted\n");
                goto err_free_fcb_contracts;
        }
 
@@ -505,6 +569,7 @@ CORBA_long register_resource(fres_contract_broker obj,
        res->mng = forb_object_duplicate(desc->manager);
 
        fcb_alloc_init_root_field(res);
+       sc_contracts_init_head(res);
        ul_logmsg("Registering manager for resource %d.%d\n",
                  restype, resid);
        fcb_resource_insert(fcb, res);
@@ -622,6 +687,30 @@ struct forb_fres_contract_broker_impl impl = {
        .get_resources = get_resources,
 };
 
+void peer_discovery_callback(const forb_orb peer_orb, const char *orb_id)
+{
+       forb_server_id server_id;
+       char server_id_str[sizeof(forb_server_id)*2+1];
+
+       forb_get_server_id(peer_orb, &server_id);
+       forb_server_id_to_string(server_id_str, &server_id, sizeof(server_id_str));
+#if 0
+       ul_logmsg("peer discovered: %s (orb_id '%s')\n", server_id_str, orb_id);
+#endif
+       if (strcmp(orb_id, "org.frescor.fcb") == 0) {
+               fosa_abs_time_t now;
+               fosa_rel_time_t delay;
+               fosa_clock_get_time(CLOCK_REALTIME, &now);
+               delay = fosa_abs_time_extract_interval(start_time, now);
+               ul_logmsg("node joined: %s (time %ld ms)\n", server_id_str,
+                         fosa_rel_time_to_msec(delay));
+       }
+}
+
+void peer_dead_callback(const forb_orb peer_orb, const char *orb_id)
+{
+}
+
 int main(int argc, char *argv[])
 {
        forb_orb orb;
@@ -629,8 +718,16 @@ int main(int argc, char *argv[])
        fres_contract_broker fcb;
        forb_executor_t executor;
        int ret;
+       forb_init_attr_t attr = {
+               .orb_id = "org.frescor.fcb",
+               .peer_discovery_callback = peer_discovery_callback,
+               .peer_dead_callback = peer_dead_callback,
+       };
+
+
+       fosa_clock_get_time(CLOCK_REALTIME, &start_time);
 
-       orb = forb_init(&argc, &argv, "fcb");
+       orb = forb_init(&argc, &argv, &attr);
        if (!orb) error(1, errno, "FORB initialization failed");
 
 #ifdef CONFIG_FCB_INET
index 6bf66e806895196d79c277723ae5d05b86593f7b..148f1dc472cc794b8fe16571700cc712baf544ae 100644 (file)
@@ -161,6 +161,14 @@ module fres {
                        sequence<container_ptr> variants;
                };
 
+               /// Power Management
+               struct power_management {
+                       fosa_rel_time_t period;
+                       fosa_rel_time_t max_budget[3];
+                       fosa_rel_time_t min_budget[3];
+                       fosa_rel_time_t min_expiration;
+               };
+
        };
        
 };
index 14a202e35daf0dcca3c1c2b08ba430d4f230f233..a067c4134e16936020629232512e59138c847fbd 100644 (file)
@@ -76,6 +76,27 @@ fres_block_duplicate_spare_capacity(enum fres_block_type type, const void *block
                .to_string   = fres_block_##type##_to_string            \
        }
 
+static size_t indent_str(char *dest, size_t size, char *src, unsigned indent_by)
+{
+       char *p = src;
+       size_t written = 0;
+       while (*p && size > 1) {
+               if (p == src || *(p-1) == '\n') { /* indent */
+                       int i;
+                       for (i=0; i<indent_by; i++) {
+                               *dest++ = ' ';
+                               written++;
+                               size--;
+                       }
+               }
+               *dest++ = *p++;
+               written++;
+               size--;
+       }
+       *dest = 0;
+       return written;
+}
+
 int fres_block_label_to_string(char *dest, size_t size, enum fres_block_type type,
                               const void *block_data)
 {
@@ -119,23 +140,62 @@ int fres_block_timing_reqs_to_string(char *dest, size_t size, enum fres_block_ty
                );
 }
 
+int fres_block_spare_capacity_to_string(char *dest, size_t size, enum fres_block_type type,
+                                       const void *block_data)
+{
+       int i, ret;
+       char *orig_dest = dest;
+       const fres_block_spare_capacity *s = block_data;
+       ret = snprintf(dest, size,
+                      "granularity: %s\n"
+                      "importance: %d\n"
+                      "weight:     %d\n"
+                      "stability time: %g\n",
+                      s->granularity == FRSH_GR_CONTINUOUS ? "continuous" :
+                      s->granularity == FRSH_GR_DISCRETE ? "discrete" : "?",
+                      s->importance, s->weight, fosa_rel_time_to_double(s->stability_time));
+       dest += ret;
+       size -= ret;
+       for (i=0; i < s->variants._length; i++) {
+               char tmp[1000];
+               ret = snprintf(dest, size, "Variant %d:\n", i);
+               dest += ret;
+               size -= ret;
+               ret = fres_container_to_string(tmp, sizeof(tmp),
+                                              forb_sequence_elem(s->variants, i));
+               ret = indent_str(dest, size, tmp, 2);
+               dest += ret;
+               size -= ret;
+       }
+       return dest - orig_dest;
+}
+
 int fres_block_csects_to_string(char *dest, size_t size, enum fres_block_type type,
                                const void *block_data)
 {
        return snprintf(dest, size, "Coming Soon...\n");
 }
 
+int fres_block_power_management_to_string(char *dest, size_t size, enum fres_block_type type,
+                                         const void *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 desc_default(power_management);
 
 static const struct fres_block_desc desc_spare_capacity = {
+       .name        = "spare_capacity",
        .size        = sizeof(fres_block_spare_capacity),
        .serialize   = (fres_block_serialize_fnc_t*)fres_block_spare_capacity_serialize, \
        .deserialize = (fres_block_deserialize_fnc_t*)fres_block_spare_capacity_deserialize, \
-       .duplicate   = fres_block_duplicate_spare_capacity
+       .duplicate   = fres_block_duplicate_spare_capacity,
+       .to_string   = fres_block_spare_capacity_to_string
 };
 
 /**
@@ -148,6 +208,8 @@ static const struct fres_block_desc *block_registry[FRES_NUM_BLOCKS] = {
        [FRES_BLOCK_BASIC] = &desc_default_basic,
        [FRES_BLOCK_TIMING_REQS] = &desc_default_timing_reqs,
        [FRES_BLOCK_CSECTS] = &desc_default_csects,
+       [FRES_BLOCK_SPARE_CAPACITY] = &desc_spare_capacity,
+       [FRES_BLOCK_POWER_MANAGEMENT] = &desc_default_power_management,
 };
 
 /** 
@@ -590,21 +652,11 @@ fres_container_to_string(char *dest, size_t size, const struct fres_container *c
                                }
                                if (block_registry[type]->to_string) {
                                        char tmp[1000];
-                                       char *p = tmp;;
-                                       ret = block_registry[type]->to_string(tmp, sizeof(tmp), type, b->u.data);
-                                       while (*p) {
-                                               if (p == tmp || *(p-1) == '\n') { /* indent */
-                                                       int i;
-                                                       for (i=0; i<2; i++) {
-                                                               *dest++ = ' ';
-                                                               written++;
-                                                               size--;
-                                                       }
-                                               }
-                                               *dest++ = *p++;
-                                               written++;
-                                               size--;
-                                       }
+                                       block_registry[type]->to_string(tmp, sizeof(tmp), type, b->u.data);
+                                       ret = indent_str(dest, size, tmp, 2);
+                                       written += ret;
+                                       size -= ret;
+                                       dest += ret;
                                }
                                break;
                        case FRES_BLOCK_STREAM:
@@ -620,6 +672,7 @@ fres_container_to_string(char *dest, size_t size, const struct fres_container *c
                }
        }
        ret = written;
+       *dest = 0;
 err:
        return ret;
 }
@@ -675,3 +728,33 @@ int fres_container_merge(struct fres_container *dest,
        }
        return 0;
 }
+
+/** 
+ * Copy blocks from a container into another one. Blocks present in
+ * both @a src and @a dest are replaced in @a dest.
+ * 
+ * @param dest Destination of copy operation
+ * @param src Source of copy operation
+ * 
+ * @return Zero on success, non-zero error core on error.
+ */
+int fres_container_copy(struct fres_container *dest,
+                       const struct fres_container *src)
+{
+       enum fres_block_type type;
+       int ret;
+       
+       for (type=0; type<FRES_NUM_BLOCKS; type++) {
+               const struct fres_block *sb = &src->blocks[type];
+               struct fres_block *db = &dest->blocks[type];
+               
+               if (sb->state != FRES_BLOCK_EMPTY) { 
+                       fres_container_del_block(dest, type);
+                       ret = fres_block_duplicate(db, sb, type);
+                       if (ret) {
+                               return ret;
+                       }
+               }
+       }
+       return 0;
+}
index 228e266b6609bc54fd71d9dbb2082b4dde5b3720..dabc877f43eeb8866f98012db786b46d975bbfd6 100644 (file)
@@ -84,7 +84,9 @@ enum fres_block_type {
        FRES_BLOCK_TIMING_REQS,
        FRES_BLOCK_CSECTS,
        FRES_BLOCK_SPARE_CAPACITY,
+       FRES_BLOCK_POWER_MANAGEMENT,
        FRES_BLOCK_DUMMY_SCHED, /**< See resources/dummy/res_dummy_idl.idl */
+       FRES_BLOCK_DISK_SCHED, /** < See resources/disk_bfq/res_disk_idl.idl */
        FRES_BLOCK_CLUSTER_TREE_TRAFFIC, /**< resources/cluster_tree/cluster_tree_idl.idl */
        FRES_BLOCK_FWP_SCHED,
        FRES_BLOCK_ITEM_NODES, /**< resources/item/item_idl.idl */
@@ -168,6 +170,7 @@ FRES_CONTAINER_ACCESSOR(BASIC,          basic)
 FRES_CONTAINER_ACCESSOR(TIMING_REQS,    timing_reqs)
 FRES_CONTAINER_ACCESSOR(CSECTS,                csects)
 FRES_CONTAINER_ACCESSOR(SPARE_CAPACITY, spare_capacity)
+FRES_CONTAINER_ACCESSOR(POWER_MANAGEMENT, power_management)
 
 int
 fres_block_register(enum fres_block_type, const struct fres_block_desc *desc);
@@ -184,6 +187,9 @@ fres_container_get_num_blocks(const struct fres_container *c);
 int fres_container_merge(struct fres_container *dest,
                         const struct fres_container *src);
 
+int fres_container_copy(struct fres_container *dest,
+                       const struct fres_container *src);
+
 #ifdef __cplusplus
 } /* extern "C"*/
 #endif
index 1b6cc845c78a349402ee5e9e239cabb8a7d345ca..5fae762fc6cbe64d491f3029935e48fa48eea7db 100644 (file)
@@ -85,8 +85,10 @@ err:
 
 void fres_contract_destroy(struct fres_contract *contract)
 {
-       fres_container_destroy(contract->container);
-       free(contract);
+       if (contract) {
+               fres_container_destroy(contract->container);
+               free(contract);
+       }
 }
 
 struct fres_contract *
index 5f426c36d34fcd2064715e939c293e789ef78c64..6cd91026682e925e5f0d4998dda238cc8114f915 100644 (file)
@@ -222,6 +222,7 @@ FRES_CONTRACT_ACCESSOR(basic)
 FRES_CONTRACT_ACCESSOR(timing_reqs)
 FRES_CONTRACT_ACCESSOR(csects)
 FRES_CONTRACT_ACCESSOR(spare_capacity)
+FRES_CONTRACT_ACCESSOR(power_management)
 
 #ifdef __cplusplus
 } /* extern "C"*/
index 59d0e90522d6e525538630c935fce109cfaa661c..673267a10def3d202258b1386e40f5c5b65e79c6 100644 (file)
@@ -85,13 +85,12 @@ struct fres_threads_vres fres_threads_vres;
 GAVL_CUST_NODE_INT_IMP(fres_threads_vres_nolock        /* cust_prefix */,
                       struct fres_threads_vres /* cust_root_t */,
                       struct fres_thread_vres  /* cust_item_t */,
-                      fosa_thread_id_t         /* cust_key_t */,
+                      fres_thread_vres_key_t   /* cust_key_t */,
                       threads                  /* cust_root_node */,
                       node                     /* cust_item_node */,
-                      id                       /* cust_item_key */,
+                      thread_vres              /* cust_item_key */,
                       fres_thread_vres_cmp     /* cust_cmp_fnc */);
 
-
 /** 
  * Inserts vres to the global vres "registry".
  * 
@@ -129,6 +128,25 @@ fres_vreses_find(fres_contract_id_t *id)
        return ret;
 }
 
+struct fres_vres *
+fres_vreses_find_label(fres_block_label *label, fres_block_resource *res)
+{
+       struct fres_vres *item;
+
+       gavl_cust_for_each(fres_vreses_nolock, &fres_vreses, item) {
+               struct fres_contract *c = item->perceived;
+               fres_block_label *l = fres_contract_get_label(c);
+               fres_block_resource *r = fres_contract_get_resource(c);
+
+               if (strncmp(l->label, label->label, sizeof(label->label)) &&
+                   res->resource_type == r->resource_type &&
+                   res->resource_id == r->resource_id)
+                       return item;
+       }
+
+       return NULL;
+}
+
 
 #define save_errno(cmd) do { int _e = errno; cmd; errno = _e; } while(0)
 
@@ -284,68 +302,69 @@ fres_vres_t *fra_get_vres(fres_contract_id_t *id)
 }
 
 static inline
-int fres_threads_vres_insert(struct fres_thread_vres *th)
+int fres_threads_vres_insert(struct fres_thread_vres *tv)
 {
        int ret;
 
        fosa_mutex_lock(&fres_threads_vres.mutex);
-       ret = fres_threads_vres_nolock_insert(&fres_threads_vres, th);
+       ret = fres_threads_vres_nolock_insert(&fres_threads_vres, tv);
        fosa_mutex_unlock(&fres_threads_vres.mutex);
 
        return ret;
 }
 
 static inline
-int fres_threads_vres_delete(struct fres_thread_vres *th)
+int fres_threads_vres_delete(struct fres_thread_vres *tv)
 {
        int ret;
 
        fosa_mutex_lock(&fres_threads_vres.mutex);
-       ret = fres_threads_vres_nolock_delete(&fres_threads_vres, th);
+       ret = fres_threads_vres_nolock_delete(&fres_threads_vres, tv);
        fosa_mutex_unlock(&fres_threads_vres.mutex);
 
        return ret;
 }
 
 static inline
-struct fres_thread_vres *fres_threads_vres_find(const fosa_thread_id_t *id)
+struct fres_thread_vres *fres_threads_vres_find(const fres_thread_vres_key_t *key)
 {
        struct fres_thread_vres *ret;
 
        fosa_mutex_lock(&fres_threads_vres.mutex);
-       ret = fres_threads_vres_nolock_find(&fres_threads_vres, id);
+       ret = fres_threads_vres_nolock_find(&fres_threads_vres, key);
        fosa_mutex_unlock(&fres_threads_vres.mutex);
 
        return ret;
 }
 
 /** 
- * Creates binding from a thread to VRES; if binding already exists,
- * it is updated.
+ * Creates binding from a thread to VRES of specified type;
+ * if binding already exists, it fails... The old one should be
+ * deleted first.
  * 
- * @param id Thread ID bounded to @a vres.
+ * @param id Thread ID bounded to @a vres of type @vres_type.
  * @param vres VRES
  * 
  * @return Positive number when a new binding was inserted, zero when
  * binding was changed and -1 on error.
  */
-int fra_insert_thread_vres(const fosa_thread_id_t *id, fres_vres_t *vres)
+int fra_insert_thread_vres(const fosa_thread_id_t *id,
+                          int vres_type,
+                          fres_vres_t *vres)
 {
-       struct fres_thread_vres *th;
+       fres_thread_vres_key_t key;
+       struct fres_thread_vres *tv;
 
-       th = fres_threads_vres_find(id);
-       if (th) {
-               fosa_mutex_lock(&fres_threads_vres.mutex);
-               th->vres = vres;
-               fosa_mutex_unlock(&fres_threads_vres.mutex);
+       key.thread_id = *id;
+       key.vres_type = vres_type;
 
-               return 0;
-       }
+       tv = fres_threads_vres_find(&key);
+       if (tv) return -1;
 
-       th = fres_thread_vres_new(id, vres);
-       if (!th) return -1;
+       tv = fres_thread_vres_new(id, vres_type, vres);
+       if (!tv) return -1;
 
-       return fres_threads_vres_insert(th);
+       return !fres_threads_vres_insert(tv);
 }
 
 /** 
@@ -355,22 +374,29 @@ int fra_insert_thread_vres(const fosa_thread_id_t *id, fres_vres_t *vres)
  * 
  * @return Zero on success, -1 on when the thread was not bound.
  */
-int fra_delete_thread_vres(const fosa_thread_id_t *id)
+int fra_delete_thread_vres(const fosa_thread_id_t *id, int vres_type)
 {
-       struct fres_thread_vres *th;
-       int ret = 0;
+       struct fres_thread_vres *tv;
+       fres_thread_vres_key_t key;
+       int ret;
+
+       key.thread_id = *id;
+       key.vres_type = vres_type;
 
        fosa_mutex_lock(&fres_threads_vres.mutex);
-       th = fres_threads_vres_nolock_find(&fres_threads_vres, id);
-       if (th) {
-               fres_threads_vres_nolock_delete(&fres_threads_vres, th);
-       } else {
+       tv = fres_threads_vres_nolock_find(&fres_threads_vres, &key);
+       if (!tv) {
                ret = -1;
+               goto retr;
        }
+
+       ret = fres_threads_vres_nolock_delete(&fres_threads_vres, tv);
        fosa_mutex_unlock(&fres_threads_vres.mutex);
-       if (ret == 0) {
-               fres_thread_vres_destroy(th);
-       }
+       if (ret) goto retr;
+
+       ret = !fres_threads_vres_delete(tv);
+
+retr:
        return ret;
 }
 
@@ -384,9 +410,16 @@ int fra_delete_thread_vres(const fosa_thread_id_t *id)
  * @todo Is this function needed if we have
  * fra_get_vres_thread_vres()?
  */
-fres_thread_vres_t *fra_get_thread_vres(const fosa_thread_id_t *id)
+fres_thread_vres_t *fra_get_thread_vres
+  (const fosa_thread_id_t *id,
+   int vres_type)
 {
-       return fres_threads_vres_find(id);
+       fres_thread_vres_key_t key;
+
+       key.thread_id = *id;
+       key.vres_type = vres_type;
+
+       return fres_threads_vres_find(&key);
 }
 
 /** 
@@ -396,14 +429,19 @@ fres_thread_vres_t *fra_get_thread_vres(const fosa_thread_id_t *id)
  * 
  * @return VRES on NULL in the thread is not bound.
  */
-fres_vres_t *fra_get_vres_thread_vres(const fosa_thread_id_t *id)
+fres_vres_t *fra_get_vres_thread_vres
+  (const fosa_thread_id_t *id,
+   int vres_type)
 {
-       fres_thread_vres_t *th_vres;
+       fres_thread_vres_key_t key;
+       fres_thread_vres_t *tv;
 
-       th_vres = fres_threads_vres_find(id);
-       if (!th_vres) return NULL;
+       key.thread_id = *id;
+       key.vres_type = vres_type;
 
-       return th_vres->vres;
+       tv = fres_threads_vres_find(&key);
+       if (!tv) return NULL;
 
+       return tv->vres;
 }
 
index 0a1c5bc2d1887c232a0952f702def69fca44f777..512a6c24e9b5b347d81d8b2ef24a1c04a1c1d62b 100644 (file)
@@ -81,6 +81,8 @@ GAVL_CUST_NODE_INT_DEC(fres_vreses_nolock /* cust_prefix */,
 
 extern struct fres_vreses fres_vreses;
 
+struct fres_vres *
+fres_vreses_find_label(fres_block_label *label, fres_block_resource *res);
 
 /** Registry of all threads in an application that are bound to a VRES. */
 struct fres_threads_vres {
@@ -91,10 +93,10 @@ struct fres_threads_vres {
 GAVL_CUST_NODE_INT_DEC(fres_threads_vres_nolock        /* cust_prefix */,
                       struct fres_threads_vres /* cust_root_t */,
                       struct fres_thread_vres  /* cust_item_t */,
-                      fosa_thread_id_t         /* cust_key_t */,
+                      fres_thread_vres_key_t   /* cust_key_t */,
                       threads                  /* cust_root_node */,
                       node                     /* cust_item_node */,
-                      id                       /* cust_item_key */,
+                      thread_vres              /* cust_item_key */,
                       fres_thread_vres_cmp     /* cust_cmp_fnc */)
 
 extern struct fres_threads_vres fres_threads_vres;
@@ -179,6 +181,21 @@ struct fres_allocator {
        int (*apply_vres_changes)(fres_vres_t *vreses[], unsigned length, void *priv);
        /*@}*/
 
+       /** @name Feedback module support */
+       /*@{*/
+       int (*set_spare_bandwidth)(fres_vres_t *vres);
+       int (*get_desired_budget)(fres_vres_t *vres, frsh_rel_time_t *p_budget_out);
+       int (*set_desired_budget)(fres_vres_t *vres_id, frsh_rel_time_t *p_budget_in);
+       int (*get_actual_budget)(fres_vres_t *vres_id, frsh_rel_time_t *budget);
+       /*@}*/
+
+       int (*bind_thread)(fres_vres_t *vres, fosa_thread_id_t thread);
+       int (*unbind_thread)(fosa_thread_id_t thread);
+
+       int (*vres_get_job_usage)(const fres_vres_t *vres, frsh_rel_time_t *spent);
+       int (*vres_get_remaining_budget)(const fres_vres_t *vres, frsh_rel_time_t *budget);
+       int (*vres_get_usage)(const fres_vres_t *vres, frsh_rel_time_t *spent);
+
        void *priv;             /**< Pointer to allocator's private data */
 
        /**
@@ -198,12 +215,20 @@ void fra_registry_init(forb_orb              orb,
 int fra_register(struct fres_allocator *allocator);
 int fra_activate(frsh_resource_type_t res_type,
                 frsh_resource_id_t   res_id);
+struct fres_allocator *fra_get(frsh_resource_type_t res_type,
+                              frsh_resource_id_t   res_id);
 
 fres_vres_t *fra_get_vres(fres_contract_id_t *id);
 
-int fra_insert_thread_vres(const fosa_thread_id_t *id, fres_vres_t *vres);
-int fra_delete_thread_vres(const fosa_thread_id_t *id);
-fres_thread_vres_t *fra_get_thread_vres(const fosa_thread_id_t *id);
-fres_vres_t *fra_get_vres_thread_vres(const fosa_thread_id_t *id);
+int fra_insert_thread_vres(const fosa_thread_id_t *id,
+                          int vres_type,
+                          fres_vres_t *vres);
+int fra_delete_thread_vres(const fosa_thread_id_t *id,
+                          int vres_type);
+fres_thread_vres_t *fra_get_thread_vres(const fosa_thread_id_t *id,
+                                       int vres_type);
+fres_vres_t *fra_get_vres_thread_vres(const fosa_thread_id_t *id,
+                                     int vres_type);
 
 #endif
+
index 13cfab0c9d19a98ce92fdf1b12afbafb4a5dde7f..a27de8407993a1ddd74bf2d8f4a6ff84d816a6f4 100644 (file)
@@ -240,3 +240,30 @@ int fra_activate(frsh_resource_type_t res_type,
 
        return ret;
 }
+
+/** 
+ * Returns allocator for a given resource, previously registered by
+ * fra_register().
+ * 
+ * @param res_type 
+ * @param res_id 
+ * 
+ * @return Pointer to the resource allocator or NULL if no allocator
+ * is registered for the resource.
+ */
+struct fres_allocator *fra_get(frsh_resource_type_t res_type,
+                              frsh_resource_id_t   res_id)
+{
+       struct registered_allocator *ra;
+       struct fres_allocator key, *pkey=&key;
+
+       pkey->res_type = res_type;
+       pkey->res_id = res_id;
+       
+       ra = fra_registry_find(&registry, &pkey);
+       if (ra) {
+               return ra->allocator;
+       } else {
+               return NULL;
+       }
+}
index a487638cedd3080b95b85bb9f1fb3fb9cbe87c8d..e3ef0092cd22d519448a594fd5412513a39fbef4 100644 (file)
@@ -101,25 +101,27 @@ void fres_vres_destroy(fres_vres_t *vres)
 
 fres_thread_vres_t *fres_thread_vres_new
   (const fosa_thread_id_t *id,
+   int vres_type,
    fres_vres_t *vres)
 {
-       fres_thread_vres_t *th;
+       fres_thread_vres_t *tv;
 
-       th = malloc(sizeof(*th));
-       if (!th) goto out;
+       tv = malloc(sizeof(*tv));
+       if (!tv) goto out;
 
-       memset(th, 0, sizeof(*th));
-       th->id = *id;
-       th->vres = vres;
+       memset(tv, 0, sizeof(*tv));
+       tv->thread_vres.thread_id = *id;
+       tv->thread_vres.vres_type = vres_type;
+       tv->vres = vres;
 
 out:
-       return th;
+       return tv;
 }
 
-void fres_thread_vres_destroy(fres_thread_vres_t *th_vres)
+void fres_thread_vres_destroy(fres_thread_vres_t *tv)
 {
-       if (!th_vres) return;
+       if (!tv) return;
 
-       free(th_vres);
+       free(tv);
 }
 
index f17baf31e2824ad691646ab4206fab1f3d683ee2..22f7d77dac0550fbebb31b6ef5e9d196ccef1367 100644 (file)
@@ -47,6 +47,7 @@
 /**
  * @file   fres_vres.h
  * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ *        Dario Faggioli <faggioli@gandalf.sssup.it>
  * @date   Wed Feb 18 16:00:15 2009
  * 
  * @brief  VRES definition
@@ -108,8 +109,13 @@ void fres_vres_destroy(fres_vres_t *vres);
 /**
  * Representation of thread to VRES binding.
  */
+typedef struct fres_thread_vres_key {
+       fosa_thread_id_t thread_id;
+       int vres_type;
+} fres_thread_vres_key_t;
+
 typedef struct fres_thread_vres {
-       fosa_thread_id_t id;
+       struct fres_thread_vres_key thread_vres;
        fres_vres_t *vres;
 
        fosa_abs_time_t job_start_time;
@@ -119,15 +125,31 @@ typedef struct fres_thread_vres {
 } fres_thread_vres_t;
 
 static inline
-int fres_thread_vres_cmp(const fosa_thread_id_t *a, const fosa_thread_id_t *b)
+int fres_thread_vres_cmp
+  (const fres_thread_vres_key_t *a,
+   const fres_thread_vres_key_t *b)
 {
-       return fosa_thread_equal(*a, *b);
+       /*
+        * TODO:
+        *  Make this a little bit less specific!
+        */
+       if (a->thread_id.linux_tid < a->thread_id.linux_tid)
+               return -1;
+       else if (a->thread_id.linux_tid > a->thread_id.linux_tid)
+               return +1;
+       else if (a->vres_type < b->vres_type)
+               return -1;
+       else if (a->vres_type > b->vres_type)
+               return +1;
+
+       return 0;
 }
 
-fres_thread_vres_t *fres_thread_vres_new
-  (const fosa_thread_id_t *id,
-   fres_vres_t *vres);
+fres_thread_vres_t *fres_thread_vres_new(const fosa_thread_id_t *id,
+                                        int vres_type,
+                                        fres_vres_t *vres);
 
-void fres_thread_vres_destroy(fres_thread_vres_t *th_vres);
+void fres_thread_vres_destroy(fres_thread_vres_t *tv);
 
 #endif
+
index db8abaab8a3221f5e8bd25ad223b29f03eadbb4e..7758ff2567f41ca0a6e24b228cf283fe5c26acc0 100644 (file)
@@ -1,22 +1,32 @@
 SUBDIRS = tests
 
 shared_LIBRARIES = frsh
-frsh_SOURCES = frsh_contract.c frsh_vres.c frsh_synchobj.c frsh_distributed.c frsh_core.c frsh_spare_capacity.c frsh_error.c frsh_thread.c frsh_sharedobj.c
+frsh_SOURCES = frsh_contract.c frsh_vres.c frsh_synchobj.c frsh_distributed.c frsh_core.c \
+               frsh_spare_capacity.c frsh_error.c frsh_thread.c frsh_sharedobj.c frsh_power.c frsh_feedback.c
 include_HEADERS = frsh_opaque_types.h frsh_forb.h
-frsh_LIBS = fna fcb_client forb contract synchobj sharedobj fra ulut fosa $(allocator-libs-y)
+frsh_LIBS = fna fcb_client forb contract synchobj sharedobj fra ulut fosa $(allocator-libs-y) $(platform-libs-y)
 
 config_include_HEADERS = frsh_resources.h
 frsh_resources_DEFINES = CONFIG_RESOURCE_DUMMY \
                         CONFIG_AQUOSA\
                         CONFIG_CPUCG\
+                        CONFIG_DISKBFQ\
                         CONFIG_FWP \
-                        CONFIG_RESOURCE_ITEM
+                        CONFIG_RESOURCE_ITEM \
+                        CONFIG_ACPI_LCD \
+                        CONFIG_ACPI_CPU \
+                        CONFIG_ACPI_BATTERY
 
 allocator-libs-$(CONFIG_RESOURCE_DUMMY) += fra_dummy
 allocator-libs-$(CONFIG_RESOURCE_ITEM) += fra_item
 allocator-libs-$(CONFIG_FWP) += frsh_fwp fwp
 allocator-libs-$(CONFIG_AQUOSA) += frshaqcpu
 allocator-libs-$(CONFIG_CPUCG) += frshcpucg
+allocator-libs-$(CONFIG_DISKBFQ) += frshdiskbfq
+
+platform-libs-$(CONFIG_ACPI_CPU) += acpi_cpu
+platform-libs-$(CONFIG_ACPI_LCD) += acpi_lcd
+platform-libs-$(CONFIG_ACPI_BATTERY) += acpi_battery
 
 ifneq ($(AQUOSA_ROOT),)
 LOADLIBES += -L $(AQUOSA_ROOT)/lib
index c672d29424bf46fa4773d9861e823e081afcc9e1..b726217175005547ad6740c85c6524d787bd7e86 100644 (file)
@@ -62,6 +62,7 @@
 #include <fcb.h>
 #include "frsh_forb.h"
 #include <fra_generic.h>
+#include <frsh_energy_management.h>
 
 /**********************************/
 /* -----===== FRSH API =====----- */
@@ -209,7 +210,7 @@ int frsh_contract_set_resource_and_label
        return 0;
 }
 
-int frsh_get_resource_and_label
+int frsh_contract_get_resource_and_label
   (const frsh_contract_t *contract,
    frsh_resource_type_t *resource_type,
    frsh_resource_id_t *resource_id,
@@ -320,6 +321,31 @@ int frsh_contract_get_timing_reqs
        return 0;
 }
 
+static
+int __contract_check_min_expiration(const frsh_contract_t *contract)
+{
+       fres_block_power_management *p;
+       int ret = 0;
+
+       p = fres_contract_get_power_management(*contract);
+       if (p && !fosa_rel_time_is_null(p->min_expiration)) {
+               frsh_abs_time_t req_time, exp_time;
+
+               fosa_clock_get_time(FOSA_CLOCK_REALTIME, &req_time);
+               req_time = fosa_abs_time_incr(req_time, p->min_expiration);
+
+               ret = frsh_battery_get_expiration(&exp_time);
+               if (ret) goto err;
+
+               if (fosa_abs_time_smaller(req_time, exp_time))
+                       ret = FRSH_ERR_CONTRACT_REJECTED;
+       }
+
+err:
+       return ret;
+}
+
+
 int frsh_contract_negotiate
   (const frsh_contract_t *contract,
    frsh_vres_id_t        *vres)
@@ -336,6 +362,15 @@ int frsh_contract_negotiate
                goto err;
        }
 
+       /* TODO: Battery time check should be moved to
+        * FCB. Implementation of FRSH API is meant only as a thin
+        * wrapper of FRES framework and the FRES framework could
+        * theoretically be used without FRSH API. Moreover, if there
+        * is some logging mechanism in FCB, this contract rejection
+        * will not be logged. */
+       ret = __contract_check_min_expiration(contract);
+       if (ret) goto err;
+
        /* Activate allocator */
        r = fres_contract_get_resource(*contract);
        if (r) {
@@ -417,6 +452,9 @@ int frsh_contract_renegotiate_sync
                goto out;
        }
 
+       ret = __contract_check_min_expiration(new_contract);
+       if (ret) goto out;
+
        contract = fres_contract_duplicate(*new_contract);
        if (!contract) {
                ret = errno;
index 907d2a252f27d6136d28288f403cb043281e8e16..79012b1b833146920a3f33349616d90ecd8b84eb 100644 (file)
 #include <cpucg_res.h>
 #endif
 
+#ifdef CONFIG_DISKBFQ
+#include <diskbfq_res.h>
+#endif
+
 #ifdef CONFIG_RESOURCE_DUMMY
 #include <res_dummy.h>
 #endif
@@ -93,11 +97,14 @@ static void *alloc_executor_thread(void *arg)
 int frsh_init()
 {
        int ret;
+       struct forb_init_attr attr = {
+               .orb_id = "org.frescor.frsh_app"
+       };
        
-       frsh_forb_global.orb = forb_init(NULL, NULL, "frsh");
+       frsh_forb_global.orb = forb_init(NULL, NULL, &attr);
        if (!frsh_forb_global.orb) {
-               if (errno) return errno;
-               else return -1;
+               ret = errno;
+               goto err;
        }
 
        frsh_forb_global.fcb = forb_resolve_reference(frsh_forb_global.orb,
@@ -127,6 +134,11 @@ int frsh_init()
        if (ret) goto err;
 #endif
 
+#ifdef CONFIG_DISKBFQ
+       ret = diskbfq_fra_init();
+       if (ret) goto err;
+#endif
+
 #ifdef FRSH_DISTRIBUTED_MODULE_SUPPORTED
        ret = frsh_distributed_init();
        if (ret) goto err;
@@ -142,6 +154,7 @@ int frsh_init()
        
        return 0;
 err:
+       if (ret == -1) ret = errno;
        return ret;
 }
 
diff --git a/frsh_api/frsh_feedback.c b/frsh_api/frsh_feedback.c
new file mode 100644 (file)
index 0000000..86bfb44
--- /dev/null
@@ -0,0 +1,132 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FRSH (FRescor ScHeduler)                        */
+/*                                                                       */
+/* FRSH is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FRSH is distributed in the hope that it will be       */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty   */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   */
+/* General Public License for more details. You should have received a   */
+/* copy of the GNU General Public License along with FRSH; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FRSH header files in a file,        */
+/* instantiating FRSH generics or templates, or linking other files      */
+/* with FRSH objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   frsh_feedback.c
+ * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ * @date   Wed Feb 20 14:53:22 2009
+ * 
+ * @brief  Feedback module of FRSH_FORB framework
+ * 
+ */
+
+#include <frsh_core.h>
+#include <fra_generic.h>
+#include "frsh_forb.h"
+#include <frsh_resources.h>
+
+#ifdef CONFIG_AQUOSA
+#include <aqcpu_res.h>
+#endif
+#ifdef CONFIG_CPUCG
+#include <cpucg_res.h>
+#endif
+#ifdef CONFIG_DISKBFQ
+#include <diskbfq_res.h>
+#endif
+
+static frsh_vres_id_t spare_vres;
+
+int frsh_feedback_get_spare(frsh_contract_t *spare_contract)
+{
+       return frsh_vres_get_contract(spare_vres, spare_contract);
+}
+
+int frsh_feedback_set_spare
+  (const frsh_contract_t *spare_contract)
+{
+       int ret = 0;
+       frsh_vres_id_t spare_vres;
+
+       if (!spare_contract || !*spare_contract)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       ret = frsh_contract_negotiate(spare_contract, &spare_vres);
+       if (ret) return ret;
+
+
+       if (spare_vres->allocator->set_spare_bandwidth) {
+               ret = spare_vres->allocator->set_spare_bandwidth(spare_vres);
+       } else {
+               ret = FRSH_ERR_NOT_IMPLEMENTED;
+       }
+
+       return ret;
+}
+
+int frsh_feedback_get_desired_budget
+  (frsh_vres_id_t vres_id,
+   frsh_rel_time_t *p_budget_out)
+{
+       if (vres_id->allocator->get_desired_budget) {
+               return vres_id->allocator->get_desired_budget(vres_id, p_budget_out);
+       } else {
+               return FRSH_ERR_NOT_IMPLEMENTED;
+       }
+}
+
+int frsh_feedback_set_desired_budget
+  (frsh_vres_id_t vres_id,
+   frsh_rel_time_t *p_budget_in)
+{
+       if (vres_id->allocator->set_desired_budget) {
+               return vres_id->allocator->set_desired_budget(vres_id, p_budget_in);
+       } else {
+               return FRSH_ERR_NOT_IMPLEMENTED;
+       }
+}
+
+int frsh_feedback_get_actual_budget
+  (frsh_vres_id_t vres_id,
+   frsh_rel_time_t *budget)
+{
+       if (vres_id->allocator->get_actual_budget) {
+               return vres_id->allocator->get_actual_budget(vres_id, budget);
+       } else {
+               return FRSH_ERR_NOT_IMPLEMENTED;
+       }
+}
+
diff --git a/frsh_api/frsh_power.c b/frsh_api/frsh_power.c
new file mode 100644 (file)
index 0000000..ee7ed86
--- /dev/null
@@ -0,0 +1,375 @@
+/**
+ * @file   frsh_power.c
+ * @author Michael Trimarchi <trimarchimichael@yahoo.it>
+ *         Dario Faggioli <faggioli@gandalf.sssup.it>
+ *
+ * @brief  FRSH core thread related functions not implamented in managers..
+ *
+ *
+ */
+
+#include <string.h>
+
+#include <fres_contract.h>
+#include <fres_contract_idl.h>
+#include <fres_blocks.h>
+#include <fcb.h>
+#include <fra_generic.h>
+#include <frsh_forb.h>
+#include "frsh_resources.h"
+#ifdef CONFIG_ACPI_CPU
+#  include <fra_acpi_cpu.h>
+#endif
+#ifdef CONFIG_ACPI_BATTERY
+#  include "fra_acpi_battery.h"
+#endif
+#ifdef CONFIG_ACPI_LCD
+#  include <fra_acpi_lcd.h>
+#endif
+#include <frsh.h>
+
+static inline int __is_a_valid_power(int level)
+{
+       if (level >= 0 && level < 3 )
+               return 1;
+
+       return 0;
+}
+
+static inline
+fres_block_power_management *__dup_power_management(frsh_contract_t *contract)
+{
+       fres_block_power_management *p, *old_p;
+
+       old_p = fres_contract_get_power_management(*contract);
+       p = malloc(sizeof(*p));
+       if (!p) return 0;
+       /**
+        * Needed since frsh_contract_del_xxx frees the
+        *  old block.
+        **/
+       if (old_p)
+               memcpy(p, old_p, sizeof(*old_p));
+       else
+               bzero(p, sizeof(*p));
+
+       return p;
+}
+
+int frsh_contract_set_min_expiration(frsh_contract_t *contract,
+                                    frsh_rel_time_t min_expiration)
+{
+       fres_block_power_management *p;
+       int ret;
+
+       if (!contract || !*contract)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       p = __dup_power_management(contract);
+       if (!p)
+               return ENOMEM;
+
+       p->min_expiration = min_expiration;
+
+       fres_contract_del_power_management(*contract);
+       ret = fres_contract_add_power_management(*contract, p);
+       if (ret) {
+               free(p);
+               return errno;
+       }
+
+       return FRSH_NO_ERROR;
+}
+
+int frsh_contract_get_min_expiration(const frsh_contract_t *contract,
+                                    frsh_rel_time_t *min_expiration)
+{
+       fres_block_power_management *p;
+
+       if (!contract || !*contract)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       p = fres_contract_get_power_management(*contract);
+       if (!p)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       *min_expiration = p->min_expiration;
+
+       return FRSH_NO_ERROR;
+}
+
+int frsh_contract_set_min_budget_pow
+  (frsh_contract_t *contract,
+   frsh_power_level_t power_level,
+   const frsh_rel_time_t *pow_min_budget)
+{
+       fres_block_power_management *b;
+       int ret;
+
+       if (!contract || !*contract ||
+           !pow_min_budget)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       b = __dup_power_management(contract);
+       if (!b)
+               return ENOMEM;
+
+       b->min_budget[power_level] = *pow_min_budget;
+
+       fres_contract_del_power_management(*contract);
+       ret = fres_contract_add_power_management(*contract, b);
+       if (ret) {
+               free(b);
+               return errno;
+       }
+
+       return FRSH_NO_ERROR;
+}
+
+int frsh_contract_get_min_budget_pow
+  (const frsh_contract_t *contract,
+   frsh_power_level_t power_level,
+   frsh_rel_time_t *pow_min_budget)
+{
+       fres_block_power_management *b;
+
+       if (!contract || !*contract ||
+           !__is_a_valid_power(power_level))
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       b = fres_contract_get_power_management(*contract);
+       if (!b)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       *pow_min_budget = b->min_budget[power_level];
+
+       return FRSH_NO_ERROR;
+}
+
+int frsh_contract_set_max_budget_pow
+  (frsh_contract_t *contract,
+   frsh_power_level_t power_level,
+   const frsh_rel_time_t *pow_max_budget)
+{
+       fres_block_power_management *b;
+       int ret;
+
+       if (!contract || !*contract ||
+           !pow_max_budget || !__is_a_valid_power(power_level))
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       b = __dup_power_management(contract);
+       if (!b)
+               return ENOMEM;
+
+       b->max_budget[power_level] = *pow_max_budget;
+
+       fres_contract_del_power_management(*contract);
+       ret = fres_contract_add_power_management(*contract, b);
+       if (ret) {
+               free(b);
+               return errno;
+       }
+
+       return FRSH_NO_ERROR;
+}
+
+int frsh_contract_get_max_budget_pow(const frsh_contract_t *contract,
+                                    frsh_power_level_t power_level,
+                                    frsh_rel_time_t *pow_max_budget)
+{
+       fres_block_power_management *b;
+
+       if (!contract || !*contract ||
+            !__is_a_valid_power(power_level)) {
+                return FRSH_ERR_BAD_ARGUMENT;
+       }
+
+       b = fres_contract_get_power_management(*contract);
+       if (!b)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       *pow_max_budget = b->max_budget[power_level];
+
+       return FRSH_NO_ERROR;
+}
+
+int frsh_contract_set_utilization_pow
+  (frsh_contract_t *contract,
+   frsh_power_level_t power_level,
+   const frsh_rel_time_t *budget,
+   const frsh_rel_time_t *period,
+   const frsh_rel_time_t *deadline)
+{
+       return FRSH_ERR_NOT_IMPLEMENTED;
+}
+
+int frsh_contract_get_utilization_pow
+  (const frsh_contract_t *contract,
+   frsh_power_level_t power_level,
+   frsh_rel_time_t *budget,
+   frsh_rel_time_t *period,
+   frsh_rel_time_t *deadline)
+{
+       return FRSH_ERR_NOT_IMPLEMENTED;;
+}
+
+/* FIXME: What happens when one application set one power-level and
+ * second application different level. I think this function should
+ * not be part of API. It should be used internally (e.g. by contract
+ * broker) to achieve the requirements specified by
+ * frsh_contract_set_min_expiration() and similar functions.
+ *
+ * This implementation also skips FCB when doing changes to resources,
+ * which is certainly not good, because resource manager does not know
+ * about the change.
+ */
+int frsh_resource_set_power_level
+  (frsh_resource_type_t resource_type,
+   frsh_resource_id_t resource_id,
+   frsh_power_level_t power_level)
+{
+
+       if (!__is_a_valid_power(power_level))
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       switch(resource_type)
+       {
+#ifdef CONFIG_ACPI_CPU
+               case FRSH_RT_PROCESSOR:
+               {
+                       int ret;
+                       ret = fra_CPU_power_init(resource_id);
+                       if (ret) return FRSH_ERR_INTERNAL_ERROR;
+                       ret = fra_CPU_set_power(resource_id, power_level);
+                       if (ret) return FRSH_ERR_INTERNAL_ERROR;
+
+                       /**
+                        * @TODO:
+                        * if (i budget sono effettivamente diversi)
+                        *      rinegozia i contratti coi nuovi valori
+                        **/
+                       break;
+               }
+#endif
+#ifdef CONFIG_ACPI_LCD
+               case FRSH_RT_LCD:
+               {
+                       int ret;
+                       ret = fra_LCD_power_init(resource_id);
+                       if (ret) return FRSH_ERR_INTERNAL_ERROR;
+                       ret = fra_LCD_set_power(resource_id, power_level);
+                       if (ret) return FRSH_ERR_INTERNAL_ERROR;
+                       break;
+               }
+#endif
+               default:
+                       return FRSH_ERR_NOT_IMPLEMENTED;
+       }
+
+       return FRSH_NO_ERROR;
+}
+
+int frsh_resource_get_power_level
+  (frsh_resource_type_t resource_type,
+   frsh_resource_id_t resource_id,
+   frsh_power_level_t *power_level)
+{
+       switch(resource_type)
+       {
+#ifdef CONFIG_ACPI_CPU
+               case FRSH_RT_PROCESSOR:
+               {
+                       int ret;
+                       ret = fra_CPU_get_power(resource_id,
+                                               (int*) power_level);
+                       if (ret) return FRSH_ERR_INTERNAL_ERROR;
+
+                       break;
+               }
+#endif
+#ifdef CONFIG_ACPI_LCD
+               case FRSH_RT_LCD:
+               {
+                       int ret;
+                       ret = fra_LCD_get_power(resource_id,
+                                               (int*) power_level);
+                       if (ret) return FRSH_ERR_INTERNAL_ERROR;
+
+                       break;
+               }
+#endif
+               default:
+                       return FRSH_ERR_NOT_IMPLEMENTED;
+       }
+
+       return FRSH_NO_ERROR;
+}
+
+int frsh_resource_get_num_power_levels
+  (frsh_resource_type_t resource_type,
+   frsh_resource_id_t resource_id,
+   int *num_power_levels)
+{
+       int ret;
+
+       *num_power_levels = 1;
+
+       switch(resource_type)
+       {
+               case FRSH_RT_PROCESSOR:
+               {
+                       ret = fra_CPU_power_init(resource_id);
+                       if (ret) goto out;
+
+                       break;
+               }
+               case FRSH_RT_LCD:
+               {
+                       ret = fra_LCD_power_init(resource_id);
+                       if (ret) goto out;
+
+                       break;
+               }
+               default:
+                       return FRSH_ERR_NOT_IMPLEMENTED;
+       }
+
+       /**
+        * @FIXME:
+        *   This looks tremendous... But the number '3' is hardcoded
+        *   whereever in the headers as the number of power level, so...
+        */
+       *num_power_levels = 3;
+
+out:
+       return FRSH_NO_ERROR;
+}
+
+int frsh_battery_get_expiration(frsh_abs_time_t *expiration)
+{
+#ifdef CONFIG_ACPI_BATTERY
+       frsh_rel_time_t interval;
+       int ret;
+
+       ret = fra_battery_init();
+       if (ret) return FRSH_ERR_INTERNAL_ERROR;
+
+       ret = fra_battery_expiration(&interval);
+       if (ret == EAGAIN) {
+               *expiration = fosa_msec_to_abs_time(0);
+               goto out;
+       }
+       if (ret)
+               return FRSH_ERR_INTERNAL_ERROR;
+
+       fosa_clock_get_time(FOSA_CLOCK_REALTIME, expiration);
+       *expiration = fosa_abs_time_incr(*expiration, interval);
+
+out:
+       return FRSH_NO_ERROR;
+#else
+       return FRSH_ERR_NOT_IMPLEMENTED;        
+#endif
+}
+
index f86d7b7932e280c59ca955d794239d41e9924bfb..5806c7c3b0bf018d70395eda5e29ee6b40b42ddd 100644 (file)
@@ -47,6 +47,7 @@
 /**
  * @file   frsh_spare_capacity.c
  * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
  * 
  * @brief  Implementation of FRSH contract API on top of FRES contracts.
  * 
@@ -88,20 +89,65 @@ int frsh_contract_set_reclamation_params
            (granularity == FRSH_GR_DISCRETE && utilization_set == NULL))
                return FRSH_ERR_BAD_ARGUMENT;
 
-       if (granularity != FRSH_GR_CONTINUOUS)
+       if (granularity != FRSH_GR_CONTINUOUS &&
+           granularity != FRSH_GR_DISCRETE)
                return FRSH_ERR_NOT_IMPLEMENTED;
 
        s = malloc(sizeof(*s));
        if (!s) return ENOMEM; 
+       memset(s, 0, sizeof(*s));
 
        s->budget = *budget_max;
        s->period = *period_min;
        s->granularity = granularity;
-       /*
-        * TODO:
-        *  support utilization-set for discrete spare
-        *  capacity distribution.
-        */
+
+       if (utilization_set) {
+               int i;
+               forb_sequence_alloc_buf(s->variants, utilization_set->size);
+               for (i=0; i<utilization_set->size; i++) {
+                       struct fres_container *c = NULL;
+                       fres_block_basic *b = NULL;
+                       fres_block_timing_reqs *t = NULL;
+                       c = fres_container_new();
+                       if (!c)
+                               goto err;
+                       b = malloc(sizeof(*b));
+                       if (!b)
+                               goto err_ut;
+                       t = malloc(sizeof(*t));
+                       if (!t)
+                               goto err_ut;
+
+                       b->budget = utilization_set->utilizations[i].budget;
+                       b->period = utilization_set->utilizations[i].period;
+                       /* FIXME: workload and contract type should be
+                        * the same as in basic_params. The easyest
+                        * solution would be to split basic block to
+                        * two blocks - (budget, period) and
+                        * (workload, contract_type).
+                        * Note: frsh_contract_set_reclamation_params()
+                        * should be defined differently. */
+                       b->workload = FRSH_WT_BOUNDED;
+                       b->contract_type = FRSH_CT_REGULAR;
+                       ret = fres_container_add_basic(c, b);
+
+                       t->d_equals_t = true; /* FIXME: the same as above */
+                       t->deadline = utilization_set->utilizations[i].deadline;
+
+                       ret = fres_container_add_timing_reqs(c, t);
+
+                       forb_sequence_elem(s->variants, i) = c;
+                       continue;
+               err_ut:
+                       fres_container_destroy(c);
+                       free(b); /* FIXME: Possible double free */
+                       free(t);
+                       goto err;
+               }
+               s->variants._length = utilization_set->size;
+       }
+       /* TODO: In case of CONTINUOUS granularity copy min and max
+        * requirements to the variants. */
        s->importance = importance;
        s->weight = weight;
        s->stability_time = *stability_time;
@@ -109,12 +155,14 @@ int frsh_contract_set_reclamation_params
        fres_contract_del_spare_capacity(*contract);
        ret = fres_contract_add_spare_capacity(*contract, s);
 
-       if (ret) {
-               free(s);
-               return errno;
-       }
+       if (ret)
+               goto err;
 
        return FRSH_NO_ERROR;
+err:
+       forb_sequence_free_buf(s->variants, forb_no_destructor);
+       free(s);
+       return errno;
 }
 
 int frsh_contract_get_reclamation_params
index 7822e487be9e6c796989e636a6ffac014c1a52ed..800e336d967827e7a337db6e9a97effd3e2251de 100644 (file)
@@ -94,7 +94,7 @@ int frsh_synchobj_wait
        fres_thread_vres_t *th_vres;
        int ret = 0;
 
-       th_vres = fra_get_thread_vres(&thread);
+       th_vres = fra_get_thread_vres(&thread, FRSH_RT_PROCESSOR);
        if (!th_vres) goto out;
 
        __frsh_synchobj_check_wcet_and_deadline(thread,
@@ -127,7 +127,7 @@ int frsh_synchobj_wait_with_timeout
        fres_thread_vres_t *th_vres;
        int ret = 0;
 
-       th_vres = fra_get_thread_vres(&thread);
+       th_vres = fra_get_thread_vres(&thread, FRSH_RT_PROCESSOR);
        if (!th_vres) goto out;
 
        __frsh_synchobj_check_wcet_and_deadline(thread,
@@ -164,7 +164,7 @@ int frsh_timed_wait
        fres_thread_vres_t *th_vres;
        int ret = 0;
 
-       th_vres = fra_get_thread_vres(&thread);
+       th_vres = fra_get_thread_vres(&thread, FRSH_RT_PROCESSOR);
        if (!th_vres) goto out;
 
        __frsh_synchobj_check_wcet_and_deadline(thread,
@@ -185,16 +185,18 @@ out:
        return ret;
 }
 
-int frsh_vresperiod_wait(unsigned long period_num,
-                         frsh_rel_time_t       *next_budget,
-                         frsh_rel_time_t       *next_period,
-                         bool                  *was_deadline_missed,
-                         bool                  *was_budget_overran)
+int frsh_vresperiod_wait
+  (unsigned long period_num,
+   frsh_rel_time_t       *next_budget,
+   frsh_rel_time_t       *next_period,
+   bool                  *was_deadline_missed,
+   bool                  *was_budget_overran)
 {
        return FRSH_ERR_NOT_IMPLEMENTED;
 }
 
 int frsh_get_period_number(const frsh_vres_id_t vres, long *period_num)
+
 {
        return FRSH_ERR_NOT_IMPLEMENTED;
 }
index 24605e52d82eee0b1223fc0fc2bccdee255d40fd..5fa687c38e2ea753d963901ae5db6fc977187dcd 100644 (file)
@@ -6,6 +6,8 @@
  *
  *
  */
+#include <semaphore.h>
+
 #include <fres_contract.h>
 #include <fres_contract_idl.h>
 #include <frsh_core.h>
 #include <fres_blocks.h>
 #include <string.h>
 #include <fcb.h>
-#include "frsh_forb.h"
 #include <fra_generic.h>
 
+#include "frsh_forb.h"
+
+#ifdef CONFIG_AQUOSA
+#include <aqcpu_res.h>
+#endif
+#ifdef CONFIG_CPUCG
+#include <cpucg_res.h>
+#endif
+#ifdef CONFIG_DISKBFQ
+#include <diskbfq_res.h>
+#endif
+
+/**
+ * frsh_thread_bind(), bind a thread to a vres
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_BAD_ARGUMENT(*) (invalid or dummy vres)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  FRSH_ERR_ALREADY_BOUND(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ */
+int frsh_thread_bind
+  (const frsh_vres_id_t vres,
+   const frsh_thread_id_t thread)
+{
+       int ret;
+       ret = fra_insert_thread_vres(&thread, vres->allocator->res_type, vres);
+       if (ret) goto err;
+       
+       if (vres->allocator->bind_thread) {
+               ret = vres->allocator->bind_thread(vres, thread);
+       } else {
+               ret = FRSH_ERR_NOT_IMPLEMENTED;
+       }
+       if (ret) goto err_delete;
+
+       return FRSH_NO_ERROR;
+
+err_delete:
+       fra_delete_thread_vres(&thread, vres->allocator->res_type);
+err:
+       return FRSH_ERR_INTERNAL_ERROR;
+}
+
+/*
+ * frsh_thread_unbind(), unbind a thread from a vres
+ *
+ * @FIXME:
+ *  Notice that, since we don't know from which VRES the
+ *   thread should be unbound, we unboind it from all the
+ *   ones it is attached to!
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_BAD_ARGUMENT(*) (invalid thread)
+ *  FRSH_ERR_NOT_BOUND(*)
+ *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ */
+int frsh_thread_unbind(const frsh_thread_id_t thread)
+{
+       fres_vres_t *vres;
+       int ret;
+
+       /* Unbound from FRSH_RT_PROCESSOR resource (if any) */
+       vres = fra_get_vres_thread_vres(&thread, FRSH_RT_PROCESSOR);
+       if (vres) {
+               if (vres->allocator->unbind_thread) {
+                       ret = vres->allocator->unbind_thread(thread);
+               } else {
+                       ret = FRSH_ERR_NOT_IMPLEMENTED;
+               }
+               if (ret) goto err;
+
+               ret = fra_delete_thread_vres(&thread, vres->allocator->res_type);
+               if (ret) goto err;
+       }
+
+       /* Unbound from FRSH_RT_DISK resource (if any) */
+       vres = fra_get_vres_thread_vres(&thread, FRSH_RT_DISK);
+       if (vres) {
+               if (vres->allocator->unbind_thread) {
+                       ret = vres->allocator->unbind_thread(thread);
+               } else {
+                       ret = FRSH_ERR_NOT_IMPLEMENTED;
+               }
+               if (ret) goto err;
+
+               ret = fra_delete_thread_vres(&thread, vres->allocator->res_type);
+               if (ret) goto err;
+       }
+
+       return FRSH_NO_ERROR;
+err:
+       return FRSH_ERR_INTERNAL_ERROR;
+}
+
+/**
+ * structure used to pass the new created thread (or better its wrapper) the
+ * arguments it needs to bind itself to the vres.
+ */
+typedef struct wrapper_pthread_arg {
+       frsh_thread_id_t parent_thread_id;
+       frsh_thread_id_t *thread_id;
+       frsh_thread_code_t pthread_code;        /**< function to be running in thread */
+       void *pthread_arg;                      /**< thread arguments*/
+       frsh_vres_id_t vres;
+       sem_t *stopper;                         /**< semaphore to synchronize frsh call and wrapper thread */
+       int  errcode;
+} wrapper_pthread_arg_t;
+
+/*
+ * typedef struct {
+ *     pthread_t pthread_id;
+ *     pid_t linux_pid;
+ *     pid_t linux_tid;
+ * } FOSA_THREAD_ID_T_OPAQUE;
+ */
+
+/**
+ * Wrapper thread
+ * 
+ * possible exit status:
+ *  FRSH_ERR_INTENRAL_ERROR (something wrong with threads and signal handling)
+ *  FRSH_ERR_TOO_MANY_TASKS(*)
+ *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
+ *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
+ *  whatever the user provided code 'pthread_code' returns
+ */
+static void* wrapper_pthread(void *arg)
+{
+       wrapper_pthread_arg_t* pth = (wrapper_pthread_arg_t*) arg;
+       frsh_thread_id_t* thread_id = pth->thread_id;
+       void *thread_arg = pth->pthread_arg;
+       frsh_thread_code_t thread_code = pth->pthread_code;
+
+       /* bind this thread to vres */
+       *thread_id = fosa_thread_self();
+       pth->errcode = frsh_thread_bind(pth->vres, *thread_id);
+
+       sem_post(pth->stopper);
+       /* No access to pth is allowed after this point, it can vanish already */
+
+       if (pth->errcode) return NULL;
+
+       /* execute thread code */
+       return thread_code(thread_arg);
+}
+
+/*
+ * API call for 'frsh_thread_create_and_bind()', as said prepares the
+ * wrapper code argument data structure, create the new thread and wait
+ * its acknowledgment before stepping over
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_NOT_INITIALIZED
+ *  FRSH_ERR_BAD_ARGUMENT (NULL thread or thread_code)
+ *  whatever 'fosa_thread_create()' returns
+ *  FRSH_ERR_INTERNAL_ERROR 
+ */
+int frsh_thread_create_and_bind
+  (const frsh_vres_id_t vres,
+   frsh_thread_id_t *thread,
+   frsh_thread_attr_t *attr,
+   frsh_thread_code_t thread_code,
+   void *arg)
+{
+       wrapper_pthread_arg_t wp_arg;
+       sem_t stopper;
+       int ret;
+
+       sem_init(&stopper, 0, 0);
+
+       if (!thread || !thread_code || !attr)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       wp_arg.parent_thread_id = fosa_thread_self();
+       wp_arg.thread_id = thread;
+       wp_arg.pthread_code = thread_code;
+       wp_arg.pthread_arg = arg;
+       wp_arg.vres = vres;
+       wp_arg.stopper = &stopper;
+
+       /* create the wrapper thread */
+       pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
+       pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM);
+       ret = fosa_thread_create(thread, attr, wrapper_pthread,
+                               (void*)&wp_arg);
+
+       if (ret != 0)
+               return(ret);
+
+       sem_wait(&stopper);
+
+       return (wp_arg.errcode);
+}
+
 int frsh_thread_create_in_background
   (frsh_thread_code_t thread_code,
    const void *thread_arg,
@@ -26,7 +227,7 @@ int frsh_thread_create_in_background
 {
        frsh_contract_t contract;
        fosa_rel_time_t zero_msec = fosa_msec_to_rel_time(0);
-       int rv = 0;
+       int ret = 0;
 
        /* Background contract creation and negotiation */
        frsh_contract_init(&contract);
@@ -41,15 +242,18 @@ int frsh_thread_create_in_background
                                       FRSH_CT_BACKGROUND);
 
        /* It will be accepted: we are asking for 0 budget over 0 period */
-       rv = frsh_contract_negotiate(&contract, vres_id);
-       if (rv !=0) goto error;
+       ret = frsh_contract_negotiate(&contract, vres_id);
+       if (ret !=0) goto error;
+
+       ret = fosa_thread_create(thread, attr, thread_code, (void*) thread_arg);
+       if (ret != 0) goto error;
 
-       rv = fosa_thread_create(thread, attr, thread_code, (void*) thread_arg);
-       if (rv != 0) goto error;
+       ret = fra_insert_thread_vres(thread, FRSH_RT_PROCESSOR, *vres_id);
+       if (ret) goto error;
 
        return 0;
 error:
-       return rv;
+       return ret;
 }
 
 int frsh_thread_get_vres_id
@@ -59,7 +263,12 @@ int frsh_thread_get_vres_id
        if (!vres_id)
                return FRSH_ERR_BAD_ARGUMENT;
 
-       *vres_id = fra_get_vres_thread_vres(&thread);
+       /*
+        * @FIXME:
+        *  Why PROCESSOR and not DISK or NETWORK (or whatever) ??
+        */
+       *vres_id = fra_get_vres_thread_vres(&thread,
+                                           FRSH_RT_PROCESSOR);
 
        return vres_id ? 0 : EINVAL;
 }
index 1389a8370937939eef90d8271b9a7482aaacad7c..0e56d23b0de90c126d897b75cec98a5141384d28 100644 (file)
 
 #include <frsh_core.h>
 #include <fra_generic.h>
-#include "frsh_forb.h"
 #include <frsh_resources.h>
 
+#include "frsh_forb.h"
+
+#ifdef CONFIG_AQUOSA
+#include <aqcpu_res.h>
+#endif
+#ifdef CONFIG_CPUCG
+#include <cpucg_res.h>
+#endif
+#ifdef CONFIG_DISKBFQ
+#include <diskbfq_res.h>
+#endif
+
 int frsh_vres_get_priority
   (frsh_vres_id_t vres_id,
    int *priority)
@@ -84,7 +95,29 @@ int frsh_resource_get_vres_from_label
    const frsh_resource_id_t resource_id,
    frsh_vres_id_t *vres)
 {
-       return FRSH_ERR_NOT_IMPLEMENTED;
+       fres_block_resource *r;
+       fres_block_label *label;
+
+       if (!contract_label || !vres) {
+               return FRSH_ERR_BAD_ARGUMENT;
+       }
+       r = malloc(sizeof(*r));
+       if (!r) return ENOMEM;
+       r->resource_type = resource_type;
+       r->resource_id = resource_id;
+
+       label = malloc(sizeof(*label));
+       if (!label) {
+               free(r);
+               return ENOMEM;
+       }
+       strncpy(label->label, contract_label, sizeof(label->label));
+       label->label[sizeof(label->label)-1] = '\0';
+
+       *vres = fres_vreses_find_label(label, r);
+       if (*vres) return FRSH_NO_ERROR;
+
+       return FRSH_ERR_CONTRACT_LABEL_UNKNOWN;
 }
 
 int frsh_vres_get_renegotiation_status
@@ -123,3 +156,45 @@ int frsh_vres_get_budget_and_period
        return 0;
 }
 
+int frsh_vres_get_usage
+  (const frsh_vres_id_t vres,
+   frsh_rel_time_t *spent)
+{
+       if (!vres || !spent) {
+               return FRSH_ERR_BAD_ARGUMENT;
+       }
+       if (vres->allocator->vres_get_usage) {
+               return vres->allocator->vres_get_usage(vres, spent);
+       } else {
+               return FRSH_ERR_NOT_IMPLEMENTED;
+       }
+}
+
+int frsh_vres_get_job_usage
+  (const frsh_vres_id_t vres,
+   frsh_rel_time_t *spent)
+{
+       if (!vres || !spent) {
+               return FRSH_ERR_BAD_ARGUMENT;
+       }
+       if (vres->allocator->vres_get_job_usage) {
+               return vres->allocator->vres_get_job_usage(vres, spent);
+       } else {
+               return FRSH_ERR_NOT_IMPLEMENTED;
+       }
+}
+
+int frsh_vres_get_remaining_budget
+  (const frsh_vres_id_t vres,
+   frsh_rel_time_t *budget)
+{
+       if (!vres || !budget) {
+               return FRSH_ERR_BAD_ARGUMENT;
+       }
+       if (vres->allocator->vres_get_remaining_budget) {
+               return vres->allocator->vres_get_remaining_budget(vres, budget);
+       } else {
+               return FRSH_ERR_NOT_IMPLEMENTED;
+       }
+}
+
index b7829674bb9047e24e6aef4ebe775d76e1ba64b9..b864abbf24eede22b05fa3a6d7df86bd74576fba 100644 (file)
@@ -2,6 +2,9 @@
 test_PROGRAMS += negotiation
 negotiation_SOURCES = negotiation.c
 
+test_PROGRAMS += spare_capacity
+spare_capacity_SOURCES = spare_capacity.c
+
 test_PROGRAMS += negobench
 negobench_SOURCES = negobench.c
 
diff --git a/frsh_api/tests/spare_capacity.c b/frsh_api/tests/spare_capacity.c
new file mode 100644 (file)
index 0000000..ddfe204
--- /dev/null
@@ -0,0 +1,104 @@
+#include <frsh.h>
+#include <error.h>
+#include <res_dummy.h>
+
+#define NUM_CONTRACTS 3
+#define NUM_VARIANTS 3
+
+#define MSEC(x) fosa_msec_to_rel_time(x)
+
+struct contract_data {
+       fosa_rel_time_t stability_time;
+       int importance;
+       int weight;
+       frsh_utilization_t variants[NUM_VARIANTS];
+};
+
+int main(int argc, char *argv[])
+{
+       struct contract_data d[NUM_CONTRACTS] = {
+               { /* Contract 1 */
+                       .stability_time = MSEC(0), .importance = 0, .weight = 1,
+                       .variants = {
+                               { .budget = MSEC(10),  .period = MSEC(100),  .deadline = MSEC(100) },
+                               { .budget = MSEC(20),  .period = MSEC(100),  .deadline = MSEC(100) },
+                               { .budget = MSEC(30),  .period = MSEC(100),  .deadline = MSEC(100) },
+                       }
+               },
+               { /* Contract 2 */
+                       .stability_time = MSEC(1000), .importance = 0, .weight = 1,
+                       .variants = {
+                               { .budget = MSEC(30),  .period = MSEC(100),  .deadline = MSEC(100) },
+                               { .budget = MSEC(30),  .period = MSEC( 80),  .deadline = MSEC( 80) },
+                               { .budget = MSEC(30),  .period = MSEC( 60),  .deadline = MSEC( 60) },
+                       }
+               },
+               { /* Contract 3 */
+                       .stability_time = MSEC(10*1000), .importance = 0, .weight = 1,
+                       .variants = {
+                               { .budget = MSEC(10),  .period = MSEC(100),  .deadline = MSEC(50) },
+                               { .budget = MSEC(20),  .period = MSEC( 80),  .deadline = MSEC(40) },
+                               { .budget = MSEC(30),  .period = MSEC( 60),  .deadline = MSEC(30) },
+                       }
+               },
+       };
+       int ret;
+       frsh_contract_t contract[NUM_CONTRACTS];
+       frsh_vres_id_t vres[NUM_CONTRACTS];
+       frsh_signal_info_t si;
+       int i, j;
+
+       ret = frsh_init();
+       if (ret) PERROR_AND_EXIT(ret, "frsh_init");
+
+       /* Negotiate contracts */
+       for (i=0; i<NUM_CONTRACTS; i++) {
+               ret = frsh_contract_init(&contract[i]);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_contract_init");
+
+               ret = frsh_contract_set_resource_and_label(
+                       &contract[i],
+                       DUMMY_RESOURCE_TYPE, DUMMY_RESOURCE_ID,
+                       NULL);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_resource_and_label");
+
+               ret = frsh_contract_set_basic_params(&contract[i],
+                                                    &d[i].variants[0].budget,
+                                                    &d[i].variants[0].period,
+                                                    FRSH_WT_BOUNDED,
+                                                    FRSH_CT_REGULAR);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_basic_params");
+
+               ret = frsh_contract_set_timing_reqs(&contract[i], false, &d[i].variants[0].deadline,
+                                           0, si, 0, si);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_timing_reqs");
+
+               frsh_utilization_set_t utilization_set = { .size = NUM_VARIANTS };
+               for (j=0; j<NUM_VARIANTS; j++)
+                       utilization_set.utilizations[j] = d[i].variants[j];
+               ret = frsh_contract_set_reclamation_params(&contract[i],
+                                                          &d[i].stability_time,
+                                                          &d[i].variants[NUM_VARIANTS-1].budget,
+                                                          &d[i].variants[NUM_VARIANTS-1].period,
+                                                          FRSH_GR_DISCRETE,
+                                                          &utilization_set,
+                                                          d[i].importance,
+                                                          d[i].weight);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_reclamation_params");
+
+               char s[1000];
+               memset(s, 0, sizeof(s));
+               fres_contract_to_string(s, sizeof(s), contract[i]);
+               puts(s);
+
+               ret = frsh_contract_negotiate(&contract[i], &vres[i]);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_contract_negotiate");
+       }
+
+       /* Cancel contracts */
+       for (i=0; i<NUM_CONTRACTS; i++) {
+               ret = frsh_contract_cancel(vres[i]);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_contract_cancel");
+       }
+       return 0;
+}
diff --git a/resources/acpi_battery/Makefile b/resources/acpi_battery/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
+
diff --git a/resources/acpi_battery/Makefile.omk b/resources/acpi_battery/Makefile.omk
new file mode 100644 (file)
index 0000000..4e8cd4b
--- /dev/null
@@ -0,0 +1,12 @@
+default_CONFIG = CONFIG_ACPI_BATTERY=y
+
+ifeq ($(CONFIG_ACPI_BATTERY),y)
+shared_LIBRARIES = acpi_battery
+
+acpi_battery_SOURCES = fra_acpi_battery.c
+acpi_battery_LIBS += fosa rt acpi
+
+include_HEADERS = fra_acpi_battery.h
+
+SUBDIRS=tests
+endif
diff --git a/resources/acpi_battery/fra_acpi_battery.c b/resources/acpi_battery/fra_acpi_battery.c
new file mode 100644 (file)
index 0000000..01c983d
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * @file   fres_acpi_cpu.c
+ * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ *        Michael Trimarchi <trimarchimichael@yahoo.it>
+ * 
+ * @brief  Implementation of shared CPU related ACPI functions.
+ * 
+ */
+
+#include "fra_acpi_battery.h"
+
+static global_t acpi_globals;
+
+static int which_batt;
+static battery_t *battery;
+
+static int battery_initialized = 0;
+
+int fra_battery_init()
+{
+       if (battery_initialized == 1) return 0;
+
+       init_acpi_batt(&acpi_globals);
+       init_acpi_acadapt(&acpi_globals);
+
+       battery_initialized = 1;
+
+       return 0;
+}
+
+int fra_battery_expiration(fosa_rel_time_t *expiration)
+{
+       int i, ret;
+       long rmng_msec;
+
+       if (!battery_initialized) return EINVAL;
+
+       read_acpi_acstate(&acpi_globals);
+       if (acpi_globals.adapt.ac_state != P_BATT)
+               return EAGAIN;
+
+       rmng_msec = 0;
+       for (i = 0; i < acpi_globals.batt_count; i++) {
+               ret = read_acpi_batt(i);
+               if (ret == SUCCESS) {
+                       rmng_msec +=
+                               (long) batteries[i].remaining_time * 60000;
+               }
+       }
+
+       *expiration  = fosa_msec_to_rel_time(rmng_msec);
+
+       return 0;
+}
+
diff --git a/resources/acpi_battery/fra_acpi_battery.h b/resources/acpi_battery/fra_acpi_battery.h
new file mode 100644 (file)
index 0000000..1cde0e1
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef ACPI_BATTERY
+#define ACPI_BATTERY
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <string.h>
+#include <libacpi.h>
+
+#include <fosa.h>
+
+int fra_battery_init();
+
+int fra_battery_expiration(fosa_abs_time_t *expiration);
+
+#endif
+
diff --git a/resources/acpi_battery/tests/Makefile b/resources/acpi_battery/tests/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
+
diff --git a/resources/acpi_battery/tests/Makefile.omk b/resources/acpi_battery/tests/Makefile.omk
new file mode 100644 (file)
index 0000000..ccd7cf1
--- /dev/null
@@ -0,0 +1,5 @@
+test_PROGRAMS = acpi_battery_test
+acpi_battery_test_SOURCES = acpi_battery_test.c
+LOADLIBES += -L $(AQUOSA_ROOT)/lib -lqreslib -lqsuplib
+#aqcpumngr_LIBS = frm forb contract fosa rt ulut fcb_client
+lib_LOADLIBES += pthread rt frsh qreslib
diff --git a/resources/acpi_battery/tests/acpi_battery_test.c b/resources/acpi_battery/tests/acpi_battery_test.c
new file mode 100644 (file)
index 0000000..09c84df
--- /dev/null
@@ -0,0 +1,93 @@
+#include <frsh.h>
+#include <aqcpu_res.h>
+#include <error.h>
+
+int main()
+{
+       int ret;
+       frsh_vres_id_t vres;
+       frsh_contract_t contract;
+       frsh_rel_time_t budget, period;
+       frsh_rel_time_t duration, expiration;
+       unsigned long long duration_msec = 10000;
+
+       if (frsh_init())
+               error(1, 0, "FRSH initialization failed\n");
+       
+       /* Contract negotiation for CPU */
+       ret = frsh_contract_init(&contract);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_init");
+               
+       budget = fosa_msec_to_rel_time(10);
+       period = fosa_msec_to_rel_time(100);
+       ret = frsh_contract_set_basic_params(&contract,
+                                            &budget,
+                                            &period,
+                                            FRSH_WT_BOUNDED,
+                                            FRSH_CT_REGULAR);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_basic_params");
+
+       ret = frsh_contract_set_resource_and_label(&contract, FRSH_RT_PROCESSOR,
+                                                       0,"TEST_VRES");
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_resource_and_label");
+
+       ret = frsh_contract_set_min_budget_pow(&contract, FRSH_PLT_HIGH, &budget);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_min_budget_pow (FRSH_PLT_HIGH)");
+
+       ret = frsh_contract_set_min_budget_pow(&contract, FRSH_PLT_MEDIUM, &budget);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_min_budget_pow (FRSH_PLT_MEDIUM)");
+
+       ret = frsh_contract_set_min_budget_pow(&contract, FRSH_PLT_LOW, &budget);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_min_budget_pow (FRSH_PLT_LOW)");
+
+       duration = fosa_msec_to_rel_time(duration_msec);
+       ret = frsh_contract_set_min_expiration(&contract, duration);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_min_expiration");
+
+       ret = frsh_contract_get_min_expiration(&contract, &duration);
+       if (ret || fosa_rel_time_to_msec(duration) != duration_msec)
+               PERROR_AND_EXIT(ret, "frsh_contract_get_min_expiration");
+       printf("Minimum duration correctly set to: %lu\n", fosa_rel_time_to_msec(duration));
+
+       ret = frsh_contract_negotiate(&contract, &vres);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_negotiate");
+       printf("Aqcpu vres negotiated, vres-ID: %d\n", (int) vres);
+
+       while (1) {
+               duration_msec += duration_msec;
+               duration = fosa_msec_to_rel_time(duration_msec);
+
+               ret = frsh_contract_set_min_expiration(&contract, duration);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_min_expiration");
+
+               ret = frsh_contract_get_min_expiration(&contract, &duration);
+               if (ret || fosa_rel_time_to_msec(duration) != duration_msec) {
+                       //PERROR_AND_EXIT(ret, "frsh_contract_get_duration");
+                       printf("%lu %lu\n", fosa_rel_time_to_msec(duration), duration_msec);
+                       break;
+               }
+               printf("Minimum duration correctly set to: %lu\n",
+                      fosa_rel_time_to_msec(duration));
+
+               ret = frsh_battery_get_expiration(&expiration);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_battery_get_expiration");
+
+               ret = frsh_contract_renegotiate_sync(&contract, vres);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_contract_renegotiate_sync");
+
+               printf("Contract with minimum expiration %lu renegotiated."
+                      "System expiration time: %lu\n",
+                      fosa_rel_time_to_msec(duration),
+                      fosa_abs_time_to_msec(expiration));
+
+               sleep(3);
+       }
+
+       ret = frsh_contract_cancel(vres);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_cancel");
+
+       printf("Test PASSED!\n");
+               
+       return 0;       
+}
+
diff --git a/resources/acpi_battery/tests/config.omk b/resources/acpi_battery/tests/config.omk
new file mode 100644 (file)
index 0000000..906e662
--- /dev/null
@@ -0,0 +1,7 @@
+CONFIG_AQUOSA=y
+CFLAGS+=-save-temps
+CONFIG_FWP=n
+CONFIG_RESOURCE_DUMMY=n
+CONFIG_RESOURCE_ITEM=n
+CONFIG_RESOURCE_CLUSTER_TREE=n
+
diff --git a/resources/acpi_cpu/Makefile b/resources/acpi_cpu/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
+
diff --git a/resources/acpi_cpu/Makefile.omk b/resources/acpi_cpu/Makefile.omk
new file mode 100644 (file)
index 0000000..cbea2a4
--- /dev/null
@@ -0,0 +1,13 @@
+default_CONFIG = CONFIG_ACPI_CPU=y
+
+ifeq ($(CONFIG_ACPI_CPU),y)
+shared_LIBRARIES = acpi_cpu
+
+acpi_cpu_SOURCES = fra_acpi_cpu.c
+acpi_cpu_LIBS += fosa rt m cpufreq
+
+include_HEADERS = fra_acpi_cpu.h
+
+SUBDIRS=tests
+
+endif
diff --git a/resources/acpi_cpu/fra_acpi_cpu.c b/resources/acpi_cpu/fra_acpi_cpu.c
new file mode 100644 (file)
index 0000000..b7bc9bb
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * @file   fres_acpi_cpu.c
+ * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ *        Michael Trimarchi <trimarchimichael@yahoo.it>
+ * 
+ * @brief  Implementation of shared CPU related ACPI functions.
+ * 
+ */
+
+#include "fra_acpi_cpu.h"
+
+static int frequency_initialized = 0;
+
+static unsigned long freqs[3];
+
+int fra_CPU_power_init(int cpu)
+{
+       int ret;
+       int i, j, freq_num = 0;
+       struct cpufreq_available_governors *governors, *g;
+       struct cpufreq_available_frequencies *frequencies, *f;
+
+       if (frequency_initialized == 1) return 0;
+
+       ret = cpufreq_cpu_exists(cpu);
+       if (ret) return EINVAL;
+
+       governors = cpufreq_get_available_governors(cpu);
+       if (!governors) return EINVAL;
+       for (g = governors; g != NULL; g = g->next)
+               if (strncmp("userspace", g->governor, sizeof(*g->governor)) == 0)
+                       break;
+       cpufreq_put_available_governors(governors);
+
+       if (g == NULL) return EINVAL;
+
+       ret = cpufreq_modify_policy_governor(cpu, "userspace");
+       if (ret) return EPERM;
+
+
+       frequencies = cpufreq_get_available_frequencies(cpu);
+       if (!frequencies) return EINVAL;
+       for (f = frequencies; f; f = f->next, freq_num++)
+               ;
+
+       f = frequencies;
+       i = j = 0;
+       while (f) {
+               if (i == 0 ||
+                   i == ((int)ceil((double)freq_num / 2.0f)) ||
+                   i == freq_num - 1) {
+                       freqs[j] = f->frequency;
+                       j++;
+               }
+               i++;
+               f = f->next;
+       }
+       cpufreq_put_available_frequencies(frequencies);
+
+       frequency_initialized = 1;
+
+       return 0;
+}
+
+int fra_CPU_get_power(int cpu, int *level)
+{
+       unsigned long freq;
+       int i;
+
+       if (!frequency_initialized) return EINVAL;
+
+       freq = cpufreq_get(cpu);
+       for (i = 0; i < 3; i++)
+               if (freqs[i] == freq) {
+                       *level = i;
+                       return 0;
+               }
+
+       return EINVAL;
+}
+
+int fra_CPU_set_power(int cpu, int level)
+{
+       if (!frequency_initialized ||
+           level >= 3)
+               return EINVAL;
+
+       return cpufreq_set_frequency(cpu, freqs[level]);
+}
+
diff --git a/resources/acpi_cpu/fra_acpi_cpu.h b/resources/acpi_cpu/fra_acpi_cpu.h
new file mode 100644 (file)
index 0000000..4264455
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef ACPI_CPU
+#define ACPI_CPU
+
+#include <string.h>
+#include <math.h>
+#include <cpufreq.h>
+
+#include <fosa.h>
+
+int fra_CPU_power_init(int cpu);
+
+int fra_CPU_get_power(int cpu, int *level);
+
+int fra_CPU_set_power(int cpu, int level);
+
+#endif
+
diff --git a/resources/acpi_cpu/tests/Makefile b/resources/acpi_cpu/tests/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
+
diff --git a/resources/acpi_cpu/tests/Makefile.omk b/resources/acpi_cpu/tests/Makefile.omk
new file mode 100644 (file)
index 0000000..8749910
--- /dev/null
@@ -0,0 +1,5 @@
+test_PROGRAMS = acpi_cpu_test
+acpi_cpu_test_SOURCES = acpi_cpu_test.c
+LOADLIBES += -L $(AQUOSA_ROOT)/lib -lqreslib -lqsuplib
+#aqcpumngr_LIBS = frm forb contract fosa rt ulut fcb_client
+lib_LOADLIBES += pthread rt frsh qreslib
diff --git a/resources/acpi_cpu/tests/acpi_cpu_test.c b/resources/acpi_cpu/tests/acpi_cpu_test.c
new file mode 100644 (file)
index 0000000..2dd9f45
--- /dev/null
@@ -0,0 +1,42 @@
+#include <frsh.h>
+#include <error.h>
+
+int main()
+{
+       int power_levels;
+       int ret;
+
+       if (frsh_init())
+               error(1, 0, "FRSH initialization failed\n");
+
+       ret = frsh_resource_get_num_power_levels(FRSH_RT_PROCESSOR,
+                                                0, &power_levels);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_resource_get_num_power_levels");
+       printf("Number of power levels suppoerted: %d\n", power_levels);
+
+       if (power_levels == 1)
+               PERROR_AND_EXIT(EINVAL, "Different power levels not supported");
+
+       printf("Starting...\n");
+
+       sleep(3);
+       ret = frsh_resource_set_power_level(FRSH_RT_PROCESSOR,
+                                           0, FRSH_PLT_HIGH);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_resource_set_power_level");
+       printf("FRSH_PLT_MEDIUM correctly set\n");
+
+       sleep(3);
+       ret = frsh_resource_set_power_level(FRSH_RT_PROCESSOR,
+                                           0, FRSH_PLT_MEDIUM);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_resource_set_power_level");
+       printf("FRSH_PLT_MEDIUM correctly set\n");
+
+       sleep(3);
+       ret = frsh_resource_set_power_level(FRSH_RT_PROCESSOR,
+                                           0, FRSH_PLT_LOW);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_resource_set_power_level");
+       printf("FRSH_PLT_LOW correctly set\n");
+
+       return 0;       
+}
+
diff --git a/resources/acpi_cpu/tests/config.omk b/resources/acpi_cpu/tests/config.omk
new file mode 100644 (file)
index 0000000..906e662
--- /dev/null
@@ -0,0 +1,7 @@
+CONFIG_AQUOSA=y
+CFLAGS+=-save-temps
+CONFIG_FWP=n
+CONFIG_RESOURCE_DUMMY=n
+CONFIG_RESOURCE_ITEM=n
+CONFIG_RESOURCE_CLUSTER_TREE=n
+
diff --git a/resources/acpi_lcd/Makefile b/resources/acpi_lcd/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
+
diff --git a/resources/acpi_lcd/Makefile.omk b/resources/acpi_lcd/Makefile.omk
new file mode 100644 (file)
index 0000000..5f5dc57
--- /dev/null
@@ -0,0 +1,13 @@
+default_CONFIG = CONFIG_ACPI_LCD=y
+
+ifeq ($(CONFIG_ACPI_LCD),y)
+shared_LIBRARIES = acpi_lcd
+
+acpi_lcd_SOURCES = fra_acpi_lcd.c
+acpi_lcd_LIBS += fosa rt m acpi
+
+include_HEADERS = fra_acpi_lcd.h
+
+SUBDIRS=tests
+endif
+
diff --git a/resources/acpi_lcd/fra_acpi_lcd.c b/resources/acpi_lcd/fra_acpi_lcd.c
new file mode 100644 (file)
index 0000000..827b9e2
--- /dev/null
@@ -0,0 +1,175 @@
+/**
+ * @file   fres_acpi_cpu.c
+ * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ *        Michael Trimarchi <trimarchimichael@yahoo.it>
+ * 
+ * @brief  Implementation of LCD related ACPI functions.
+ * 
+ */
+
+#include "fra_acpi_lcd.h"
+
+static unsigned long bright[3];
+
+static lcd_type_t lcd_initialized = NONE;
+
+static int __parse_proc_brightness(FILE *fd)
+{
+       char buffer[1024];
+       int bright_buf[100], n_bright = 0;
+       char *token, *ptr = buffer;
+
+       if (!fscanf(fd, "levels:%[^\n]", buffer))
+               return -1;
+
+       while ((token = strtok(ptr, " ")) > 0 &&
+              n_bright < 100) {
+               bright_buf[n_bright] = atoi(token);
+
+               ptr = NULL;
+               n_bright++;
+       }
+
+       bright[0] = bright_buf[n_bright];
+       bright[1] = bright_buf[((int)ceil((double)n_bright / 2.0f))];
+       bright[3] = bright_buf[0];
+
+       return 0;
+}
+
+static inline int __setup_lcd_type()
+{
+       int ret = 0;
+       FILE *fd;
+
+       if (lcd_initialized != NONE)
+               return 0;
+
+       fd = fopen(PROC_LCD_PATH_1 "/brightness", "r");
+       if (fd) {
+               ret = __parse_proc_brightness(fd);
+               if (ret) goto end;
+
+               lcd_initialized = PROC_1;
+
+               goto end;
+       }
+
+       fd = fopen(PROC_LCD_PATH_2 "/brightness", "r");
+       if (fd) {
+               ret = __parse_proc_brightness(fd);
+               if (ret) goto end;
+
+               lcd_initialized = PROC_2;
+
+               goto end;
+       }
+
+       fd = fopen(SYS_LCD_PATH_1 "/brightness", "r");
+       if (fd) {
+               /* @TODO: to be done! */
+
+               lcd_initialized = SYS_1;
+
+               goto end;
+       }
+
+       fd = popen("smartdimmer -g", "r");
+       if (fd) {
+               ret = pclose(fd);
+               if (ret) {
+                       fprintf(stderr, "Problems using smartdimmer\n");
+                       return errno;
+               }
+               bright[0] = 100;
+               bright[1] = 43;
+               bright[3] = 15;
+
+               lcd_initialized = NV;
+
+               goto end;
+       }
+
+       return EINVAL;
+
+end:
+       fclose(fd);
+       return ret;
+}
+
+static int __set_proc_brightness(FILE *fd, int level)
+{
+       int ret;
+
+       ret = fprintf(fd, "%d", bright[level]);
+       if (ret <= 0) {
+               fprintf(stderr,
+                       "Could not set brightness level %d\n",
+                       level);
+               return errno;
+       }
+
+        return 0;
+}
+
+static int __set_lcd_brightness(int level)
+{
+       FILE *fd;
+       int ret = 0;
+       char str[128];
+
+       if (lcd_initialized == NONE)
+               return EINVAL;
+
+       if (lcd_initialized == PROC_1) {
+               fd = fopen(PROC_LCD_PATH_1 "/brightness", "w");
+               if (!fd)
+                       goto err;
+
+               ret = __set_proc_brightness(fd, level);
+               if (ret)
+                       return EINVAL;
+       } else if (lcd_initialized == PROC_2) {
+               fd = fopen(PROC_LCD_PATH_2 "/brightness", "w");
+               if (!fd)
+                       goto err;
+
+               ret = __set_proc_brightness(fd, level);
+               if (ret)
+                       return EINVAL;
+       } else if (lcd_initialized == SYS_1) {
+               /* @TODO: to be done! */        
+       } else if (lcd_initialized == NV) {
+               sprintf(str, "smartdimmer -s %lu", bright[level]);
+               fd = popen(str, "r");
+               if (!fd) {
+                       fprintf(stderr,
+                               "Could not set brightness level %d\n",
+                               level);
+                       return errno;
+               }
+       }
+
+       fclose(fd);
+err:
+       return ret;
+}
+
+int fra_LCD_power_init(int lcd)
+{
+       return __setup_lcd_type();
+}
+
+int fra_LCD_get_power(int lcd, int *level)
+{
+       /**
+        * @TODO: to be implemented!
+        **/
+       return EINVAL;
+}
+
+int fra_LCD_set_power(int lcd, int level)
+{
+       return __set_lcd_brightness(level);
+}
+
diff --git a/resources/acpi_lcd/fra_acpi_lcd.h b/resources/acpi_lcd/fra_acpi_lcd.h
new file mode 100644 (file)
index 0000000..bbe79e4
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef ACPI_LCD
+#define ACPI_LCD
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <math.h>
+
+#include <fosa.h>
+
+#define PROC_LCD_PATH_1        "/proc/acpi/video/VID/LCD/"
+#define PROC_LCD_PATH_2        "/proc/acpi/video/VID1/LCD/"
+#define SYS_LCD_PATH_1 "/sys/class/backlight/acpi_video0/"
+
+typedef enum lcd_type {
+       NONE = 0,
+       PROC_1 = 1,
+       PROC_2 = 2,
+       SYS_1 = 3,
+       NV = 4
+} lcd_type_t;
+
+int fra_LCD_power_init(int lcd);
+
+int fra_LCD_get_power(int lcd, int *level);
+
+int fra_LCD_set_power(int lcd, int level);
+
+#endif
+
diff --git a/resources/acpi_lcd/tests/Makefile b/resources/acpi_lcd/tests/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
+
diff --git a/resources/acpi_lcd/tests/Makefile.omk b/resources/acpi_lcd/tests/Makefile.omk
new file mode 100644 (file)
index 0000000..97b229f
--- /dev/null
@@ -0,0 +1,5 @@
+test_PROGRAMS = acpi_lcd_test
+acpi_lcd_test_SOURCES = acpi_lcd_test.c
+LOADLIBES += -L $(AQUOSA_ROOT)/lib -lqreslib -lqsuplib
+#aqcpumngr_LIBS = frm forb contract fosa rt ulut fcb_client
+lib_LOADLIBES += pthread rt frsh qreslib
diff --git a/resources/acpi_lcd/tests/acpi_lcd_test.c b/resources/acpi_lcd/tests/acpi_lcd_test.c
new file mode 100644 (file)
index 0000000..add72a2
--- /dev/null
@@ -0,0 +1,42 @@
+#include <frsh.h>
+#include <error.h>
+
+int main()
+{
+       int power_levels;
+       int ret;
+
+       if (frsh_init())
+               error(1, 0, "FRSH initialization failed\n");
+
+       ret = frsh_resource_get_num_power_levels(FRSH_RT_LCD,
+                                                0, &power_levels);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_resource_get_num_power_levels");
+       printf("Number of power levels suppoerted: %d\n", power_levels);
+
+       if (power_levels == 1)
+               PERROR_AND_EXIT(EINVAL, "Different power levels not supported");
+
+       printf("Starting...\n");
+
+       sleep(5);
+       ret = frsh_resource_set_power_level(FRSH_RT_LCD,
+                                           0, FRSH_PLT_HIGH);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_resource_set_power_level");
+       printf("FRSH_PLT_MEDIUM correctly set\n");
+
+       sleep(5);
+       ret = frsh_resource_set_power_level(FRSH_RT_LCD,
+                                           0, FRSH_PLT_MEDIUM);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_resource_set_power_level");
+       printf("FRSH_PLT_MEDIUM correctly set\n");
+
+       sleep(5);
+       ret = frsh_resource_set_power_level(FRSH_RT_LCD,
+                                           0, FRSH_PLT_LOW);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_resource_set_power_level");
+       printf("FRSH_PLT_LOW correctly set\n");
+
+       return 0;       
+}
+
diff --git a/resources/acpi_lcd/tests/config.omk b/resources/acpi_lcd/tests/config.omk
new file mode 100644 (file)
index 0000000..906e662
--- /dev/null
@@ -0,0 +1,7 @@
+CONFIG_AQUOSA=y
+CFLAGS+=-save-temps
+CONFIG_FWP=n
+CONFIG_RESOURCE_DUMMY=n
+CONFIG_RESOURCE_ITEM=n
+CONFIG_RESOURCE_CLUSTER_TREE=n
+
index f6342fcfaea7c1c1d98cde2aefc65f57239ffce5..dc0e2ef2b7d40f813a41dda7f1fde5db19fa1088 100644 (file)
@@ -170,8 +170,8 @@ int main(int argc, char *argv[])
 {
        forb_orb orb;
        int ret;
-
-       orb = forb_init(&argc, &argv, "frm_cluster_tree");
+       forb_init_attr_t attr = { .orb_id = "org.frescor.frm.cluster_tree" };
+       orb = forb_init(&argc, &argv, &attr);
        if (!orb) error(1, errno, "forb_init");
 
        fres_block_register_cluster_tree();
index 2a12dc0fc3fda7413e90232ad248e17b9fc596f5..d66364a55adc7c6fb64a219bcf773ab33d16d82b 100644 (file)
@@ -1,7 +1,6 @@
 shared_LIBRARIES = frshaqcpu
 CFLAGS += -I $(AQUOSA_ROOT)/include
-LOADLIBES += -L $(AQUOSA_ROOT)/lib
-LOADLIBES += -Xlinker -rpath -Xlinker $(AQUOSA_ROOT)/lib
-frshaqcpu_SOURCES += frsh_aqcpu.c aqcpu_contract.c aqcpu_fra.c 
+frshaqcpu_SOURCES += aqcpu_contract.c aqcpu_fra.c 
 include_HEADERS += aqcpu_contract.h aqcpu_res.h
+frshaqcpu_LDFLAGS += -L $(AQUOSA_ROOT)/lib -Xlinker -rpath -Xlinker $(AQUOSA_ROOT)/lib
 frshaqcpu_LIBS += qreslib qsuplib
index 75840e2b28c859efe3d6e3e3ab8bd81140a530f1..c5566b628039dce086bb96b3e7e07014408d4730 100644 (file)
@@ -59,6 +59,8 @@
 #include <fra_generic.h>
 
 #include "aquosa/qres_lib.h"
+#include "aquosa/qsup_lib.h"
+
 #include "aqcpu_contract.h"
 
 UL_LOG_CUST(ulogd_fra_aqcpu);
@@ -82,6 +84,11 @@ static int aqcpu_create_vres(fres_vres_t *vres, void *priv)
        qres_sid_t sid;
        qos_rv rv;
 
+       if (vres->priv) {
+               errno = -EINVAL;
+               return -1;
+       }
+
        /* get aqcpu params from contract */
        get_aqcpu_params(vres, &cpu_params);
        /* create cpu vres */
@@ -102,8 +109,8 @@ static int aqcpu_create_vres(fres_vres_t *vres, void *priv)
 /*
  * aqcpu_cancel_vres(), cancels vres 
  *
- * The thread bound to the vres are unbound, and so, detached from their
- * AQuoSA resource reservation servers and continue their execution according
+ * The threads bound to the vres are unbound, and so, detached from their
+ * AQuoSA resource reservation server and continue their execution according
  * to the standard Linux scheduler policies.
  *
  */
@@ -112,7 +119,7 @@ static int aqcpu_cancel_vres(fres_vres_t *vres, void *priv)
        qres_sid_t sid;
        qos_rv qrv;
        
-       if (vres->priv) {
+       if (!vres->priv) {
                errno = -EINVAL;
                return -1;
        }
@@ -137,13 +144,14 @@ static int aqcpu_cancel_vres(fres_vres_t *vres, void *priv)
  * possible.
  *
  */
+static
 int aqcpu_change_vres(fres_vres_t *vres, void *priv)
 {
        aqcpu_params_t cpu_params;
        qres_sid_t sid;
        qos_rv qrv;
        
-       if (vres->priv) {
+       if (!vres->priv) {
                errno = -EINVAL;
                return -1;
        }
@@ -161,15 +169,6 @@ int aqcpu_change_vres(fres_vres_t *vres, void *priv)
        return 0;
 }
 
-static struct fres_allocator aqcpu_allocator = {
-       .res_type = FRSH_RT_PROCESSOR,
-       .res_id = 0,  /* CPU ID 0 */
-       .create_vres = aqcpu_create_vres,
-       .cancel_vres = aqcpu_cancel_vres,
-       .change_vres = aqcpu_change_vres,
-       .priv = NULL
-};
-
 /*
  * installed as an exit handler (with 'atexit()') by the initialization
  * code... For now it only calls the cleanup function of the AQuoSA
@@ -179,6 +178,222 @@ static inline void aqcpu_cleanup_wrapper() {
        qres_cleanup();
 }
 
+static
+int aqcpu_fra_exit()
+{
+       qos_rv rv;
+
+       rv = qres_cleanup();
+       return qos_rv_int(rv);
+}
+
+static
+int fra_CPU_bind_thread
+  (fres_vres_t *vres,
+   const fosa_thread_id_t thread)
+{
+       qos_rv  qrv;
+       qres_sid_t sid = *((qres_sid_t*)vres->priv);
+
+       if ((qrv = qres_attach_thread(sid, thread.linux_pid,
+           thread.linux_tid)) != QOS_OK)
+               goto err;
+
+       return 0;
+err:
+       return -1;
+}
+
+static
+int fra_CPU_unbind_thread(const fosa_thread_id_t thread)
+{
+       qos_rv  qrv;
+       qres_sid_t  sid;
+
+       if (qres_get_sid(thread.linux_pid, thread.linux_tid, &sid) != QOS_OK)
+               goto err;
+
+       if ((qrv = qres_detach_thread(sid, thread.linux_pid,
+           thread.linux_tid)) != QOS_OK)
+               goto err;
+
+       return 0;
+err:
+       return -1;
+}
+
+static
+int fra_CPU_get_usage
+  (const fres_vres_t *vres,
+   fosa_rel_time_t *spent)
+{
+       qres_sid_t sid = *((qres_sid_t*)vres->priv);
+       qres_time_t exec_budget;
+       qos_rv rv;
+
+       if (!spent)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       rv = qres_get_exec_time(sid, &exec_budget, NULL);
+       if (rv != QOS_OK) return EINVAL;
+
+       *spent = fosa_usec_to_rel_time(exec_budget);
+
+       return 0;
+}
+
+static
+int fra_CPU_get_job_usage
+  (const fres_vres_t *vres,
+   fosa_rel_time_t *spent)
+{
+       qres_sid_t sid = *((qres_sid_t*)vres->priv);
+       qres_params_t q_params;
+       qres_time_t curr_budget;
+       qos_rv rv;
+
+       if (!spent)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       rv = qres_get_params(sid, &q_params);
+       if (rv != QOS_OK) return EINVAL;
+       rv = qres_get_curr_budget(sid, &curr_budget);
+       if (rv != QOS_OK) return EINVAL;
+
+       *spent = fosa_usec_to_rel_time(q_params.Q - curr_budget);
+
+       return 0;
+}
+
+static
+int fra_CPU_get_remaining_budget
+  (const fres_vres_t *vres,
+   fosa_rel_time_t *budget)
+{
+       qres_sid_t sid = *((qres_sid_t*)vres->priv);
+       qres_time_t curr_budget;
+       qos_rv rv;
+
+       if (!budget)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       rv = qres_get_curr_budget(sid, &curr_budget);
+       if (rv != QOS_OK) return EINVAL;
+
+       *budget = fosa_usec_to_rel_time(curr_budget);
+
+       return 0;
+}
+
+static
+int fra_CPU_set_spare_bandwidth(fres_vres_t *vres)
+{
+       qres_sid_t fake_sid = (qres_sid_t) -1;
+       aqcpu_params_t cpu_params;
+       qos_rv rv;
+
+       /* get aqcpu params from contract */
+       get_aqcpu_params(vres, &cpu_params);
+
+       
+       /* reserve CPU bandwidth for feedback */
+       rv = qsup_reserve_spare(r2bw(cpu_params.Q, cpu_params.P));
+       if (rv != QOS_OK) return qos_rv_int(rv);
+
+       printf("Created AQCPU spare (period=%lld us, budget=%lld us)\n",
+                       cpu_params.P, cpu_params.Q);
+       if ((vres->priv = malloc(sizeof(qres_sid_t)))) {
+               memcpy(vres->priv, &fake_sid, sizeof(qres_sid_t));
+       }
+
+       return 0;
+}
+
+static
+int fra_CPU_get_desired_budget
+  (fres_vres_t *vres,
+   frsh_rel_time_t *p_budget_out)
+{
+       qres_sid_t sid = *((qres_sid_t*)vres->priv);
+       qres_params_t q_params;
+       qos_rv rv;
+
+       if (!p_budget_out)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       rv = qres_get_params(sid, &q_params);
+       if (rv != QOS_OK) return EINVAL;
+
+       *p_budget_out = fosa_usec_to_rel_time(q_params.Q);
+
+       return 0;
+}
+
+static
+int fra_CPU_set_desired_budget
+  (fres_vres_t *vres,
+   fosa_rel_time_t *p_budget_in)
+{
+       qres_sid_t sid = *((qres_sid_t*)vres->priv);
+       qres_params_t q_params;
+       qos_rv rv;
+
+       if (!p_budget_in)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       rv = qres_get_params(sid, &q_params);
+       if (rv != QOS_OK) return EINVAL;
+
+       q_params.Q = fosa_rel_time_to_usec(*p_budget_in);
+
+       rv = qres_set_params(sid, &q_params);
+       if (rv != QOS_OK) return EINVAL;
+
+       return 0;
+}
+
+static
+int fra_CPU_get_actual_budget
+  (fres_vres_t *vres,
+   fosa_rel_time_t *budget)
+{
+       qres_sid_t sid = *((qres_sid_t*)vres->priv);
+       qres_time_t appr_budget;
+       qos_rv rv;
+
+       if (!budget)
+               return FRSH_ERR_BAD_ARGUMENT;
+
+       rv = qres_get_appr_budget(sid, &appr_budget);
+       if (rv != QOS_OK) return EINVAL;
+
+       *budget = fosa_usec_to_rel_time(appr_budget);
+
+       return 0;
+}
+
+static struct fres_allocator aqcpu_allocator = {
+       .res_type = FRSH_RT_PROCESSOR,
+       .res_id = 0,  /* CPU ID 0 */
+       .create_vres = aqcpu_create_vres,
+       .cancel_vres = aqcpu_cancel_vres,
+       .change_vres = aqcpu_change_vres,
+
+       .bind_thread = fra_CPU_bind_thread,
+       .unbind_thread = fra_CPU_unbind_thread,
+
+       .vres_get_usage = fra_CPU_get_usage,
+       .vres_get_job_usage = fra_CPU_get_job_usage,
+       .vres_get_remaining_budget = fra_CPU_get_remaining_budget,
+
+       .set_spare_bandwidth = fra_CPU_set_spare_bandwidth,
+       .get_desired_budget = fra_CPU_get_desired_budget,
+       .set_desired_budget = fra_CPU_set_desired_budget,
+       .get_actual_budget = fra_CPU_get_actual_budget,
+       
+       .priv = NULL
+};
+
 /*
  * aqcpu_fra_init(), initialize FRSH for the calling process
  *
@@ -202,7 +417,7 @@ int aqcpu_fra_init(void)
        if ((qrv = qres_init()) != QOS_OK) {
                return -1;
        }
-       
+
        if ((rv = fra_register(&aqcpu_allocator))) {
                qres_cleanup();
                return rv;
@@ -217,11 +432,3 @@ int aqcpu_fra_init(void)
 
        return 0;
 }
-
-int aqcpu_fra_exit()
-{
-       qos_rv rv;
-
-       rv = qres_cleanup();
-       return qos_rv_int(rv);
-}
index f316b43c408740e137c2367661c2718705f5fb8a..709bc637343aaea209dde87e8edad3466596e810 100644 (file)
 #ifndef AQCPU_RES_H
 #define AQCPU_RES_H
 
+#include <fres_vres.h>
+
 #include <forb.h>
 #include <fcb.h>
-#include <frsh_core.h>
 
 int aqcpu_fra_init(void);
 
diff --git a/resources/cpu_aquosa/lib/frsh_aqcpu.c b/resources/cpu_aquosa/lib/frsh_aqcpu.c
deleted file mode 100644 (file)
index 23aaebc..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-// -----------------------------------------------------------------------
-//  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
-//
-//    Universidad de Cantabria,              SPAIN
-//    University of York,                    UK
-//    Scuola Superiore Sant'Anna,            ITALY
-//    Kaiserslautern University,             GERMANY
-//    Univ. Politécnica  Valencia,           SPAIN
-//    Czech Technical University in Prague,  CZECH REPUBLIC
-//    ENEA                                   SWEDEN
-//    Thales Communication S.A.              FRANCE
-//    Visual Tools S.A.                      SPAIN
-//    Rapita Systems Ltd                     UK
-//    Evidence                               ITALY
-//    
-//    See http://www.frescor.org
-//
-//           FRESCOR project (FP6/2005/IST/5-034026) is funded
-//        in part by the European Union Sixth Framework Programme
-//        The European Union is not liable of any use that may be
-//        made of this code.
-//
-//
-//  based on previous work (FSF) done in the FIRST project
-//                       
-//   Copyright (C) 2005  Mälardalen University, SWEDEN
-//                       Scuola Superiore S.Anna, ITALY
-//                       Universidad de Cantabria, SPAIN
-//                       University of York, UK
-//
-//   FSF API web pages: http://marte.unican.es/fsf/docs
-//                      http://shark.sssup.it/contrib/first/docs/
-//
-//  This file is part of FRSH API
-//
-//  FRSH API is free software; you can  redistribute it and/or  modify
-//  it under the terms of  the GNU General Public License as published by
-//  the Free Software Foundation;  either  version 2, or (at  your option)
-//  any later version.
-//
-//  FRSH API  is distributed  in  the hope  that  it  will  be useful,  but
-//  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
-//  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
-//  General Public License for more details.
-//
-//  You should have  received a  copy of  the  GNU  General Public License
-//  distributed  with  FRSH API;  see file COPYING.   If not,  write to the
-//  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
-//  02111-1307, USA.
-//
-//  As a special exception, if you include this header file into source
-//  files to be compiled, this header file does not by itself cause
-//  the resulting executable to be covered by the GNU General Public
-//  License.  This exception does not however invalidate any other
-//  reasons why the executable file might be covered by the GNU General
-//  Public License.
-// -----------------------------------------------------------------------
-//==============================================
-//  ******** *******    ********  **      **
-//  **///// /**////**  **//////  /**     /**
-//  **      /**   /** /**        /**     /**
-//  ******* /*******  /********* /**********
-//  **////  /**///**  ////////** /**//////**
-//  **      /**  //**        /** /**     /**
-//  **      /**   //** ********  /**     /**
-//  //       //     // ////////   //      // 
-//
-// FRSH(FRescor ScHeduler), pronounced "fresh"
-//==============================================
-
-/*
- * frsh_aqcpu.c
- *
- * This file contains the implementation of FRSH API core functions on top
- * of the AQuoSA framework, on GNU/Linux platform.
- *
- */
-
-/* Linux files */
-#include <unistd.h>
-#include <linux/unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#ifndef _XOPEN_SOURCE
-#  define _XOPEN_SOURCE 500
-#endif
-#ifndef __USE_UNIX98
-#  define __USE_UNIX98
-#endif
-#include <pthread.h>
-#include <semaphore.h>
-#include <stdio.h>
-#include <string.h>
-
-/* FRSH files */
-#include <frsh_cpp_macros.h>
-#include <fosa.h>
-#include <frsh_core_types.h>
-#include <frsh_error.h>
-#include <frsh_time.h>
-
-#include <fres_vres.h>
-#include <fra_generic.h>
-
-/* AQuoSA files */
-#include <aquosa/qres_lib.h>
-#include <aquosa/qsup_lib.h>
-
-
-/**
- * structure used to pass the new created thread (or better its wrapper) the
- * arguments it needs to bind itself to the vres.
- */
-typedef struct {
-       frsh_thread_id_t parent_thread_id;
-       frsh_thread_id_t *thread_id;
-       frsh_thread_code_t pthread_code; /**< function to be running in thread */
-       void *pthread_arg;               /**< thread arguments*/
-       frsh_vres_id_t vres;
-       sem_t *stopper; /**< semaphore to synchronize frsh call and wrapper thread */
-       int  errcode;
-} wrapper_pthread_arg_t;
-
-/*typedef struct {
-               pthread_t pthread_id;
-               pid_t linux_pid;
-               pid_t linux_tid;
-} FOSA_THREAD_ID_T_OPAQUE;*/
-
-/**
- * frsh_thread_bind(), bind a thread to a vres
- *
- * possible return values:
- *  FRSH_NO_ERROR
- *  FRSH_ERR_NOT_INITIALIZED
- *  FRSH_BAD_ARGUMENT(*) (invalid or dummy vres)
- *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
- *  FRSH_ERR_ALREADY_BOUND(*)
- *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
- */
-int frsh_thread_bind(const frsh_vres_id_t vres, const frsh_thread_id_t thread)
-{
-       int ret;
-       qos_rv  qrv;
-       qres_sid_t  sid =  *((qres_sid_t*)vres->priv);
-
-       /*if (!aqcpu_is_initialized) {
-                 return(FRSH_ERR_NOT_INITIALIZED);
-       }*/
-
-       ret = fra_insert_thread_vres(&thread, vres);
-       if (ret) goto err;
-
-       if ((qrv = qres_attach_thread(sid, thread.linux_pid, 
-               thread.linux_tid)) != QOS_OK)
-                       goto err_delete;
-
-       return FRSH_NO_ERROR;
-
-err_delete:
-       fra_delete_thread_vres(&thread);
-err:
-       return FRSH_ERR_INTERNAL_ERROR;
-}
-
-/*
- * frsh_thread_unbind(), unbind a thread from a vres
- *
- * possible return values:
- *  FRSH_NO_ERROR
- *  FRSH_ERR_NOT_INITIALIZED
- *  FRSH_BAD_ARGUMENT(*) (invalid thread)
- *  FRSH_ERR_NOT_BOUND(*)
- *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
- */
-int frsh_thread_unbind(const frsh_thread_id_t thread)
-{
-       int ret;
-       qos_rv  qrv;
-       qres_sid_t  sid;
-
-       if (qres_get_sid(thread.linux_pid, thread.linux_tid, &sid) != QOS_OK)
-               goto err;
-
-       ret = fra_delete_thread_vres(&thread);
-       if (ret) goto err;
-
-       if ((qrv = qres_detach_thread(sid, thread.linux_pid, 
-               thread.linux_tid)) != QOS_OK)
-               goto err;
-
-       return FRSH_NO_ERROR; 
-err:
-       return FRSH_ERR_INTERNAL_ERROR;
-}
-
-/**
- * Wrapper thread
- * 
- * possible exit status:
- *  FRSH_ERR_INTENRAL_ERROR (something wrong with threads and signal handling)
- *  FRSH_ERR_TOO_MANY_TASKS(*)
- *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
- *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
- *  whatever the user provided code 'pthread_code' returns
- */
-static void* wrapper_pthread(void *arg)
-{
-       wrapper_pthread_arg_t* pth = (wrapper_pthread_arg_t*) arg;      
-       frsh_thread_id_t* thread_id = pth->thread_id;   
-       void *thread_arg = pth->pthread_arg;
-       frsh_thread_code_t thread_code = pth->pthread_code;
-       int  errcode;
-       
-       *thread_id = fosa_thread_self();
-       /* bind this thread to vres */
-       errcode = frsh_thread_bind(pth->vres, *thread_id);
-       pth->errcode = errcode;
-       
-       sem_post(pth->stopper); 
-       /* No access to pth is allowed after this point, it can vanish already */
-
-       if (errcode) /* vres binding was not successful */
-               return NULL;
-
-       /* execute thread function */   
-       return thread_code(thread_arg);
-}
-
-/*
- * frsh_thread_bind(), create a new thread and bind it to a vres
- * frsh_thread_create_in_background(), create a new thread and a new BACKGROUND contract 
- * and bind them
- *
- * The two functions both create a new thread and bind it to a vres, existing
- * fr the former, created for the latter.
- *
- * The implementation uses a wrapper function as the new thread code (it's
- * the simplest way to handle some issues on POSIX 'pthread_t' and
- * 'pthread_self()', for a detailed explanation of the "problem" ask the
- * authors via e-mail) which, on its turn, bind itself to the vres and then
- * run the user provided code. The API calls simply create the new thread,
- * using the wrapper thread code, and return.
- *
- * Note that in order to return the caller the descriptor of the new created
- * thread (known to the wrapped thread but not entirely to the API calls) a
- * special 'struct' data type is passed as the parameter of the wrapper thread
- * and a simple synchronization mechanism based on semaphore is realized.
- *
- * possible return values:
- *  see below the comments of each specific API call
- */
-
-/*
- * API call for 'frsh_thread_create_and_bind()', as said prepares the
- * wrapper code argument data structure, create the new thread and wait
- * its acknowledgment before stepping over
- *
- * possible return values:
- *  FRSH_NO_ERROR
- *  FRSH_ERR_NOT_INITIALIZED
- *  FRSH_ERR_BAD_ARGUMENT (NULL thread or thread_code)
- *  whatever 'fosa_thread_create()' returns
- *  FRSH_ERR_INTERNAL_ERROR 
- */
-int frsh_thread_create_and_bind(const frsh_vres_id_t vres,
-       frsh_thread_id_t *thread,
-       frsh_thread_attr_t *attr,
-       frsh_thread_code_t thread_code,
-       void *arg)
-{
-       wrapper_pthread_arg_t wp;
-       int rv;
-       sem_t stopper; 
-
-       sem_init(&stopper, 0, 0);
-       
-       /* check for framework initialization and arguments */
-       /*if (!frsh_initialized)
-               PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
-               "can't proceed before initializing FRSH with 'frsh_init()'!");
-       if ((thread == NULL) || (thread_code == NULL))
-               PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
-               "can't create a thread with NULL thread_core or return it in a NULL thread");
-       */
-
-       wp.parent_thread_id = fosa_thread_self();
-       wp.thread_id = thread;  
-       wp.pthread_code = thread_code;
-       wp.pthread_arg = arg;   
-       wp.vres = vres;
-       wp.stopper = &stopper;
-
-       /* create the wrapper thread */ 
-       rv = fosa_thread_create(thread, attr, wrapper_pthread, (void*)&wp);
-       if (rv != 0)
-               return(rv);
-       
-       sem_wait(&stopper);
-       return (wp.errcode);
-}
-
-int frsh_vres_get_usage
-  (const frsh_vres_id_t vres,
-   frsh_rel_time_t *spent)
-{
-       qres_sid_t sid = *((qres_sid_t*) vres->priv);
-       qres_time_t exec_budget;
-       qos_rv rv;
-
-       if (!spent)
-               return FRSH_ERR_BAD_ARGUMENT;
-
-       rv = qres_get_exec_time(sid, &exec_budget, NULL);
-       if (rv != QOS_OK) return EINVAL;
-
-       *spent = frsh_usec_to_rel_time(exec_budget);
-
-       return 0;
-}
-
-int frsh_vres_get_job_usage
-  (const frsh_vres_id_t vres,
-   frsh_rel_time_t *spent)
-{
-       qres_sid_t sid = *((qres_sid_t*) vres->priv);
-       qres_params_t q_params;
-       qres_time_t curr_budget;
-       qos_rv rv;
-
-       if (!spent)
-               return FRSH_ERR_BAD_ARGUMENT;
-
-       rv = qres_get_params(sid, &q_params);
-       if (rv != QOS_OK) return EINVAL;
-       rv = qres_get_curr_budget(sid, &curr_budget);
-       if (rv != QOS_OK) return EINVAL;
-
-       *spent = frsh_usec_to_rel_time(q_params.Q - curr_budget);
-
-       return 0;
-}
-
-int frsh_vres_get_remaining_budget
-  (const frsh_vres_id_t vres,
-   frsh_rel_time_t *budget)
-{
-       qres_sid_t sid = *((qres_sid_t*) vres->priv);
-       qres_time_t curr_budget;
-       qos_rv rv;
-
-       if (!budget)
-               return FRSH_ERR_BAD_ARGUMENT;
-
-       rv = qres_get_curr_budget(sid, &curr_budget);
-       if (rv != QOS_OK) return EINVAL;
-
-       *budget = frsh_usec_to_rel_time(curr_budget);
-
-       return 0;
-}
-
-int frsh_feedback_get_spare
-  (frsh_contract_t *spare_contract)
-{
-       /**
-        * TODO:
-        *  retreive the special feedback contract.
-        */
-       return FRSH_ERR_NOT_IMPLEMENTED;
-}
-
-int frsh_feedback_set_spare
-  (const frsh_contract_t *spare_contract)
-{
-       int ret = 0;
-       frsh_vres_id_t vres_id;
-       fres_block_basic *b;
-       qos_rv rv;
-
-       if (!spare_contract || !*spare_contract)
-               return FRSH_ERR_BAD_ARGUMENT;
-
-       ret = frsh_contract_negotiate(spare_contract, &vres_id);
-       if (ret) goto err;
-
-       b = fres_contract_get_basic(*spare_contract);
-       if (!b) return EINVAL;
-       rv = qsup_reserve_spare(r2bw(frsh_rel_time_to_usec(b->budget), frsh_rel_time_to_usec(b->period)));
-       if (rv != QOS_OK) return EINVAL;
-
-err:
-       return ret;
-}
-
-int frsh_feedback_get_desired_budget
-  (frsh_vres_id_t vres_id,
-   frsh_rel_time_t *p_budget_out)
-{
-       qres_sid_t sid = *((qres_sid_t*) vres_id->priv);
-       qres_params_t q_params;
-       qos_rv rv;
-
-       if (!p_budget_out)
-               return FRSH_ERR_BAD_ARGUMENT;
-
-       rv = qres_get_params(sid, &q_params);
-       if (rv != QOS_OK) return EINVAL;
-
-       *p_budget_out = frsh_usec_to_rel_time(q_params.Q);
-
-       return 0;
-}
-
-int frsh_feedback_set_desired_budget
-  (frsh_vres_id_t vres_id,
-   frsh_rel_time_t *p_budget_in)
-{
-       qres_sid_t sid = *((qres_sid_t*) vres_id->priv);
-       qres_params_t q_params;
-       qos_rv rv;
-
-       if (!p_budget_in)
-               return FRSH_ERR_BAD_ARGUMENT;
-
-       rv = qres_get_params(sid, &q_params);
-       if (rv != QOS_OK) return EINVAL;
-
-       q_params.Q = frsh_rel_time_to_usec(*p_budget_in);
-
-       rv = qres_set_params(sid, &q_params);
-       if (rv != QOS_OK) return EINVAL;
-
-       return 0;
-}
-
-int frsh_feedback_get_actual_budget
-  (frsh_vres_id_t vres_id,
-   frsh_rel_time_t *budget)
-{
-       qres_sid_t sid = *((qres_sid_t*) vres_id->priv);
-       qres_time_t appr_budget;
-       qos_rv rv;
-
-       if (!budget)
-               return FRSH_ERR_BAD_ARGUMENT;
-
-       rv = qres_get_appr_budget(sid, &appr_budget);
-       if (rv != QOS_OK) return EINVAL;
-
-       *budget = frsh_usec_to_rel_time(appr_budget);
-
-       return 0;
-}
-
index 3995e1d5275295922b5ea41fce160aa82efa6160..5abd720a1dc9179bab696f74903c70d0a401c37c 100644 (file)
@@ -1,5 +1,6 @@
 bin_PROGRAMS = frm_aqcpu
 frm_aqcpu_SOURCES = frm_aqcpu.c
 LOADLIBES += -L $(AQUOSA_ROOT)/lib -lqreslib -lqsuplib
-frm_aqcpu_LIBS = frm forb contract fosa rt ulut fcb_client
+LOADLIBES += -Xlinker -rpath -Xlinker $(AQUOSA_ROOT)/lib
+frm_aqcpu_LIBS = frm forb contract fosa rt ulut fcb_client qreslib qsuplib
 lib_LOADLIBES+= frsh
index c4d857947ad5407db7e9cbef653ba135618b8812..b2dc91218b31a6d61ae0a2529116a55bfd91a78d 100644 (file)
 UL_LOG_CUST(ulogd_frm_aqcpu);
 ul_log_domain_t ulogd_fra_fwp = {UL_LOGL_DEB, "frm_aqcpu"};
 
-static int aqcpu_dummy_admtest(struct fres_sa_scenario *scenario, void *priv, 
-                               bool *schedulable)
+static int aqcpu_admtest(struct fres_sa_scenario *scenario, void *priv, 
+                        bool *schedulable)
 {
        struct fres_sa_contract *c;
+       long int period, budget;
+       long int sum_utilization = 0;
 
-       fres_sa_scenario_for_each_contract(scenario, c) {
+       fres_sa_scenario_for_each_no_cancel_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);
 
+               period = fosa_rel_time_to_msec(basic->period);
+               budget = fosa_rel_time_to_msec(basic->budget);
+
                ul_logdeb("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));
+                      id, period, budget);
 
+               sum_utilization+= budget*100/period;
        }
-       *schedulable = scenario->num_contracts <= 3;
+       *schedulable = sum_utilization < 100;
        printf("=> %s\n", schedulable?"schedulable":"not schedulable");
                
        return 0;
@@ -93,7 +97,7 @@ static int aqcpu_dummy_admtest(struct fres_sa_scenario *scenario, void *priv,
 static const struct fres_res_manager frm = {
        .res_type = FRSH_RT_PROCESSOR,
        .res_id = 0,
-       .admission_test = aqcpu_dummy_admtest,
+       .admission_test = aqcpu_admtest,
        .priv = NULL
 };
 
@@ -101,8 +105,9 @@ int main(int argc, char *argv[])
 {
        forb_orb orb;
        int ret;
-
-       orb = forb_init(&argc, &argv, "frm_aqcpu");
+       forb_init_attr_t attr = { .orb_id = "org.frescor.frm.aqcpu" };
+       
+       orb = forb_init(&argc, &argv, &attr);
        if (!orb) error(1, errno, "forb_init");
        
        ret = frm_register_and_run(orb, &frm);
index 56d2fec47de250363cfea588e415c00d6cd4ac1f..cdc4d894f469e7681ecbffca4aaef14db851b2b5 100644 (file)
@@ -2,4 +2,4 @@ test_PROGRAMS = aqcputest
 aqcputest_SOURCES = aqcputest.c
 LOADLIBES += -L $(AQUOSA_ROOT)/lib -lqreslib -lqsuplib
 #aqcpumngr_LIBS = frm forb contract fosa rt ulut fcb_client
-lib_LOADLIBES += pthread rt frshaqcpu frsh qreslib
+lib_LOADLIBES += pthread rt frsh qreslib
index dcb530250b3858bbb622e7767bf063c25ac0c5d0..122a9aacb8b60545d7359e46d5a35d1a1e5b4893 100644 (file)
@@ -4,15 +4,32 @@
 
 void* work_thread()
 {
-       int i;
+       int ret;
+       unsigned long i = 0;
+       frsh_vres_id_t vres_id;
 
        printf("I am alive! \n");
-       while(1) {
-               printf("I am alive! \n");
+       while(i != 1E9) {
                i++;
 
+               printf("I am alive, run %lu!\n", i);
+
+               ret = frsh_thread_get_vres_id(fosa_thread_self(), &vres_id);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_get_vres_id");
+
+               printf("\tvres retrieved from thread-ID: %d\n", (int) vres_id);
+
+               //ret = frsh_resource_get_vres_from_label("TEST_VRES",
+               //                                      FRSH_RT_PROCESSOR,
+               //                                      0,
+               //                                      &vres_id);
+               //
+               //if (ret) PERROR_AND_EXIT(ret, "frsh_get_vres_from_label");
+               //
+               //printf("\ton retrived from label: %d\n", (int) vres_id);
        }
 
+       return EXIT_SUCCESS;
 }
 
 int main()
@@ -22,39 +39,53 @@ int main()
        frsh_thread_id_t thread;
        frsh_contract_t contract;
        frsh_rel_time_t budget, period;
+       frsh_rel_time_t zero = fosa_msec_to_rel_time(0);
        int ret;
 
-       if (frsh_init()) {
-               error(1, 0, "FRSH initialization failed\n");
-
-       }
+       if (frsh_init())
+               error(1, errno, "FRSH initialization failed\n");
        
        /* Contract negotiation for CPU */
        ret = frsh_contract_init(&contract);
        if (ret) PERROR_AND_EXIT(ret, "frsh_contract_init");
                
        budget = fosa_msec_to_rel_time(10);
-       period = fosa_msec_to_rel_time(2000);
+       period = fosa_msec_to_rel_time(100);
        ret = frsh_contract_set_basic_params(&contract,
                                             &budget,
                                             &period,
                                             FRSH_WT_BOUNDED,
                                             FRSH_CT_REGULAR);
        if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_basic_params");
+
        ret = frsh_contract_set_resource_and_label(&contract, FRSH_RT_PROCESSOR,
-                                                       0,"aqcpu_cont1");
+                                                       0,"TEST_VRES");
        if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_resource_and_label");
 
+       ret = frsh_contract_set_reclamation_params(&contract,
+                                                  &zero,
+                                                  &budget,
+                                                  &period,
+                                                  FRSH_GR_CONTINUOUS,
+                                                  NULL,
+                                                  0,
+                                                  0);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_reclamation_params");
+
        ret = frsh_contract_negotiate(&contract, &vres);
        if (ret) PERROR_AND_EXIT(ret, "frsh_contract_negotiate");
 
-       printf("Aqcpu vres negotiated\n");
+       printf("Aqcpu vres negotiated, vres-ID: %d\n", (int) vres);
        pthread_attr_init(&attr);
        ret = frsh_thread_create_and_bind(vres, &thread, &attr, 
                                work_thread, (void*) NULL);
        if (ret) PERROR_AND_EXIT(ret, "frsh_thread_create_and_bind");
        
        pthread_join(thread.pthread_id, (void**) NULL); 
+
+       ret = frsh_contract_cancel(vres);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_cancel");
+
        printf("Test PASSED!\n");
                
        return 0;       
index 451dc026b4c34b37e0e32f496898d05cb486f5ff..f1dbf6b610bc26aaabf4a761d7418b00d86ab134 100644 (file)
@@ -1,5 +1,5 @@
 shared_LIBRARIES = frshcpucg
-frshcpucg_SOURCES += frsh_cpucg.c cpucg_contract.c cpucg_fra.c 
+frshcpucg_SOURCES += cpucg_contract.c cpucg_fra.c 
 include_HEADERS += cpucg_contract.h cpucg_res.h timespec_usec_ops.h
 frshcpucg_LIBS += cgroup  
 #include_HEADERS +=$(wildcard aquosa/qresmod/*.h)
index 80bb14f662c902a56eecd50d1217d355015c2106..69d3216892a27d1f86874eea17bb8e37a5e74ef6 100644 (file)
@@ -178,6 +178,8 @@ int cpucg_change_vres(fres_vres_t *vres, void *priv)
        return 0;
 }
 
+
+
 static struct fres_allocator cpucg_allocator = {
        .res_type = FRSH_RT_PROCESSOR,
        .res_id = 0,  /* CPU ID 0 */
@@ -233,3 +235,110 @@ int cpucg_fra_exit()
 {
        return 0;
 }
+
+int fra_CPU_bind_thread
+  (const fres_vres_t vres,
+   const fosa_thread_id_t thread)
+{
+       struct cgroup* cgroup = (struct cgroup*)vres->priv;
+       struct sched_param param;
+       int p, policy, ret;
+
+       /* if (!aqcpu_is_initialized) {
+        *      return(FRSH_ERR_NOT_INITIALIZED);
+        * }
+        */
+
+       pthread_getschedparam(pthread_self(), &policy, &param);
+       p = param.sched_priority;
+       printf("policy = %d, priority = %d\n", policy, p);
+       if (p == 0) {
+               param.sched_priority = 1;
+               pthread_setschedparam(pthread_self(), SCHED_RR, &param);
+               pthread_getschedparam(pthread_self(), &policy, &param);
+               printf("changed policy = %d, changed priority = %d\n",
+                       policy, param.sched_priority);
+       }
+
+       if (cgroup_attach_task_pid(cgroup, thread.linux_tid))
+               goto err;
+
+       return 0;
+err:
+       return -1;
+}
+
+int fra_CPU_unbind_thread(const fosa_thread_id_t thread)
+{
+       int ret;
+
+       /* TODO: solve thread -> vres mapping */
+#if 0
+       char path[FILENAME_MAX];
+       struct cgroup* cgroup = (struct cgroup*)vres->priv;
+       FILE* taskf;
+
+       /* if (!aqcpu_is_initialized) {
+        *      return(FRSH_ERR_NOT_INITIALIZED);
+        * }
+        */
+
+       if (!cg_build_path(cgroup->name, path, cgroup->controller[i]->name)){
+               return FRSH_ERR_INTERNAL_ERROR;
+       }
+
+       strcat(path, "tasks");
+       taskf = fopen(path, "w");
+       if (!taskf) {
+               return FRSH_ERR_INTERNAL_ERROR;
+       }
+       fclose(taskf);
+#endif
+
+       return 0;
+err:
+       return -1;
+}
+
+int fra_CPU_get_usage
+  (const fres_vres_t vres,
+   fosa_rel_time_t *spent)
+{
+       return -1;
+}
+
+int fra_CPU_get_job_usage
+  (const fres_vres_t vres,
+   fosa_rel_time_t *spent)
+{
+       return -1;
+}
+
+int fra_CPU_get_remaining_budget
+  (const fres_vres_t vres,
+   fosa_rel_time_t *budget)
+{
+       return -1;
+}
+
+int fra_CPU_get_desired_budget
+  (fres_vres_t vres,
+   frsh_rel_time_t *p_budget_out)
+{
+       return -1;
+}
+
+int fra_CPU_set_desired_budget
+  (fres_vres_t vres,
+   fosa_rel_time_t *p_budget_in)
+{
+       return -1;
+}
+
+int fra_CPU_get_actual_budget
+  (fres_vres_t vres,
+   fosa_rel_time_t *budget)
+{
+       return -1;
+}
+
index 40cc0c61b69b61ead8e613990bf8f650d267cba5..26a018231a5bbd84091b3db3ba2d8a3e8924c067 100644 (file)
@@ -7,5 +7,29 @@
 
 int cpucg_fra_init(void);
 
+int fra_CPU_bind_thread(fres_vres_t vres, fosa_thread_id_t thread);
+int fra_CPU_unbind_thread(fosa_thread_id_t thread);
+
+int frsh_vres_get_job_usage
+  (const frsh_vres_id_t vres,
+   frsh_rel_time_t *spent)
+{
+        return FRSH_ERR_NOT_IMPLEMENTED;
+}
+
+int fra_CPU_get_usage(const fres_vres_t vres,
+                      fosa_rel_time_t *spent);
+int fra_CPU_get_job_usage(const fres_vres_t vres,
+                          fosa_rel_time_t *spent)
+int fra_CPU_get_remaining_budget(const fres_vres_t vres,
+                                 fosa_rel_time_t *budget);
+
+int fra_CPU_get_desired_budget(fres_vres_t vres,
+                               frsh_rel_time_t *p_budget_out);
+int fra_CPU_set_desired_budget(fres_vres_t vres,
+                              fosa_rel_time_t *p_budget_in);
+int fra_CPU_get_actual_budget(fres_vres_t vres,
+                             fosa_rel_time_t *budget);
+
 #endif /* CPUCG_RES_H */
 
diff --git a/resources/cpucg/lib/frsh_cpucg.c b/resources/cpucg/lib/frsh_cpucg.c
deleted file mode 100644 (file)
index 4539851..0000000
+++ /dev/null
@@ -1,380 +0,0 @@
-// -----------------------------------------------------------------------
-//  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
-//
-//    Universidad de Cantabria,              SPAIN
-//    University of York,                    UK
-//    Scuola Superiore Sant'Anna,            ITALY
-//    Kaiserslautern University,             GERMANY
-//    Univ. Politécnica  Valencia,           SPAIN
-//    Czech Technical University in Prague,  CZECH REPUBLIC
-//    ENEA                                   SWEDEN
-//    Thales Communication S.A.              FRANCE
-//    Visual Tools S.A.                      SPAIN
-//    Rapita Systems Ltd                     UK
-//    Evidence                               ITALY
-//    
-//    See http://www.frescor.org
-//
-//           FRESCOR project (FP6/2005/IST/5-034026) is funded
-//        in part by the European Union Sixth Framework Programme
-//        The European Union is not liable of any use that may be
-//        made of this code.
-//
-//
-//  based on previous work (FSF) done in the FIRST project
-//                       
-//   Copyright (C) 2005  Mälardalen University, SWEDEN
-//                       Scuola Superiore S.Anna, ITALY
-//                       Universidad de Cantabria, SPAIN
-//                       University of York, UK
-//
-//   FSF API web pages: http://marte.unican.es/fsf/docs
-//                      http://shark.sssup.it/contrib/first/docs/
-//
-//  This file is part of FRSH API
-//
-//  FRSH API is free software; you can  redistribute it and/or  modify
-//  it under the terms of  the GNU General Public License as published by
-//  the Free Software Foundation;  either  version 2, or (at  your option)
-//  any later version.
-//
-//  FRSH API  is distributed  in  the hope  that  it  will  be useful,  but
-//  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
-//  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
-//  General Public License for more details.
-//
-//  You should have  received a  copy of  the  GNU  General Public License
-//  distributed  with  FRSH API;  see file COPYING.   If not,  write to the
-//  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
-//  02111-1307, USA.
-//
-//  As a special exception, if you include this header file into source
-//  files to be compiled, this header file does not by itself cause
-//  the resulting executable to be covered by the GNU General Public
-//  License.  This exception does not however invalidate any other
-//  reasons why the executable file might be covered by the GNU General
-//  Public License.
-// -----------------------------------------------------------------------
-//==============================================
-//  ******** *******    ********  **      **
-//  **///// /**////**  **//////  /**     /**
-//  **      /**   /** /**        /**     /**
-//  ******* /*******  /********* /**********
-//  **////  /**///**  ////////** /**//////**
-//  **      /**  //**        /** /**     /**
-//  **      /**   //** ********  /**     /**
-//  //       //     // ////////   //      // 
-//
-// FRSH(FRescor ScHeduler), pronounced "fresh"
-//==============================================
-
-/*
- * frsh_aqcpu.c
- *
- * This file contains the implementation of FRSH API core functions on top
- * of the AQuoSA framework, on GNU/Linux platform.
- *
- */
-
-/* Linux files */
-#include <unistd.h>
-#include <linux/unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#define __USE_UNIX98
-#include <pthread.h>
-#include <semaphore.h>
-#include <stdio.h>
-#include <string.h>
-
-/* FRSH files */
-#include <frsh_cpp_macros.h>
-#include <fosa.h>
-#include <frsh_core_types.h>
-#include <frsh_error.h>
-
-#include <fres_vres.h>
-#include <fra_generic.h>
-#include <libcgroup.h>
-
-/* local timepsec <-> usec utility macros */
-#include "timespec_usec_ops.h"
-
-
-/**
- * structure used to pass the new created thread (or better its wrapper) the
- * arguments it needs to bind itself to the vres.
- */
-typedef struct {
-       frsh_thread_id_t parent_thread_id;
-       frsh_thread_id_t *thread_id;
-       frsh_thread_code_t pthread_code; /**< function to be running in thread */
-       void *pthread_arg;               /**< thread arguments*/
-       frsh_vres_id_t vres;
-       sem_t *stopper; /**< semaphore to synchronize frsh call and wrapper thread */
-       int  errcode;
-} wrapper_pthread_arg_t;
-
-/*typedef struct {
-               pthread_t pthread_id;
-               pid_t linux_pid;
-               pid_t linux_tid;
-} FOSA_THREAD_ID_T_OPAQUE;*/
-
-/**
- * frsh_thread_bind(), bind a thread to a vres
- *
- * possible return values:
- *  FRSH_NO_ERROR
- *  FRSH_ERR_NOT_INITIALIZED
- *  FRSH_BAD_ARGUMENT(*) (invalid or dummy vres)
- *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
- *  FRSH_ERR_ALREADY_BOUND(*)
- *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
- */
-int frsh_thread_bind(const frsh_vres_id_t vres, const frsh_thread_id_t thread)
-{
-       struct cgroup* cgroup = (struct cgroup*)vres->priv;
-       struct sched_param param;
-       int ret;
-
-       /*if (!aqcpu_is_initialized) {
-                 return(FRSH_ERR_NOT_INITIALIZED);
-       }*/
-
-       ret = fra_insert_thread_vres(&thread, vres);
-       if (ret) goto err;
-
-       if (cgroup_attach_task_pid(cgroup, thread.linux_tid)) {
-                       return FRSH_ERR_INTERNAL_ERROR;
-       }
-       
-       /*sched_getparam(thread.linux_tid, &param);
-       if (param.sched_priority == 0) {
-               param.sched_priority = 1;
-               if (sched_setscheduler(thread.linux_tid, SCHED_RR, 
-                       &param) == -1) {
-                       return FRSH_ERR_INTERNAL_ERROR;
-               }
-       }*/
-
-       return FRSH_NO_ERROR;
-err:
-       return FRSH_ERR_INTERNAL_ERROR;
-}
-
-/*
- * frsh_thread_unbind(), unbind a thread from a vres
- *
- * possible return values:
- *  FRSH_NO_ERROR
- *  FRSH_ERR_NOT_INITIALIZED
- *  FRSH_BAD_ARGUMENT(*) (invalid thread)
- *  FRSH_ERR_NOT_BOUND(*)
- *  FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
- */
-int frsh_thread_unbind(const frsh_thread_id_t thread)
-{
-       int ret;
-       /* TODO: solve thread -> vres mapping */
-#if 0
-       char path[FILENAME_MAX];
-       struct cgroup* cgroup = (struct cgroup*)vres->priv;
-       FILE* taskf;
-
-       /*if (!aqcpu_is_initialized) {
-                 return(FRSH_ERR_NOT_INITIALIZED);
-       }*/
-       
-       if (!cg_build_path(cgroup->name, path, cgroup->controller[i]->name)){
-               return FRSH_ERR_INTERNAL_ERROR;
-       }
-       
-       strcat(path, "tasks");
-       taskf = fopen(path, "w");
-       if (!taskf) {
-               return FRSH_ERR_INTERNAL_ERROR;
-       }
-       fclose(taskf);
-#endif
-
-       ret = fra_delete_thread_vres(&thread);
-       if (ret) goto err;
-
-       return FRSH_NO_ERROR;
-err:
-       return FRSH_ERR_INTERNAL_ERROR;
-}
-
-/**
- * Wrapper thread
- * 
- * possible exit status:
- *  FRSH_ERR_INTENRAL_ERROR (something wrong with threads and signal handling)
- *  FRSH_ERR_TOO_MANY_TASKS(*)
- *  FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
- *  FRSH_ERR_NOT_CONTRACTED_VRES(*)
- *  whatever the user provided code 'pthread_code' returns
- */
-static void* wrapper_pthread(void *arg)
-{
-       wrapper_pthread_arg_t* pth = (wrapper_pthread_arg_t*) arg;      
-       frsh_thread_id_t* thread_id = pth->thread_id;   
-       void *thread_arg = pth->pthread_arg;
-       frsh_thread_code_t thread_code = pth->pthread_code;
-       int  errcode;
-       
-       *thread_id = fosa_thread_self();
-       /* bind this thread to vres */
-       errcode = frsh_thread_bind(pth->vres, *thread_id);
-       pth->errcode = errcode;
-
-       sem_post(pth->stopper);
-       /* No access to pth is allowed after this point, it can vanish already */
-
-       if (errcode) /* vres binding was not successful */
-               return NULL;
-
-       /* execute thread function */   
-       return thread_code(thread_arg);
-}
-
-/*
- * frsh_thread_bind(), create a new thread and bind it to a vres
- * frsh_thread_create_in_background(), create a new thread and a new BACKGROUND contract 
- * and bind them
- *
- * The two functions both create a new thread and bind it to a vres, existing
- * fr the former, created for the latter.
- *
- * The implementation uses a wrapper function as the new thread code (it's
- * the simplest way to handle some issues on POSIX 'pthread_t' and
- * 'pthread_self()', for a detailed explanation of the "problem" ask the
- * authors via e-mail) which, on its turn, bind itself to the vres and then
- * run the user provided code. The API calls simply create the new thread,
- * using the wrapper thread code, and return.
- *
- * Note that in order to return the caller the descriptor of the new created
- * thread (known to the wrapped thread but not entirely to the API calls) a
- * special 'struct' data type is passed as the parameter of the wrapper thread
- * and a simple synchronization mechanism based on semaphore is realized.
- *
- * possible return values:
- *  see below the comments of each specific API call
- */
-
-/*
- * API call for 'frsh_thread_create_and_bind()', as said prepares the
- * wrapper code argument data structure, create the new thread and wait
- * its acknowledgment before stepping over
- *
- * possible return values:
- *  FRSH_NO_ERROR
- *  FRSH_ERR_NOT_INITIALIZED
- *  FRSH_ERR_BAD_ARGUMENT (NULL thread or thread_code)
- *  whatever 'fosa_thread_create()' returns
- *  FRSH_ERR_INTERNAL_ERROR 
- */
-int frsh_thread_create_and_bind(const frsh_vres_id_t vres,
-       frsh_thread_id_t *thread,
-       frsh_thread_attr_t *thread_attr,
-       frsh_thread_code_t thread_code,
-       void *arg)
-{
-       wrapper_pthread_arg_t wp;
-       int rv;
-       sem_t stopper;
-       struct sched_param param;
-       int p = 0;
-       frsh_thread_attr_t updated_attr;
-
-       sem_init(&stopper, 0, 0);
-       
-       if (!thread || !thread_code || !thread_attr)
-               return FRSH_ERR_BAD_ARGUMENT;
-
-       wp.parent_thread_id = fosa_thread_self();
-       wp.thread_id = thread;  
-       wp.pthread_code = thread_code;
-       wp.pthread_arg = arg;   
-       wp.vres = vres;
-       wp.stopper = &stopper;
-
-       pthread_attr_getschedparam(thread_attr, &param);
-       p = param.sched_priority;
-       printf("priority = %d\n", p);
-       if (p == 0) {
-               updated_attr = *thread_attr;
-               param.sched_priority = 1;
-               pthread_attr_setschedparam(&updated_attr, &param);
-               pthread_attr_getschedparam(&updated_attr, &param);
-               printf("changed priority = %d\n", param.sched_priority);
-               pthread_attr_setinheritsched(&updated_attr, PTHREAD_EXPLICIT_SCHED);
-               pthread_attr_setschedpolicy(&updated_attr, SCHED_RR);
-               pthread_attr_setscope(&updated_attr, PTHREAD_SCOPE_SYSTEM);
-               thread_attr = &updated_attr; 
-       }
-       
-       /* create the wrapper thread */ 
-       rv = fosa_thread_create(thread, thread_attr, wrapper_pthread, (void*)&wp);
-       if (rv != 0)
-               return(rv);
-       
-       sem_wait(&stopper);
-       return (wp.errcode);
-}
-
-int frsh_vres_get_usage
-  (const frsh_vres_id_t vres,
-   frsh_rel_time_t *spent)
-{
-       return FRSH_ERR_NOT_IMPLEMENTED;
-}
-
-int frsh_vres_get_job_usage
-  (const frsh_vres_id_t vres,
-   frsh_rel_time_t *spent)
-{
-       return FRSH_ERR_NOT_IMPLEMENTED;
-}
-
-int frsh_vres_get_remaining_budget
-  (const frsh_vres_id_t vres,
-   frsh_rel_time_t *budget)
-{
-       return FRSH_ERR_NOT_IMPLEMENTED;
-}
-
-int frsh_feedback_get_spare
-  (frsh_contract_t *spare_contract)
-{
-       return FRSH_ERR_NOT_IMPLEMENTED;
-}
-
-int frsh_feedback_set_spare
-  (const frsh_contract_t *spare_contract)
-{
-       return FRSH_ERR_NOT_IMPLEMENTED;
-}
-
-int frsh_feedback_get_desired_budget
-  (frsh_vres_id_t vres_id,
-   frsh_rel_time_t *p_budget_out)
-{
-       return FRSH_ERR_NOT_IMPLEMENTED;
-}
-
-int frsh_feedback_set_desired_budget
-  (frsh_vres_id_t vres_id,
-   frsh_rel_time_t *p_budget_in)
-{
-       return FRSH_ERR_NOT_IMPLEMENTED;
-}
-
-int frsh_feedback_get_actual_budget
-  (frsh_vres_id_t vres_id,
-   frsh_rel_time_t *budget)
-{
-       return FRSH_ERR_NOT_IMPLEMENTED;
-}
-
diff --git a/resources/disk_bfq/Makefile b/resources/disk_bfq/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
+
diff --git a/resources/disk_bfq/Makefile.omk b/resources/disk_bfq/Makefile.omk
new file mode 100644 (file)
index 0000000..6374147
--- /dev/null
@@ -0,0 +1,10 @@
+default_CONFIG = CONFIG_DISKBFQ=x
+default_CONFIG = CONFIG_DISKBFQ_SCHED_NAME="bfq"
+default_CONFIG = CONFIG_DISKBFQ_QUEUE_PATH="/sys/class/block/%s/queue/"
+default_CONFIG = CONFIG_DISKBFQ_SCHED_PATH="scheduler"
+default_CONFIG = CONFIG_DISKBFQ_BUDGET_PATH="iosched/budget"
+
+ifeq ($(CONFIG_DISKBFQ),y)
+SUBDIRS = lib mngr #tests
+CFLAGS+= -Wall -Wextra -D_REENTRANT
+endif
diff --git a/resources/disk_bfq/README b/resources/disk_bfq/README
new file mode 100644 (file)
index 0000000..a7984f7
--- /dev/null
@@ -0,0 +1,4 @@
+Prerequisites
+
+TODO: write down something about BFQ.
+
diff --git a/resources/disk_bfq/lib/Makefile b/resources/disk_bfq/lib/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
+
diff --git a/resources/disk_bfq/lib/Makefile.omk b/resources/disk_bfq/lib/Makefile.omk
new file mode 100644 (file)
index 0000000..0aee03e
--- /dev/null
@@ -0,0 +1,7 @@
+shared_LIBRARIES = frshdiskbfq
+frshdiskbfq_SOURCES += diskbfq_contract.c diskbfq_fra.c disk_block.c
+include_HEADERS += diskbfq_contract.h diskbfq_res.h res_disk.h
+include_GEN_HEADERS = res_disk_idl.h
+frshdiskbfq_LIBS += fra
+frshdiskbfq_CLIENT_IDL = res_disk_idl.idl
+
diff --git a/resources/disk_bfq/lib/disk_block.c b/resources/disk_bfq/lib/disk_block.c
new file mode 100644 (file)
index 0000000..d9165da
--- /dev/null
@@ -0,0 +1,71 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FRSH (FRescor ScHeduler)                        */
+/*                                                                       */
+/* FRSH is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FRSH is distributed in the hope that it will be       */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty   */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   */
+/* General Public License for more details. You should have received a   */
+/* copy of the GNU General Public License along with FRSH; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FRSH header files in a file,        */
+/* instantiating FRSH generics or templates, or linking other files      */
+/* with FRSH objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   disk_block.c
+ * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ * 
+ * @brief  Description contract blocks specific to dummy resource
+ * 
+ * 
+ */
+#include <res_disk.h>
+#include <fres_container.h>
+
+static const struct fres_block_desc disk_block_desc = {
+       .name = "disk_sched",
+       .size = sizeof(fres_block_disk_sched),
+       .serialize = (fres_block_serialize_fnc_t*)fres_block_disk_sched_serialize,
+       .deserialize = (fres_block_deserialize_fnc_t*)fres_block_disk_sched_deserialize,
+       .duplicate = fres_block_duplicate_default
+};
+
+int fres_block_register_disk_sched()
+{
+       return fres_block_register(FRES_BLOCK_DISK_SCHED,
+                                  &disk_block_desc);
+}
+
diff --git a/resources/disk_bfq/lib/diskbfq_contract.c b/resources/disk_bfq/lib/diskbfq_contract.c
new file mode 100644 (file)
index 0000000..77787dd
--- /dev/null
@@ -0,0 +1,15 @@
+#include "diskbfq_contract.h"
+
+int get_diskbfq_params(fres_vres_t *vres, diskbfq_params_t *params)
+{
+       fres_block_basic *basic;
+               
+       /* get params from contract */
+       basic = fres_contract_get_basic(vres->new);
+       
+       params->P = timespec_to_usec(basic->period);
+       params->Q = timespec_to_usec(basic->budget);
+
+       return 0;
+}
+
diff --git a/resources/disk_bfq/lib/diskbfq_contract.h b/resources/disk_bfq/lib/diskbfq_contract.h
new file mode 100644 (file)
index 0000000..b53a2fd
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef DISKBFQ_CONTRACT_H
+#include <fra_generic.h>
+
+typedef 
+struct diskbfq_params_t {
+       long long P;
+       long long Q;
+} diskbfq_params_t;
+
+int get_diskbfq_params(fres_vres_t *vres, diskbfq_params_t *params);
+
+#endif /* DISKBFQ_CONTRACT_H */
diff --git a/resources/disk_bfq/lib/diskbfq_fra.c b/resources/disk_bfq/lib/diskbfq_fra.c
new file mode 100644 (file)
index 0000000..670f804
--- /dev/null
@@ -0,0 +1,302 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FRESCOR CPUCG (cpu control group)               */
+/*                                                                       */
+/* FWP is free software; you can redistribute it and/or modify it        */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FWP is distributed in the hope that it will be        */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty   */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   */
+/* General Public License for more details. You should have received a   */
+/* copy of the GNU General Public License along with FWP; see file       */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including AQCPU header files in a file,       */
+/* instantiating FWP generics or templates, or linking other files       */
+/* with FWP objects to produce an executable application, does not       */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   diskbfq_fra.c
+ * @author Dario Faggiolir <faggioli@gandalf.sssup.it>
+ * 
+ * @brief
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <ul_log.h>
+#include <fra_generic.h>
+#include "diskbfq_contract.h"
+#include "res_disk.h"
+
+UL_LOG_CUST(ulogd_fra_cpucg);
+//ul_log_domain_t ulogd_fra_cpucg = {UL_LOGL_MSG, "fra_cpucg"};
+
+static int diskbfq_initialized = 0; /* initialization flag */
+
+/*
+ * Test whether BFQ disk scheduler modue is initialized 
+ */
+static inline int diskbfq_is_initialized()
+{
+       return (diskbfq_initialized == 1);
+}
+
+static int diskbfq_create_vres(fres_vres_t *vres, void *priv)
+{
+       fres_block_basic *basic;
+       fres_block_disk_sched *disk_sched;
+       char id[40];
+
+       /*
+        * for disk, reserving the bandwidth does not
+        * make any sense.
+        *
+        * All that we must do is prepare the
+        * vres storing the I/O priority the thread that
+        * will be bound to it will acquire.
+        */
+       fres_contract_id_to_string(id, &vres->id, sizeof(id));
+       basic = fres_contract_get_basic(vres->new);
+       disk_sched = fres_contract_get_disk_sched(vres->new);
+       if (!(vres->priv = malloc(sizeof(int))))
+               return -1;
+
+       memcpy(vres->priv, &disk_sched->ioprio, sizeof(int));
+       printf("Created BFQ VRES (ioprio=%d budget=%ld ms, period=%ld ms)\n",
+              disk_sched->ioprio,
+              fosa_rel_time_to_msec(basic->budget),
+              fosa_rel_time_to_msec(basic->period));
+
+       return 0;
+}
+
+static int diskbfq_cancel_vres(fres_vres_t *vres, void *priv)
+{
+       if (!vres->priv) {
+               errno = -EINVAL;
+               return -1;
+       }
+
+       /*
+        * As before, it is not possible to "free" disk
+        * bandwidth.
+        *
+        * All that we do is free vres memory, the bandwidth
+        * is automatically released when the thread is unbound
+        * from the vres itself.
+        */
+       printf("Canceled DISK VRES (ioprio=%d)\n", *((int*)vres->priv));
+       free(vres->priv);
+
+       return 0;
+}
+
+static
+int diskbfq_change_vres(fres_vres_t *vres, void *priv)
+{
+       fres_block_disk_sched *disk_sched;
+
+       if (!vres->priv) {
+               errno = -EINVAL;
+               return -1;
+       }
+
+       disk_sched = fres_contract_get_disk_sched(vres->new);
+       printf("Changed BFQ VRES from ioprio=%d to ioprio=%d\n",
+              *((int*)vres->priv), (int) disk_sched->ioprio);
+       memcpy(vres->priv, &disk_sched->ioprio, sizeof(int));
+
+       return 0;
+}
+
+int diskbfq_fra_exit()
+{
+       return 0;
+}
+
+static
+int fra_DISK_bind_thread
+  (fres_vres_t *vres,
+   const fosa_thread_id_t thread)
+{
+       fres_block_basic *b;
+       int ret, ioprio = *((int*)vres->priv);
+       struct fres_contract *contract = vres->perceived;
+
+       b = fres_contract_get_basic(contract);
+       if (b->contract_type == FRSH_CT_REGULAR)
+           ioprio = DISKBFQ_IOPRIO_DEFAULT;
+       else if (b->contract_type == FRSH_CT_BACKGROUND)
+                ioprio |= IOPRIO_CLASS_IDLE << IOPRIO_CLASS_SHIFT;
+       else
+               goto err;
+
+       /* ret = ioprio_set(IOPRIO_WHO_PROCESS, gettid(), ioprio); */
+       ret = syscall(__NR_ioprio_set, IOPRIO_WHO_PROCESS,
+                     syscall(__NR_gettid), ioprio);
+       if (ret) goto err;
+
+       return 0;
+err:
+       return -1;
+}
+
+static
+int fra_DISK_unbind_thread(const fosa_thread_id_t thread)
+{
+       int ret;
+
+       /* ret = ioprio_set(IOPRIO_WHO_PROCESS, gettid(), IOPRIO_DEFAULT); */
+       ret = syscall(__NR_ioprio_set, IOPRIO_WHO_PROCESS,
+                     syscall(__NR_gettid), IOPRIO_PRIO_DEFAULT);
+       if (ret)
+               return -1;
+
+       return 0;
+}
+
+static
+int fra_DISK_get_usage
+  (const fres_vres_t *vres,
+   fosa_rel_time_t *spent)
+{
+       return -1;
+}
+
+static
+int fra_DISK_get_job_usage
+  (const fres_vres_t *vres,
+   fosa_rel_time_t *spent)
+{
+       return -1;
+}
+
+static
+int fra_DISK_get_remaining_budget
+  (const fres_vres_t *vres,
+   fosa_rel_time_t *budget)
+{
+       return -1;
+}
+
+static
+int fra_DISK_set_spare_bandwidth
+  (fres_vres_t *vres)
+{
+       return -1;
+}
+
+static
+int fra_DISK_get_desired_budget
+  (fres_vres_t *vres,
+   frsh_rel_time_t *p_budget_out)
+{
+       return -1;
+}
+
+static
+int fra_DISK_set_desired_budget
+  (fres_vres_t *vres,
+   fosa_rel_time_t *p_budget_in)
+{
+       return -1;
+}
+
+static
+int fra_DISK_get_actual_budget
+  (fres_vres_t *vres,
+   fosa_rel_time_t *budget)
+{
+       return -1;
+}
+
+static struct fres_allocator diskbfq_allocator = {
+       .res_type = FRSH_RT_DISK,
+       .res_id = 0,  /* DISK ID 0 */
+       .create_vres = diskbfq_create_vres,
+       .cancel_vres = diskbfq_cancel_vres,
+       .change_vres = diskbfq_change_vres,
+
+       .bind_thread = fra_DISK_bind_thread,
+       .unbind_thread = fra_DISK_unbind_thread,
+
+       .vres_get_usage = fra_DISK_get_usage,
+       .vres_get_job_usage = fra_DISK_get_job_usage,
+       .vres_get_remaining_budget = fra_DISK_get_remaining_budget,
+
+       .set_spare_bandwidth = fra_DISK_set_spare_bandwidth,
+       .get_desired_budget = fra_DISK_get_desired_budget,
+       .set_desired_budget = fra_DISK_set_desired_budget,
+       .get_actual_budget = fra_DISK_get_actual_budget,
+
+       .priv = NULL
+};
+
+/*
+ * diskbfq_fra_init()
+ *
+ * initialize FRSH for the calling process
+ *
+ * Must be called before starting using the framework.
+ * No FRSH call will be successful if this routine is not invoked
+ *
+ * Note that no BACKGROUND is created and negotiated and the caller thread
+ * is bound to no BACKGROUND vres, since no way is provided in order of
+ * specifying the contract label and get back the vres id!
+ *
+ * Note also that, since in this implementation the threads/processes with
+ * backgound contracts are left into the default Linux scheduler hands' and
+ * not attached to any AQuoSA server, while we're violating what D-AC2v1
+ * (pag. 14) says, we achieve exactly the same behaviour!!
+ *
+ * possible return values:
+ *  FRSH_NO_ERROR
+ *  FRSH_ERR_ALREADY_INITIALIZED
+ *  FRSH_ERR_INTERNAL_ERROR (something, different from the previous case, gone wrong)
+ */
+int diskbfq_fra_init(void)
+{
+       if (diskbfq_is_initialized()) {
+               return -1;
+       }
+
+       fres_block_register_disk_sched();
+       if (fra_register(&diskbfq_allocator)) {
+               return -1;
+       }
+       
+       diskbfq_initialized = 1;
+       return 0;
+}
+
diff --git a/resources/disk_bfq/lib/diskbfq_res.h b/resources/disk_bfq/lib/diskbfq_res.h
new file mode 100644 (file)
index 0000000..a7cdb8a
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef DISKBFQ_RES_H
+#define DISKBFQ_RES_H
+
+#include <forb.h>
+#include <fcb.h>
+#include <frsh_core.h>
+
+int diskbfq_fra_init(void);
+
+int fra_DISK_bind_thread(fres_vres_t *vres, fosa_thread_id_t thread);
+int fra_DISK_unbind_thread(fosa_thread_id_t thread);
+
+int fra_DISK_get_usage(const fres_vres_t *vres,
+                      fosa_rel_time_t *spent);
+int fra_DISK_get_job_usage(const fres_vres_t *vres,
+                          fosa_rel_time_t *spent);
+int fra_DISK_get_remaining_budget(const fres_vres_t *vres,
+                                 fosa_rel_time_t *budget);
+
+int fra_DISK_set_spare_bandwidth(fres_vres_t *vres);
+
+int fra_DISK_get_desired_budget(fres_vres_t *vres,
+                               frsh_rel_time_t *p_budget_out);
+int fra_DISK_set_desired_budget(fres_vres_t *vres,
+                               fosa_rel_time_t *p_budget_in);
+int fra_DISK_get_actual_budget(fres_vres_t *vres,
+                              fosa_rel_time_t *budget);
+
+#endif /* DISKBFQ_RES_H */
+
diff --git a/resources/disk_bfq/lib/res_disk.h b/resources/disk_bfq/lib/res_disk.h
new file mode 100644 (file)
index 0000000..174f667
--- /dev/null
@@ -0,0 +1,114 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FRSH (FRescor ScHeduler)                        */
+/*                                                                       */
+/* FRSH is free software; you can redistribute it and/or modify it       */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FRSH is distributed in the hope that it will be       */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty   */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   */
+/* General Public License for more details. You should have received a   */
+/* copy of the GNU General Public License along with FRSH; see file      */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FRSH header files in a file,        */
+/* instantiating FRSH generics or templates, or linking other files      */
+/* with FRSH objects to produce an executable application, does not      */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+
+/**
+ * @file   res_disk.h
+ * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ * 
+ * @brief  Disk resource declarations
+ * 
+ * 
+ */
+
+#ifndef RES_DISK_H
+#define RES_DISK_H
+
+#include <unistd.h>
+#include <linux/unistd.h>
+#include <sys/syscall.h>
+#include <asm/unistd.h>
+
+#include <forb.h>
+#include <fcb.h>
+#include <res_disk_idl.h>
+#include <fres_contract.h>
+#include <fres_container.h>
+
+enum {
+       IOPRIO_CLASS_NONE,
+       IOPRIO_CLASS_RT,
+       IOPRIO_CLASS_BE,
+       IOPRIO_CLASS_IDLE,
+};
+
+enum {
+       IOPRIO_WHO_PROCESS = 1,
+       IOPRIO_WHO_PGRP,
+       IOPRIO_WHO_USER,
+};
+
+#define IOPRIO_CLASS_SHIFT     13
+/**
+ * @FIXME:
+ *   Why all these can't be config parameters?
+ **/
+//#define SYSFS_BFQ_NAME       CONFIG_DISKBFQ_SCHED_NAME       /* default  = "bfq" */
+//#define SYSFS_BFQ_BASIC_PATH CONFIG_DISKBFQ_QUEUE_PATH       /* default = "/sys/class/block/%s/queue" */
+//#define SYSFS_BFQ_SCHED_PATH CONFIG_DISKBFQ_QUEUE_PATH CONFIG_DISKBFQ_SCHED_PATH
+//#define SYSFS_BFQ_BUDGET_PATH        CONFIG_DISKBFQ_QUEUE_PATH CONFIG_DISKBFQ_BUDGET_PATH    /* default = CONFIG_DISKBFQ_QUEUE_PATH "iosched/budget" */
+#define SYSFS_BFQ_NAME         "bfq"
+#define SYSFS_BFQ_BASIC_PATH   "/sys/block/%s/queue/"
+#define SYSFS_BFQ_SCHED_PATH   SYSFS_BFQ_BASIC_PATH "scheduler"
+#define SYSFS_BFQ_BUDGET_PATH  SYSFS_BFQ_BASIC_PATH "iosched/max_budget"
+
+#define DISKBFQ_WEIGHT_MAX     100
+
+#define IOPRIO_PRIO_DEFAULT    4
+#define IOPRIO_CLASS_DEFAULT   IOPRIO_CLASS_BE
+#define DISKBFQ_IOPRIO_DEFAULT \
+       (IOPRIO_PRIO_DEFAULT || (IOPRIO_CLASS_DEFAULT << IOPRIO_CLASS_SHIFT))
+
+int fra_disk_init(void);
+int fres_block_register_disk_sched(void);
+
+/* Define fres_container_(add|get|del)_disk_sched. */
+FRES_CONTAINER_ACCESSOR(DUMMY_SCHED, disk_sched);
+
+/* Define fres_contract_(add|get|del)_disk_sched. */
+FRES_CONTRACT_ACCESSOR(disk_sched);
+
+#endif
+
diff --git a/resources/disk_bfq/lib/res_disk_idl.idl b/resources/disk_bfq/lib/res_disk_idl.idl
new file mode 100644 (file)
index 0000000..406d3b5
--- /dev/null
@@ -0,0 +1,72 @@
+////////////////////////////////////////////////////////////////////////////
+// ---------------------------------------------------------------------- //
+// Copyright (C) 2006 - 2008 FRESCOR consortium partners:                //
+//                                                                       //
+//   Universidad de Cantabria,              SPAIN                        //
+//   University of York,                    UK                           //
+//   Scuola Superiore Sant'Anna,            ITALY                        //
+//   Kaiserslautern University,             GERMANY                      //
+//   Univ. Politécnica  Valencia,           SPAIN                       //
+//   Czech Technical University in Prague,  CZECH REPUBLIC               //
+//   ENEA                                   SWEDEN                       //
+//   Thales Communication S.A.              FRANCE                       //
+//   Visual Tools S.A.                      SPAIN                        //
+//   Rapita Systems Ltd                     UK                           //
+//   Evidence                               ITALY                        //
+//                                                                       //
+//   See http://www.frescor.org for a link to partners' websites         //
+//                                                                       //
+//          FRESCOR project (FP6/2005/IST/5-034026) is funded            //
+//       in part by the European Union Sixth Framework Programme         //
+//       The European Union is not liable of any use that may be         //
+//       made of this code.                                              //
+//                                                                       //
+//                                                                       //
+// based on previous work (FSF) done in the FIRST project                //
+//                                                                       //
+//  Copyright (C) 2005  Mälardalen University, SWEDEN                   //
+//                      Scuola Superiore S.Anna, ITALY                   //
+//                      Universidad de Cantabria, SPAIN                          //
+//                      University of York, UK                           //
+//                                                                       //
+//  FSF API web pages: http:marte.unican.es/fsf/docs                     //
+//                     http:shark.sssup.it/contrib/first/docs/           //
+//                                                                       //
+//  This file is part of FORB (Frescor Object Request Broker)            //
+//                                                                       //
+// FORB is free software; you can redistribute it and/or modify it       //
+// under terms of the GNU General Public License as published by the     //
+// Free Software Foundation; either version 2, or (at your option) any   //
+// later version.  FORB is distributed in the hope that it will be       //
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty   //
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   //
+// General Public License for more details. You should have received a   //
+// copy of the GNU General Public License along with FORB; see file      //
+// COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  //
+// Cambridge, MA 02139, USA.                                             //
+//                                                                       //
+// As a special exception, including FORB header files in a file,        //
+// instantiating FORB generics or templates, or linking other files      //
+// with FORB objects to produce an executable application, does not      //
+// by itself cause the resulting executable application to be covered    //
+// by the GNU General Public License. This exception does not            //
+// however invalidate any other reasons why the executable file might be  //
+// covered by the GNU Public License.                                    //
+////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @file   res_disk_idl.idl
+ * @author Dario Faggioli <faggioli@gandalf.sssup.it>
+ * 
+ * @brief  Contract data block for disk resource
+ * 
+ * 
+ */
+module fres {
+       module block {
+               struct disk_sched {
+                       long weight;
+                       long ioprio;
+               };
+       };
+};
diff --git a/resources/disk_bfq/mngr/Makefile b/resources/disk_bfq/mngr/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
+
diff --git a/resources/disk_bfq/mngr/Makefile.omk b/resources/disk_bfq/mngr/Makefile.omk
new file mode 100644 (file)
index 0000000..e28d529
--- /dev/null
@@ -0,0 +1,9 @@
+
+bin_PROGRAMS = frm_diskbfq
+frm_diskbfq_SOURCES = diskbfq_mngr.c diskbfq_th.c ../lib/disk_block.c
+frm_dummy_CLIENT_IDL = res_disk_idl.idl
+frm_diskbfq_LIBS = frm forb contract fosa m rt ulut fcb_client frshdiskbfq
+
+include_HEADERS = diskbfq_th.h ../lib/res_disk.h
+include_GEN_HEADERS = ../lib/res_disk_idl.h
+
diff --git a/resources/disk_bfq/mngr/diskbfq_mngr.c b/resources/disk_bfq/mngr/diskbfq_mngr.c
new file mode 100644 (file)
index 0000000..180d466
--- /dev/null
@@ -0,0 +1,287 @@
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                */
+/*                                                                       */
+/*   Universidad de Cantabria,              SPAIN                        */
+/*   University of York,                    UK                           */
+/*   Scuola Superiore Sant'Anna,            ITALY                        */
+/*   Kaiserslautern University,             GERMANY                      */
+/*   Univ. Politécnica  Valencia,           SPAIN                       */
+/*   Czech Technical University in Prague,  CZECH REPUBLIC               */
+/*   ENEA                                   SWEDEN                       */
+/*   Thales Communication S.A.              FRANCE                       */
+/*   Visual Tools S.A.                      SPAIN                        */
+/*   Rapita Systems Ltd                     UK                           */
+/*   Evidence                               ITALY                        */
+/*                                                                       */
+/*   See http://www.frescor.org for a link to partners' websites         */
+/*                                                                       */
+/*          FRESCOR project (FP6/2005/IST/5-034026) is funded            */
+/*       in part by the European Union Sixth Framework Programme         */
+/*       The European Union is not liable of any use that may be         */
+/*       made of this code.                                              */
+/*                                                                       */
+/*                                                                       */
+/*  This file is part of FRESCOR BFQ disk bandwidth reservation                  */
+/*                                                                       */
+/* FWP is free software; you can redistribute it and/or modify it        */
+/* under terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2, or (at your option) any   */
+/* later version.  FWP is distributed in the hope that it will be        */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty   */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   */
+/* General Public License for more details. You should have received a   */
+/* copy of the GNU General Public License along with FWP; see file       */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                             */
+/*                                                                       */
+/* As a special exception, including FWP header files in a file,         */
+/* instantiating FWP generics or templates, or linking other files       */
+/* with FWP objects to produce an executable application, does not       */
+/* by itself cause the resulting executable application to be covered    */
+/* by the GNU General Public License. This exception does not            */
+/* however invalidate any other reasons why the executable file might be  */
+/* covered by the GNU Public License.                                    */
+/**************************************************************************/
+#include <frm_generic.h>
+#include <forb.h>
+#include <error.h>
+#include <errno.h>
+#include <fres_sa_scenario.h>
+#include <stdbool.h>
+#include <ul_log.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "res_disk.h"
+#include "diskbfq_th.h"
+
+UL_LOG_CUST(ulogd_frm_diskbfq);
+ul_log_domain_t ulogd_fra_fwp = {UL_LOGL_DEB, "frm_diskbfq"};
+
+struct disk_data {
+       double throughput;
+       int budget;
+};
+
+static int bandwidth_to_weight(struct disk_data *data,
+                              unsigned long budget,
+                              unsigned long period)
+{
+       float th, weight;
+       //unsigned long q_i, p_i;
+       int b, w_i;
+
+       th = data->throughput / 10E9;
+       b = data->budget;
+
+       /* Convert to nanoseconds! */
+       //q_i *= 1000;
+       //p_i *= 1000;
+
+       if (period < b / th)
+               return -1;
+
+       weight = (DISKBFQ_WEIGHT_MAX * budget) / (period - (b / th));
+       w_i = floor(weight);
+       if (weight != w_i)
+               w_i++;
+
+       return w_i;
+}
+
+static int weight_to_ioprio(int weight)
+{
+       if (weight >= 100)
+               return 0;
+       if (weight > 14)
+               return 1;
+       if (weight == -1)
+               return -1;
+
+       return 8 - 1 - (weight / 2);
+}
+
+static int diskbfq_admtest(struct fres_sa_scenario *scenario,
+                          void *priv, 
+                          bool *schedulable)
+{
+       struct fres_sa_contract *c;
+       long int period, budget;
+       long int sum_weight = 0;
+       struct disk_data *data = priv;
+
+       fres_sa_scenario_for_each_contract(scenario, c) {
+               fres_block_basic *basic;
+               fres_block_resource *resource;
+               fres_block_disk_sched *disk_sched;
+               char id[40];
+
+               fres_contract_id_to_string(id, &c->contract->id, sizeof(id));
+               basic = fres_contract_get_basic(c->contract);
+               resource = fres_contract_get_resource(c->contract);
+
+               period = fosa_rel_time_to_nsec(basic->period);
+               budget = fosa_rel_time_to_nsec(basic->budget);
+               printf("processing: id=%s, period=%ld ms, budget=%ld ms\n",
+                      id, period, budget);
+
+               if (c->contract == c->new) {
+                       int ret;
+
+                       /* Calc weight and IO prio for the new contracts */
+                       disk_sched = malloc(sizeof(*disk_sched));
+                       if (!disk_sched) return -1;
+
+                       disk_sched->weight = bandwidth_to_weight(data,
+                                                                budget,
+                                                                period);
+                       disk_sched->ioprio =
+                               weight_to_ioprio(disk_sched->weight);
+                       ret = fres_contract_add_disk_sched(c->contract,
+                                                          disk_sched);
+                       if (ret) {
+                               fprintf(stderr,
+                                       "Cannot add disk_sched block\n");
+                               free(disk_sched);
+                               return -1;
+                       }
+               } else {
+                       disk_sched = fres_contract_get_disk_sched(c->contract);
+                       if (!disk_sched) {
+                               fprintf(stderr,
+                                       "disk_sched is not present\n");
+                               return -1;
+                       }
+               }
+               sum_weight += disk_sched->weight;
+       }
+
+       printf("sum_weight=%ld, max_weight=%d\n",
+              sum_weight,
+              DISKBFQ_WEIGHT_MAX);
+       *schedulable = sum_weight < DISKBFQ_WEIGHT_MAX;
+       printf("=>%s\n", (*schedulable) ? "schedulable" : "not schedulable");
+
+       return 0;
+}
+
+struct disk_data disk;
+
+static struct fres_res_manager frm = {
+       .res_type = FRSH_RT_DISK,
+       .res_id = 0,
+       .admission_test = diskbfq_admtest,
+       .priv = &disk
+};
+
+int main(int argc, char *argv[])
+{
+       forb_init_attr_t attr = { .orb_id = "org.frescor.frm.diskbfq" };
+       forb_orb orb;
+       FILE* fd;
+       int readers = 4;
+       char disk_dev[40], *disk_name = disk_dev;
+       char path[128], scheduler[128];
+       int i, opt, ret;
+
+       if (argc < 3) {
+err_usage:
+               fprintf(stderr, "Usage:\n %s "
+                       "-i disk_id -d disk_device [-n readers]\n",
+                       argv[0]);
+               error(1, EINVAL, "frm_diskbfq");
+       }
+
+       while ((opt = getopt(argc, argv, "i:d:n:")) != -1) {
+               switch (opt) {
+                       case 'i':
+                               frm.res_id = atoi(optarg);
+                               break;
+                       case 'd':
+                               strncpy(disk_dev,
+                                       optarg, sizeof(disk_dev));
+
+                               for (i = strlen(disk_dev) - 1; i >= 0; i--) {
+                                       if (disk_dev[i] == '/') {
+                                               disk_name = disk_dev + i + 1;
+                                               break;
+                                       }
+                               }
+                               break;
+                       case 'n':
+                               readers = atoi(optarg);
+                               break;
+                       default:
+                               goto err_usage;
+               }
+       }
+
+       orb = forb_init(&argc, &argv, &attr);
+       if (!orb) error(1, errno, "forb_init");
+
+       /*
+        * Check if BFQ I/O scheduler is available
+        *  in the system.
+        */
+       snprintf(path, 128,
+                SYSFS_BFQ_SCHED_PATH,
+                disk_name);
+       if (!(fd = fopen(path, "rw")))
+               error(1, errno, "frm_generic_run");
+
+       ret = fscanf(fd, "%128[^\n]", scheduler);
+       if (ret == 0 || ret == EOF)
+               error(1, errno, "frm_generic_run");
+       if (!strstr(scheduler, SYSFS_BFQ_NAME))
+               error(1, errno, "frm_generic_run");
+
+       /**
+        * Now check if BFQ is the default I/O scheduler
+        *  for the specific disk and set it to so if not.
+        **/
+       else if (!strstr(scheduler, "[" SYSFS_BFQ_NAME "]")) {
+               rewind(fd);
+               ret = fprintf(fd, SYSFS_BFQ_NAME);
+               if (ret && ret != EOF)
+                       ret = fflush(fd);
+               if (ret == 0 || ret == EOF)
+                       error(1, errno, "frm_generic_run");
+       }
+       fclose(fd);
+
+       snprintf(path, sizeof(path),
+                SYSFS_BFQ_BUDGET_PATH,
+                disk_name);
+       if (!(fd = fopen(path, "r")))
+               error(1, errno, "frm_generic_run");
+
+       ret = fscanf(fd, "%d", &disk.budget);
+       if (ret == 0 || ret == EOF)
+               error(1, errno, "frm_generic_run");
+       fclose(fd);
+
+       /**
+        * Estimate the disk throughput in order to achieve
+        *  effective weight assignement during runtime.
+        **/
+       disk.throughput = estimate_throughput(disk_dev, readers);
+       if (disk.throughput < 0.0)
+               error(1, errno, "frm_generic_run");
+
+       fprintf(stdout, "disk name: %s\n"
+               "scheduler: %s\n"
+               "disk aggregate throughput: %f\n"
+               "scheduling budget: %d\n",
+               disk_name, SYSFS_BFQ_NAME, disk.throughput, disk.budget);
+
+       /* Register fres_block_disk_sched to contract handling
+        *  functions */
+        fres_block_register_disk_sched();
+
+       ret = frm_register_and_run(orb, &frm);
+       if (ret) error(1, errno, "frm_generic_run");
+       
+       return 0;
+}
+
diff --git a/resources/disk_bfq/mngr/diskbfq_th.c b/resources/disk_bfq/mngr/diskbfq_th.c
new file mode 100644 (file)
index 0000000..7bb3516
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * The only function of interest is:
+ *   double estimate_throughput(char *device, int streamers);
+ * @device: the device we want to test.
+ * @streamers: the number of sequential readers we're interested in.
+ */
+
+#include <diskbfq_th.h>
+
+/* given a device name, return its size in sectors */
+static int64_t read_size(char *device)
+{
+       int count, size, i;
+       int64_t rval;
+       char *path, *devname = device;
+       FILE *fp;
+
+       for (i = strlen(device) - 1; i >= 0; i--) {
+               if (device[i] == '/') {
+                       devname = device + i + 1;
+                       break;
+               }
+       }
+
+       size = sizeof(SYSFS_BASE) + strlen(devname) + sizeof("/size");
+       path = calloc(1, size);
+       if (!path)
+               return -ENOMEM;
+
+       snprintf(path, size, SYSFS_BASE "%s/size", devname);
+       fp = fopen(path, "r");
+       if (!fp) {
+               rval = -ENODEV;
+               goto err;
+       }
+
+       count = fscanf(fp, "%llu", (unsigned long long*) &rval);
+       if (count != 1)
+               rval = -EIO;
+
+       fclose(fp);
+err:
+       free(path);
+       return rval;
+}
+
+/* reader: reads from the device until stop_all becomes true */
+static void *reader_body(void *arg)
+{
+       struct reader_data *rdata = arg;
+       off_t offset = rdata->offset * 512;
+       char buffer[2 * READ_BLKSIZE], *bufptr;
+       ssize_t count;
+       int page_size;
+
+       /* O_DIRECT needs page-aligned buffer/offset/blksize */
+       page_size = sysconf(_SC_PAGESIZE);
+       bufptr = (char *)(((uintptr_t)buffer + page_size) & ~(page_size - 1));
+
+       while (!*rdata->stop) {
+               /* offset may lose alignment if a read ends prematurely */
+               offset = (offset + page_size) & ~(page_size - 1);
+
+               /* should not happen, wrap if we're too fast */
+               if (offset > READ_ROOM * 512 - READ_BLKSIZE)
+                       offset = rdata->offset * 512;
+
+               /* use pread() to share devfd among all the threads */
+               count = pread(rdata->devfd, bufptr, READ_BLKSIZE, offset);
+               if (count < 0) {
+                       rdata->error = errno;
+                       break;
+               }
+               rdata->completed += count / 512;
+               offset += count;
+       }
+
+       dprintf("reader: completed = %lld, error = %d\n",
+               rdata->completed, rdata->error);
+       return NULL;
+}
+
+/* wait for the termination of all the readers (collecting errors, if any) */
+static void wait_all(struct dprof_data *ddata, int *error)
+{
+       struct reader_data *rdata;
+       int i;
+
+       ddata->stop_all = 1;
+       for (i = 0; i < ddata->streamers; i++) {
+               rdata = ddata->reader_data + i;
+               if (!rdata->started)
+                       continue;
+               pthread_join(rdata->id, NULL);
+               if (rdata->error && error)
+                       *error = rdata->error;
+       }
+}
+
+/* create and start all the readers */
+static struct dprof_data *create_readers(int streamers, int devfd,
+                                        int64_t devsize)
+{
+       struct dprof_data *ddata;
+       struct reader_data *rdata;
+       int i, error = 0;
+       off_t step;
+
+       ddata = calloc(1, sizeof(struct reader_data) * streamers +
+                      sizeof(struct dprof_data));
+       if (!ddata)
+               return NULL;
+
+       ddata->streamers = streamers;
+
+       /* space the readers evenly over the disk surface */
+       step = (devsize - streamers * READ_ROOM) / streamers;
+
+       for (i = 0; i < streamers; i++) {
+               rdata = ddata->reader_data + i;
+               rdata->offset = step * i;
+               rdata->stop = &ddata->stop_all;
+               rdata->devfd = devfd;
+
+               error = pthread_create(&rdata->id, NULL, reader_body, rdata);
+               if (error) {
+                       wait_all(ddata, NULL);
+                       free(ddata);
+                       return NULL;
+               }
+               rdata->started = 1;
+       }
+
+       return ddata;
+}
+
+/* return the throughput, in KiB/s */
+static double calc_throughput(struct dprof_data *ddata,
+                             struct timeval *begin,
+                             struct timeval *end)
+{
+       struct reader_data *rdata;
+       double total = 0, delta;
+       int i;
+
+       for (i = 0; i < ddata->streamers; i++) {
+               rdata = ddata->reader_data + i;
+               total += rdata->completed;
+       }
+
+       delta = end->tv_usec - begin->tv_usec;
+       delta += (end->tv_sec - begin->tv_sec) * 1000000.0;
+
+       /* total is in sectors, delta in usecs, convert to KiB/s */
+       return total / delta * (512 * 1000000 / 1024);
+}
+
+double estimate_throughput(char *device, int streamers)
+{
+       struct timeval begin, end;
+       struct dprof_data *ddata;
+       double throughput = -1;
+       int64_t devsize;
+       int devfd, error = 0;
+
+       /* get device size */
+       devsize = read_size(device);
+       if (devsize < 0)
+               return -1;
+
+       /* open the device */
+       devfd = open(device, O_RDONLY | O_DIRECT);
+       if (devfd < 0)
+               return -1;
+
+       /* let the good times roll... */
+       gettimeofday(&begin, NULL);
+
+       /* start all the threads */
+       ddata = create_readers(streamers, devfd, devsize);
+       if (!ddata)
+               goto err;
+
+       /* let them read */
+       sleep(MEAS_INTERVAL);
+
+       /* wait for their completion */
+       wait_all(ddata, &error);
+
+       /* this is the end... */
+       gettimeofday(&end, NULL);
+
+       if (!error)
+               throughput = calc_throughput(ddata, &begin, &end);
+       free(ddata);
+
+err:
+       close(devfd);
+
+       return throughput;
+}
+
diff --git a/resources/disk_bfq/mngr/diskbfq_th.h b/resources/disk_bfq/mngr/diskbfq_th.h
new file mode 100644 (file)
index 0000000..c4c67b9
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE < 500)
+#define _XOPEN_SOURCE 500
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#ifdef CONFIG_DISKBFQ_DEBUG
+#define dprintf(fmt...) printf(fmt)
+#else
+#define dprintf(fmt...)
+#endif
+
+/* reserve 1GiB per client */
+#define READ_ROOM      (2048ULL * 1024)
+
+/* read 512KiB per transaction */
+#define READ_BLKSIZE   (1024ULL * 512)
+
+/* (max) 5 seconds */
+#define MEAS_INTERVAL  5
+
+#define SYSFS_BASE     "/sys/block/"
+#define DROP_CACHES    "/proc/sys/vm/drop_caches"
+
+/* per-reader descriptor */
+struct reader_data {
+       pthread_t id;
+       size_t completed;
+       off_t offset;
+       int devfd;
+       int started;
+       int error;
+       volatile int *stop;
+};
+
+/* global state, malloc'd to allow estimate_througput() to be reentrant */
+struct dprof_data {
+       int streamers;
+       volatile int stop_all;
+       struct reader_data reader_data[];
+};
+
+double estimate_throughput(char *device, int streamers);
+
diff --git a/resources/disk_bfq/tests/Makefile b/resources/disk_bfq/tests/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
+
diff --git a/resources/disk_bfq/tests/Makefile.omk b/resources/disk_bfq/tests/Makefile.omk
new file mode 100644 (file)
index 0000000..f93b82b
--- /dev/null
@@ -0,0 +1,4 @@
+test_PROGRAMS = cpucgtest
+cpucgtest_SOURCES = cpucgtest.c
+#aqcpumngr_LIBS = frm forb contract fosa rt ulut fcb_client
+lib_LOADLIBES += pthread rt frshcpucg frsh 
diff --git a/resources/disk_bfq/tests/config.omk b/resources/disk_bfq/tests/config.omk
new file mode 100644 (file)
index 0000000..6b8084f
--- /dev/null
@@ -0,0 +1,7 @@
+CONFIG_DISKBFQ=y
+CFLAGS+=-save-temps
+CONFIG_FWP=n
+CONFIG_RESOURCE_DUMMY=n
+CONFIG_RESOURCE_ITEM=n
+CONFIG_RESOURCE_CLUSTER_TREE=n
+
diff --git a/resources/disk_bfq/tests/diskbfq.c b/resources/disk_bfq/tests/diskbfq.c
new file mode 100644 (file)
index 0000000..2951b4e
--- /dev/null
@@ -0,0 +1,62 @@
+#include <frsh.h>
+#include <diskbfq_res.h>
+#include <error.h>
+
+void* work_thread()
+{
+       int i;
+
+       printf("I am alive! \n");
+       while(1) {
+               printf("I am alive! \n");
+               i++;
+
+       }
+
+}
+
+int main()
+{
+       frsh_vres_id_t vres;
+       frsh_thread_attr_t attr;
+       frsh_thread_id_t thread;
+       frsh_contract_t contract;
+       frsh_rel_time_t budget, period;
+       int ret;
+
+       if (frsh_init()) {
+               error(1, 0, "FRSH initialization failed\n");
+
+       }
+       
+       /* Contract negotiation for CPU */
+       ret = frsh_contract_init(&contract);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_init");
+               
+       budget = fosa_msec_to_rel_time(50);
+       period = fosa_msec_to_rel_time(100);
+       ret = frsh_contract_set_basic_params(&contract,
+                                            &budget,
+                                            &period,
+                                            FRSH_WT_BOUNDED,
+                                            FRSH_CT_REGULAR);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_basic_params");
+       ret = frsh_contract_set_resource_and_label(&contract, FRSH_RT_DISK,
+                                                       0,"aqcpu_cont1");
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_resource_and_label");
+
+       ret = frsh_contract_negotiate(&contract, &vres);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_contract_negotiate");
+
+       printf("Disk (BFQ) vres negotiated\n");
+       pthread_attr_init(&attr);
+       ret = frsh_thread_create_and_bind(vres, &thread, &attr, 
+                               work_thread, (void*) NULL);
+       if (ret) PERROR_AND_EXIT(ret, "frsh_thread_create_and_bind");
+       
+       pthread_join(thread.pthread_id, (void**) NULL); 
+       printf("Test PASSED!\n");
+               
+       return 0;       
+}
+
index 1700e926856677cfb5f087eda505d88d6177c3d1..0fe5fe142ef197851b93efe8ab31fcb87267755c 100644 (file)
@@ -143,8 +143,8 @@ int main(int argc, char *argv[])
 {
        forb_orb orb;
        int ret;
-
-       orb = forb_init(&argc, &argv, "frm_dummy");
+       forb_init_attr_t attr = { .orb_id = "org.frescor.frm.dummy" };
+       orb = forb_init(&argc, &argv, &attr);
        if (!orb) error(1, errno, "forb_init");
 
        /* Register fres_block_dummy_sched to contract handling
index c82ca328bcd44f94ab0d9037f5542aef1a820012..4ec8f9c8cc593c3fe51d5ace615bb5657d0232ea 100644 (file)
@@ -113,8 +113,8 @@ int main(int argc, char *argv[])
 {
        forb_orb orb;
        int ret;
-
-       orb = forb_init(&argc, &argv, "frm_fpga");
+       forb_init_attr_t attr = { .orb_id = "org.frescor.frm.fpga" };
+       orb = forb_init(&argc, &argv, &attr);
        if (!orb) error(1, errno, "forb_init");
 
        /* Register fres_block_fpga to contract handling
index cfe4db7657137ef7569baeb196dd22a8fbc2dad5..4b02479c5cb6d680db73fc757bcaafb51102201a 100644 (file)
@@ -239,8 +239,8 @@ int main(int argc, char *argv[])
        char platform[]="telosb";       
        char *parametrsITEM[] ={NULL,device,platform};
 
-
-       orb = forb_init(&argc, &argv, "frm_item");
+       forb_init_attr_t attr = { .orb_id = "org.frescor.frm.item" };
+       orb = forb_init(&argc, &argv, &attr);
        if (!orb) error(1, errno, "forb_init");