--- /dev/null
+/**************************************************************************/
+/* ---------------------------------------------------------------------- */
+/* 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;
+ fres_block_basic *b;
+
+ if (!spare_contract || !*spare_contract)
+ return FRSH_ERR_BAD_ARGUMENT;
+
+ ret = frsh_contract_negotiate(spare_contract, &spare_vres);
+ if (ret) goto err;
+
+ b = fres_contract_get_basic(*spare_contract);
+ switch(r->resource_type)
+ {
+ case FRSH_RT_CPU:
+ {
+ ret = fra_CPU_set_spare_bandwidth(vres_id);
+ break;
+ }
+ case FRSH_RT_DISK:
+ {
+ ret = fra_DISK_set_spare_bandwidth(vres_id);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int frsh_feedback_get_desired_budget
+ (frsh_vres_id_t vres_id,
+ frsh_rel_time_t *p_budget_out)
+{
+ frsh_contract_t *contract = vres->percieved;
+ fres_block_resource *r = fres_contract_get_resource(*contract);
+ int ret;
+
+ switch(r->resource_type)
+ {
+ case FRSH_RT_CPU:
+ {
+ ret = fra_CPU_get_desired_budget(vres, p_budget_out);
+ break;
+ }
+ case FRSH_RT_DISK:
+ {
+ ret = fra_DISK_get_desired_budget(vres, p_budget_out);
+ break;
+ }
+ default:
+ goto err;
+ }
+ if (ret) goto err;
+
+ return FRSH_NO_ERROR;
+err:
+ return FRSH_ERR_INTERNAL_ERROR;
+}
+
+int frsh_feedback_set_desired_budget
+ (frsh_vres_id_t vres_id,
+ frsh_rel_time_t *p_budget_in)
+{
+ frsh_contract_t *contract = vres->percieved;
+ fres_block_resource *r = fres_contract_get_resource(*contract);
+ int ret;
+
+ switch(r->resource_type)
+ {
+ case FRSH_RT_CPU:
+ {
+ ret = fra_CPU_set_desired_budget(vres, p_budget_in);
+ break;
+ }
+ case FRSH_RT_DISK:
+ {
+ ret = fra_DISK_set_desired_budget(vres, p_budget_in);
+ break;
+ }
+ default:
+ goto err;
+ }
+
+ if (err) goto err;
+
+ return FRSH_NO_ERROR;
+err:
+ return FRSH_ERR_INTERNAL_ERROR;
+}
+
+int frsh_feedback_get_actual_budget
+ (frsh_vres_id_t vres_id,
+ frsh_rel_time_t *budget)
+{
+ frsh_contract_t *contract = vres->percieved;
+ fres_block_resource *r = fres_contract_get_resource(*contract);
+ int ret;
+
+ switch(r->resource_type)
+ {
+ case FRSH_RT_CPU:
+ {
+ ret = fra_CPU_get_actual_budget(vres, budget);
+ break;
+ }
+ case FRSH_RT_DISK:
+ {
+ ret = fra_DISK_get_actual_budget(vres, budget);
+ break;
+ }
+ default:
+ goto err;
+ }
+
+ if (err) goto err;
+
+ return FRSH_NO_ERROR;
+err:
+ return FRSH_ERR_INTERNAL_ERROR;
+}
+
*
*
*/
+#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)
+{
+ struct fres_contract *contract = vres->perceived;
+ fres_block_resource *r = fres_contract_get_resource(contract);
+ int ret;
+
+ ret = fra_insert_thread_vres(&thread, r->resource_type, vres);
+ if (ret) goto err;
+ switch(r->resource_type)
+ {
+ case FRSH_RT_PROCESSOR:
+ {
+ ret = fra_CPU_bind_thread(vres, thread);
+ break;
+ }
+ case FRSH_RT_DISK:
+ {
+ ret = fra_DISK_bind_thread(vres, thread);
+ break;
+ }
+ default:
+ goto err_delete;
+ }
+ if (ret) goto err_delete;
+
+ return FRSH_NO_ERROR;
+
+err_delete:
+ fra_delete_thread_vres(&thread, r->resource_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;
+ struct fres_contract *contract;
+ fres_block_resource *r;
+ int ret;
+
+ /* Unbound from FRSH_RT_PROCESSOR resource (if any) */
+ vres = fra_get_vres_thread_vres(&thread, FRSH_RT_PROCESSOR);
+ if (vres) {
+ contract = vres->perceived;
+ r = fres_contract_get_resource(contract);
+ ret = fra_CPU_unbind_thread(thread);
+ if (ret) goto err;
+
+ ret = fra_delete_thread_vres(&thread, FRSH_RT_PROCESSOR);
+ if (ret) goto err;
+ }
+
+ /* Unbound from FRSH_RT_DISK resource (if any) */
+ vres = fra_get_vres_thread_vres(&thread, FRSH_RT_DISK);
+ if (vres) {
+ contract = vres->perceived;
+ r = fres_contract_get_resource(contract);
+ ret = fra_DISK_unbind_thread(thread);
+ if (ret) goto err;
+
+ ret = fra_delete_thread_vres(&thread, FRSH_RT_DISK);
+ 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,
{
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);
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
if (!vres_id)
return FRSH_ERR_BAD_ARGUMENT;
- *vres_id = fra_get_vres_thread_vres(&thread, FRSH_RT_PROCESSOR);
+ /*
+ * @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;
}
#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)
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;
+
+ 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
return 0;
}
+int frsh_vres_get_usage
+ (const frsh_vres_id_t vres,
+ frsh_rel_time_t *spent)
+{
+ struct fres_contract *contract = vres->perceived;
+ fres_block_resource *r = fres_contract_get_resource(contract);
+ int ret;
+
+ switch(r->resource_type)
+ {
+ case FRSH_RT_PROCESSOR:
+ {
+ ret = fra_CPU_get_usage(vres, spent);
+ break;
+ }
+ case FRSH_RT_DISK:
+ {
+ ret = fra_DISK_get_usage(vres, spent);
+ break;
+ }
+ default:
+ goto err;
+ }
+ if (ret) goto err;
+
+ return FRSH_NO_ERROR;
+err:
+ return FRSH_ERR_INTERNAL_ERROR;
+}
+
+int frsh_vres_get_job_usage
+ (const frsh_vres_id_t vres,
+ frsh_rel_time_t *spent)
+{
+ struct fres_contract *contract = vres->perceived;
+ fres_block_resource *r = fres_contract_get_resource(contract);
+ int ret;
+
+ switch(r->resource_type)
+ {
+ case FRSH_RT_PROCESSOR:
+ {
+ ret = fra_CPU_get_job_usage(vres, spent);
+ break;
+ }
+ case FRSH_RT_DISK:
+ {
+ ret = fra_DISK_get_job_usage(vres, spent);
+ break;
+ }
+ default:
+ goto err;
+ }
+ if (ret) goto err;
+
+ return FRSH_NO_ERROR;
+err:
+ return FRSH_ERR_INTERNAL_ERROR;
+}
+
+int frsh_vres_get_remaining_budget
+ (const frsh_vres_id_t vres,
+ frsh_rel_time_t *budget)
+{
+ struct fres_contract *contract = vres->perceived;
+ fres_block_resource *r = fres_contract_get_resource(contract);
+ int ret;
+
+ switch(r->resource_type)
+ {
+ case FRSH_RT_PROCESSOR:
+ {
+ ret = fra_CPU_get_remaining_budget(vres, budget);
+ break;
+ }
+ case FRSH_RT_DISK:
+ {
+ ret = fra_DISK_get_remaining_budget(vres, budget);
+ break;
+ }
+ default:
+ goto err;
+ }
+ if (ret) goto err;
+
+ return FRSH_NO_ERROR;
+err:
+ return FRSH_ERR_INTERNAL_ERROR;
+}
+
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_LIBS += qreslib qsuplib
#include <fra_generic.h>
#include "aquosa/qres_lib.h"
+#include "aquosa/qsup_lib.h"
+
#include "aqcpu_contract.h"
UL_LOG_CUST(ulogd_fra_aqcpu);
errno = -EPERM;
return -1;
}
-
+
if ((rv = fra_register(&aqcpu_allocator))) {
qres_cleanup();
return rv;
rv = qres_cleanup();
return qos_rv_int(rv);
}
+
+int fra_CPU_bind_thread
+ (const 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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+int fra_CPU_get_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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
#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);
+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 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_spare_bandwidth(fres_vres_t *vres);
+
+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 /* AQCPU_RES_H */
+++ /dev/null
-// -----------------------------------------------------------------------
-// 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, FRSH_RT_PROCESSOR, 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, FRSH_RT_PROCESSOR);
-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, FRSH_RT_PROCESSOR);
- 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;
-}
-
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()
frsh_rel_time_t budget, period;
int ret;
- if (frsh_init()) {
+ 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(2000);
+ period = fosa_msec_to_rel_time(100);
ret = frsh_contract_set_basic_params(&contract,
&budget,
&period,
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_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;
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)
return 0;
}
+
+
static struct fres_allocator cpucg_allocator = {
.res_type = FRSH_RT_PROCESSOR,
.res_id = 0, /* CPU ID 0 */
{
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, ¶m);
+ 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, ¶m);
+ pthread_getschedparam(pthread_self(), &policy, ¶m);
+ 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;
+}
+
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 */
+++ /dev/null
-// -----------------------------------------------------------------------
-// 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, ¶m);
- if (param.sched_priority == 0) {
- param.sched_priority = 1;
- if (sched_setscheduler(thread.linux_tid, SCHED_RR,
- ¶m) == -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, ¶m);
- 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, ¶m);
- pthread_attr_getschedparam(&updated_attr, ¶m);
- 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;
-}
-