+++ /dev/null
-From: Michal Sojka <sojkam1@fel.cvut.cz>
-Subject: [PATCH] api-enhancements
-
-<patch description>
-
-Signed-off-by: Michal Sojka <sojkam1@fel.cvut.cz>
-default_CONFIG = CONFIG_DEMO_CAMERA=n CONFIG_DEMO_DCAMERA=y
+default_CONFIG = CONFIG_DEMO_VIDEO=y CONFIG_DEMO_CAMERA=n CONFIG_DEMO_DCAMERA=y
SUBDIRS=$(SUBDIRS-y)
+SUBDIRS-$(CONFIG_DEMO_VIDEO) += video
SUBDIRS-$(CONFIG_DEMO_CAMERA) += camera
SUBDIRS-$(CONFIG_DEMO_DCAMERA) += dcamera
+
--- /dev/null
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+ @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
--- /dev/null
+FRSH_LIBS = frsh
+lib_LOADLIBES+= m pthread rt $(FRSH_LIBS)
+
+bin_PROGRAMS = fplayer
+fplayer_SOURCES = play.c play.h
+
+bin_PROGRAMS += fplayer_th
+fplayer_th_SOURCES = play_th.c play_th.h
+
--- /dev/null
+#include "play.h"
+
+frsh_rel_time_t player_budget, player_period;
+frsh_contract_t player_contract;
+frsh_thread_id_t player_thread;
+frsh_vres_id_t player_vres;
+
+sem_t *player_stopper;
+int stopper_fd;
+
+void player(struct player_args *args)
+{
+ char cmd[255];
+
+ fprintf(stdout, "== Waiting for being bound...\n");
+
+ sem_wait(player_stopper);
+ munmap(player_stopper, sizeof(sem_t));
+
+ fprintf(stdout,
+ "== Starting playing %s, with %d/%d CPU bandwidth\n",
+ args->file, args->budget, args->period);
+
+ snprintf(cmd, 255, PLAYER_BINARY PLAYER_ARGS " %s", args->file);
+ fprintf(stdout, "== Issuing command:\n %s\n", cmd);
+
+ execlp(PLAYER_BINARY, PLAYER_BINARY, PLAYER_ARGS, args->file, (char*) NULL);
+}
+
+int main(int argc, char *argv[])
+{
+ struct player_args args;
+ int player_status;
+ pid_t player_pid;
+ int opt, terror;
+
+ if (argc < 7) {
+err_usage:
+ fprintf(stderr, "USAGE:\n"
+ "%s -b budget_usec -p period_usec -f file\n\n",
+ argv[0]);
+ error(EXIT_FAILURE, EINVAL, "Wrong argument count");
+ }
+
+ while ((opt = getopt(argc, argv, "b:p:f:")) != -1) {
+ switch (opt) {
+ case 'b':
+ args.budget = atoi(optarg);
+ break;
+ case 'p':
+ args.period = atoi(optarg);
+ break;
+ case 'f':
+ strncpy(args.file, optarg, sizeof(args.file));
+ break;
+ default:
+ goto err_usage;
+ }
+ }
+
+ PXW(frsh_init());
+
+ stopper_fd = shm_open("/stopper", O_CREAT|O_EXCL|O_RDWR, S_IRWXU);
+ if (stopper_fd < 0) assert_perror(errno);
+
+ terror = ftruncate(stopper_fd, sizeof(sem_t));
+ if (terror) {
+ shm_unlink("/stopper");
+ assert_perror(errno);
+ }
+
+ player_stopper = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE,
+ MAP_SHARED, stopper_fd, 0);
+ if (player_stopper == MAP_FAILED) {
+ shm_unlink("/stopper");
+ assert_perror(errno);
+ }
+
+ terror = close(stopper_fd);
+ if (terror) {
+ shm_unlink("/stopper");
+ assert_perror(errno);
+ }
+
+ sem_init(player_stopper, 1, 0);
+ fprintf(stderr, "FRSH initialized\n");
+
+ player_budget = fosa_usec_to_rel_time(args.budget);
+ player_period = fosa_usec_to_rel_time(args.period);
+ PXW(frsh_contract_init(&player_contract));
+ PXW(frsh_contract_set_basic_params(&player_contract,
+ &player_budget,
+ &player_period,
+ FRSH_WT_INDETERMINATE,
+ FRSH_CT_REGULAR));
+ PXW(frsh_contract_set_resource_and_label(&player_contract,
+ FRSH_RT_PROCESSOR,
+ 0,
+ "PLAYER_CONTRACT"));
+ fprintf(stdout, "Player contract initialized\n");
+
+ PXW(frsh_contract_negotiate(&player_contract, &player_vres));
+ fprintf(stdout, "Player contract negotiated\n");
+
+ terror = player_pid = fork();
+ if (terror < 0) {
+ /* error */
+ assert_perror(errno);
+ } else if (!terror) {
+ /* child process: */
+ player(&args);
+ }
+
+ player_thread.linux_pid = player_thread.linux_tid = player_pid;
+ PXW(frsh_thread_bind(player_vres, player_thread));
+ fprintf(stdout, "Player thread bound to its contract\n");
+
+ sem_post(player_stopper);
+ munmap(player_stopper, sizeof(sem_t));
+ shm_unlink("/stopper");
+
+ waitpid(player_pid, &player_status, 0);
+ if (WIFEXITED(player_status))
+ fprintf(stdout, "Playback finished normally\n");
+ else if (WIFSIGNALED(player_status))
+ fprintf(stdout, "Playback aborted\n");
+
+ PXW(frsh_contract_cancel(player_vres));
+
+ exit(EXIT_SUCCESS);
+}
+
--- /dev/null
+#ifndef _PLAY_H_
+#define _PLAY_H_
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <error.h>
+#include <assert.h>
+#include <semaphore.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include <frsh.h>
+
+#define PLAYER_BINARY "mplayer"
+#define PLAYER_ARGS " -fs -zoom "
+
+struct player_args {
+ int budget, period;
+ char file[128];
+};
+
+void player(struct player_args *args);
+
+#endif /* _PLAY_H_ */
+
--- /dev/null
+#include "play_th.h"
+
+static void player_cleanup(void *arg)
+{
+ frsh_vres_id_t vres;
+
+ frsh_thread_get_vres_id(fosa_thread_self(), &vres);
+ frsh_contract_cancel(vres);
+}
+
+void *player(void *thread_args)
+{
+ struct player_args *args = (struct player_args*) thread_args;
+
+ frsh_rel_time_t player_budget, player_period;
+ frsh_contract_t player_contract;
+ frsh_vres_id_t player_vres;
+
+ int terror, status;
+ char cmd[255];
+
+ fprintf(stdout, "== Waiting for being bound...\n");
+
+ fprintf(stdout,
+ "== Starting playing %s, with %d/%d CPU bandwidth\n",
+ args->file, args->budget, args->period);
+
+ player_budget = fosa_usec_to_rel_time(args->budget);
+ player_period = fosa_usec_to_rel_time(args->period);
+ PXW(frsh_contract_init(&player_contract));
+ PXW(frsh_contract_set_basic_params(&player_contract,
+ &player_budget,
+ &player_period,
+ FRSH_WT_INDETERMINATE,
+ FRSH_CT_REGULAR));
+ PXW(frsh_contract_set_resource_and_label(&player_contract,
+ FRSH_RT_PROCESSOR,
+ 0,
+ "PLAYER_CONTRACT"));
+ fprintf(stdout, "== Player contract initialized\n");
+
+ PXW(frsh_contract_negotiate(&player_contract, &player_vres));
+ fprintf(stdout, "== Player contract negotiated\n");
+
+ pthread_cleanup_push(player_cleanup, NULL);
+
+ PXW(frsh_thread_bind(player_vres, fosa_thread_self()));
+ fprintf(stdout, "== Player thread bound to its contract\n");
+
+ snprintf(cmd, 255, PLAYER_BINARY PLAYER_ARGS " %s", args->file);
+
+ fprintf(stdout, "== Issuing command:\n %s\n", cmd);
+
+ status = system(cmd);
+
+ if (WIFEXITED(status))
+ fprintf(stdout, "== Playback finished normally\n");
+ else if (WIFSIGNALED(status))
+ fprintf(stdout, "== Playback aborted\n");
+
+ pthread_cleanup_pop(1);
+
+ pthread_exit(EXIT_SUCCESS);
+}
+
+int main(int argc, char *argv[])
+{
+ pthread_t player_thread;
+ pthread_attr_t player_attr;
+ struct player_args args;
+ int opt, terror;
+
+ if (argc < 7) {
+err_usage:
+ fprintf(stderr, "USAGE:\n"
+ "%s -b budget_usec -p period_usec -f file\n\n",
+ argv[0]);
+ error(EXIT_FAILURE, EINVAL, "Wrong argument count");
+ }
+
+ while ((opt = getopt(argc, argv, "b:p:f:")) != -1) {
+ switch (opt) {
+ case 'b':
+ args.budget = atoi(optarg);
+ break;
+ case 'p':
+ args.period = atoi(optarg);
+ break;
+ case 'f':
+ strncpy(args.file, optarg, sizeof(args.file));
+ break;
+ default:
+ goto err_usage;
+ }
+ }
+
+ PXW(frsh_init());
+ fprintf(stdout, "FRSH initialized\n");
+
+ terror = pthread_attr_init(&player_attr);
+ if (terror) assert_perror(errno);
+
+ terror = pthread_create(&player_thread, &player_attr, player, (void*) &args);
+ if (terror) assert_perror(errno);
+ fprintf(stdout, "FRSH thread created, waiting for its termination...\n");
+
+ terror = pthread_join(player_thread, NULL);
+ if (terror) assert_perror(errno);
+ fprintf(stdout, "FRSH thread ended. Exiting\n\n");
+
+ exit(EXIT_SUCCESS);
+}
+
--- /dev/null
+#ifndef _PLAY_H_
+#define _PLAY_H_
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <error.h>
+#include <assert.h>
+#include <semaphore.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include <frsh.h>
+
+#define PLAYER_BINARY "mplayer"
+#define PLAYER_ARGS " -fs -zoom "
+
+struct player_args {
+ int budget, period;
+ char file[128];
+};
+
+void *player(void *args);
+
+#endif /* _PLAY_H_ */
+
fcb_SOURCES = fcb.c
fcb_LIBS = contract fosa forb pthread rt ulut frm_client fra_client
+fcb_LIBS += frsh # For frsh_strerror
fcb_SERVER_IDL = fcb.idl
lib_LIBRARIES += fcb_client
struct fcb_contract {
fres_contract_id_t id;
+ struct res_alloc *ra; /**< Allocator for this contract TODO: Remove contract if allocator is destroyed */
gavl_node_t node_fcb;
ul_list_node_t node_sc;
- int next_sc_variant;
- int reserved_sc_variant;
+ ul_list_node_t node_reservation;
+ struct {
+ int initial;
+ int try;
+ } sc_variant;
fosa_abs_time_t end_of_stability_period;
- struct fres_contract *user_contract;
- struct fres_contract *reserved_contract;
+ struct fres_contract *user_contract; /* The contract sent by user. Set after sucessfull neotiation. */
+ struct fres_contract *requested_contract; /* User request for the contract. Set by prepare_reservation_requests() in the beginning of negotiation. */
struct fres_contract *to_be_reserved_contract;
+ struct fres_contract *schedulable_contract;
};
/**
gavl_cust_root_field_t contracts; /**< Contracts negotiated by this FCB */
};
+/** List of contracts to be reserved during spare capacity rebalancing */
+struct reservation_list {
+ ul_list_head_t fcb_contracts;
+ unsigned length;
+};
+
struct fcb_contract *fcb_contract_new(fres_contract_id_t *id)
{
struct fcb_contract *fcb_contract;
if (fcb_contract->user_contract) {
fres_contract_destroy(fcb_contract->user_contract);
}
+ if (fcb_contract->to_be_reserved_contract) {
+ fres_contract_destroy(fcb_contract->to_be_reserved_contract);
+ }
+ if (fcb_contract->requested_contract) {
+ fres_contract_destroy(fcb_contract->requested_contract);
+ }
+ if (fcb_contract->schedulable_contract) {
+ fres_contract_destroy(fcb_contract->requested_contract);
+ }
free(fcb_contract);
}
sc_contracts /* cust_head_field */, \
node_sc /* cust_node_field */);
+UL_LIST_CUST_DEC(reservation_list /* cust_prefix */, \
+ struct reservation_list /* cust_head_t */, \
+ struct fcb_contract /* cust_item_t */, \
+ fcb_contracts /* cust_head_field */, \
+ node_reservation /* cust_node_field */);
+
/* Container for negotiated contracts */
GAVL_CUST_NODE_INT_DEC(fcb_contract /* cust_prefix */, \
struct fcb /* cust_root_t */, \
#define o2fcb(o) (struct fcb*)forb_instance_data(o)
-struct res_key *
-get_res_key(const struct fcb *fcb, const struct fres_contract *contract, struct res_key *key)
+struct res_key*
+get_res_key(const struct fres_contract *contract, struct res_key *key)
{
fres_block_resource *block_res;
block_res = fres_contract_get_resource(contract);
- if (!block_res && !fres_contract_id_is_empty(&contract->id)) {
- /* If the contract doesn't have resource information,
- * this might be cancelation or renegotiation request,
- * so look at our database for formerly submited
- * contract. */
- struct fcb_contract *fcb_contract;
- fcb_contract = fcb_contract_find(fcb, &contract->id);
- if (fcb_contract) {
- block_res = fres_contract_get_resource(fcb_contract->user_contract);
- }
- }
if (!block_res) {
ul_logerr("No resource specified\n");
return NULL;
}
/**
- * Checks whether all contracts refers to a single resource.
+ * Fills in an array of fcb_contracts according to requests submited
+ * to negotiate_contracts(). For every contract in @a contracts, there
+ * is one fcb_contract in @a fcb_contracts array.
*
- * @param fcb
- * @param contracts Array of contract pointers.
- * @param num Number of contracts.
+ * @param fcb
+ * @param fcb_contracts Where to store pointers to fcb_contracts
+ * @param resource Resource for which negotiation is being done.
+ * @param app Application which requests negotiation
+ * @param contracts Contracts submited to negotiate_contracts()
+ * @param num Number of contracts in contracts (which is the same as the number in fcb_contracts).
*
- * @return If all contracts refer to a signle resource, pointer to the
- * coresponding resource structure is returned. Otherwise, NULL is
- * returned.
+ * @return Zero on success, non-zero error code on error.
*/
-struct resource *
-check_single_resource(struct fcb *fcb, struct fres_contract *contracts[], int num)
+static int
+prepare_fcb_contracts(struct fcb *fcb, struct fcb_contract *fcb_contracts[],
+ struct resource **resource,
+ forb_server_id *app,
+ struct fres_contract *contracts[], int num)
{
- struct resource *resource = NULL;
unsigned i;
+ struct fcb_contract *fc;
+ struct res_alloc *ra;
struct res_key key, key2 = {-1,-1};
for (i=0; i<num; i++) {
- if (!get_res_key(fcb, contracts[i], &key)) {
- return NULL;
+ 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);
+ fc = fcb_contract_new(&c->id);
+ if (!fc)
+ return errno;
+ fcb_contracts[i] = fc;
+ if (!get_res_key(c, &key)) {
+ return FRSH_ERR_RESOURCE_ID_INVALID;
+ }
+ } else {
+ fc = fcb_contract_find(fcb, &c->id);
+ if (!fc) {
+ char str[60];
+ fres_contract_id_to_string(str, &c->id, sizeof(str));
+ ul_logerr("Attempt to change unknown contract %s\n", str);
+ return FRES_ERR_NOTHING_TO_RENEGOTIATE;
+ } else {
+ fcb_contracts[i] = fc;
+ if (fres_contract_get_num_blocks(c) == 0) {
+ /* Cancelation */
+ get_res_key(fc->user_contract, &key);
+ } else {
+ /* Renegotiation */
+ if (!get_res_key(c, &key)) {
+ return FRSH_ERR_RESOURCE_ID_INVALID;
+ }
+ }
+ }
+ }
+ fc->requested_contract = c;
+
+ /* Check that all contracts are for the same resource */
+ if (i==0) {
+ key2 = key;
+ *resource = fcb_resource_find(fcb, &key);
+ if (!*resource) {
+ ul_logerr("No resource manager for %d.%d registered\n",
+ key.type, key.id);
+ return FRSH_ERR_RESOURCE_ID_INVALID;
+ }
}
- if (i==0) key2 = key;
else if (key.type != key2.type ||
key.id != key2.id) {
- return NULL;
+ ul_logerr("Contract #%d differs in resource!\n", i);
+ return FRSH_ERR_RESOURCE_ID_INVALID;
+ }
+
+ /* Find allocator for this request */
+ ra = fcb_alloc_find(*resource, app);
+ if (!ra) {
+ char str[60];
+ forb_server_id_to_string(str, app, sizeof(str));
+ ul_logerr("No resource allocator found for %d.%d and %s\n",
+ (*resource)->key.type, (*resource)->key.id, str);
+ return FRES_ERR_NO_RESOURCE_ALLOCATOR;
}
+ fc->ra = ra;
+ }
+ return 0;
+}
+
+static void fres_contract_ptr_destroy(struct fres_contract **p)
+{
+ fres_contract_destroy(*p);
+}
+
+/**
+ * @param resource Resource for which to rebalance capacity and negotiate new contracts
+ * @param fcb_contract New requests to negotiate
+ * @param num The number of elements in @a fcb_contract
+ * @param[out] rl List with changed contracts to be commited
+ */
+static void
+prepare_reservation_list(struct resource *resource,
+ struct fcb_contract *fcb_contract[], int num,
+ struct reservation_list *rl)
+{
+ int i;
+ fosa_abs_time_t now;
+ struct fcb_contract *fc;
+
+ reservation_list_init_head(rl);
+ rl->length = 0;
+ for (i=0; i<num; i++) {
+ assert(fcb_contract[i]->requested_contract != NULL);
+ reservation_list_insert(rl, fcb_contract[i]);
+ rl->length++;
}
-
- resource = fcb_resource_find(fcb, &key);
- if (!resource) {
- ul_logerr("No resource manager for %d.%d registered\n",
- key.type, key.id);
+ fosa_clock_get_time(CLOCK_REALTIME, &now);
+ ul_list_for_each(sc_contracts, resource, fc) {
+ if (fosa_abs_time_smaller(fc->end_of_stability_period, now) &&
+ fc->requested_contract == NULL) /* Do not insert contract inserted above */
+ {
+ reservation_list_insert(rl, fc);
+ rl->length++;
+ }
}
- return resource;
}
/**
*
*
- * @param fcb
- * @param contracts
- * @param num
+ * @param resource Resource for which to rebalance capacity and negotiate new contracts
+ * @param rl List with changed contracts to be commited
*
- * @return Zero on success, non-zero error code on error.
+ * @return Zero on success, non-zero error code on error
*/
static int
-prepare_reservation_contracts(struct fcb *fcb, struct fres_contract *contracts[], int num)
+rebalance_spare_capacity_and_reserve(struct resource *resource,
+ struct reservation_list *rl)
{
+ int ret;
unsigned i;
- struct fcb_contract *fcb_contract;
-
- for (i=0; i<num; i++) {
- struct fres_contract *c = contracts[i];
+ struct fcb_contract *fc;
+ fres_block_spare_capacity *s;
+
+ fres_contract_ptr_seq contracts;
+ forb_sequence_alloc_buf(contracts, rl->length);
+ contracts._length = rl->length;
+ i=0;
+ /* Initialize optimization */
+ ul_list_for_each(reservation_list, rl, fc) {
+ fc->to_be_reserved_contract =
+ fc->requested_contract ? fres_contract_duplicate(fc->requested_contract) :
+ fc->user_contract ? fres_contract_duplicate(fc->user_contract) :
+ NULL;
+ assert(fc->to_be_reserved_contract != NULL);
+
+ forb_sequence_elem(contracts, i) = fc->to_be_reserved_contract;
+ i++;
- if (fres_contract_id_is_empty(&c->id)) {
- /* Normal negotiation request */
- forb_uuid_generate((forb_uuid_t *)&c->id);
- continue;
- }
- if (fres_contract_get_num_blocks(c) == 0) {
- /* Nothing to do for deletion requesst */
- continue;
+ s = fres_contract_get_spare_capacity(fc->to_be_reserved_contract);
+ if (s && s->granularity == FRSH_GR_DISCRETE) {
+ fc->sc_variant.initial = s->variants._length - 1;
+ fc->sc_variant.try = fc->sc_variant.initial;
}
+ }
- /* Renegotiation */
- fcb_contract = fcb_contract_find(fcb, &c->id);
- if (fcb_contract) {
- /* Copy missing blocks from fcb_contract to contract */
- fres_contract_merge(c, fcb_contract->user_contract);
- } else {
- char str[60];
- fres_contract_id_to_string(str, &c->id, sizeof(str));
- ul_logerr("Attempt to renegotiate unknown contract %s\n", str);
- return FRES_ERR_NOTHING_TO_RENEGOTIATE;
+ bool all_combinations_tried;
+ int criterion, best_criterion = -1;
+ struct fcb_contract *fcb_changed;
+ /* Exhaustive search. Try all combinations of spare capacity
+ * variants and find the one with best creterion. */
+ do {
+ all_combinations_tried = true;
+ fcb_changed = NULL;
+ criterion = 0;
+ /* Prepare spare capacity variant */
+ ul_list_for_each(reservation_list, rl, fc) {
+ s = fres_contract_get_spare_capacity(fc->to_be_reserved_contract);
+ /* TODO: Simulate continuous granularity by discretization */
+ if (s && s->granularity == FRSH_GR_DISCRETE) {
+ fres_container_copy(fc->to_be_reserved_contract->container,
+ forb_sequence_elem(s->variants, fc->sc_variant.try));
+ criterion += fc->sc_variant.try;
+
+ if (fcb_changed == NULL) {
+ /* Chnage tried variant for the next round */
+ fc->sc_variant.try = fc->sc_variant.try > 0 ?
+ fc->sc_variant.try - 1 :
+ s->variants._length - 1;
+ /* Do not change other
+ * contracts unless we have
+ * tried all variants */
+ if (fc->sc_variant.try != fc->sc_variant.initial) {
+ fcb_changed = fc;
+ }
+ }
+ if (fc->sc_variant.try != fc->sc_variant.initial)
+ all_combinations_tried = false;
+ }
}
- }
- return 0;
-}
+ if (criterion > best_criterion) {
+ CORBA_Environment ev;
+ /* Reserve contract */
+ ret = fres_resource_manager_reserve_contracts(resource->mng, &contracts, &ev);
+ if (forb_exception_occurred(&ev)) {
+ ret = FRES_ERR_FORB_EXCEPTION;
+ ul_logerr("FORB exception when reserving contracts\n");
+ goto err;
+ }
+ if (ret < 0) {
+ ul_logerr("Contract reservation error %d\n", ret);
+ ret = FRES_ERR_ADMISSION_TEST;
+ goto err;
+ }
+ if (ret == 0) { /* negotiation succeeded */
+ best_criterion = criterion;
+ }
+ }
+ } while (!all_combinations_tried);
-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));
+ if (best_criterion == -1) {
+ ret = FRSH_ERR_CONTRACT_REJECTED;
+ } else {
+ /* At least some variant succeeded */
+ ret = 0;
+ sc_contracts_init_head(resource);
+ ul_list_for_each(reservation_list, rl, fc) {
+ s = fres_contract_get_spare_capacity(fc->to_be_reserved_contract);
+ if (s && s->granularity == FRSH_GR_DISCRETE) {
+ sc_contracts_insert(resource, fc);
+ }
+ }
+ }
+err:
+ ul_list_for_each(reservation_list, rl, fc) {
+ fres_contract_destroy(fc->to_be_reserved_contract);
+ fc->to_be_reserved_contract = NULL;
}
+ forb_sequence_free_buf(contracts, forb_no_destructor);
+ return ret;
}
+/**
+ * Create/change VReses according to @a schedulable_contracts.
+ *
+ * There might be more allocators for schedulable contracts, so merge
+ * adjacent vreses with the same allocator together and create/change
+ * them in one step. Also the order of schedulable contracts might be
+ * different from the initial order od ids in commit_contracts()
+ * therefore we have to search for every contract.
+ */
static int
-rebalance_spare_capacity_and_reserve(struct fcb *fcb, struct resource *resource,
- struct fcb_contract *fcb_contract[], int num)
+change_vreses(struct fcb *fcb, fres_contract_ptr_seq *schedulable_contracts)
{
- 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;
+ struct res_alloc *last_ra = NULL;
+ fres_contract_ptr_seq vreses;
+ int i, ret;
+ CORBA_Environment ev;
+
+ forb_sequence_alloc_buf(vreses, schedulable_contracts->_length);
+ vreses._length = 0;
+
+ for (i=0; i<schedulable_contracts->_length; i++) {
+ struct fcb_contract *fc;
+ struct fres_contract *sc = schedulable_contracts->_buffer[i];
+
+ fc = fcb_contract_find(fcb, &sc->id);
+ assert(fc != NULL);
+
+ if (true /* TODO: if the schedulable contract is changed */) {
+ if (last_ra != fc->ra) {
+ if (vreses._length) {
+ ret = fres_resource_allocator_change_vreses(last_ra->ra,
+ &vreses, &ev);
+ if (forb_exception_occurred(&ev)) {
+ ret = FRES_ERR_FORB_EXCEPTION;
+ goto err;
+ }
+ if (ret) goto err;
+ }
+ vreses._length = 0;
+ }
+ vreses._buffer[vreses._length] = sc;
+ vreses._length++;
+ fres_contract_destroy(fc->schedulable_contract);
+ fc->schedulable_contract = fres_contract_duplicate(sc);
+ last_ra = fc->ra;
+
}
- } while (ret != 0)
-#endif
- return 0;
+ }
+ ret = fres_resource_allocator_change_vreses(last_ra->ra,
+ &vreses, &ev);
+ if (forb_exception_occurred(&ev))
+ ret = FRES_ERR_FORB_EXCEPTION;
+err:
+ forb_sequence_free_buf(vreses, forb_no_destructor);
+ return ret;
}
CORBA_long
{
struct fcb *fcb = o2fcb(obj);
struct resource *resource;
- struct res_alloc *ra;
int ret;
forb_server_id app;
fres_contract_ptr_seq *schedulable_contracts;
- struct fcb_contract **fcb_contracts;
+ struct fcb_contract **fcb_contracts, *fc;
unsigned i;
- fres_contract_id_seq* ids;
-
- resource = check_single_resource(fcb, contracts->_buffer, contracts->_length);
- if (!resource) {
- ret = FRSH_ERR_RESOURCE_ID_INVALID;
- goto err;
- }
-
- 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) {
- char str[60];
- forb_server_id_to_string(str, &app, sizeof(str));
- ul_logerr("No resource allocator found for %d.%d and %s\n",
- resource->key.type, resource->key.id, str);
- ret = FRES_ERR_NO_RESOURCE_ALLOCATOR;
- goto err;
- }
+ fres_contract_id_seq commit_ids;
- /* 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) {
+ /* Prepare output sequence for the case we return eariler with
+ * an error */
+ forb_sequence_alloc(*ids_out, 0);
+ if (!*ids_out) {
ev->major = FORB_EX_NO_MEMORY;
goto err;
}
- memset(ids, 0, sizeof(*ids));
- CORBA_sequence_set_release(ids, CORBA_TRUE);
- *ids_out = ids;
- ids->_buffer = malloc(contracts->_length*sizeof(ids->_buffer[0]));
- if (!ids->_buffer) {
- ret = errno;
- goto err;
- }
- ids->_length = ids->_maximum = contracts->_length;
- for (i=0; i<contracts->_length; i++) {
- ids->_buffer[i] = contracts->_buffer[i]->id;
- }
+ CORBA_sequence_set_release(*ids_out, CORBA_TRUE);
+
+ forb_get_req_source(obj, &app);
fcb_contracts = malloc(sizeof(fcb_contracts[0])*contracts->_length);
if (!fcb_contracts) {
}
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);
- if (!fcb_contracts[i]) {
- ret = errno ? errno : -1;
- goto err_free_fcb_contracts;
- }
- fcb_contracts[i]->user_contract = fres_contract_duplicate(c);
- if (!fcb_contracts[i]->user_contract) {
- ret = errno ? errno : -1;
- goto err_free_fcb_contracts;
- }
- }
- }
+ ret = prepare_fcb_contracts(fcb, fcb_contracts, &resource,
+ &app, contracts->_buffer, contracts->_length);
+ if (ret)
+ goto err_free_fcb_contracts;
+
+ struct reservation_list rl;
+ prepare_reservation_list(resource,
+ fcb_contracts, contracts->_length,
+ &rl);
- /* 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) {
+ /* Allocate all the needed memory before doing reservation. If
+ * there is no enough memory, it has no sense to call resource
+ * manager. */
+ forb_sequence_alloc_buf(commit_ids, rl.length);
+ if (!commit_ids._buffer) {
+ ret = errno;
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(s) was not accepted\n");
+
+ /* Reserve contracts */
+ ret = rebalance_spare_capacity_and_reserve(resource, &rl);
+ if (ret) {
+ if (ret == FRSH_ERR_CONTRACT_REJECTED) {
+ ul_logmsg("Contract(s) was/were rejected\n");
+ } else {
+ char msg[100];
+ fres_strerror(ret, msg, sizeof(msg));
+ ul_logerr("Reservation error: %s\n", msg);
+ }
goto err_free_fcb_contracts;
}
- /* Commit contract */
- fres_resource_manager_commit_contracts(resource->mng, ids,
+ /* Commit contracts */
+ commit_ids._length = rl.length;
+ i=0;
+ ul_list_for_each(reservation_list, &rl, fc) {
+ forb_sequence_elem(commit_ids, i) = fc->id;
+ i++;
+ }
+
+ fres_resource_manager_commit_contracts(resource->mng, &commit_ids,
&schedulable_contracts, ev);
if (forb_exception_occurred(ev)) {
ret = FRES_ERR_FORB_EXCEPTION;
goto err_cancel_reservation;
}
- /* Create VRes */
- ret = fres_resource_allocator_change_vreses(ra->ra, schedulable_contracts, ev);
- if (CORBA_sequence_get_release(schedulable_contracts)) {
- int i;
- for (i=0; i<schedulable_contracts->_length; i++) {
- fres_contract_destroy(schedulable_contracts->_buffer[i]);
+ /* Add new contracts to our fcb database for later
+ * reference. Canceled contracts are removed below. */
+ for (i=0; i<contracts->_length; i++) {
+ fc = fcb_contracts[i];
+
+ if (fc->user_contract) {
+ if (fres_contract_get_num_blocks(fc->requested_contract) > 0) {
+ /* Renegotiation */
+ fres_contract_destroy(fc->user_contract);
+ fc->user_contract = fres_contract_duplicate(fc->requested_contract);
+ /* Note: requested_contract is also
+ * pointed by contracts parameter and
+ * will be freed by FORB. */
+ fc->requested_contract = NULL;
+ }
+ } else {
+ /* Insert new contracts */
+ fcb_contract_insert(fcb, fcb_contracts[i]);
+ fc->user_contract = fres_contract_duplicate(fc->requested_contract);
+ fc->requested_contract = NULL;
+ /* See the note above. */
}
- forb_free(schedulable_contracts->_buffer);
}
- forb_free(schedulable_contracts);
- if (forb_exception_occurred(ev)) {
- ret = FRES_ERR_FORB_EXCEPTION;
+
+ ret = change_vreses(fcb, schedulable_contracts);
+ if (ret)
goto err_cancel_reservation;
- }
+
+ forb_sequence_free(schedulable_contracts, fres_contract_ptr_destroy);
if (ret != 0) {
- ul_logmsg("VRes was not created\n");
- goto err_cancel_reservation;
+ ul_logerr("VRes was not created\n");
+ goto err_cancel_contracts;
}
- /* Update database of negotiated contracts stored for later reference */
+
+ /* Return IDs and delete canceled contracts from out database */
+ forb_sequence_alloc_buf(**ids_out, contracts->_length);
+ if (!(*ids_out)->_buffer) {
+ ev->major = FORB_EX_NO_MEMORY;
+ goto err_cancel_contracts;
+ }
+ (*ids_out)->_length = contracts->_length;
for (i=0; i<contracts->_length; i++) {
- struct fcb_contract *fcb_contract;
- fcb_contract = fcb_contract_find(fcb, &contracts->_buffer[i]->id);
- /* Delete canceled or renegotiated user contract */
- if (fcb_contract) {
- fcb_contract_delete(fcb, fcb_contract);
- fcb_contract_destroy(fcb_contract);
- }
- if (fcb_contracts[i]) {
- /* Insert new contracts */
- fcb_contract_insert(fcb, fcb_contracts[i]);
+ struct fcb_contract *fc = fcb_contracts[i];
+ forb_sequence_elem(**ids_out, i) = fc->id;
+
+ if (fc->requested_contract &&
+ fres_contract_get_num_blocks(fc->requested_contract) == 0) {
+ fcb_contract_delete(fcb, fc);
+ /* Note: requested_contract is also pointed by
+ * contracts parameter and will be freed by FORB. */
+ fc->requested_contract = NULL;
+ fcb_contract_destroy(fc);
}
}
-
return 0;
+err_cancel_contracts:
+ /* TODO */
+ goto err_free_fcb_contracts;
err_cancel_reservation:
- fres_resource_manager_cancel_reservations(resource->mng, ids, ev);
+ fres_resource_manager_cancel_reservations(resource->mng, &commit_ids, ev);
err_free_fcb_contracts:
- for (i=0; i<contracts->_length; i++)
- fcb_contract_destroy(fcb_contracts[i]);
+ for (i=0; i<contracts->_length; i++) {
+ fc = fcb_contracts[i];
+ if (fc && !fc->user_contract) {
+ fcb_contracts[i]->requested_contract = NULL; /* Destroyed by FORB */
+ fcb_contract_destroy(fcb_contracts[i]);
+ }
+ }
free(fcb_contracts);
err:
return ret;
}
+void redistribute_spare_capacity(fres_contract_broker obj,
+ const frsh_resource_type_t restype,
+ const frsh_resource_id_t resid,
+ CORBA_Environment *ev)
+{
+ struct fcb *fcb = o2fcb(obj);
+ struct res_key key = {restype, resid };
+ struct resource *resource;
+ struct reservation_list rl;
+
+ resource = fcb_resource_find(fcb, &key);
+
+ prepare_reservation_list(resource, NULL, 0, &rl);
+
+/* forb_sequence_alloc(ids, rl.length); */
+/* if (!ids || !ids->_buffer) { */
+/* ev->major = FORB_EX_NO_MEMORY; */
+/* goto err_free_fcb_contracts; */
+/* } */
+/* CORBA_sequence_set_release(ids, CORBA_TRUE); */
+/* *ids_out = ids; /\* ids is freed by FORB *\/ */
+
+
+ rebalance_spare_capacity_and_reserve(resource, &rl);
+ /* Commit */
+}
+
CORBA_long register_resource(fres_contract_broker obj,
const frsh_resource_type_t restype,
const frsh_resource_id_t resid,
fcb_alloc_insert(res, ra);
return 0;
err:
- return -1;
+ return FRSH_ERR_RESOURCE_ID_INVALID;
}
void get_resources(fres_contract_broker obj, fres_resource_seq** resources, CORBA_Environment *ev)
.negotiate_contracts = negotiate_contracts,
.register_resource = register_resource,
.register_allocator = register_allocator,
+ .redistribute_spare_capacity = redistribute_spare_capacity,
.get_resources = get_resources,
};
* contract is determined as follows:
* - neg: contracts without ID
* - cancel: contracts with an ID and without any block
- * - reneg: contracts without ID and some blocks (these
- * blocks will be replaced in the previous contract).
+ * - reneg: contracts with ID and some blocks (the old
+ * contract will we replaced by the new one).
*
* @param[out] ids IDs of the newly negotiated
* contracts, if negotiation was successful. Ordering
*/
long negotiate_contracts(in contract::ptr_seq contracts, out contract::id_seq ids);
+ /**
+ * Redistributes spare capacity for a given resource.
+ * This is meant as a support for resources with
+ * variable capacity (WiFi) as a mean for applications
+ * to adapt to the changed capacity.
+ *
+ * @param restype For which resource to perform
+ * redistribution.
+ */
+ void redistribute_spare_capacity(in frsh_resource_type_t restype,
+ in frsh_resource_id_t resid);
+
/**
* Returns sequence of registered resources.
*
MSG(NOTHING_TO_RENEGOTIATE);
MSG(BLOCK_DUP);
MSG(NO_RESOURCE_ALLOCATOR);
+ MSG(ADMISSION_TEST);
+ MSG(KERNEL_SUPPORT_MISSING);
}
if (s == NULL) return FRSH_ERR_BAD_ARGUMENT;
FRES_ERR_NOTHING_TO_RENEGOTIATE,
FRES_ERR_BLOCK_DUP,
FRES_ERR_NO_RESOURCE_ALLOCATOR,
+ FRES_ERR_ADMISSION_TEST,
+ FRES_ERR_KERNEL_SUPPORT_MISSING,
};
int fres_strerror (int error, char *message, size_t size);
*
* @param allocator
*
- * @return Zero on success, -1 on error.
+ * @return Zero on success, non-zero error code on error.
*/
static int register_fra_to_fcb(struct fres_allocator *allocator)
{
allocator->res_type,
allocator->res_id,
fra, &env);
- if (forb_exception_occurred(&env) || ret != 0) {
+ if (forb_exception_occurred(&env)) {
+ ret = FRES_ERR_FORB_EXCEPTION;
goto err_release;
}
+ if (ret)
+ goto err_release;
return 0;
err_release:
save_errno(forb_object_release(fra));
- return -1;
+ return ret;
}
/**
* @param res_type
* @param res_id
*
- * @return Zero on success, -1 on error.
+ * @return Zero on success, non-zero error code on error.
*/
int fra_activate(frsh_resource_type_t res_type,
{
struct fres_allocator key, *pkey=&key;
struct registered_allocator *ra;
- int ret = -1;
+ int ret;
key.res_type = res_type;
key.res_id = res_id;
ra->registered_with_fcb = true;
}
}
+ } else {
+ ret = FRSH_ERR_RESOURCE_ID_INVALID;
}
return ret;
ret = frsh_battery_get_expiration(&exp_time);
if (ret) goto err;
- if (fosa_abs_time_smaller(req_time, exp_time))
+ if (fosa_abs_time_smaller(exp_time, req_time))
ret = FRSH_ERR_CONTRACT_REJECTED;
}
/* Activate allocator */
r = fres_contract_get_resource(*contract);
if (r) {
- fra_activate(r->resource_type,
- r->resource_id);
+ ret = fra_activate(r->resource_type,
+ r->resource_id);
+ if (ret) goto err;
}
/* Negotiate contract */
"SCHED_POLICY_NOT_COMPATIBLE ",
"SERVER_WORKLOAD_NOT_COMPATIBLE ",
"ALREADY_BOUND ",
- "WRONG_NETWORK ",
+ "RESOURCE_ID_INVALID ",
"TOO_LARGE ",
"BUFFER_FULL ",
"NO_SPACE ",
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);
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);
case FRSH_RT_PROCESSOR:
{
int ret;
+
+ ret = fra_CPU_power_init(resource_id);
+ if (ret) return FRSH_ERR_INTERNAL_ERROR;
ret = fra_CPU_get_power(resource_id,
(int*) power_level);
if (ret) return FRSH_ERR_INTERNAL_ERROR;
case FRSH_RT_LCD:
{
int ret;
+
+ ret = fra_LCD_power_init(resource_id);
+ if (ret) return FRSH_ERR_INTERNAL_ERROR;
ret = fra_LCD_get_power(resource_id,
(int*) power_level);
if (ret) return FRSH_ERR_INTERNAL_ERROR;
return FRSH_NO_ERROR;
}
+int frsh_resource_get_speed
+ (frsh_resource_type_t resource_type,
+ frsh_resource_id_t resource_id,
+ frsh_power_level_t power_level,
+ double *speed_ratio)
+{
+ 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_get_speed(resource_id,
+ (int) power_level,
+ speed_ratio);
+ if (ret) return FRSH_ERR_INTERNAL_ERROR;
+
+ 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_get_speed(resource_id,
+ (int) power_level,
+ speed_ratio);
+ 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,
switch(resource_type)
{
+#ifdef CONFIG_ACPI_CPU
case FRSH_RT_PROCESSOR:
{
-#ifdef CONFIG_ACPI_CPU
ret = fra_CPU_power_init(resource_id);
if (ret) goto out;
-#endif
break;
}
+#endif
#ifdef CONFIG_ACPI_LCD
case FRSH_RT_LCD:
{
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;
+ if (ret == EAGAIN) return ret;
+ 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;
{ /* 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) },
+ { .budget = MSEC(40), .period = MSEC(100), .deadline = MSEC(100) },
+ { .budget = MSEC(40), .period = MSEC( 80), .deadline = MSEC( 80) },
+ { .budget = MSEC(40), .period = MSEC( 60), .deadline = MSEC( 60) },
}
},
{ /* Contract 3 */
if (ret) PERROR_AND_EXIT(ret, "frsh_contract_negotiate");
}
+ printf("Waiting for stability period to end\n");
+ sleep(2);
+ printf("Trying to renegotiate the 3rd contract again\n");
+ ret = frsh_contract_renegotiate_sync(&contract[2], vres[2]);
+ if (ret) PERROR_AND_EXIT(ret, "frsh_contract_negotiate");
+
/* Cancel contracts */
for (i=0; i<NUM_CONTRACTS; i++) {
ret = frsh_contract_cancel(vres[i]);
#include <frsh.h>
-#include <aqcpu_res.h>
-#include <error.h>
int main()
{
- int ret;
+ int terror;
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;
+ frsh_rel_time_t current, duration, expiration;
+ unsigned long duration_msec, duration_step;
- if (frsh_init())
- error(1, 0, "FRSH initialization failed\n");
+ PXW(frsh_init());
+
+ PXW(frsh_contract_init(&contract));
+
+ duration_msec = duration_step = 1000UL * 60UL * 10UL;
- /* 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");
+ PXW(frsh_contract_set_basic_params(&contract,
+ &budget,
+ &period,
+ FRSH_WT_BOUNDED,
+ FRSH_CT_REGULAR));
+
+ PXW(frsh_contract_set_resource_and_label(&contract, FRSH_RT_PROCESSOR, 0,"TEST_VRES"));
+
+ PXW(frsh_contract_set_min_budget_pow(&contract, FRSH_PLT_HIGH, &budget));
- 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");
+ PXW(frsh_contract_set_min_budget_pow(&contract, FRSH_PLT_MEDIUM, &budget));
- 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)");
+ PXW(frsh_contract_set_min_budget_pow(&contract, FRSH_PLT_LOW, &budget));
- 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)");
+ terror = frsh_battery_get_expiration(&expiration);
+ if (terror == EAGAIN)
+ PERROR_AND_EXIT(terror, "frsh_battery_get_expiration: system running on AC");
+ if (terror)
+ PERROR_AND_EXIT(terror, "frsh_battery_get_expiration");
- 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)");
+ fosa_clock_get_time(FOSA_CLOCK_REALTIME, ¤t);
+ printf("System battery wil expire in %lu seconds\n",
+ fosa_rel_time_to_msec(fosa_abs_time_decr(expiration, current)) / 1000UL);
+
+ printf("Starting with minumum diration = %lu seconds\n"
+ " ans stepping by %lu seconds.\n",
+ duration_msec / 1000UL,
+ duration_step / 1000UL);
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");
+ PXW(frsh_contract_set_min_expiration(&contract, duration));
- 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));
+ PXW(frsh_contract_get_min_expiration(&contract, &duration));
- ret = frsh_contract_negotiate(&contract, &vres);
- if (ret) PERROR_AND_EXIT(ret, "frsh_contract_negotiate");
+ PXW(frsh_contract_negotiate(&contract, &vres));
printf("Aqcpu vres negotiated, vres-ID: %d\n", (int) vres);
while (1) {
- duration_msec += duration_msec;
+ duration_msec += duration_step;
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));
+ fosa_clock_get_time(FOSA_CLOCK_REALTIME, ¤t);
+ printf(" Renegotiating the contract with minimum expiration %lu sec.\n"
+ " System expiration time: %lu seconds\n",
+ fosa_rel_time_to_msec(duration) / 1000UL,
+ fosa_rel_time_to_msec(fosa_abs_time_decr(expiration, current)) / 1000UL);
- ret = frsh_battery_get_expiration(&expiration);
- if (ret) PERROR_AND_EXIT(ret, "frsh_battery_get_expiration");
+ PXW(frsh_contract_set_min_expiration(&contract, duration));
- 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));
+ PXW(frsh_battery_get_expiration(&expiration));
+ terror = frsh_contract_renegotiate_sync(&contract, vres);
+ if (terror == FRSH_ERR_CONTRACT_REJECTED) {
+ PERROR_FRESCOR(terror, "frsh_contract_renegotiate_sync");
+ goto out;
+ }
+ if (terror) PERROR_AND_EXIT(terror, "frsh_contract_renegotiate_sync");
sleep(3);
}
- ret = frsh_contract_cancel(vres);
- if (ret) PERROR_AND_EXIT(ret, "frsh_contract_cancel");
+out:
+ PXW(frsh_contract_cancel(vres));
printf("Test PASSED!\n");
int fra_CPU_set_power(int cpu, int level)
{
- if (!frequency_initialized ||
- level >= 3)
+ if (!frequency_initialized || level >= 3)
return EINVAL;
return cpufreq_set_frequency(cpu, freqs[level]);
}
+int fra_CPU_get_speed(int cpu, int level, double *ratio)
+{
+ if (!frequency_initialized || level >= 3)
+ return EINVAL;
+
+ *ratio = (double) freqs[level] / freqs[0];
+
+ return 0;
+}
+
int fra_CPU_set_power(int cpu, int level);
+int fra_CPU_get_speed(int cpu, int level, double *ratio);
+
#endif
#include <frsh.h>
-#include <error.h>
int main()
{
+ frsh_power_level_t level;
int power_levels;
- int ret;
+ double speed;
+ int terror;
- if (frsh_init())
- error(1, 0, "FRSH initialization failed\n");
+ PXW(frsh_init());
- 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");
+ PXW(frsh_resource_get_num_power_levels(FRSH_RT_PROCESSOR, 0, &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");
+
+ PXW(frsh_resource_get_power_level(FRSH_RT_PROCESSOR, 0, &level));
+ PXW(frsh_resource_get_speed(FRSH_RT_PROCESSOR, 0, level, &speed));
+ printf("Starting with power level %d, speed = %f\n", level, speed);
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");
+ PXW(frsh_resource_set_power_level(FRSH_RT_PROCESSOR, 0, FRSH_PLT_HIGH));
+ PXW(frsh_resource_get_power_level(FRSH_RT_PROCESSOR, 0, &level));
+ PXW(frsh_resource_get_speed(FRSH_RT_PROCESSOR, 0, level, &speed));
+ printf("%d (FRSH_PLT_HIGH) correctly set, speed = %f\n", level, speed);
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");
+ PXW(frsh_resource_set_power_level(FRSH_RT_PROCESSOR, 0, FRSH_PLT_MEDIUM));
+ PXW(frsh_resource_get_power_level(FRSH_RT_PROCESSOR, 0, &level));
+ PXW(frsh_resource_get_speed(FRSH_RT_PROCESSOR, 0, level, &speed));
+ printf("%d (FRSH_PLT_MEDIUM) correctly set, speed = %f\n", level, speed);
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");
+ PXW(frsh_resource_set_power_level(FRSH_RT_PROCESSOR, 0, FRSH_PLT_LOW));
+ PXW(frsh_resource_get_power_level(FRSH_RT_PROCESSOR, 0, &level));
+ PXW(frsh_resource_get_speed(FRSH_RT_PROCESSOR, 0, level, &speed));
+ printf("%d (FRSH_PLT_LOW) correctly set, speed = %f\n", level, speed);
- return 0;
+ return 0;
}
int ret = 0;
char str[128];
- if (lcd_initialized == NONE)
+ if (lcd_initialized == NONE || level >= 3)
return EINVAL;
if (lcd_initialized == PROC_1) {
return __set_lcd_brightness(level);
}
+int fra_LCD_get_speed(int lcd, int level, double *ratio)
+{
+ if (lcd_initialized == NONE || level >= 3)
+ return EINVAL;
+
+ *ratio = bright[level]/bright[0];
+
+ return 0;
+}
+
int fra_LCD_set_power(int lcd, int level);
+int fra_LCD_get_speed(int lcd, int level, double *ratio);
+
#endif
#include <frsh.h>
-#include <error.h>
int main()
{
+ frsh_power_level_t level;
int power_levels;
- int ret;
+ double speed;
+ int terror;
- if (frsh_init())
- error(1, 0, "FRSH initialization failed\n");
+ PXW(frsh_init());
- 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");
+ PXW(frsh_resource_get_num_power_levels(FRSH_RT_LCD, 0, &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;
+
+ PXW(frsh_resource_get_power_level(FRSH_RT_LCD, 0, &level));
+ PXW(frsh_resource_get_speed(FRSH_RT_LCD, 0, level, &speed));
+ printf("Starting with power level %d, speed = %f\n", level, speed);
+
+ sleep(3);
+ PXW(frsh_resource_set_power_level(FRSH_RT_LCD, 0, FRSH_PLT_HIGH));
+ PXW(frsh_resource_get_power_level(FRSH_RT_LCD, 0, &level));
+ PXW(frsh_resource_get_speed(FRSH_RT_LCD, 0, level, &speed));
+ printf("%d (FRSH_PLT_HIGH) correctly set, speed = %f\n", level, speed);
+
+ sleep(3);
+ PXW(frsh_resource_set_power_level(FRSH_RT_LCD, 0, FRSH_PLT_MEDIUM));
+ PXW(frsh_resource_get_power_level(FRSH_RT_LCD, 0, &level));
+ PXW(frsh_resource_get_speed(FRSH_RT_LCD, 0, level, &speed));
+ printf("%d (FRSH_PLT_MEDIUM) correctly set, speed = %f\n", level, speed);
+
+ sleep(3);
+ PXW(frsh_resource_set_power_level(FRSH_RT_LCD, 0, FRSH_PLT_LOW));
+ PXW(frsh_resource_get_power_level(FRSH_RT_LCD, 0, &level));
+ PXW(frsh_resource_get_speed(FRSH_RT_LCD, 0, level, &speed));
+ printf("%d (FRSH_PLT_LOW) correctly set, speed = %f\n", level, speed);
+
+ return 0;
}
return 0;
}
+int aqcpu_fra_activate(forb_orb orb)
+{
+ qos_rv qrv;
+ if ((qrv = qres_init()) != QOS_OK) {
+ if (qrv == QOS_E_MISSING_COMPONENT) {
+ return FRES_ERR_KERNEL_SUPPORT_MISSING;
+ } else
+ return FRSH_ERR_INTERNAL_ERROR;
+ }
+
+ /* install the cleanup function of th AQuoSA framework as an exit
+ * handler function (quite futile but, for now, it's sufficent) */
+ if (atexit(aqcpu_cleanup_wrapper))
+ return(FRSH_ERR_INTERNAL_ERROR);
+
+ aqcpu_initialized = 1;
+
+ return 0;
+}
+
static struct fres_allocator aqcpu_allocator = {
.res_type = FRSH_RT_PROCESSOR,
.res_id = 0, /* CPU ID 0 */
.get_desired_budget = fra_CPU_get_desired_budget,
.set_desired_budget = fra_CPU_set_desired_budget,
.get_actual_budget = fra_CPU_get_actual_budget,
+
+ .activate_callback = aqcpu_fra_activate,
.priv = NULL
};
*/
int aqcpu_fra_init(void)
{
- qos_rv qrv;
int rv;
- if ((qrv = qres_init()) != QOS_OK) {
- return -1;
- }
-
if ((rv = fra_register(&aqcpu_allocator))) {
qres_cleanup();
return rv;
}
- /* install the cleanup function of th AQuoSA framework as an exit
- * handler function (quite futile but, for now, it's sufficent) */
- if (atexit(aqcpu_cleanup_wrapper))
- return(FRSH_ERR_INTERNAL_ERROR);
-
- aqcpu_initialized = 1;
-
return 0;
}
struct dummy_data *data = priv;
struct fres_sa_contract *c;
int ret;
+ long int utilization = 0;
#ifdef CONFIG_RESOURCE_DUMMY_VERBOSE
printf("Admission test:\n");
fosa_rel_time_to_msec(basic->period),
fosa_rel_time_to_msec(basic->budget), dummy_sched->priority);
#endif
+ utilization +=
+ 1000*fosa_rel_time_to_msec(basic->budget) /
+ fosa_rel_time_to_msec(basic->period);
}
- *schedulable = scenario->num_contracts <= 3;
+ scenario->utilization = utilization/10;
+ *schedulable = utilization < 1000;
+
#ifdef CONFIG_RESOURCE_DUMMY_VERBOSE
- printf("=> %s\n", *schedulable?"schedulable":"not schedulable");
+ printf("utilization=%ld.%03ld => %s\n", utilization/1000, utilization%1000,
+ *schedulable?"schedulable":"not schedulable");
#endif
return 0;