vres on pure 2.6 linux for rt threads.
config_include_HEADERS = frsh_resources.h
frsh_resources_DEFINES = CONFIG_RESOURCE_DUMMY \
CONFIG_AQUOSA\
+ CONFIG_CPUCG\
CONFIG_FWP \
CONFIG_RESOURCE_ITEM
allocator-libs-$(CONFIG_RESOURCE_ITEM) += fra_item
allocator-libs-$(CONFIG_FWP) += frsh_fwp fwp
allocator-libs-$(CONFIG_AQUOSA) += frshaqcpu
+allocator-libs-$(CONFIG_CPUCG) += frshcpucg
#include <aqcpu_res.h>
#endif
+#ifdef CONFIG_CPUCG
+#include <cpucg_res.h>
+#endif
+
#ifdef CONFIG_RESOURCE_DUMMY
#include <res_dummy.h>
#endif
ret = aqcpu_fra_init();
if (ret) goto err;
#endif
+#ifdef CONFIG_CPUCG
+ ret = cpucg_fra_init();
+ if (ret) goto err;
+#endif
#ifdef CONFIG_RESOURCE_DUMMY
ret = fra_dummy_init();
if (ret) goto err;
--- /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
+default_CONFIG = CONFIG_CPUCG=x
+
+ifeq ($(CONFIG_CPUCG),y)
+SUBDIRS = lib mngr tests
+CFLAGS+= -Wall -Wextra -D_REENTRANT
+endif
+#include_HEADERS +=$(wildcard aquosa/qresmod/*.h)
+#include_HEADERS +=$(wildcard aquosa/rresmod/*.h)
--- /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
+shared_LIBRARIES = frshcpucg
+frshcpucg_SOURCES += frsh_cpucg.c 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)
+#include_HEADERS +=$(wildcard aquosa/rresmod/*.h)
--- /dev/null
+#include "cpucg_contract.h"
+
+int get_cpucg_params(fres_vres_t *vres, cpucg_params_t *params)
+{
+ fres_block_basic *basic;
+
+ /* get params from contract */
+ basic = fres_contract_get_basic(vres->new);
+
+ /* core contract parameters */
+ params->P = timespec_to_usec(basic->period);
+ /* non-core contract parameters */
+ /* right now, the same as minimum budget */
+ params->Q = timespec_to_usec(basic->budget);
+
+ return 0;
+}
+
--- /dev/null
+#ifndef CPUCG_CONTRACT_H
+#include "timespec_usec_ops.h"
+#include <fra_generic.h>
+
+typedef
+struct cpucg_params_t {
+ long long P;
+ long long Q;
+} cpucg_params_t;
+
+int get_cpucg_params(fres_vres_t *vres, cpucg_params_t *params);
+
+#endif /* CPUCG_CONTRACT_H */
--- /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 FRESCOR CPUCG (cpu control group) */
+/* */
+/* FWP is free software; you can redistribute it and/or modify it */
+/* under terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2, or (at your option) any */
+/* later version. FWP is distributed in the hope that it will be */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* General Public License for more details. You should have received a */
+/* copy of the GNU General Public License along with FWP; see file */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
+/* Cambridge, MA 02139, USA. */
+/* */
+/* As a special exception, including AQCPU header files in a file, */
+/* instantiating FWP generics or templates, or linking other files */
+/* with FWP objects to produce an executable application, does not */
+/* by itself cause the resulting executable application to be covered */
+/* by the GNU General Public License. This exception does not */
+/* however invalidate any other reasons why the executable file might be */
+/* covered by the GNU Public License. */
+/**************************************************************************/
+#include <ul_log.h>
+#include <fra_generic.h>
+
+#include "cpucg_contract.h"
+#include <stdio.h>
+#include <libcgroup.h>
+
+UL_LOG_CUST(ulogd_fra_cpucg);
+//ul_log_domain_t ulogd_fra_cpucg = {UL_LOGL_MSG, "fra_cpucg"};
+
+static int cpucg_initialized = 0; /* initialization flag */
+
+#define CGNAME 20
+/*
+ * Permissions
+ */
+static uid_t tuid = 0;
+static gid_t tgid = 0;
+static uid_t cuid = 0;
+static gid_t cgid = 0;
+
+static int vres_inc = 0;
+
+/*
+ * Test whether Aquosa Cpu modue is initialized
+ */
+static inline int cpucg_is_initialized()
+{
+ return (cpucg_initialized == 1);
+}
+
+static inline char* cpucg_get_name(void)
+{
+ char* cgname = malloc(CGNAME);
+ snprintf(cgname, CGNAME, "%d", getpid() + vres_inc++);
+
+ return cgname;
+}
+
+static int cpucg_create_vres(fres_vres_t *vres, void *priv)
+{
+ cpucg_params_t cpu_params;
+ struct cgroup_controller *cpucntl;
+ struct cgroup* ccg;
+ long int period;
+ long int budget;
+ char* cgroup_name;
+ int ret;
+
+ /* get aqcpu params from contract */
+ get_cpucg_params(vres, &cpu_params);
+ period = cpu_params.P;
+ budget = cpu_params.Q;
+
+ /* create cpu vres */
+ cgroup_name = cpucg_get_name();
+ ccg = cgroup_new_cgroup(cgroup_name);
+ cgroup_set_uid_gid(ccg, tuid, tgid, cuid, cgid);
+ cpucntl = cgroup_add_controller(ccg, "cpu");
+ printf("To be Created CGCPU VRES(period=%ld us, budget=%ld us)\n",
+ period, budget);
+ cgroup_add_value_uint64(cpucntl, "cpu.rt_period_us", period);
+ cgroup_add_value_uint64(cpucntl, "cpu.rt_runtime_us", budget);
+
+ if ((ret = cgroup_create_cgroup(ccg, 1))) {
+ return ret;
+ }
+
+ printf("Created CGCPU VRES(period=%lld us, budget=%lld us)\n",
+ period, budget);
+ vres->priv = ccg;
+
+ return 0;
+}
+
+/*
+ * aqcpu_cancel_vres(), cancels vres
+ *
+ * The thread bound to the vres are unbound, and so, detached from their
+ * AQuoSA resource reservation servers and continue their execution according
+ * to the standard Linux scheduler policies.
+ *
+ */
+static int cpucg_cancel_vres(fres_vres_t *vres, void *priv)
+{
+ struct cgroup *cgroup;
+
+ if (vres->priv) {
+ errno = -EINVAL;
+ return -1;
+ }
+
+ cgroup = (struct cgroup*) vres->priv;
+ /* TODO: Solve migration
+ cgroup_delete_cgroup(cgroup, 1);*/
+ printf("Canceled CGCPU VRES\n");
+ cgroup_free(&cgroup);
+
+ return 0;
+}
+
+/* aqcpu_vres_change(), change some parameters of a vres
+ *
+ * In fact, since that AQuoSA call doesn't deal with _its_ Q_min (budget_min
+ * for in FRSH semantic) parameter all the renegotiation will be accepted but
+ * the new temporal behaviour is not guaranteed!
+ * Obviously this is a bug and should/will be corrected in AQuoSA as soon as
+ * possible.
+ *
+ */
+int cpucg_change_vres(fres_vres_t *vres, void *priv)
+{
+ struct cgroup *cgroup;
+ cpucg_params_t cpu_params;
+
+ if (vres->priv) {
+ errno = -EINVAL;
+ return -1;
+ }
+
+ cgroup = (struct cgroup*) vres->priv;
+
+ /* get aqcpu params from contract */
+ get_cpucg_params(vres, &cpu_params);
+
+ /* TODO:
+ * cgroup->controller[0]->values[0]->value = cpu_params.P;
+ cgroup->controller[0]->values[1]->value = cpu_params.Q; */
+
+ ul_logmsg("AQCPU VRES params changed(period=%lld us,"
+ "budget=%lld us)\n", cpu_params.P, cpu_params.Q);
+
+ return 0;
+}
+
+static struct fres_allocator cpucg_allocator = {
+ .res_type = FRSH_RT_PROCESSOR,
+ .res_id = 0, /* CPU ID 0 */
+ .create_vres = cpucg_create_vres,
+ .cancel_vres = cpucg_cancel_vres,
+ .change_vres = cpucg_change_vres,
+ .priv = NULL
+};
+
+/*
+ * cpucg_fra_init()
+ *
+ * initialize FRSH for the calling process
+ *
+ * Must be called before starting using the framework.
+ * No FRSH call will be successful if this routine is not invoked
+ *
+ * Note that no BACKGROUND is created and negotiated and the caller thread
+ * is bound to no BACKGROUND vres, since no way is provided in order of
+ * specifying the contract label and get back the vres id!
+ *
+ * Note also that, since in this implementation the threads/processes with
+ * backgound contracts are left into the default Linux scheduler hands' and
+ * not attached to any AQuoSA server, while we're violating what D-AC2v1
+ * (pag. 14) says, we achieve exactly the same behaviour!!
+ *
+ * possible return values:
+ * FRSH_NO_ERROR
+ * FRSH_ERR_ALREADY_INITIALIZED
+ * FRSH_ERR_INTERNAL_ERROR (something, different from the previous case, gone wrong)
+ */
+int cpucg_fra_init(void)
+{
+ if (cpucg_is_initialized()) {
+ return -1;
+ }
+
+ /* TODO: tets whether cpu controller is mounted */
+ //if (cgroup_init() || !cgroup_test_subsys_mounted("cpu")) {
+ if (cgroup_init()) {
+ return -1;
+ }
+
+ if (fra_register(&cpucg_allocator)) {
+ return -1;
+ }
+
+ cpucg_initialized = 1;
+ return 0;
+}
+
+int cpucg_fra_exit()
+{
+ return 0;
+}
--- /dev/null
+#ifndef CPUCG_RES_H
+#define CPUCG_RES_H
+
+#include <forb.h>
+#include <fcb.h>
+#include <frsh_core.h>
+
+int cpucg_fra_init(void);
+
+#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 <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;
+
+ /*if (!aqcpu_is_initialized) {
+ return(FRSH_ERR_NOT_INITIALIZED);
+ }*/
+
+
+ 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;
+}
+
+/*
+ * 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)
+{
+ /* 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 FRSH_NO_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;
+
+ *thread_id = fosa_thread_self();
+ /* bind this thread to vres */
+ pth->errcode = frsh_thread_bind(pth->vres, *thread_id);
+
+ sem_post(pth->stopper);
+ if (pth->errcode) /* vres binding was not successful */
+ return NULL;
+
+ /* execute thread function */
+ return pth->pthread_code(pth->pthread_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;
+ struct sched_param param;
+ int p;
+
+ 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;
+
+ pthread_attr_getschedparam(attr, ¶m);
+ p = param.sched_priority;
+ printf("priority = %d\n", p);
+ if (p == 0) {
+ param.sched_priority = 1;
+ pthread_attr_setschedparam(attr, ¶m);
+ pthread_attr_getschedparam(attr, ¶m);
+ printf("changed priority = %d\n", param.sched_priority);
+ pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
+ pthread_attr_setschedpolicy(attr, SCHED_RR);
+ pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM);
+ }
+
+ /* 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);
+}
+
+/*
+ * API call for 'frsh_thread_create_in_background()', as said creates a
+ * background contract and negotiate it (we know they're always accepted
+ * but we need to get the service thread account fo the new vres), then
+ * create the new thread, exactly as seen in 'frsh_thread_create_and_bind()'
+ * and wait for its acknowledgment
+ *
+ * possible return values:
+ * FRSH_NO_ERROR
+ * FRSH_ERR_NOT_INITIALIZED
+ * FRSH_ERR_BAD_ARGUMENT (NULL thread_id, thread_code, contract_label or vres_id)
+ * FRSH_ERR_TOO_MANY_VRES(*)
+ * FRSH_ERR_CONTRACT_ID_ALREADY_EXISTS(*)
+ * FRSH_ERR_CONTRACT_REJECTED(*)
+ * whatever 'fosa_thread_create()' returns
+ * FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ * FRSH_ERR_INTERNAL_ERROR (something wrong in signal handling)
+ */
+int frsh_thread_create_in_background(frsh_thread_code_t thread_code,
+ const void *thread_arg,
+ const frsh_contract_label_t contract_label,
+ frsh_thread_attr_t *attr,
+ frsh_thread_id_t *thread_id,
+ frsh_vres_id_t *vres_id)
+{
+ return FRSH_ERR_NOT_IMPLEMENTED;
+}
+
+/*
+ * frsh_thread_get_vres_id(), get the id vres of a vres bound to a thread
+ *
+ * Asks the service thread for the id of a particular vres, knowing the thread
+ * bound to it.
+ *
+ * The code below only prepares the message, send it and wait for the answer,
+ * for details on the implementation check 'get_thread_vres_id()' in the
+ * frsh_service_th.c source file
+ * possible return values:
+ * FRSH_NO_ERROR
+ * FRSH_ERR_NOT_INITIALIZED
+ * FRSH_BAD_ARGUMENT(*) (invalid thread or NULL vres)
+ * FRSH_ERR_NOT_BOUND(*) (-IMPOSSIBLE- thread not bound)
+ * FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ * FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_thread_get_vres_id(const frsh_thread_id_t thread,
+ frsh_vres_id_t *vres_id)
+{
+ return FRSH_ERR_NOT_IMPLEMENTED;
+}
+
+/*
+ * frsh_thread_self(), get the thread and vres id of the caller
+ *
+ * Simply returns the thread id of the caller and the vres id to which
+ * (if any) it's bound.
+ *
+ * Note that the thread id is always returned, while the retrieval of the vres
+ * id can be skipped passing a NULL pointer as vres_self argument.
+ *
+ * Nota also that the thread id could be retieved via a simple FOSA call, while
+ * for the vres id we can only ask it to the service thread.
+ *
+ * possible return values:
+ * FRSH_NO_ERROR
+ * FRSH_ERR_NOT_INITIALIZED
+ * FRSH_ERR_BAD_ARGUMENT (NULL thread_self)
+ * all that 'frsh_thread_get_vres_id()' returns (FRSH_ERR_NOT_BOUND)
+ * FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ * FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread)
+ */
+int frsh_thread_self(frsh_thread_id_t *thread_self, frsh_vres_id_t *vres_self)
+{
+ return FRSH_ERR_NOT_IMPLEMENTED;
+}
+
+
+
+/////////////////////////////////////////////
+// S E R V I C E T H R E A D T U N I N G
+/////////////////////////////////////////////
+
+/*
+ * frsh_service_thread_set_data(), adapt timing guarantees for the service thread
+ *
+ * Modifies the execution period and budget of the service thread from the
+ * defaults configured for it and negotiated during service thread
+ * initialization.
+ *
+ * Here we only request the operation sending a message to the service thread
+ * itself (and waiting for the answer), check the service thread main code
+ * in the frsh_service_th.c source file for the implementation details.
+ *
+ * possible return values:
+ * FRSH_NO_ERROR
+ * FRSH_ERR_NOT_INITIALIZED
+ * FRSH_ERR_BAD_ARGUMENT (NULL or inconsistent budget or period)
+ * FRSH_ERR_CONTRACT_REJECTED(*)
+ * FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ * FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread) *
+ */
+int frsh_service_thread_set_data(const struct timespec *budget,
+ const struct timespec *period,
+ bool *accepted)
+{
+ return FRSH_ERR_NOT_IMPLEMENTED;
+}
+
+/*
+ * frsh_service_thread_get_data(), obtain timing guarantees for the service thread
+ *
+ * Obtains the actual execution period and budget of the service.
+ *
+ * Here we only request the operation sending a message to the service thread
+ * itself (and waiting for the answer), check the service thread main code
+ * in the frsh_service_th.c source file for the implementation details.
+ *
+ * possible return values:
+ * FRSH_NO_ERROR
+ * FRSH_ERR_NOT_INITIALIZED
+ * FRSH_ERR_BAD_ARGUMENT (NULL budget or period)
+ * FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
+ * FRSH_ERR_INVALID_SCHEDULER_REPLY (error in communication with the service thread) *
+ */
+int frsh_service_thread_get_data(frsh_rel_time_t *budget, frsh_rel_time_t *period)
+{
+
+ return FRSH_ERR_NOT_IMPLEMENTED;
+}
--- /dev/null
+#ifndef __TIMESPEC_USEC_OPS_H__
+#define __TIMESPEC_USEC_OPS_H__
+
+/*
+ * timespec_usec_ops.h
+ *
+ * ...
+ */
+
+#include <time.h>
+
+#define equal_timespec(t1, t2) \
+ ( ( (t1)->tv_sec == (t2)->tv_sec ) && ( (t1)->tv_nsec == (t2)->tv_nsec ) )
+
+#define increment_timespec(t) \
+do { \
+ (t)->tv_nsec ++; \
+ if ((t)->tv_nsec >= 1000000000UL) { \
+ (t)->tv_sec ++; \
+ (t)->tv_nsec -= 1000000000UL; \
+ } \
+} while(0)
+
+#define decrement_timespec(t) \
+do { \
+ if ( (t)->tv_nsec == 0) { \
+ (t)->tv_nsec = 1000000000UL; \
+ (t)->tv_sec --; \
+ } \
+ else \
+ (t)->tv_nsec --; \
+} while(0)
+
+#define sum_timespec(t1, t2, ts) \
+do { \
+ (ts)->tv_sec = (t1)->tv_sec + (t2)->tv_sec; \
+ (ts)->tv_nsec = (t1)->tv_nsec + (t2)->tv_nsec; \
+ while ( (ts)->tv_nsec >= 1000000000UL) { \
+ (ts)->tv_sec ++; \
+ (ts)->tv_nsec -= 1000000000UL; \
+ } \
+} while(0)
+
+#define sub_timespec(t1, t2, ts) \
+do { \
+ if ( (t2)->tv_sec < (t1)->tv_sec || \
+ ((t2)->tv_sec == (t1)->tv_nsec && (t2)->tv_nsec < (t1)->tv_nsec) ) { \
+ (ts)->tv_sec = (t1)->tv_sec - (t2)->tv_sec; \
+ (ts)->tv_nsec = (t1)->tv_nsec - (t2)->tv_sec; \
+ while ( (ts)->tv_nsec < 0) { \
+ (ts)->tv_sec --; \
+ (ts)->tv_nsec = (ts)->tv_nsec + 1000000000UL; \
+ } \
+ } else { \
+ (ts)->tv_sec = 0UL; \
+ (ts)->tv_nsec = 0UL; \
+ } \
+} while(0)
+
+#define zero_timespec(t) \
+do { \
+ (t)->tv_sec = 0; \
+ (t)->tv_nsec = 0; \
+} while(0)
+
+#define is_zero_timespec(t) \
+( (t)->tv_sec == 0 && (t)->tv_nsec == 0 )
+
+#endif /* __TIMESPEC_USEC_OPS_H__ */
--- /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
+bin_PROGRAMS = cpucgmngr
+cpucgmngr_SOURCES = cpucg_mngr.c
+cpucgmngr_LIBS = frm forb contract fosa rt ulut fcb_client
+lib_LOADLIBES+= frsh
--- /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 FRESCOR CPUCG (cpu control group) */
+/* */
+/* FWP is free software; you can redistribute it and/or modify it */
+/* under terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2, or (at your option) any */
+/* later version. FWP is distributed in the hope that it will be */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* General Public License for more details. You should have received a */
+/* copy of the GNU General Public License along with FWP; see file */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
+/* Cambridge, MA 02139, USA. */
+/* */
+/* As a special exception, including FWP header files in a file, */
+/* instantiating FWP generics or templates, or linking other files */
+/* with FWP objects to produce an executable application, does not */
+/* by itself cause the resulting executable application to be covered */
+/* by the GNU General Public License. This exception does not */
+/* however invalidate any other reasons why the executable file might be */
+/* covered by the GNU Public License. */
+/**************************************************************************/
+#include <frm_generic.h>
+#include <forb.h>
+#include <error.h>
+#include <errno.h>
+#include <fres_sa_scenario.h>
+#include <stdbool.h>
+#include <ul_log.h>
+#include <stdio.h>
+
+UL_LOG_CUST(ulogd_frm_cpucg);
+ul_log_domain_t ulogd_fra_fwp = {UL_LOGL_DEB, "frm_cpucg"};
+
+/**
+ * root cgroup`s period
+ */
+static unsigned int global_period_us;
+/**
+ * root cgroup`s runtime
+ */
+static unsigned int global_runtime_us;
+
+static int cpucg_admtest(struct fres_sa_scenario *scenario, void *priv,
+ bool *schedulable)
+{
+ struct fres_sa_contract *c;
+ long int period, budget;
+ long int sum_utilization = 0;
+
+ fres_sa_scenario_for_each_contract(scenario, c) {
+ fres_block_basic *basic;
+ char id[40];
+ fres_contract_id_to_string(id, &c->contract->id, sizeof(id));
+ basic = fres_contract_get_basic(c->contract);
+
+ period = fosa_rel_time_to_msec(basic->period);
+ budget = fosa_rel_time_to_msec(basic->budget);
+ printf("processing : id=%s, period=%ld ms, budget=%ld ms\n",
+ id,period, budget);
+ //ul_logdeb("processing : id=%s, period=%ld ms, budget=%ld ms\n",
+ // id,period, budget);
+
+ sum_utilization+= budget*100/period;
+ }
+ printf("sum_ut= %ld global_ut=%ld \n", sum_utilization, (global_runtime_us*100/global_period_us));
+ *schedulable = (sum_utilization < (global_runtime_us*100/global_period_us));
+ printf("=> %s\n", (*schedulable)?"schedulable":"not schedulable");
+
+ return 0;
+}
+
+static const struct fres_res_manager frm = {
+ .res_type = FRSH_RT_PROCESSOR,
+ .res_id = 0,
+ .admission_test = cpucg_admtest,
+ .priv = NULL
+};
+
+int main(int argc, char *argv[])
+{
+ forb_orb orb;
+ FILE* fd;
+ int ret;
+
+ orb = forb_init(&argc, &argv, "frm_cpucg");
+ if (!orb) error(1, errno, "forb_init");
+
+ if (!(fd = fopen("/proc/sys/kernel/sched_rt_period_us", "r"))) {
+ error(1, errno, "frm_generic_run");
+ }
+ ret = fscanf(fd,"%d", &global_period_us);
+ printf("sched_rt_period_us= %d\n", global_period_us);
+ if (ret == 0 || ret == EOF) {
+ error(1, errno, "frm_generic_run");
+ }
+ fclose(fd);
+
+ if (!(fd = fopen("/proc/sys/kernel/sched_rt_runtime_us", "r"))) {
+ error(1, errno, "frm_generic_run");
+ }
+ ret = fscanf(fd,"%d", &global_runtime_us);
+ printf("sched_rt_runtime_us= %d\n", global_runtime_us);
+ if (ret == 0 || ret == EOF) {
+ error(1, errno, "frm_generic_run");
+ }
+ fclose(fd);
+
+ ret = frm_register_and_run(orb, &frm);
+ if (ret != 0) {
+ error(1, errno, "frm_generic_run");
+ }
+
+ return 0;
+}
--- /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
+test_PROGRAMS = cpucgtest
+cpucgtest_SOURCES = cpucgtest.c
+#aqcpumngr_LIBS = frm forb contract fosa rt ulut fcb_client
+lib_LOADLIBES += pthread rt frshcpucg frsh
--- /dev/null
+CONFIG_AQUOSA=y
+CFLAGS+=-save-temps
+CONFIG_FWP=n
+CONFIG_RESOURCE_DUMMY=n
+CONFIG_RESOURCE_ITEM=n
+CONFIG_RESOURCE_CLUSTER_TREE=n
+
--- /dev/null
+#include <frsh.h>
+#include <cpucg_res.h>
+#include <error.h>
+
+void* work_thread()
+{
+ int i;
+
+ printf("I am alive! \n");
+ while(1) {
+ printf("I am alive! \n");
+ i++;
+
+ }
+
+}
+
+int main()
+{
+ frsh_vres_id_t vres;
+ frsh_thread_attr_t attr;
+ frsh_thread_id_t thread;
+ frsh_contract_t contract;
+ frsh_rel_time_t budget, period;
+ int ret;
+
+ if (frsh_init()) {
+ error(1, 0, "FRSH initialization failed\n");
+
+ }
+
+ /* Contract negotiation for CPU */
+ ret = frsh_contract_init(&contract);
+ if (ret) PERROR_AND_EXIT(ret, "frsh_contract_init");
+
+ budget = fosa_msec_to_rel_time(50);
+ period = fosa_msec_to_rel_time(100);
+ ret = frsh_contract_set_basic_params(&contract,
+ &budget,
+ &period,
+ FRSH_WT_BOUNDED,
+ FRSH_CT_REGULAR);
+ if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_basic_params");
+ ret = frsh_contract_set_resource_and_label(&contract, FRSH_RT_PROCESSOR,
+ 0,"aqcpu_cont1");
+ if (ret) PERROR_AND_EXIT(ret, "frsh_contract_set_resource_and_label");
+
+ ret = frsh_contract_negotiate(&contract, &vres);
+ if (ret) PERROR_AND_EXIT(ret, "frsh_contract_negotiate");
+
+ printf("Aqcpu vres negotiated\n");
+ pthread_attr_init(&attr);
+ ret = frsh_thread_create_and_bind(vres, &thread, &attr,
+ work_thread, (void*) NULL);
+ if (ret) PERROR_AND_EXIT(ret, "frsh_thread_create_and_bind");
+
+ pthread_join(thread.pthread_id, (void**) NULL);
+ printf("Test PASSED!\n");
+
+ return 0;
+}
+