default_CONFIG = CONFIG_AQUOSA=x
ifeq ($(CONFIG_AQUOSA),y)
-shared_LIBRARIES = aqcpu
-CFLAGS += -I /usr/local/aquosa/include
-frsh_aquosa_SOURCES += frsh_aqcpu.c aqcpu_contract.c aqcpu_sched.c
-include_HEADERS += aqcpu_contract.h timespec_usec_ops.h
+SUBDIRS = lib mngr
+CFLAGS+= -Wall -Wextra -D_REENTRANT
endif
#include_HEADERS +=$(wildcard aquosa/qresmod/*.h)
#include_HEADERS +=$(wildcard aquosa/rresmod/*.h)
+++ /dev/null
-#include "aqcpu_contract.h"
-
-int get_cpu_vres(struct forb_contract *contract, qres_sid_t *vres)
-{
- return 0;
-}
-
-int set_cpu_vres(struct forb_contract *contract, qres_sid_t vres)
-{
- return 0;
-}
-
-int get_cpu_params(struct forb_contract *contract, cpu_params_t *cpu_params)
-{
-#if 0
- /* core contract parameters */
- cpu_params->Q_min = timespec_to_usec(contract->budget_min);
- cpu_params->P = timespec_to_usec(contract->period_max);
- /* non-core contract parameters */
- cpu_params->Q = timespec_to_usec(contract->budget_max);
- /* AQuoSA specific configuration */
- cpu_params->flags = 0x000;
- cpu_params->flags |= QOS_F_PERSISTENT;
- /* if we're negotiating for the service thread create
- * a soft server */
- if (contract == &service_th_contract) {
- qres_contract.flags |= QOS_F_SOFT;
- }
-
- cpu_params->timeout = 0;
-#endif
- return 0;
-}
-
-int set_cpu_params(struct forb_contract *contract, cpu_params_t *cpu_params)
-{
- return 0;
-}
+++ /dev/null
-#ifndef CPU_CONTRACT_H
-#include "aquosa/qres_lib.h"
-#include "timespec_usec_ops.h"
-#include "forb_contract.h"
-
-typedef qres_params_t cpu_params_t;
-
-int get_cpu_vres(struct forb_contract *contract, qres_sid_t *vres);
-int set_cpu_vres(struct forb_contract *contract, qres_sid_t vres);
-
-int get_cpu_params(struct forb_contract *contract, cpu_params_t *cpu_params);
-int set_cpu_params(struct forb_contract *contract, cpu_params_t *cpu_params);
-
-#endif /* CPU_CONTRACT_H */
+++ /dev/null
-#include "aquosa/qres_lib.h"
-#include "aqcpu_contract.h"
-
-int aqcpu_sched_init()
-{
- if (qres_init() != QOS_OK) {
- return -1;
- }
-
- /* register to DTM */
- return 0;
-}
-
-int aqcpu_vres_create(struct forb_contract *contract)
-{
- cpu_params_t cpu_params;
- qres_sid_t sid;
-
- /* get params from contract */
- get_cpu_params(contract, &cpu_params);
- /* create cpu vres */
- if (qres_create_server(&cpu_params, &sid) == QOS_E_SYSTEM_OVERLOAD)
- return FRSH_ERR_CONTRACT_REJECTED;
- else
- return FRSH_ERR_INTERNAL_ERROR;
- /* qres server was created */
- return set_cpu_vres(contract, sid);
-}
-
-/*
- * aqcpu_vres_cancel(), cancel 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.
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (invalid_vres)
- * FRSH_ERR_INTENRAL_ERROR
- */
-int aqcpu_vres_cancel(struct forb_contract *contract)
-{
- qres_sid_t sid;
- qos_rv qres_status;
-
- get_cpu_vres(contract, &sid);
- qres_status = qres_destroy_server(sid);
- if (qres_status != QOS_OK)
- return FRSH_ERR_INTERNAL_ERROR;
-
- return -1;
-}
-
-/* aqcpu_vres_change(), change some parameters of a vres
- *
- * All is done (of course!) without removing the old vres and creating a new
- * one, thanks to AQuoSA "change parameters" library API call, but this
- * actually put an issue in place.
- * 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.
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (invalid vres or not matching contract types)
- * FRSH_ERR_INTENRAL_ERROR (something wrong with AQuoSA)
- */
-int aqcpu_change_vres(struct forb_contract *contract)
-{
- cpu_params_t cpu_params;
- qres_sid_t sid;
- qos_rv qres_status;
-
- get_cpu_vres(contract, &sid);
- /* get params from contract */
- get_cpu_params(contract, &cpu_params);
- /* set cpu params */
- qres_status = qres_set_params(sid, &cpu_params);
- /* create the vres as an AQuoSA resource reservation server */
- if (qres_status == QOS_E_SYSTEM_OVERLOAD)
- return FRSH_ERR_CONTRACT_REJECTED;
- else
- return FRSH_ERR_INTERNAL_ERROR;
-}
-
-int aqcpu_sched_exit()
-{
- qos_rv rv;
-
- rv = qres_cleanup();
- return qos_rv_int(rv);
-}
-
-#if 0
-sched_ops aqcpu_sched_ops = {
- .init = aquosa_init();
- .exit = aquosa_exit();
- .create_vres = aquosa_create_vres();
- .cancel_vres = aquosa_cancel_vres();
- .change_vres = aquosa_change_vres();
- /*
- *.get_vres_usage
- *.get_remaining_budget
- */
-};
-#endif
--- /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 = aqcpu
+CFLAGS += -I /usr/local/aquosa/include
+frsh_aquosa_SOURCES += frsh_aqcpu.c aqcpu_contract.c aqcpu_sched.c
+include_HEADERS += aqcpu_contract.h timespec_usec_ops.h
+#include_HEADERS +=$(wildcard aquosa/qresmod/*.h)
+#include_HEADERS +=$(wildcard aquosa/rresmod/*.h)
--- /dev/null
+#include "aqcpu_contract.h"
+
+int get_aqcpu_params(fres_vres_t *vres, cpu_params_t *params)
+{
+ fres_block_basic *basic;
+
+ /* get params from contract */
+ basic = fres_contract_get_basic(vres->new);
+ /* core contract parameters */
+ cpu_params->Q_min = timespec_to_usec(basic->budget);
+ cpu_params->P = timespec_to_usec(basic->period);
+ /* non-core contract parameters */
+ /* right now, the same as minimum budget */
+ cpu_params->Q = timespec_to_usec(basic->budget);
+ /* AQuoSA specific configuration */
+ cpu_params->flags = 0x000;
+ cpu_params->flags |= QOS_F_PERSISTENT;
+ /* if we're negotiating for the service thread create
+ * a soft server */
+ /*if (contract == &service_th_contract) {
+ qres_contract.flags |= QOS_F_SOFT;
+ }*/
+
+ cpu_params->timeout = 0;
+ return 0;
+}
+
--- /dev/null
+#ifndef AQCPU_CONTRACT_H
+#include "aquosa/qres_lib.h"
+#include "timespec_usec_ops.h"
+
+typedef qres_params_t cpu_params_t;
+
+int get_aqcpu_params(fres_vres_t *vres, cpu_params_t *params);
+
+#endif /* AQCPU_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 AQCPU (Aquosa CPU) */
+/* */
+/* 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 <ul_log.h>
+#include <fra_generic.h>
+
+#include "aquosa/qres_lib.h"
+#include "aqcpu_contract.h"
+
+UL_LOG_CUST(ulogd_fra_aqcpu);
+ul_log_domain_t ulogd_fra_fwp = {UL_LOGL_DEB, "fra_aqcpu"};
+
+static int aqcpu_create_vres(fres_vres_t *vres, void *priv)
+{
+ cpu_params_t cpu_params;
+ qres_sid_t sid;
+ qos_rv rv;
+
+ /* get aqcpu params from contract */
+ get_aqcpu_params(vres, cpu_params);
+ /* create cpu vres */
+ rv = qres_create_server(&cpu_params, &sid);
+ if (rv != QOS_OK) {
+ return qos_rv_int(rv);
+ }
+
+ ul_logdeb("Created AQCPU VRES(sid=%d period=%ld us, budget=%ld us)\n",
+ sid, cpu_params->P, cpu_params->Q_min);
+ if (vres->priv = malloc(sizeof(qres_sid_t))) {
+ memcpy(vres->priv, &sid, sizeof(qres_sid_t));
+ }
+
+ 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 aqcpu_cancel_vres(fres_vres_t *vres, void *priv)
+{
+ qres_sid_t sid;
+ qos_rv qrv;
+
+ if (vres->priv) {
+ errno = -EINVAL;
+ return -1;
+ }
+ memcpy(&sid, vres->priv, sizeof(qres_sid_t));
+
+ qrv = qres_destroy_server(sid);
+ if (qrv != QOS_OK) {
+ return qos_rv_int(qrv);
+ }
+ ul_logdeb("Canceled AQCPU VRES(sid=%d)\n",sid);
+ 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 aqcpu_change_vres(fres_vres_t *vres, void *priv)
+{
+ cpu_params_t cpu_params;
+ qres_sid_t sid;
+ qos_rv qrv;
+
+ if (vres->priv) {
+ errno = -EINVAL;
+ return -1;
+ }
+ memcpy(&sid, vres->priv, sizeof(qres_sid_t));
+
+ /* get aqcpu params from contract */
+ get_aqcpu_params(vres, cpu_params);
+
+ /* set cpu params */
+ qrv = qres_set_params(sid, &cpu_params);
+
+ ul_logdeb("AQCPU VRES(sid=%d) params changed(period=%ld us,"
+ "budget=%ld us)\n",sid, cpu_params->P,cpu_params->Q_min);
+
+ return 0;
+}
+
+static struct fres_allocator aqcpu_allocator = {
+ .res_type = FRSH_RT_CPU,
+ .res_id = 0, /* CPU ID 0 */
+ .create_vres = aqcpu_create_vres,
+ .cancel_vres = aqcpu_cancel_vres,
+ .change_vres = aqcpu_change_vres,
+ .priv = NULL
+};
+
+int fra_aqcpu_init(forb_orb orb, fres_contract_broker fcb, forb_executor_t *executor)
+{
+ if (qres_init() != QOS_OK) {
+ return -1;
+ }
+
+ return fra_register(orb, fcb, executor, &fwp_allocator);
+}
+
+int fra_aqcpu_exit()
+{
+ qos_rv rv;
+
+ rv = qres_cleanup();
+ return qos_rv_int(rv);
+}
--- /dev/null
+module fres {
+ module block {
+ struct aqcpu_reqs {
+ fosa_rel_time_t budget_min;
+ unsigned short flags;
+ /* add more contract specific params */
+ };
+
+ struct aqcpu_sched {
+ /* params added by resource manager for
+ * scheduling purposes
+ */
+ }
+ };
+};
+
+++ /dev/null
-
-/***************************************************************************/
-/* H A R D D I S K H A N D L I N G U T I L I T Y F U N C T I O N S */
-/***************************************************************************/
-
-static bool disk_init()
-{
- int i;
-
- for (i = 0; i < N_DISKS; i++) {
- disk[i].aggregate_bw = DISK_DEFAULT_AGGREGATE_BW;
- disk[i].sched_budget = DISK_DEFAULT_SCHED_BUDGET;
- disk[i].weight_sum = 0;
- disk[i].thread_num = 0;
- }
-
- return true;
-}
-
-static inline unsigned int disk_sched_ioprio(unsigned int weight) {
-
- if (weight == 100)
- return 0;
- if (weight > 14)
- return 1;
- return 8 - 1 - (weight / 2);
-}
-
-static inline unsigned int disk_sched_ioweight(frsh_resource_id_t disk_id, struct timespec budget, struct timespec period) {
- float th, weight;
- int b, w_i;
- unsigned long int q_i, p_i;
-
- th = disk[disk_id_2_index(disk_id)].aggregate_bw / 10E9;
- b = disk[disk_id_2_index(disk_id)].sched_budget;
-
- /* nsec */
- q_i = timespec_to_usec(budget);
- p_i = timespec_to_usec(period);
- q_i *= 1000;
- p_i *= 1000;
-
- if (p_i < b / th)
- return -1;
-
- weight = (DISK_WEIGHT_MAX * q_i ) / (p_i - (b / th));
- w_i = floor(weight);
-
- if (weight != w_i)
- w_i++;
-
- return w_i;
-}
-
-static inline float disk_sched_iobandwidth(frsh_resource_id_t disk_id, unsigned int weight) {
- return (float) weight * (disk[disk_id_2_index(disk_id)].aggregate_bw / disk[disk_id_2_index(disk_id)].weight_sum);
-}
-
+++ /dev/null
-// -----------------------------------------------------------------------
-// Copyright (C) 2006 - 2007 FRESCOR consortium partners:
-//
-// Universidad de Cantabria, SPAIN
-// University of York, UK
-// Scuola Superiore Sant'Anna, ITALY
-// Kaiserslautern University, GERMANY
-// Univ. Politécnica Valencia, SPAIN
-// Czech Technical University in Prague, CZECH REPUBLIC
-// ENEA SWEDEN
-// Thales Communication S.A. FRANCE
-// Visual Tools S.A. SPAIN
-// Rapita Systems Ltd UK
-// Evidence ITALY
-//
-// See http://www.frescor.org for a link to partners' websites
-//
-// FRESCOR project (FP6/2005/IST/5-034026) is funded
-// in part by the European Union Sixth Framework Programme
-// The European Union is not liable of any use that may be
-// made of this code.
-//
-//
-// based on previous work (FSF) done in the FIRST project
-//
-// Copyright (C) 2005 Mälardalen University, SWEDEN
-// Scuola Superiore S.Anna, ITALY
-// Universidad de Cantabria, SPAIN
-// University of York, UK
-//
-// FSF API web pages: http://marte.unican.es/fsf/docs
-// http://shark.sssup.it/contrib/first/docs/
-//
-// This file is part of 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_service_th.c
- *
- * This file contains the implementation of the service thread for the
- * contract (re)negotiation of the FRSH implementation on top of AQuoSA
- * framework, on GNU/Linux platform
- *
- * Though AQuoSA is process/thread neutral the "service thread" is implemented
- * as a classic UNIX process (i.e. the more general approach).
- * As an effect there may be cases where behaviour and semantic is quite
- * different from the FRSH API specifications and documents and we try to
- * exhamine them in a separate document
- */
-
-/*******************/
-/* I N C L U D E S */
-/*******************/
-
-/* service thread local data structures include files */
-#include "frsh_service_th_types.h"
-#include "frsh_service_th.h"
-#include "frsh_configuration_parameters.h"
-
-/***********************************/
-/* G L O B A L V A R I A B L E S */
-/***********************************/
-
-/*
- * service thread utility data structures:
- *
- * for the correct implementation and functionality of the service thread
- * some data structures, such as the PID of the service thread itself, the
- * socket and the pidfile descriptors and the service thread contract, thread
- * descriptor and vres, need to be global since they're accessed within
- * various function or signal handlers
- */
-static FILE *pid_fd; /* used (by clients) to check if a service thread is running */
-static int sock; /* main communication channel between clints and the service thread */
-static pid_t service_th_pid; /* used (by clients) to check if "the correct" service thread is running */
-frsh_contract_t service_th_contract = { /* initialized here for the sake of simplicity */
- .resource_id = FRSH_RESOURCE_ID_DEFAULT,
- .resource_type = FRSH_RT_PROCESSOR,
- .contract_label = "SERVICE_TH",
- .budget_min = FOSA_USEC_TO_REL_TIME(FRSH_SERVICE_THREAD_BUDGET_USECS),
- .period_max = FOSA_USEC_TO_REL_TIME(FRSH_SERVICE_THREAD_PERIOD_USECS),
- .workload = FRSH_WT_INDETERMINATE,
- .contract_type = FRSH_CT_REGULAR,
- .d_equals_t = true,
- .deadline = {0, 0},
- .budget_overrun_signal = FRSH_NULL_SIGNAL,
- .budget_overrun_siginfo.sival_int = 0,
- .deadline_miss_signal = FRSH_NULL_SIGNAL,
- .deadline_miss_siginfo.sival_int = 0,
- /* Non-core contract attributes */
- .budget_max = FOSA_USEC_TO_REL_TIME(FRSH_SERVICE_THREAD_BUDGET_USECS), // ???
- .period_min = FOSA_USEC_TO_REL_TIME(FRSH_SERVICE_THREAD_PERIOD_USECS), // ???
- .utilization_set.size = 0,
- .granularity = FRSH_DEFAULT_GRANULARITY,
- .importance = FRSH_DEFAULT_IMPORTANCE,
- .weight = FRSH_DEFAULT_WEIGHT,
- .stability_time = {0, 0},
- .preemption_level = 0,
- .critical_sections.size = 0,
- .policy = FRSH_NONE,
- .protocol_info.body = NULL,
- .protocol_info.size = 0,
- .queueing_info.queue_size = 0,
- .queueing_info.queue_policy = FRSH_QRP_OLDEST,
- .max_loss_rate = 0,
- .minimum_memory = (size_t)0,
- .maximum_memory = (size_t)0
-};
-frsh_thread_id_t service_th_thread;
-frsh_vres_id_t service_th_vres_id;
-
-/* Contract negotiation mutex semaphore */
-frsh_mutex_t contract_mutex;
-
-/**/
-frsh_contract_t *feedback_spare_contract;
-
-/*
- * service thread fundamental data structures:
- *
- * these data structure are the key ones for the implementation of the service
- * thread functionalities, that is keep in memory the negotiated contracts,
- * the vres they're attached and the thread bound to them.
- * Three different data structures, an hash table for the contracts and two
- * array (well a bit more than simple array... We call them "repositories")
- * for vres and threads, are used.
- *
- * We need a service request queueing structure and a thread pool too in order
- * to implement a multithreaded version of the service thread.
- *
- * They also are all global because they need to be accessible in almost any
- * of the function defined in this file!
- *
- * The data types used are declared in the "frsh_service_th_types.h" file and
- * should be visible _only_ within _this_ source file
- */
-static contract_hash_table_t contract_hash_table; /* hash table for the contracts */
-static vres_repo_t vres_repo; /* negotiated vres repository */
-static disk_t disk[N_DISKS]; /* parameters for the HDs in the system */
-
-
-/***********************************************/
-/* F R S H U T I L I T Y F U N C T I O N S */
-/***********************************************/
-
-/*
- * negotiate_contract(), negotiate a new contract
- *
- * If there're room in the vres repository and if the specified contract label
- * is not in use creates a new vres with the parameters of the provided
- * contract.
- *
- * The vres repository is update accordingly with the contract type and the
- * contract label is added to the hash table
- *
- * All the three possible type of contracts are negotiable and the
- * implementation handle them such as:
- * - REGULAR contracts are attached to an AQuoSA resource reservation
- * scheduler and it's min_budget/max_period CPU ratio is guaranteed
- * - BACKGROUND contracts are not negotiated nor assigned a vres, they're
- * "accounted for" but their scheduling is left to Linux (with it's
- * default scheduler implementation)
- * - DUMMY contracts are assigned a vres with no possibility of bounding
- * a thread/process to it. It's not the cleanest way of handling them but,
- * for now, it's ok
- *
- * Note that all the REGULAR and DUMMY vres are considered in order to check
- * if the limit has been reached
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_TOO_MANY_VRES
- * FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS
- * FRSH_ERR_CONTRACT_REJECTED
- * FRSH_ERR_INTENRAL_ERROR
- */
-static int negotiate_contract(const frsh_contract_t *contract, frsh_vres_id_t *vres)
-{
- qres_params_t qres_contract;
- qres_sid_t contract_sid;
- qos_rv qres_status;
- int vres_ind;
- contract_hash_data_t *contract_data_ptr;
-
- /* check if there is at least one free vres */
- if (get_vres_number() + get_dummy_vres_number() >= FRSH_MAX_N_VRES)
- return FRSH_ERR_TOO_MANY_VRES;
- /* try to add the label into the hash table (with temporary data) */
- if (contract_hash_add(contract->contract_label, &contract_data_ptr) != HASH_NO_ERROR)
- return FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS;
- contract_data_ptr->vres_index = -1;
-
- switch (contract->resource_type) {
- case FRSH_RT_PROCESSOR:
- {
- switch (contract->contract_type) {
- /* create a FRSH_CT_REGULAR or FRSH_CT_DUMMY
- * contract (they handled with, well, almost the same code) */
- case FRSH_CT_REGULAR:
- case FRSH_CT_DUMMY:
- {
- /* core contract parameters */
- qres_contract.Q_min = timespec_to_usec(contract->budget_min);
- qres_contract.P = timespec_to_usec(contract->period_max);
- /* non-core contract parameters */
- qres_contract.Q = timespec_to_usec(contract->budget_max);
- /* AQuoSA specific configuration */
- qres_contract.flags = 0x000;
- qres_contract.flags |= QOS_F_PERSISTENT;
- /* if we're negotiating for the service thread create a soft server */
- if (contract == &service_th_contract)
- qres_contract.flags |= QOS_F_SOFT;
- qres_contract.timeout = 0;
- /* create the vres as an AQuoSA resource reservation server */
- qres_status = qres_create_server(&qres_contract, &contract_sid);
- if (qres_status != QOS_OK) {
- /* something went wrong, remove the label (I know it's present)! */
- contract_hash_del(contract->contract_label);
- if (qres_status == QOS_E_SYSTEM_OVERLOAD)
- return FRSH_ERR_CONTRACT_REJECTED;
- else
- return FRSH_ERR_INTERNAL_ERROR;
- } else {
- /* add the contracted vres to the repository
- * NB. it automatically handle the case the contract
- * is of CT_DUMMY type */
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- vres_ind = contract_sid; /* suggests a position for the new vres entry (see 'vres_repo_put()') */
- if (!vres_repo_put(contract, contract_sid, &vres_ind)) {
- contract_hash_del(contract->contract_label);
- /* we need to check it again in order to return the correct error message! */
- if (get_vres_number() + get_dummy_vres_number() >= FRSH_MAX_N_VRES)
- return FRSH_ERR_TOO_MANY_VRES;
- else
- return FRSH_ERR_INTERNAL_ERROR;
- }
-#else /* !FRSH_ENABE_SERVICE_MULTITHREAD */
- /* no multithreading, so we already know the operation
- * will be successful (if no internal errors occur) */
- vres_ind = contract_sid; /* suggests a position for the new vres entry (see 'vres_repo_put()') */
- if (!vres_repo_put(contract, contract_sid, &vres_ind))
- return FRSH_ERR_INTERNAL_ERROR;
-#endif
- *vres = vres_index_2_id(vres_ind);
- /* update data field of the hash table with the vres id */
- contract_data_ptr->vres_index = vres_ind;
- }
- break;
- }
- /* create a FRSH_CT_BACKGROUND vres
- * simply adding it to the repository*/
- case FRSH_CT_BACKGROUND:
- {
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- if (!vres_repo_put(contract, FRSH_QRES_BACKGROUND_SID, &vres_ind)) {
- contract_hash_del(contract->contract_label);
- /* we need to check it again! */
- if (get_vres_number() + get_dummy_vres_number() >= FRSH_MAX_N_VRES)
- return FRSH_ERR_TOO_MANY_VRES;
- else
- return FRSH_ERR_INTERNAL_ERROR;
- }
-#else /* !FRSH_ENABE_SERVICE_MULTITHREAD */
- /* no multithreading, so we already know the operation
- * will be successful (if no internal errors occur) */
- if (!vres_repo_put(contract, FRSH_QRES_BACKGROUND_SID, &vres_ind))
- return FRSH_ERR_INTERNAL_ERROR;
-#endif
- *vres = vres_index_2_id(vres_ind);
- /* update data field of the hash table with the vres id */
- contract_data_ptr->vres_index = vres_ind;
- break;
- }
- default:
- {
- contract_hash_del(contract->contract_label);
- return FRSH_ERR_INTERNAL_ERROR;
- }
- }
- break;
- }
- case FRSH_RT_DISK:
- {
- switch (contract->contract_type) {
- case FRSH_CT_REGULAR:
- case FRSH_CT_DUMMY:
- {
- unsigned int weight;
-
- weight = disk_sched_ioweight(disk_id_2_index(contract->resource_id),
- contract->budget_min,
- contract->period_max);
- if (weight == -1) {
- contract_hash_del(contract->contract_label);
- return FRSH_ERR_CONTRACT_REJECTED;
- }
- syslog(LOG_DEBUG, "weight calculated to value: %d", weight);
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_lock(&disk[disk_id_2_index(contract->resource_id)].mutex);
-#endif
-
- if (disk[disk_id_2_index(contract->resource_id)].thread_num != 0 ||
- !equal_timespec(&contract->budget_min, &contract->period_max)) {
- if (disk[disk_id_2_index(contract->resource_id)].weight_sum + weight > DISK_WEIGHT_MAX) {
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&disk[disk_id_2_index(contract->resource_id)].mutex);
-#endif
- contract_hash_del(contract->contract_label);
- return FRSH_ERR_CONTRACT_REJECTED;
- }
- }
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- if (!vres_repo_put(contract, weight, &vres_ind)) {
- contract_hash_del(contract->contract_label);
- /* we need to check it again! */
- if (get_vres_number() + get_dummy_vres_number() >= FRSH_MAX_N_VRES)
- return FRSH_ERR_TOO_MANY_VRES;
- else
- return FRSH_ERR_INTERNAL_ERROR;
- }
-#else /* !FRSH_ENABE_SERVICE_MULTITHREAD */
- /* no multithreading, so we already know the operation
- * will be successful (if no internal errors occur) */
- if (!vres_repo_put(contract, weight, &vres_ind))
- return FRSH_ERR_INTERNAL_ERROR;
-#endif
- *vres = vres_index_2_id(vres_ind);
- /* update data field of the hash table with the vres id */
- contract_data_ptr->vres_index = vres_ind;
-
- disk[disk_id_2_index(contract->resource_id)].thread_num++;
- disk[disk_id_2_index(contract->resource_id)].weight_sum += weight;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&disk[disk_id_2_index(contract->resource_id)].mutex);
-#endif
- break;
- }
- case FRSH_CT_BACKGROUND:
- {
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- if (!vres_repo_put(contract, FRSH_QRES_BACKGROUND_DISK, &vres_ind)) {
- contract_hash_del(contract->contract_label);
- /* we need to check it again! */
- if (get_vres_number() + get_dummy_vres_number() >= FRSH_MAX_N_VRES)
- return FRSH_ERR_TOO_MANY_VRES;
- else
- return FRSH_ERR_INTERNAL_ERROR;
- }
-#else /* !FRSH_ENABE_SERVICE_MULTITHREAD */
- /* no multithreading, so we already know the operation
- * will be successful (if no internal errors occur) */
- if (!vres_repo_put(contract, FRSH_QRES_BACKGROUND_DISK, &vres_ind))
- return FRSH_ERR_INTERNAL_ERROR;
-#endif
- *vres = vres_index_2_id(vres_ind);
- /* update data field of the hash table with the vres id */
- contract_data_ptr->vres_index = vres_ind;
-
- break;
- }
- default:
- {
- contract_hash_del(contract->contract_label);
- return FRSH_ERR_INTERNAL_ERROR;
- }
- }
- break;
- }
- default:
- {
- contract_hash_del(contract->contract_label);
- return FRSH_ERR_INTERNAL_ERROR;
- }
- }
-
- return FRSH_NO_ERROR;
-}
-
-/*
- * bind_thread(), bind a thread to a vres
- *
- * If there's room for a new thread and the provided vres is valid and
- * contracted attaches a thread to it.
- *
- * The thread and vres repositories are update accordingly and all proceeds
- * as described in the docs and API specs
- *
- * This function is used every time the binding of a thread to a vres need
- * to be establiched, i.e., for example, in both the FRSH API call of
- * 'frsh_thread_create_and_bind()' and 'frsh_thread_bind()'
- *
- * Note that we make not possible to bind a thread to a DUMMY vres and, if
- * such an event is going to happen, we return an error code (BAD_ARGUMENT) to
- * the caller (thread/process)
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_TOO_MANY_TASKS
- * FRSH_ERR_BAD_ARGUMENT
- * FRSH_ERR_NOT_CONTRACTED_VRES
- * FRSH_ERR_INTENRAL_ERROR
- */
-static int bind_thread(const frsh_thread_id_t *thread,
- const frsh_vres_id_t vres_id)
-{
- qres_sid_t thread_sid, vres_sid;
- int thread_ind;
- frsh_vres_id_t old_vres_id;
-
- /* check if there is at least one more free thread */
- if (get_threads_number() == FRSH_MAX_N_THREADS)
- return FRSH_ERR_TOO_MANY_TASKS;
- /* catch also the case a dummy vres is provided */
- if (!check_vres_repo_ind(vres_id_2_index(vres_id)) ||
- vres_repo_isdummy(vres_id_2_index(vres_id)))
- return FRSH_ERR_BAD_ARGUMENT;
- /* check if vres is contracted */
- if (vres_repo_isfree(vres_id_2_index(vres_id)))
- return FRSH_ERR_NOT_CONTRACTED_VRES;
-
- switch (get_vres_entry(vres_id)->contract.resource_type) {
- case FRSH_RT_PROCESSOR:
- {
- /* check if vres has already a thread bound (and hierarcical scheduling is not enabled!) */
- if (!FRSH_HIERARCHICAL_MODULE_SUPPORTED &&
- get_vres_entry(vres_id)->processor.threads_number > 0)
- return FRSH_ERR_ALREADY_BOUND;
- /* start checking if the provided thread
- * is already bound to a vres (if yes we have to move it) */
- if (thread_repo_find(thread, &thread_ind)) {
- /* thread found, it's already bound! */
- old_vres_id = get_thread_entry(thread_ind)->vres;
- if (get_vres_entry(old_vres_id)->contract.contract_type == FRSH_CT_REGULAR) {
- /* detach the thread from the old server */
- thread_sid = get_vres_entry(old_vres_id)->processor.sid;
- if (qres_detach_thread(thread_sid, thread->linux_pid, thread->linux_tid) != QOS_OK)
- return FRSH_ERR_INTERNAL_ERROR;
- }
-
- /* remove the thread from the repository, we'll place
- * it back into it when we've bound again to the provided vres*/
- if (thread_repo_free(thread_ind))
- return FRSH_ERR_INTERNAL_ERROR;
- }
- /* attach the thread to the provided vres */
- vres_sid = get_vres_entry(vres_id)->processor.sid;
- if (get_vres_entry(vres_id)->contract.contract_type == FRSH_CT_REGULAR) {
- if (qres_attach_thread(vres_sid, thread->linux_pid, thread->linux_tid) != QOS_OK)
- return FRSH_ERR_INTERNAL_ERROR;
- }
- break;
- }
- case FRSH_RT_DISK:
- {
- get_vres_entry(vres_id)->disk.ioprio_old = syscall(__NR_ioprio_get, IOPRIO_WHO_PROCESS);
- syslog(LOG_DEBUG, "old ioprio value for the thread = %d", get_vres_entry(vres_id)->disk.ioprio_old);
- if (get_vres_entry(vres_id)->contract.contract_type == FRSH_CT_REGULAR) {
- syslog(LOG_DEBUG, "calculating ioprio with weight = %d", get_vres_entry(vres_id)->disk.weight);
- get_vres_entry(vres_id)->disk.ioprio = disk_sched_ioprio(get_vres_entry(vres_id)->disk.weight);
- syslog(LOG_DEBUG, "ioprio set to: %d", get_vres_entry(vres_id)->disk.ioprio);
- if (!syscall(__NR_ioprio_set,
- IOPRIO_WHO_PROCESS,
- syscall(__NR_gettid),
- get_vres_entry(vres_id)->disk.ioprio | IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT))
- return FRSH_ERR_INTERNAL_ERROR;
- } else {
- syslog(LOG_DEBUG, "no ioprio for background type contracts");
- if (!syscall(__NR_ioprio_set,
- IOPRIO_WHO_PROCESS,
- syscall(__NR_gettid),
- IOPRIO_CLASS_IDLE << IOPRIO_CLASS_SHIFT))
- return FRSH_ERR_INTERNAL_ERROR;
- }
- break;
- }
- default:
- {
- return FRSH_ERR_INTERNAL_ERROR;
- break;
- }
- }
- /* insert the thread into thread repository */
- thread_ind = vres_id_2_index(vres_id); /* suggests a position for the new thread entry (see 'thread_repo_put()') */
- if (!thread_repo_put(thread, vres_id, &thread_ind))
- return FRSH_ERR_INTERNAL_ERROR;
-
- return FRSH_NO_ERROR;
-}
-
-/*
- * unbind_thread(), unbind a thread from a vres
- *
- * If there's room for a new thread and the provided vres is valid and
- * contracted attaches a thread to it.
- *
- * The thread and vres repositories are update accordingly and all proceeds
- * as described in the docs and API specs
- *
- * This function is used every time the binding of a thread to a vres need
- * to be establiched, i.e., for example, in both the FRSH API call of
- * 'frsh_thread_create_and_bind()' and 'frsh_thread_bind()'
- *
- * Note that we make not possible to bind a thread to a DUMMY vres and, if
- * such an event is going to happen, we return an error code (BAD_ARGUMENT) to
- * the caller (thread/process)
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT
- * FRSH_ERR_NOT_BOUND
- * FRSH_ERR_INTENRAL_ERROR
- */
-static int unbind_thread(const frsh_thread_id_t *thread)
-{
- int thread_ind;
- frsh_vres_id_t vres_id;
- qres_sid_t thread_sid;
-
- if (!thread_repo_find(thread, &thread_ind))
- return FRSH_ERR_BAD_ARGUMENT;
- if (get_thread_entry(thread_ind)->vres == FRSH_NOT_VALID_VRES_ID)
- /* shouldn't be possible but... Who knows!?!? */
- return FRSH_ERR_NOT_BOUND;
-
- /* get the vres the thread is bound to */
- vres_id = get_thread_entry(thread_ind)->vres;
-
- switch (get_vres_entry(vres_id)->contract.resource_type) {
- case FRSH_RT_PROCESSOR:
- {
- if (get_vres_entry(vres_id)->contract.contract_type == FRSH_CT_REGULAR) {
-
- /* get the AQuoSA server the thread is attached to
- * and detach the thread from the server */
- thread_sid = get_vres_entry(vres_id)->processor.sid;
- if (qres_detach_thread(thread_sid, thread->linux_pid, thread->linux_tid) != QOS_OK)
- return FRSH_ERR_INTERNAL_ERROR;
- }
- break;
- }
- case FRSH_RT_DISK:
- {
- if (!syscall(__NR_ioprio_set,
- IOPRIO_WHO_PROCESS,
- syscall(__NR_gettid),
- get_vres_entry(vres_id)->disk.ioprio_old))
- return FRSH_ERR_INTERNAL_ERROR;
- break;
- }
- default:
- {
- return FRSH_ERR_INTERNAL_ERROR;
- break;
- }
- }
-
- if (!thread_repo_free(thread_ind))
- return FRSH_ERR_INTERNAL_ERROR;
-
- return FRSH_NO_ERROR;
-}
-
-/*
- * get_thread_vres_id(), retrieve the id of the vres the thread is bound to
- *
- * If a valid and bound thread is provided returns the id of the vres to which
- * it is bound.
- *
- * No repositories or other data structures need updating and, if debugging is
- * disabled, no AQuoSA library call is needed, infos are available in the
- * internal data structures as well.
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (thread not exists)
- * FRSH_ERR_NOT_BOUND (-IMPOSSIBLE- thread exists but it's not bound to any vres)
- * FRSH_ERR_INTENRAL_ERROR
- */
-static int get_thread_vres_id(const frsh_thread_id_t *thread, frsh_vres_id_t *vres)
-{
- int thread_ind;
-
- if (!thread_repo_find(thread, &thread_ind))
- return FRSH_ERR_BAD_ARGUMENT;
- if (get_thread_entry(thread_ind)->vres == -1)
- /* shouldn't be possible but... Who knows!?!? */
- return FRSH_ERR_NOT_BOUND;
-
- *vres = get_thread_entry(thread_ind)->vres;
-
- return FRSH_NO_ERROR;
-}
-
-/*
- * get_contract(), retrieve the contract associated with a vres
- *
- * If a valid and contracted vres is provided returns the contract
- * negotiated for it.
- *
- * No repositories or other data structures need updating nor any
- * AQuoSA library call is needed, whole info is available in the
- * internal data structures.
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (invalid vres)
- * FRSH_ERR_NOT_CONTRACTED_VRES
- */
-static int get_contract(const frsh_vres_id_t vres_id, frsh_contract_t *contract)
-{
- if (!check_vres_repo_ind(vres_id_2_index(vres_id)))
- return FRSH_ERR_BAD_ARGUMENT;
- if (vres_repo_isfree(vres_id_2_index(vres_id)))
- return FRSH_ERR_NOT_CONTRACTED_VRES;
-
- *contract = get_vres_entry(vres_id)->contract;
-
- return FRSH_NO_ERROR;
-}
-
-/*
- * get_label_vres_id(), retrieve the vres id using a contract label
- *
- * If a valid contract label is provided returns the vres id associated
- * to such a contract
- *
- * No repositories or other data structures need updating nor any
- * AQuoSA library call is needed, whole info is available in the
- * internal data structures.
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (unknown contract label)
- * //FRSH_ERR_CONTRACT_LABEL_UNKNOWN (unknown contract label)
- */
-static int get_label_vres_id(const frsh_contract_label_t contract_label,
- frsh_vres_id_t *vres)
-{
- contract_hash_data_t *data_ptr;
-
- if (contract_hash_find(contract_label, &data_ptr) != HASH_LABEL_FOUND)
- //return FRSH_ERR_CONTRACT_LABEL_UNKNOWN;
- return FRSH_ERR_BAD_ARGUMENT;
-
- *vres = vres_index_2_id(data_ptr->vres_index);
-
- return FRSH_NO_ERROR;
-}
-
-/*
- * cancel_contract(), remove a negotiated contract
- *
- * If a valid vres is provided deletes the contract associated to it and
- * destroys the vres itself, removing it from the repository, while the
- * contract label is removed from the hash table.
- *
- * 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.
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (invalid_vres)
- * FRSH_ERR_NOT_CONTRACTED_VRES
- * FRSH_ERR_INTENRAL_ERROR
- */
-static int cancel_contract(const frsh_vres_id_t vres)
-{
- qres_sid_t vres_sid;
-
- if (!check_vres_repo_ind(vres_id_2_index(vres)))
- return FRSH_ERR_BAD_ARGUMENT;
- if (vres_repo_isfree(vres_id_2_index(vres)))
- return FRSH_ERR_NOT_CONTRACTED_VRES;
-
- switch (get_vres_entry(vres)->contract.resource_type) {
- case FRSH_RT_PROCESSOR:
- {
- /* cache the sid of the AQuoSA server and then call
- * the repository remove routine for the vres (it handle all the
- * work because locking of right mutexes, if we're multithreaded, is needed)*/
- vres_sid = get_vres_entry(vres)->processor.sid;
- if (!vres_repo_free(vres_id_2_index(vres)))
- return FRSH_ERR_INTERNAL_ERROR;
- /* destroy the AQuoSA server (if it exists!) using the cached value */
- if (vres_sid != FRSH_QRES_BACKGROUND_SID)
- if (qres_destroy_server(vres_sid) != QOS_OK)
- return FRSH_ERR_INTERNAL_ERROR;
-
- break;
- }
- case FRSH_RT_DISK:
- {
- if (get_vres_entry(vres)->disk.weight != FRSH_QRES_BACKGROUND_DISK) {
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_lock(&disk[disk_id_2_index(get_vres_entry(vres)->contract.resource_id)].mutex);
-#endif
- disk[disk_id_2_index(get_vres_entry(vres)->contract.resource_id)].weight_sum -= get_vres_entry(vres)->disk.weight;
-
- if (disk[disk_id_2_index(get_vres_entry(vres)->contract.resource_id)].weight_sum < 0) {
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&disk[disk_id_2_index(get_vres_entry(vres)->contract.resource_id)].mutex);
-#endif
- return FRSH_ERR_INTERNAL_ERROR;
- }
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&disk[disk_id_2_index(get_vres_entry(vres)->contract.resource_id)].mutex);
-#endif
- }
-
- if (!vres_repo_free(vres_id_2_index(vres)))
- return FRSH_ERR_INTERNAL_ERROR;
- break;
- }
- default:
- {
- return FRSH_ERR_INTERNAL_ERROR;
- break;
- }
- }
-
- /* cancel any contract type (REGULAR, DUMMY and BACKGROUND)
- * can be handled with almost the same code */
- if (contract_hash_del(get_vres_entry(vres)->contract.contract_label) != HASH_NO_ERROR)
- return FRSH_ERR_INTERNAL_ERROR;
-
- return FRSH_NO_ERROR;
-}
-
-/* renegotiate_contract(), change some parameters of a contract
- *
- * Tries to change the parameters of a contracted vres with a negotiation
- * of a new contract for it.
- * All parameters can be changed but the contract type, which need to maintain
- * the value of the original contract.
- *
- * All is done (of course!) without removing the old vres and creating a new
- * one, thanks to AQuoSA "change parameters" library API call, but this
- * actually put an issue in place.
- * 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.
- *
- * Note we use this function for the service and implementation of both
- * synchronous and asynchronous renegotiation requests, check the service
- * thread main process code to check how (and how simple!)
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (invalid vres or not matching contract types)
- * FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS (new label already exists)
- * FRSH_ERR_NOT_CONTRACTED_VRES
- * FRSH_ERR_CONTRACT_REJECTED
- * FRSH_ERR_INTENRAL_ERROR (something wrong with AQuoSA)
- */
-static int renegotiate_contract(const frsh_contract_t *new_contract, const frsh_vres_id_t vres_id)
-{
- contract_hash_data_t *contract_data_ptr;
- qres_params_t qres_new_contract;
- qos_rv qres_status;
-
- if (!check_vres_repo_ind(vres_id_2_index(vres_id)))
- return FRSH_ERR_BAD_ARGUMENT;
- if (get_vres_entry(vres_id)->contract.contract_type != new_contract->contract_type)
- return FRSH_ERR_BAD_ARGUMENT;
- if (vres_repo_isfree(vres_id_2_index(vres_id)))
- return FRSH_ERR_NOT_CONTRACTED_VRES;
-
- /* check if the label is changed */
- if (strncmp(get_vres_entry(vres_id)->contract.contract_label,
- new_contract->contract_label,
- FRSH_CONTRACT_LABEL_MAXLENGTH) != 0) {
- /* so we have to try inserting the new one */
- if (contract_hash_add(new_contract->contract_label, &contract_data_ptr) != HASH_NO_ERROR)
- return FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS;
- /* update the vres reference */
- contract_data_ptr->vres_index = vres_id;
- /* and remove the old one */
- contract_hash_del(get_vres_entry(vres_id)->contract.contract_label);
- }
- /* only for REGULAR and DUMMY contracts effectively modify the AQuoSA
- * resource reservation server parameters according to the new requets */
- if (new_contract->contract_type != FRSH_CT_BACKGROUND) {
- /* setup new core contract parameters */
- qres_new_contract.Q_min = timespec_to_usec(new_contract->budget_min);
- qres_new_contract.P = timespec_to_usec(new_contract->period_max);
- /* setup new non-core contract parameters */
- qres_new_contract.Q = timespec_to_usec(new_contract->budget_max);
- qres_status = qres_set_params(get_vres_entry(vres_id)->processor.sid, &qres_new_contract);
- if (qres_status != QOS_OK) {
- get_vres_entry(vres_id)->renegotiation_status = FRSH_RS_REJECTED;
- if (qres_status == QOS_E_SYSTEM_OVERLOAD)
- return FRSH_ERR_CONTRACT_REJECTED;
- else
- return FRSH_ERR_INTERNAL_ERROR;
- }
- }
- /* update the contract of the vres and set the correct status */
- get_vres_entry(vres_id)->contract = *new_contract;
- get_vres_entry(vres_id)->renegotiation_status = FRSH_RS_ADMITTED;
-
- return FRSH_NO_ERROR;
-}
-
-/* get_renegotiation_status(), check the renogotiation status of a vres
- *
- * Simply returns the renegotiation status of a vres in the repository as
- * set by all the other functions (mainly 'renegotiate_contract()' or
- * the group operations)
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (invalid vres)
- * FRSH_ERR_NOT_CONTRACTED_VRES
- */
-static int get_renegotiation_status(const frsh_vres_id_t vres_id,
- frsh_renegotiation_status_t *renegotiation_status)
-{
- if (!check_vres_repo_ind(vres_id_2_index(vres_id)))
- return FRSH_ERR_BAD_ARGUMENT;
- if (vres_repo_isfree(vres_id_2_index(vres_id)))
- return FRSH_ERR_NOT_CONTRACTED_VRES;
-
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined(FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- assert(get_vres_entry(vres_id)->processor.sid != FRSH_QRES_NOT_VALID_SID);
-#endif
- *renegotiation_status = get_vres_entry(vres_id)->renegotiation_status;
-
- return FRSH_NO_ERROR;
-}
-
-/*
- *
- */
-static int negotiate_group(int vres_down_number, frsh_vres_id_t vres_down[], int vres_down_status[],
- int contracts_up_number, frsh_contract_t contracts_up[], frsh_vres_id_t vres_up[], int contracts_up_status[])
-{
- int i, error;
-
- /* Check the bandwidth first!! */
- error = FRSH_NO_ERROR;
- for (i = 0; i < vres_down_number; i++) {
- vres_down_status[i] = cancel_contract(vres_down[i]);
- if (!vres_down_status[i])
- error = FRSH_ERR_INTERNAL_ERROR;
- }
- for (i = 0; i < contracts_up_number; i++) {
- contracts_up_status[i] = negotiate_contract(&contracts_up[i], &vres_up[i]);
- if (!contracts_up_status[i])
- error = FRSH_ERR_INTERNAL_ERROR;
- }
-
- return error;
-}
-
-static int change_mode(int vres_down_number, frsh_vres_id_t vres_down[], int vres_down_status[],
- int contracts_touch_number, frsh_contract_t contracts_touch[], frsh_vres_id_t vres_touch[], int vres_touch_status[],
- int contracts_up_number, frsh_contract_t contracts_up[], frsh_vres_id_t vres_up[], int contracts_up_status[])
-{
- int i, error;
-
- /* Check the bandwidth first!! */
- error = FRSH_NO_ERROR;
- for (i = 0; i < vres_down_number; i++) {
- vres_down_status[i] = cancel_contract(vres_down[i]);
- if (!vres_down_status[i])
- error = FRSH_ERR_INTERNAL_ERROR;
- }
- for (i = 0; i < contracts_touch_number; i++) {
- vres_touch_status[i] = renegotiate_contract(&contracts_touch[i], vres_touch[i]);
- if (!vres_touch_status[i])
- error = FRSH_ERR_INTERNAL_ERROR;
- }
- for (i = 0; i < contracts_up_number; i++) {
- contracts_up_status[i] = negotiate_contract(&contracts_up[i], &vres_up[i]);
- if (!contracts_up_status[i])
- error = FRSH_ERR_INTERNAL_ERROR;
- }
-
- return error;
-}
-
-/*
- * get_cputime(), get CPU usage of a vres
- *
- * returns the CPU time used by an AQuoSA resource reservation server (our
- * vres) as directly reported by the library API call 'qres_get_exec_time()',
- * given the conversion from microseconds to seconds.nanoseconds 'timespec'
- *
- * Note the request has sense only for REGULAR type of contract, since only
- * them have (one or more) threads attached to a server.
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (invalid vres or wrong contract type)
- * FRSH_ERR_NOT_CONTRACTED_VRES
- * FRSH_ERR_INTERNAL_ERROR (something wrong with AQuoSA)
- */
-static int get_cputime(const frsh_vres_id_t vres_id, struct timespec *cputime)
-{
- qres_time_t exec_time, abs_time;
-
- if (!check_vres_repo_ind(vres_id_2_index(vres_id)))
- return FRSH_ERR_BAD_ARGUMENT;
- if (vres_repo_isfree(vres_id_2_index(vres_id)))
- return FRSH_ERR_NOT_CONTRACTED_VRES;
- /* only REGULAR contracts use server CPU time */
- if (get_vres_entry(vres_id)->contract.resource_type != FRSH_RT_PROCESSOR ||
- get_vres_entry(vres_id)->contract.contract_type != FRSH_CT_REGULAR)
- return FRSH_ERR_BAD_ARGUMENT;
-
- if (qres_get_exec_time(get_vres_entry(vres_id)->processor.sid, &exec_time, &abs_time) != QOS_OK)
- return FRSH_ERR_INTERNAL_ERROR;
- usec_to_timespec(*cputime, exec_time);
-
- return FRSH_NO_ERROR;
-}
-
-/*
- * get_current_budget(), get actual remaining budget of a vres
- *
- * returns the actual budget remaining in an AQuoSA resource reservation
- * server as reported by the library API call 'qres_get_curr_budget()'.
- *
- * Note the request is meaningful for all type of contract, but only
- * REGULAR ones "spend" their budget, for DUMMY and BACKGROUND contract
- * types the (constant in value!) budget defined in the 'budget_min'
- * contract parameter is returned
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (invalid vres)
- * FRSH_ERR_NOT_CONTRACTED_VRES
- * FRSH_ERR_INTERNAL_ERROR (something wrong with AQuoSA)
- */
-static int get_current_budget(const frsh_vres_id_t vres_id, struct timespec *current_budget)
-{
- qres_time_t exec_budget;
-
- if (!check_vres_repo_ind(vres_id_2_index(vres_id)))
- return FRSH_ERR_BAD_ARGUMENT;
- if (vres_repo_isfree(vres_id_2_index(vres_id)))
- return FRSH_ERR_NOT_CONTRACTED_VRES;
-
- if (get_vres_entry(vres_id)->contract.resource_type == FRSH_RT_PROCESSOR &&
- get_vres_entry(vres_id)->contract.contract_type == FRSH_CT_REGULAR) {
- /* only if the contract is of REGULAR type
- * we ask AQuoSA for the current budget of the server*/
- if (qres_get_curr_budget(get_vres_entry(vres_id)->processor.sid, &exec_budget) != QOS_OK)
- return FRSH_ERR_INTERNAL_ERROR;
- usec_to_timespec(*current_budget, exec_budget);
- } else
- /* default and constant budget value
- * is returned in case of DUMMY and BACKGROUND contracts*/
- *current_budget = get_vres_entry(vres_id)->contract.budget_min;
-
- return FRSH_NO_ERROR;
-}
-
-/* get_budget_and_period(), retrieve the budget and period contracted for a vres
- *
- * returns the budget and period values stored in the contract ('budget_min'
- * and 'period_max' fields) of a vres.
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_BAD_ARGUMENT (invalid vres)
- * FRSH_ERR_NOT_CONTRACTED_VRES
- */
-static int get_budget_and_period(const frsh_vres_id_t vres_id,
- struct timespec *budget,
- struct timespec *period)
-{
-
- if (!check_vres_repo_ind(vres_id_2_index(vres_id)))
- return FRSH_ERR_BAD_ARGUMENT;
- if (vres_repo_isfree(vres_id_2_index(vres_id)))
- return FRSH_ERR_NOT_CONTRACTED_VRES;
-
- *budget = get_vres_entry(vres_id)->contract.budget_min;
- *period = get_vres_entry(vres_id)->contract.period_max;
-
- return FRSH_NO_ERROR;
-}
-
-static int reserve_feedback(frsh_contract_t *spare_contract)
-{
- qres_time_t qres_spare_budget, qres_spare_period;
-
- /* Check the contract is a right one first!! */
-
- qres_spare_budget = timespec_to_usec(spare_contract->budget_min);
- qres_spare_period = timespec_to_usec(spare_contract->period_max);
-
- /* Note: likely to get QOS_E_UNAUTHORIZED, here, if non-root! */
- if (qsup_reserve_spare(r2bw(qres_spare_budget, qres_spare_period)) != QOS_OK)
- PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
- "can't negotiate the spare contract");
-
- feedback_spare_contract = malloc(sizeof(frsh_contract_t));
- *feedback_spare_contract = *spare_contract;
-
- return FRSH_NO_ERROR;
-}
-
-/*******************************************************************************************************/
-/* S E R V I C E T H R E A D M A I N , H A N D L E R A N D U T I L I T Y F U N C T I O N S */
-/*******************************************************************************************************/
-
-////////////////////
-// signal handlers
-////////////////////
-
-/*
- * default service thread signal handler
- *
- * it's the signal handler installed for almost any catchable signal and
- * simply notify the occurred event in syslog and exit
- *
- * Note this is particularly important since the call to 'exit()' provides
- * to invoke 'frsh_service_th_cleanup()' as it's installed as an exit
- * handler
- */
-static void frsh_service_th_default_handler(int signo)
-{
- syslog(LOG_DEBUG, "caught signal %d...", signo);
- if (signo == SIGTERM) {
- syslog(LOG_DEBUG, "exiting...");
- exit(EXIT_FAILURE);
- }
-}
-
-/*
- * temporary signal handler for the service thread initialization
- *
- * it's the signal handler temporarily installed in the client process calling
- * 'frsh_service_th_init()' in order to wait the newly created service thread
- * for signaling the end of its initialization (writing of the pidfile).
- *
- * It's removed just before the signal arrives and the default behaviour
- * is restored
- *
- * Check the code (and the comments!) below for better understanding of the
- * role of this little and innocent function!
- */
-void frsh_service_th_init_wait_handler(int s)
-{
- if (s != SIGUSR2) {
- PERROR_FRESCOR(FRSH_ERR_INTERNAL_ERROR,
- "grave error in signal handler during service thread initialization");
- exit(EXIT_FAILURE);
- }
-}
-
-#ifdef FRSH_CONFIG_ENABLE_DEBUG
-
-/*
- * signal handler for printing debugging information
- *
- * it's installed, if debugging is configured, in order to print into syslog
- * the status of the most relevant internal data structures, so we can
- * monitor the service thread activities and status.
- *
- * Note that, to keep the overhead very little, no locking or mutual
- * exclusion access to any of the data structure is in place.
- * Since the function does not modify any of the fields we risk no race
- * conditions, but the informations printed into syslog may be not the most
- * updated or may not be consistent!
- *
- * Note also the choosen signal is the standard SIGUSR1 UNIX signal (on most
- * GNU/Linux platfomrs accessible with 'kill -10 ...'
- */
-static void frsh_service_th_debug_handler(int signo)
-{
- int i;
- contract_hash_entry_t *ip;
-
- if (signo != SIGUSR1) {
- syslog(LOG_ERR, "FATAL ERROR: wrong signal %d catched, exiting!", signo);
- exit(EXIT_FAILURE);
- }
- syslog(LOG_DEBUG, "caught signal %d (SIGUSR1) => printing debugging info:", SIGUSR1);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* print informations about service requests and worker threads */
- syslog(LOG_DEBUG, " total requests queued: %d", get_queued_jobs_number());
- syslog(LOG_DEBUG, " total number of active threads: %d", get_active_thread_number());
- syslog(LOG_DEBUG, " total number of busy (active and not sleeping) threads: %d", get_busy_thread_number());
- syslog(LOG_DEBUG, " total number of sleeping threads: %d", get_sleeping_thread_number());
-#endif
-
- /* print informations about negotiated contracts
- * (stored into the hash table) */
- syslog(LOG_DEBUG, " contract hash table content:");
- for (i = 0; i < HASH_N_ELEMENTS; i++) {
- ip = (contract_hash_entry_t*) contract_hash_table.table[i];
- if (ip != NULL) {
- syslog(LOG_DEBUG, " contract in the hash table at position %d:", i);
- while (ip != NULL) {
- syslog(LOG_DEBUG, " key: %s, vres id: %d",
- ip->contract_label,
- (int) vres_index_2_id(ip->contract_data.vres_index));
- ip = ip->next;
- }
- }
- }
- /* print informations about contracted vres
- * (stored into the repository) */
- syslog(LOG_DEBUG, " total number of regular and background vres: %d", get_vres_number());
- syslog(LOG_DEBUG, " total number of dummy vres: %d", get_dummy_vres_number());
- syslog(LOG_DEBUG, " vres repository:");
- for (i = 0; i < 2 * FRSH_MAX_N_VRES; i++) {
- if (!vres_repo_isfree(i)) {
- if (i >= FRSH_MAX_N_VRES)
- syslog(LOG_DEBUG, " DUMMY VRES:");
- syslog(LOG_DEBUG, " vres repository entry with index: %d (vres id = %d):", i, vres_index_2_id(i));
- syslog(LOG_DEBUG, " contract(label): %s", get_vres_entry(i)->contract.contract_label);
- syslog(LOG_DEBUG, " sid: %d", get_vres_entry(i)->processor.sid);
- syslog(LOG_DEBUG, " threads_number: %d", get_vres_entry(i)->processor.threads_number);
- syslog(LOG_DEBUG, " first_thread_index: %d", get_vres_entry(i)->processor.first_thread_index);
- syslog(LOG_DEBUG, " renegotiation_status: %d", get_vres_entry(i)->renegotiation_status);
- }
- }
- /* print informations about bound threads
- * (stored into the repository) */
- syslog(LOG_DEBUG, " total number of bound threads: %d", get_threads_number());
- syslog(LOG_DEBUG, " thread repository content:");
- for (i = 0; i < FRSH_MAX_N_THREADS; i++) {
- if (!thread_repo_isfree(i)) {
- syslog(LOG_DEBUG, " thread repository entry with index: %d:", i);
- syslog(LOG_DEBUG, " thread: {%lu, %d, %d}",
- get_thread_entry(i)->thread.pthread_id,
- get_thread_entry(i)->thread.linux_pid,
- get_thread_entry(i)->thread.linux_tid);
- syslog(LOG_DEBUG, " vres: %d", get_thread_entry(i)->vres);
- syslog(LOG_DEBUG, " next_in_vres: %d", get_thread_entry(i)->next_in_vres);
- while (get_thread_entry(i)->next_in_vres != -1)
- syslog(LOG_DEBUG, " %d", get_thread_entry(i)->next_in_vres);
- }
- }
-}
-
-#endif /* FRSH_CONFIG_ENABLE_DEBUG */
-
-//////////////////////
-// Utility Functions
-//////////////////////
-
-/*
- * cleanup function for the service thread
- *
- * when the service thread (voluntarily or not) exits this function smoothly
- * cleanup all, i.e, cancel the contracts and, much more important, closes
- * the syslog connection and all files descriptors and unlinks the socket
- * and the pidfile
- *
- * If this function is not correcly ran a new instance of the service thread
- * can't be started without, at least, manually remove the files and do all
- * other cleanups first
- */
-static void frsh_service_th_cleanup()
-{
- int i;
-
- /* say goodbye via the log */
- syslog(LOG_INFO, "exiting: starting cleanup...");
- /* cancel all (well, all but ours) the negotiated contracts */
- for (i = 0; i < 2 * FRSH_MAX_N_VRES; i++)
- if (!check_vres_repo_entry_free(i)) {
- int vres_id = vres_index_2_id(i);
- if (vres_id == service_th_vres_id)
- /* defer the cancellation of our (service thread) contract */
- continue;
- if (cancel_contract(vres_id) != FRSH_NO_ERROR)
- syslog(LOG_ERR,
- "ERROR: cleanup: can't cancel the contract of the vres id = %d, sid = %d",
- vres_id,
- get_vres_entry(vres_id)->processor.sid);
- else
- syslog(LOG_INFO,
- "cleanup: contract cancelled for the vres id = %d, sid = %d",
- vres_id,
- get_vres_entry(vres_id)->processor.sid);
- }
- /* release the lock on the pidfile */
- funlockfile(pid_fd);
- /* close socket and pidfile descriptors */
- close(sock);
- fclose(pid_fd);
- /* remove socket and pidfile from filesystem */
- unlink(FRSH_SERVICE_TH_SOCKET);
- unlink(FRSH_SERVICE_TH_PIDFILE);
- /* cancel the service thread own contract (it automatically deallocate
- * FRSH resources and also destroy AQuoSA objects tied to them) */
- if (cancel_contract(service_th_vres_id) != FRSH_NO_ERROR)
- syslog(LOG_ERR,
- "ERROR: cleanup: can't cancel the contract of the service thread (vres id = %d, sid = %d)",
- service_th_vres_id,
- get_vres_entry(service_th_vres_id)->processor.sid);
- else
- syslog(LOG_INFO,
- "cleanup: contract cancelled for the service thread (vres id = %d, sid = %d)",
- service_th_vres_id,
- get_vres_entry(service_th_vres_id)->processor.sid);
- syslog(LOG_INFO, "exiting: ...cleanup done. Goodbye!");
- /* close syslog connection */
- closelog();
-}
-
-#if defined(FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE) && defined(FRSH_CONFIG_ENABLE_SERVICE_TH_SAFETY_CHECK)
-
-/*
- * check for service thread existence and consistency
- *
- * checks if a pidfile exists because, if not, this mean no service thread
- * is running and this could be a grave problem!
- * Also checks if the pidfile content is consistent with what the caller
- * believe the PID of the service thread is (each client save a copy of it
- * in the 'check_pid' variable during the call to 'frsh_init()', as you can
- * see down in the code), though if a service thread is running but it's not
- * the one with whom the client negotiated all its contracs (ecc.) the
- * situation is not much better than no service thread at all!!
- *
- * Note the function is called within 'frsh_service_thread_ask_for()' (defined
- * right below) and it's executed _only_ by the clients trying to connect and
- * ask for some operation to the service thread
- *
- * Note also this function has sense only if the clients and the service
- * thread are processes of the _same_ workstation!
- *
- * possible return values:
- * true (the _expected_ service thread exists)
- * false (the service thread not exists or it's pid is different from what is expected)
- */
-static inline bool frsh_service_th_check_pidfile(const pid_t pid_key)
-{
- FILE *pidfile;
- pid_t check_pid;
-
- /* check if the pidfile exists and read its content */
- if ( (pidfile = fopen(FRSH_SERVICE_TH_PIDFILE, "r")) == NULL)
- return false;
- if (fscanf(pidfile, "%d", &check_pid) <= 0) {
- fclose(pidfile);
- return false;
- }
-
- /* pid red in the pidfile is equal to what the
- * client knows is the pid of the service thread ? */
- return (pid_key == check_pid) ? true : false;
-}
-
-#endif /* FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE && FRSH_CONFIG_ENABLE_SERVICE_TH_SAFETY_CHECK */
-
-/*
- * ask for a service thread's service
- *
- * one of the only two functions exported outside this source (note it's
- * not 'static') this is the function the clients use (within the
- * implementation of the FRSH API call, ex. in frsh_core.c) in order to issue
- * the service thread a command and ask him to perform one of the available
- * services (negotiation, renegotiation, binding, ecc.).
- *
- * Requests are sent through a socket and synchronization is achieved (if
- * requested for the specific call) simply waiting for the service thread
- * itself to answer and to provide the results
- *
- * possible return values:
- * FRSH_SERVICE_TH_NO_ERROR (all ok)
- * FRSH_SERVICE_TH_ERR_SERVER (service thread is not running or the pidfile is inconsistent)
- * FRSH_SERVICE_TH_ERR_SOCKET (troubles trying to create the socket, connect, send or recive)
- */
-int frsh_service_th_ask_for(const pid_t pid_key,
- const frsh_in_msg_t *msg_in,
- frsh_out_msg_t *msg_out)
-{
- struct sockaddr_un connct_addr;
- int connct;
-
-#ifdef FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_SAFETY_CHECK
- /* check for service and calling thread consistency */
- if (!frsh_service_th_check_pidfile(pid_key))
- PERROR_AND_RETURN(FRSH_SERVICE_TH_ERR_SERVER,
- "error checking if the correct service thread is running");
-#endif
-
- /* setup the UNIX domain socket's parameters */
- memset(&connct_addr, 0, sizeof(struct sockaddr_un));
- connct_addr.sun_family = AF_UNIX;
- strncpy(connct_addr.sun_path, FRSH_SERVICE_TH_SOCKET, strlen(FRSH_SERVICE_TH_SOCKET));
- /* create the local UNIX domain socket */
- if ((connct = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
- PERROR_AND_RETURN(FRSH_SERVICE_TH_ERR_SOCKET,
- "can not create the connection to the service thread");
-#else /* !FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE */
-
- /*
- * setup a different type of socket and connectivity model (say
- * Internet STREAM or DGRAM socket on local or external
- * address, ecc.)
- *
- * NOT_YET_IMPLEMENTED
- */
-
-#endif /* FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE */
-
- /* connect to the socket to communicate with the service thread */
- if ((connect(connct, (struct sockaddr*) &connct_addr, sizeof(struct sockaddr_un))) < 0) {
- close(connct);
- PERROR_AND_RETURN(FRSH_SERVICE_TH_ERR_SOCKET,
- "can not connect to the service thread");
- }
- /* send the request message to the service thread */
- if (send(connct, (void*) msg_in, sizeof(frsh_in_msg_t), 0) < sizeof(frsh_in_msg_t)) {
- close(connct);
- PERROR_AND_RETURN(FRSH_SERVICE_TH_ERR_SOCKET,
- "can not send message to the service thread");
- }
- /* if (and only if) the issued command is _synchronous_
- * wait here untill we receive the response from the socket */
- if (msg_in->type != FRSH_MT_CHANGE_MODE_ASYNC ||
- msg_in->type != FRSH_MT_REQUEST_CONTRACT_RENEGOTIATION)
- /* receive sinchronously the reply from the service thread */
- if (recv(connct, (void*) msg_out, sizeof(frsh_out_msg_t), MSG_WAITALL) < sizeof(frsh_out_msg_t)) {
- close(connct);
- PERROR_AND_RETURN(FRSH_SERVICE_TH_ERR_SOCKET,
- "can not receive message from the service thread");
- }
- /* all done, close connection end return */
- if (close(connct) < 0)
- PERROR_AND_RETURN(FRSH_SERVICE_TH_ERR_SOCKET,
- "can not close the connection to the service thread");
-
- return FRSH_SERVICE_TH_NO_ERROR;
-}
-
-/*
- * service thread initialization function
- *
- * the only other non 'static' function of the whole file this is the
- * initialization function of the service thread and it's called by
- * all clients within the code of 'frsh_init()'.
- * If a service thread already exists (a pidfile is present) its PID
- * is red from the pidfile and saved for (optional) future safety checkings,
- * if it does not exists it is created as a new process via a standard UNIX
- * 'fork()' call and it starts executing its main code.
- *
- * Note that if the service thread is created by this code the caller blocks
- * waiting for it to signal its initialization process is up (the pidfile
- * has been written).
- * At the end of the function the original signal behaviour of all the
- * involved processes are reset to default
- *
- * possible return values:
- * FRSH_NO_ERROR (service thread already running or correctly initialized)
- * FRSH_ERR_INTERNAL_ERROR
- */
-
-static int frsh_service_th_main();
-
-int frsh_service_th_init(pid_t *pid_key)
-{
- struct stat init_fd_stat;
- FILE *pidfile;
- sigset_t init_wait_mask;
- struct sigaction init_wait_action, old_action;
-
- /* setup 'init-complete' signal handler and mask */
- init_wait_action.sa_handler = frsh_service_th_init_wait_handler;
- sigprocmask(0, NULL, &init_wait_action.sa_mask);
- sigaddset(&init_wait_action.sa_mask, SIGUSR2);
- sigprocmask(SIG_SETMASK, &init_wait_action.sa_mask, NULL);
- init_wait_action.sa_flags = 0;
- if (sigaction(SIGUSR2, &init_wait_action, &old_action) < 0)
- PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
- "can't properly initialize the service thread");
- if (stat(FRSH_SERVICE_TH_PIDFILE, &init_fd_stat) < 0) {
- if ( (service_th_pid = fork()) < 0)
- PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
- "can't create the service thread");
- else
- if (service_th_pid == 0) {
- /* reset original on-signal behaviour of the process */
- sigaction(SIGUSR2, &old_action, NULL);
- /* run main service thread code */
- frsh_service_th_main();
-
- /* we should have no chance of being here! */
- exit(EXIT_FAILURE);
- } else {
- /* setup signal masks and give the service thread
- * the chance to notify the completion of the initialization */
- sigprocmask(0, NULL, &init_wait_mask);
- sigdelset(&init_wait_mask, SIGUSR2);
- sigsuspend(&init_wait_mask);
- /* reset original on-signal behaviour even in the client */
- sigaction(SIGUSR2, &old_action, NULL);
- }
- }
- /* we're now sure the pidfile exist and we
- * can try reading it and expect we succeed in */
- if ( (pidfile = fopen(FRSH_SERVICE_TH_PIDFILE, "r")) == NULL)
- PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
- "can't open (existing!) pidfile of the service thread");
- if (fscanf(pidfile, "%d", &service_th_pid) <= 0) {
- fclose(pidfile);
- PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
- "can't read from (existing!) pidfile of service thread");
- }
- /* the actual pid of the service thread (read from pidfile) is now
- * saved in 'service_th_pid' and also returned back to the caller in 'pid_key' */
- *pid_key = service_th_pid;
-
- return FRSH_NO_ERROR;
-}
-
-/*
- * service thread main function
- *
- * it's called by the new process created to serve as the service thread, it
- * provides all initialization steps (socket, pidfile, data structures, ecc.),
- * turns the process into a daemon and start logging via syslog.
- *
- * When all is ready it starts the main cycle during which the requests from
- * the client are received and served according to the configured model
- * (single or multithreaded).
- *
- * In multithreaded implementation the service thread always enqueue all
- * incoming service requests (given there is room in the queue, and if this
- * is not the case, it simply wait) and the worker threads dequeue and handle
- * them.
- * A minimum number of thread is always active and they sleep if there is not
- * enough jobs for all. A maximum limit is defined as well and no more than
- * such a number of thread will be spawned.
- *
- * In single threaded implementation there are no worker threads and the main
- * function of the service thread takes cere of receive and handle all clients'
- * requests in the 'while (1)' cycle.
- *
- * Note that no locking and mutual exclusive access is required (and in fact is
- * not provided) if the single thread model is configured
- *
- * possible exit status:
- * EXIT_SUCCESS
- * EXIT_FAILURE
- */
-
-
-static int frsh_service_th_main()
-{
- int conn;
- struct stat pid_fd_stat;
- struct sockaddr_un sock_addr;
- struct sigaction signal_data;
- pid_t ppid;
-
- frsh_in_msg_t request;
-#ifndef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- frsh_out_msg_t reply;
-#endif
- /* backup the PID of the _real_ parent process, before daemon() calls
- * fork itslef, to detach the proces from its original session */
- ppid = getppid();
- /* reset umask */
- if (umask(0) < 0) {
- fprintf(stderr, "FATAL ERROR: FRSH service thread: can't reset the umask");
- goto frsh_service_th__exit;
- }
- /* create a new session, change the working directory
- * and reopen /dev/null as std{in,out,err} */
-
-#define DO_CHDIR 0
-#define DO_REOPEN_DEVNULL 0
-
- if (daemon(DO_CHDIR, DO_REOPEN_DEVNULL) < 0) {
- fprintf(stderr, "FATAL ERROR: FRSH service thread: can't 'daemonize' the process");
- goto frsh_service_th__exit;
- }
- /* initialize and start syslog connection */
- openlog("FRSH service thread:", LOG_CONS|LOG_PID, LOG_DAEMON);
- syslog(LOG_INFO, "new service thread started");
- /* setup common signal handlers and masks
- * (die with cleanup with almost all the signals) */
- signal_data.sa_handler = frsh_service_th_default_handler;
- sigemptyset(&signal_data.sa_mask);
- signal_data.sa_flags = 0;
- if (sigaction(SIGINT, &signal_data, NULL) < 0 ||
- sigaction(SIGHUP, &signal_data, NULL) < 0 ||
- sigaction(SIGQUIT, &signal_data, NULL) < 0 ||
- sigaction(SIGILL, &signal_data, NULL) < 0 ||
- sigaction(SIGABRT, &signal_data, NULL) < 0 ||
- sigaction(SIGBUS, &signal_data, NULL) < 0 ||
- sigaction(SIGFPE, &signal_data, NULL) < 0 ||
- /* sigaction(SIGKILL, &signal_data, NULL) < 0 || */
- sigaction(SIGUSR1, &signal_data, NULL) < 0 ||
- sigaction(SIGUSR2, &signal_data, NULL) < 0 ||
- sigaction(SIGSEGV, &signal_data, NULL) < 0 ||
- sigaction(SIGPIPE, &signal_data, NULL) < 0 ||
- sigaction(SIGALRM, &signal_data, NULL) < 0 ||
- sigaction(SIGTERM, &signal_data, NULL) < 0 ||
- sigaction(SIGCHLD, &signal_data, NULL) < 0 ||
- /* sigaction(SIGSTOP, &signal_data, NULL) < 0 || */
- sigaction(SIGTSTP, &signal_data, NULL) < 0 ||
- sigaction(SIGTTIN, &signal_data, NULL) < 0 ||
- sigaction(SIGTTOU, &signal_data, NULL) < 0) {
- syslog(LOG_ERR, "can't setup the signal handling");
- goto frsh_service_th__exit;
- }
-#ifdef FRSH_CONFIG_ENABLE_DEBUG
- /* setup debugging signal (SIGUSR1) handler and mask */
- signal_data.sa_handler = frsh_service_th_debug_handler;
- sigprocmask(0, NULL, &signal_data.sa_mask);
- signal_data.sa_flags = 0;
- if (sigaction(SIGUSR1, &signal_data, NULL) < 0)
- syslog(LOG_INFO, "WARNING: can't install SIGUSR1 for debugging purposes");
-#endif
- /* check, create and fill the pidfile */
- if (stat(FRSH_SERVICE_TH_PIDFILE, &pid_fd_stat) < 0) {
- /* pidfile does not exist, and this is good :-D */
- pid_fd = fopen(FRSH_SERVICE_TH_PIDFILE, "w");
- if (pid_fd == NULL) {
- /* can not create the pidfile, we can't continue! */
- syslog(LOG_ERR, "FATAL ERROR: error trying to create the pidfile, exiting!");
- goto frsh_service_th_pidfile_not_created;
- }
- flockfile(pid_fd);
- /* write our pid into the file */
- if (fprintf(pid_fd, "%d\n", getpid()) <= 0) {
- /* either in this case we can't continue! */
- syslog(LOG_ERR, "FATAL ERROR: error trying to write into pidfile, exiting!");
- goto frsh_service_th_pidfile_not_written;
- }
- /* flush the pidfile stream to ensure data get written */
- if (fflush(pid_fd) == EOF) {
- /* again we can't continue, we must be sure the pidfile contains our pid! */
- syslog(LOG_ERR, "FATAL ERROR: error trying to flush data into pidfile, exiting!");
- goto frsh_service_th_pidfile_not_written;
- }
- } else {
- /* Uh-Oh, the pidfile is already present, and this is very, very bad :-( */
- syslog(LOG_ERR, "FATAL ERROR: pidfile already present!");
- goto frsh_service_th_pidfile_not_created;
- }
- /* notify the waiting parent process (a client executing in the
- * 'frsh_init()' call) the pidfile has been created and he can try to read it */
- if (kill(ppid, SIGUSR2) < 0)
- syslog(LOG_INFO, "WARNING: can't notify the parent process pidfile has been created...");
-
-#ifdef FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE
- /* setup the UNIX domain socket's parameters */
- memset(&sock_addr, 0, sizeof(struct sockaddr_un));
- sock_addr.sun_family = AF_UNIX;
- strncpy(sock_addr.sun_path, FRSH_SERVICE_TH_SOCKET, strlen(FRSH_SERVICE_TH_SOCKET));
- /* create the local UNIX domain socket */
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
-#else /* !FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE */
-
- /*
- * setup a different type of socket and connectivity model (say
- * Internet STREAM or DGRAM socket on local or external
- * address, ecc.)
- *
- * NOT_YET_IMPLEMENTED
- */
-
-#endif
-
- if (sock < 0) {
- /* can't even create the socket... Very bad! :-( */
- syslog(LOG_ERR, "FATAL ERROR: can't create the socket, exiting!");
- goto frsh_service_th_socket_created;
- }
- /* bind the socket to its addressing data structure */
- if (bind(sock, (struct sockaddr*) &sock_addr, sizeof(struct sockaddr_un)) < 0) {
- /* can't bind... Maybe a server is already running? */
- syslog(LOG_ERR, "FATAL ERROR: can't bind to the socket, exiting!");
- goto frsh_service_th_socket_bound;
- }
- /* listen for connections from the clients threads */
- if (listen(sock, 0) < 0) {
- syslog(LOG_ERR, "FATAL ERROR: can't listen from the socket, exiting!");
- goto frsh_service_th_socket_bound;
- }
- /* register the cleanup function for being executed on program exit */
- if (atexit(frsh_service_th_cleanup) < 0) {
- syslog(LOG_ERR, "FATAL ERROR: can't install cleanup function, exiting!");
- goto frsh_service_th_full_cleanup;
- }
- /* initialize hash table, threads and vres repository and jobs queue */
- if ( !disk_init() ||
- !contract_hash_init() ||
- !thread_repo_init() ||
- !vres_repo_init()
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- || !service_th_queue_init() ) {
-#else
- ) {
-#endif
- syslog(LOG_ERR, "FATAL ERROR: can't initialize all the internal data structures, exiting!");
- exit(EXIT_FAILURE);
- }
- /* negotiate the contract for myself */
- if (negotiate_contract(&service_th_contract, &service_th_vres_id) != FRSH_NO_ERROR) {
- syslog(LOG_ERR, "FATAL ERROR: can't negotiate the contract for the service thread, exiting!");
- exit(EXIT_FAILURE);
- }
- /* bind the service thread to the just negotiated contract */
- service_th_thread = fosa_thread_self();
- if (bind_thread(&service_th_thread, service_th_vres_id) != FRSH_NO_ERROR) {
- syslog(LOG_ERR, "FATAL ERROR: can't bind the service thread to its contract, exiting!");
- exit(EXIT_FAILURE);
- }
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* initialize the worker thread pool
- * (if a multithreaded service thread has been configured) */
- if (!worker_thread_pool_init()) {
- syslog(LOG_ERR, "FATAL ERROR: can't initialize the worker thread pool, exiting!");
- exit(EXIT_FAILURE);
- }
-#endif
- /* main server loop */
- while (1) {
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* multithreaded service thread */
- if (service_th_queue.jobs_number >= FRSH_MAX_N_SERVICE_JOBS)
- continue;
- conn = accept(sock, NULL, NULL);
- if (conn >= 0) {
- syslog(LOG_INFO, "new connection established");
- /* receive the request */
- if (recv(conn, (void*) &request, sizeof(frsh_in_msg_t), MSG_WAITALL) < sizeof(frsh_in_msg_t))
- syslog(LOG_ERR, "can't receive request message (ERROR 0x%x)", FRSH_SERVICE_TH_ERR_SOCKET);
- else {
- enqueue_service_th_request(conn, &request);
- fosa_mutex_lock(&worker_pool.mutex);
- if (worker_pool.active_thread_number - worker_pool.busy_thread_number > 0) {
- /* at least one thread is active and sleeping
- * and we're going to awake it*/
- fosa_cond_signal(&worker_pool.sleep);
- syslog(LOG_INFO, "woken up a worker thread to handle the request");
- } else
- if (worker_pool.active_thread_number < MAX_N_WORKER_THREAD) {
- fosa_thread_create(NULL, NULL, worker_thread_code, NULL);
- syslog(LOG_INFO, "new thread created to handle the request");
- }
- fosa_mutex_unlock(&worker_pool.mutex);
- }
- }
-#else /* !FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD */
- conn = accept(sock, NULL, NULL);
- if (conn >= 0) {
- syslog(LOG_INFO, "new connection established");
- /* receive the request */
- if (recv(conn, (void*) &request, sizeof(frsh_in_msg_t), MSG_WAITALL) < sizeof(frsh_in_msg_t))
- syslog(LOG_ERR, "can't receive request message (ERROR 0x%x)", FRSH_SERVICE_TH_ERR_SOCKET);
- else {
- switch (request.type) {
- /* process client(s) requests according to the operation and
- * (simply?) colling one (or a little more) of the FRSH utility
- * function defined down in the code */
- case FRSH_MT_NEGOTIATE_CONTRACT:
- {
- syslog(LOG_DEBUG, "operation requested: NEGOTIATE_CONTRACT");
- reply.error = negotiate_contract(&request.val.negotiate_contract.contract,
- &reply.val.negotiate_contract.vres_id);
- goto answer_and_close;
- }
- case FRSH_MT_BIND_THREAD:
- {
- syslog(LOG_DEBUG, "operation requested: BIND_THREAD");
- reply.error = bind_thread(&request.val.bind_thread.thread_id,
- request.val.bind_thread.vres_id);
- goto answer_and_close;
- }
- case FRSH_MT_UNBIND_THREAD:
- {
- syslog(LOG_DEBUG, "operation requested: UNBIND_THREAD");
- reply.error = unbind_thread(&request.val.unbind_thread.thread_id);
- goto answer_and_close;
- }
- case FRSH_MT_GET_THREAD_VRES_ID:
- {
- syslog(LOG_DEBUG, "operation requested: GET_THREAD_VRES_ID");
- reply.error = get_thread_vres_id(&request.val.get_thread_vres_id.thread_id,
- &reply.val.get_thread_vres_id.vres_id);
- goto answer_and_close;
- }
- case FRSH_MT_GET_CONTRACT:
- {
- syslog(LOG_DEBUG, "operation requested: GET_CONTRACT");
- reply.error = get_contract(request.val.get_contract.vres_id,
- &reply.val.get_contract.contract);
- goto answer_and_close;
- }
- case FRSH_MT_GET_LABEL_VRES_ID:
- {
- syslog(LOG_DEBUG, "operation requested: GET_LABEL_VRES_ID");
- reply.error = get_label_vres_id(request.val.get_label_vres_id.contract_label,
- &reply.val.get_label_vres_id.vres_id);
- goto answer_and_close;
- }
- case FRSH_MT_CANCEL_CONTRACT:
- {
- syslog(LOG_DEBUG, "operation requested: CANCEL_CONTRACT");
- reply.error = cancel_contract(request.val.cancel_contract.vres_id);
- goto answer_and_close;
- }
- case FRSH_MT_RENEGOTIATE_CONTRACT:
- {
- syslog(LOG_DEBUG, "operation requested: RENEGOTIATE_CONTRACT");
- reply.error =
- renegotiate_contract(&request.val.renegotiate_contract.new_contract,
- request.val.renegotiate_contract.vres_id);
- goto answer_and_close;
- }
- case FRSH_MT_REQUEST_CONTRACT_RENEGOTIATION:
- {
- syslog(LOG_DEBUG, "operation requested: REQUEST_CONTRACT_RENEGOTIATION");
- close(conn);
- syslog(LOG_DEBUG, "aync. operation, do not wait for completion");
- syslog(LOG_INFO, "connection closed");
- reply.error =
- renegotiate_contract(&request.val.request_contract_renegotiation.new_contract,
- request.val.request_contract_renegotiation.vres_id);
-#ifdef FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE
- /* signals the completion of the operation with a signal */
- if (request.val.request_contract_renegotiation.signal != FRSH_NULL_SIGNAL)
- if (fosa_signal_queue(request.val.request_contract_renegotiation.signal,
- request.val.request_contract_renegotiation.siginfo,
- request.val.request_contract_renegotiation.thread_to_signal) != 0)
- syslog(LOG_ERR,
- "can't signal process %d with signal %d to notify the completion of the renegotiation",
- request.val.request_contract_renegotiation.thread_to_signal.linux_pid,
- request.val.request_contract_renegotiation.signal);
-#endif
- goto end_cycle;
- }
- case FRSH_MT_GET_RENEGOTIATION_STATUS:
- {
- syslog(LOG_DEBUG, "operation requested: GET_RENEGOTIATION_STATUS");
- reply.error = get_renegotiation_status(request.val.get_renegotiation_status.vres_id,
- &reply.val.get_renegotiation_status.renegotiation_status);
- goto answer_and_close;
- }
- case FRSH_MT_NEGOTIATE_GROUP:
- {
- int i;
-
- syslog(LOG_DEBUG, "operation requested: NEGOTIATE_GROUP");
- reply.error = FRSH_NO_ERROR;
- for (i = 0; i < request.val.negotiate_group.vres_down_number; i++)
- reply.error = reply.val.negotiate_group.vres_down_status[i] =
- cancel_contract(request.val.negotiate_group.vres_down[i]);
- for (i = 0; i < request.val.negotiate_group.contracts_up_number; i++)
- reply.error = reply.val.negotiate_group.contracts_up_status[i] =
- negotiate_contract(&request.val.negotiate_group.contracts_up[i],
- &reply.val.negotiate_group.vres_up[i]);
- goto answer_and_close;
- }
- case FRSH_MT_CHANGE_MODE_SYNC:
- case FRSH_MT_CHANGE_MODE_ASYNC:
- {
- int i;
-
- syslog(LOG_DEBUG, "operation requested: NEGOTIATE_GROUP");
- reply.error = FRSH_NO_ERROR;
- if (request.type == FRSH_MT_CHANGE_MODE_ASYNC) {
- close(conn);
- syslog(LOG_DEBUG, "aync. operation, do not wait for completion");
- syslog(LOG_INFO, "connection closed");
-
- }
- for (i = 0; i < request.val.change_mode.vres_down_number; i++)
- reply.error = reply.val.change_mode.vres_down_status[i] =
- cancel_contract(request.val.change_mode.vres_down[i]);
- for (i = 0; i < request.val.change_mode.contracts_touch_number; i++)
- reply.error = reply.val.change_mode.vres_touch_status[i] =
- renegotiate_contract(&request.val.change_mode.contracts_touch[i],
- request.val.change_mode.vres_touch[i]);
- for (i = 0; i < request.val.change_mode.contracts_up_number; i++)
- reply.error = reply.val.change_mode.contracts_up_status[i] =
- negotiate_contract(&request.val.change_mode.contracts_up[i],
- &reply.val.change_mode.vres_up[i]);
-#ifdef FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE
- /* signals the completion of the operation with a signal */
- if (request.val.change_mode.signal != FRSH_NULL_SIGNAL)
- if (fosa_signal_queue(request.val.change_mode.signal,
- request.val.change_mode.siginfo,
- request.val.change_mode.thread_to_signal) != 0)
- syslog(LOG_ERR,
- "can't signal process %d with signal %d to notify the completion of the renegotiation",
- request.val.change_mode.thread_to_signal.linux_pid,
- request.val.change_mode.signal);
-#endif
- if (request.type == FRSH_MT_CHANGE_MODE_SYNC)
- goto answer_and_close;
- else
- goto end_cycle;
- }
- case FRSH_MT_GET_CPUTIME:
- {
- syslog(LOG_DEBUG, "operation requested: GET_CPUTIME");
- reply.error = get_cputime(request.val.get_cputime.vres_id,
- &reply.val.get_cputime.cputime);
- goto answer_and_close;
- }
- case FRSH_MT_GET_CURRENTBUDGET:
- {
- syslog(LOG_DEBUG, "operation requested: GET_CURRENTBUDGET");
- reply.error = get_current_budget(request.val.get_currentbudget.vres_id,
- &reply.val.get_currentbudget.currentbudget);
- goto answer_and_close;
- }
- case FRSH_MT_GET_BUDGET_AND_PERIOD:
- {
- syslog(LOG_DEBUG, "operation requested: GET_BUDGET_AND_PERIOD");
- reply.error = get_budget_and_period(request.val.get_budget_and_period.vres_id,
- &reply.val.get_budget_and_period.budget,
- &reply.val.get_budget_and_period.period);
- goto answer_and_close;
- }
- case FRSH_MT_GET_SERVICE_THREAD_DATA:
- {
- syslog(LOG_DEBUG, "operation requested: GET_SERVICE_THREAD_DATA");
- reply.error = get_budget_and_period(service_th_vres_id,
- &reply.val.get_service_thread_data.budget,
- &reply.val.get_service_thread_data.period);
- goto answer_and_close;
- }
- case FRSH_MT_SET_SERVICE_THREAD_DATA:
- {
- struct timespec old_budget, old_period;
- syslog(LOG_DEBUG, "operation requested: SET_SERVICE_THREAD_DATA");
- old_budget = service_th_contract.budget_min;
- old_period = service_th_contract.period_max;
- service_th_contract.budget_min =
- request.val.set_service_thread_data.budget;
- service_th_contract.period_max =
- request.val.set_service_thread_data.period;
- reply.error =
- renegotiate_contract(&service_th_contract, service_th_vres_id);
- if (reply.error == FRSH_NO_ERROR)
- reply.val.set_service_thread_data.accepted = true;
- else {
- reply.val.set_service_thread_data.accepted = false;
- service_th_contract.budget_min = old_budget;
- service_th_contract.period_max = old_period;
- }
- goto answer_and_close;
- }
- default:
- {
- syslog(LOG_ERR, "operation requested: unknown !!");
- reply.error = FRSH_SERVICE_TH_ERR_SOCKET;
- goto answer_and_close;
- }
- }
-answer_and_close:
- if (send(conn, (void*) &reply, sizeof(frsh_out_msg_t), 0) < sizeof(frsh_out_msg_t))
- syslog(LOG_ERR, "can't send reply message (ERROR 0x%x)", FRSH_SERVICE_TH_ERR_SOCKET);
- else
- syslog(LOG_DEBUG, "command reply sent (exit status 0x%x)", reply.error);
- close(conn);
- syslog(LOG_INFO, "connection closed");
-end_cycle:
- ;
- }
- }
-#endif
- }
-
-frsh_service_th_full_cleanup:
-frsh_service_th_socket_bound:
- close(sock);
- unlink(FRSH_SERVICE_TH_SOCKET);
-frsh_service_th_socket_created:
-frsh_service_th_pidfile_not_written:
- funlockfile(pid_fd);
- fclose(pid_fd);
- unlink(FRSH_SERVICE_TH_PIDFILE);
-frsh_service_th_pidfile_not_created: /* frsh_service_th_exit: */
- closelog();
-frsh_service_th__exit:
- /* roughly exit without calling the
- * (eventually already) installed atexit handler*/
- _exit(EXIT_FAILURE);
-}
-
+++ /dev/null
-// -----------------------------------------------------------------------
-// Copyright (C) 2006 - 2007 FRESCOR consortium partners:
-//
-// Universidad de Cantabria, SPAIN
-// University of York, UK
-// Scuola Superiore Sant'Anna, ITALY
-// Kaiserslautern University, GERMANY
-// Univ. Politécnica Valencia, SPAIN
-// Czech Technical University in Prague, CZECH REPUBLIC
-// ENEA SWEDEN
-// Thales Communication S.A. FRANCE
-// Visual Tools S.A. SPAIN
-// Rapita Systems Ltd UK
-// Evidence ITALY
-//
-// See http://www.frescor.org for a link to partners' websites
-//
-// FRESCOR project (FP6/2005/IST/5-034026) is funded
-// in part by the European Union Sixth Framework Programme
-// The European Union is not liable of any use that may be
-// made of this code.
-//
-//
-// based on previous work (FSF) done in the FIRST project
-//
-// Copyright (C) 2005 Mälardalen University, SWEDEN
-// Scuola Superiore S.Anna, ITALY
-// Universidad de Cantabria, SPAIN
-// University of York, UK
-//
-// FSF API web pages: http://marte.unican.es/fsf/docs
-// http://shark.sssup.it/contrib/first/docs/
-//
-// This file is part of FRSH Implementation
-//
-// 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"
-//==============================================
-
-#ifndef FRSH_SERVICE_TH_H_
-#define FRSH_SERVICE_TH_H_
-
-/*
- * frsh_service_th.h
- *
- * This file contains the types, functions, macro and constants
- * declaration exported in order of makeing the service thread
- * reachable and accessible from the other part of the API, and
- * so from the normal process and threads requesting its services.
- *
- * All API source file and/or module that need communication with the
- * service thread need to include this header.
- *
- * Note the service thread "sub-API" is quite frugal, since it's made up
- * of only one function ('frsh_service_th_ask_for()', plus
- * 'frsh_service_th_init()' only for initialization)
- */
-
-/*******************/
-/* I N C L U D E S */
-/*******************/
-
-#include "frsh_internal_msg.h"
-
-/*******************************************/
-/* C O N S T A N T S A N D M A C R O S */
-/*******************************************/
-
-/* some beautifying constants
- * (not sure this is the best place for them but...) */
-#define FRSH_NOT_VALID_THREAD_ID -1
-#define FRSH_NOT_VALID_VRES_ID -1
-#define FRSH_QRES_NOT_VALID_SID -1
-#define FRSH_QRES_BACKGROUND_SID -5
-
-#define FRSH_QRES_NOT_VALID_DISK -1
-#define FRSH_QRES_BACKGROUND_DISK -5
-
-/* service thread specific error codes and error handling */
-#define FRSH_SERVICE_TH_NO_ERROR 0
-
-#define FRSH_SERVICE_TH_ERR_BASE_VALUE 0x02040800
-
-#define FRSH_SERVICE_TH_ERR_SERVER 0x02040801
-#define FRSH_SERVICE_TH_ERR_SOCKET 0x02040802
-#define FRSH_SERVICE_TH_ERR_COMMAND 0x02040803
-#define FRSH_SERVICE_TH_ERR_LABEL 0x02040804
-
-#define FRSH_SERVICE_TH_ERR_LAST_VALUE 0x02040805
-
-#define check_service_th_error(x) \
- ( x != FRSH_SERVICE_TH_NO_ERROR && \
- ( x <= FRSH_SERVICE_TH_ERR_BASE_VALUE \
- || x >= FRSH_SERVICE_TH_ERR_LAST_VALUE) ? 0 : 1 )
-
-/***************************************/
-/* S E R V I C E T H R E A D A P I */
-/***************************************/
-
-/* service thread initialization */
-int frsh_service_th_init(pid_t *pid_key);
-
-/* request for some service to the service thread */
-int frsh_service_th_ask_for(const pid_t pid_key,
- const frsh_in_msg_t *msg_in,
- frsh_out_msg_t *msg_out);
-
-#endif /* FRSH_SERVICE_TH_H_ */
+++ /dev/null
-// -----------------------------------------------------------------------
-// Copyright (C) 2006 - 2007 FRESCOR consortium partners:
-//
-// Universidad de Cantabria, SPAIN
-// University of York, UK
-// Scuola Superiore Sant'Anna, ITALY
-// Kaiserslautern University, GERMANY
-// Univ. Politécnica Valencia, SPAIN
-// Czech Technical University in Prague, CZECH REPUBLIC
-// ENEA SWEDEN
-// Thales Communication S.A. FRANCE
-// Visual Tools S.A. SPAIN
-// Rapita Systems Ltd UK
-// Evidence ITALY
-//
-// See http://www.frescor.org for a link to partners' websites
-//
-// FRESCOR project (FP6/2005/IST/5-034026) is funded
-// in part by the European Union Sixth Framework Programme
-// The European Union is not liable of any use that may be
-// made of this code.
-//
-//
-// based on previous work (FSF) done in the FIRST project
-//
-// Copyright (C) 2005 Mälardalen University, SWEDEN
-// Scuola Superiore S.Anna, ITALY
-// Universidad de Cantabria, SPAIN
-// University of York, UK
-//
-// FSF API web pages: http://marte.unican.es/fsf/docs
-// http://shark.sssup.it/contrib/first/docs/
-//
-// This file is part of 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"
-//==============================================
-
-#ifndef FRSH_SERVICE_TH_TYPES_H_
-#define FRSH_SERVICE_TH_TYPES_H_
-
-/*
- * frsh_service_th_types.h
- *
- * This file contains the headers (types, function declarations, ...) for
- * the contract (re)negotiation service thread of the FRSH core API
- * implementation on top of AQuoSA framework
- */
-
-/*
- * declaration of service thread local data types, symbols and constants
- *
- * all the declared symbols and structures are visible only
- * opaque (visible only to the service thread) types and prototypes */
-
-/* Standard GNU/Linux include files */
-#include <linux/unistd.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <syslog.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <string.h>
-#include <math.h>
-#include <errno.h>
-
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined (FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- #include "assert.h"
-#endif
-
-/* FRSH files */
-#include "frsh.h"
-#include "fosa.h"
-#include "frsh_internal_msg.h"
-#include "timespec_usec_ops.h"
-
-/* AQuoSA files */
-#include <aquosa/qres_lib.h>
-#include <aquosa/qsup_lib.h>
-
-/* process configuration parameters and datas */
-
-/* pidfile and socket filename and filesystem positions */
-#define FRSH_SERVICE_TH_SOCKET_PATH "/var/local/run"
-#define FRSH_SERVICE_TH_SOCKET_NAME "frsh_service_th.socket"
-#define FRSH_SERVICE_TH_SOCKET FRSH_SERVICE_TH_SOCKET_PATH "/" FRSH_SERVICE_TH_SOCKET_NAME
-#define FRSH_SERVICE_TH_PIDFILE_PATH "/var/local/run"
-#define FRSH_SERVICE_TH_PIDFILE_NAME "frsh_service_th.pid"
-#define FRSH_SERVICE_TH_PIDFILE FRSH_SERVICE_TH_PIDFILE_PATH "/" FRSH_SERVICE_TH_PIDFILE_NAME
-
-/* HD handling data structures */
-
-#define IOPRIO_CLASS_IDLE 1
-#define IOPRIO_CLASS_BE 2
-#define IOPRIO_WHO_PROCESS 1
-#define IOPRIO_CLASS_SHIFT 13
-
-#define N_DISKS 4
-#define DISK_WEIGHT_MAX 100
-#define DISK_WEIGHT_PRIO_MAX 14
-#define DISK_DEFAULT_SCHED_BUDGET ( 256 * 512 )
-#define DISK_DEFAULT_AGGREGATE_BW ( 10 * 1024 * 1024 )
-
-typedef struct disk {
- unsigned int aggregate_bw;
- unsigned int sched_budget;
- unsigned int weight_sum;
- unsigned int thread_num;
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- frsh_mutex_t mutex;
-#endif
-} disk_t;
-
-/* HD handling macros */
-
-#define disk_id_2_index(id) \
- ( id )
-
-
-/* hash table types and datas */
-
-/* generic configuration constants */
-#define HASH_KEY_LENGTH FRSH_CONTRACT_LABEL_MAXLENGTH
-#define CHAR_PER_INT ( sizeof(int) / sizeof(char) )
-#define HASH_N_ELEMENTS 75
-/* return/error codes */
-#define HASH_NO_ERROR 0x00000000
-#define HASH_LABEL_FOUND HASH_NO_ERROR
-#define HASH_LABEL_NOT_FOUND HASH_NO_ERROR
-#define HASH_ERR_INTERNAL_ERROR 0x02040608
-#define HASH_ERR_LABEL_FOUND 0x02040609
-#define HASH_ERR_LABEL_NOT_FOUND 0x0204060A
-
-/* hash table element */
-typedef union {
- int vres_index; /* index of the associated vres in the vres table */
- qres_sid_t dummy_sid; /* sid of the dummy server (if the contract id of 'dummy' type) */
-} contract_hash_data_t;
-
-typedef struct contract_hash_entry {
- struct contract_hash_entry *next; /* linked list */
- char contract_label[HASH_KEY_LENGTH]; /* label, the hash key */
- contract_hash_data_t contract_data;
-} contract_hash_entry_t;
-
-typedef struct contract_hash_table {
- contract_hash_entry_t *table[HASH_N_ELEMENTS];
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- frsh_mutex_t mutex;
-#endif
-} contract_hash_table_t;
-
-/* thread and vres storage data structures and macros */
-
-/* registered thread repository element */
-typedef struct thread_repo_entry {
- frsh_thread_id_t thread; /* thread descriptor */
- frsh_vres_id_t vres; /* vres */
- int next_in_vres; /* next thread (if any!) bound to the same vres */
-} thread_repo_entry_t;
-
-typedef struct thread_repo {
- thread_repo_entry_t repo[FRSH_MAX_N_THREADS];
- int threads_number;
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- frsh_mutex_t mutex;
-#endif
-} thread_repo_t;
-
-/* negotiated vres repository element */
-
-typedef struct vres_processor_data {
- qres_sid_t sid;
- unsigned int threads_number;
- int first_thread_index;
-} vres_processor_data_t;
-
-typedef struct vres_disk_data {
- unsigned int weight;
- unsigned int ioprio_old;
- unsigned int ioprio;
-} vres_disk_data_t;
-
-typedef struct vres_repo_entry {
- frsh_contract_t contract;
- union {
- vres_processor_data_t processor;
- vres_disk_data_t disk;
- };
- /*qres_sid_t sid;
- unsigned int threads_number;
- int first_thread_index;*/
- frsh_renegotiation_status_t renegotiation_status;
-} vres_repo_entry_t;
-
-typedef struct vres_repo {
-/* NB. we use FRSH_MAX_N_VRES (first ones) element for CT_REGULAR vres and
- * FRSH_MAX_N_VRES (last ones) for CT_DUMMY vres */
- vres_repo_entry_t repo[2 * FRSH_MAX_N_VRES];
- int vres_number;
- int dummy_vres_number;
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- frsh_mutex_t mutex;
-#endif
-} vres_repo_t;
-
-/* translate from 'vres' and it's index in the repository of the
- * contracted ones (for cleanness, we don't want to break the opaqueness
- * of frsh_vres_id_t all around the code) */
-#define vres_id_2_index(id)\
- ( id )
-#define vres_index_2_id(ind) \
- ( ind )
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
-
-#define MAX_N_WORKER_THREAD FRSH_MAX_N_SERVICE_JOBS
-#define MIN_N_WORKER_THREAD 5
-
-typedef struct worker_thread_pool {
- int active_thread_number;
- int free_thread_number, busy_thread_number;
- frsh_mutex_t mutex;
- fosa_cond_t sleep;
-} worker_thread_pool_t;
-
-typedef struct request_entry {
- frsh_in_msg_t msg;
- int conn;
- int valid;
-} request_entry_t;
-
-typedef struct service_th_queue {
- request_entry_t queue[FRSH_MAX_N_SERVICE_JOBS];
- int first, last;
- int jobs_number;
- frsh_mutex_t mutex;
-} service_th_queue_t;
-
-#endif /* FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD */
-
-#endif /* FRSH_SERVICE_TH_TYPES_H_ */
+++ /dev/null
-
-
-/***********************************************************/
-/* H A S H T A B L E U T I L I T Y F U N C T I O N S */
-/***********************************************************/
-
-/*
- * initialize the table
- *
- * sets all pointers of the array table of the hash table to NULL
- * and init the mutex (if a multithreaded service thread has
- * been configured)
- *
- * possible return values:
- * true (all ok)
- * false (something wrong with the mutex)
- */
-static bool contract_hash_init()
-{
- int i;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- if (fosa_mutex_init(&contract_hash_table.mutex, 0) != 0)
- return false;
-#endif
- for (i = 0; i < HASH_N_ELEMENTS; i++)
- contract_hash_table.table[i] = NULL;
-
- return true;
-}
-
-/*
- * hash function
- *
- * obtains the hash (int) value associated to the (string) key provided
- * simply accessing each character as an integer value and summing them all
- *
- * always returns the hash value (no room for errors!)
- */
-static unsigned int contract_hash_hash(const char *key_str)
-{
- int i, step = CHAR_PER_INT;
- unsigned int hash = 0;
- unsigned int key_val = 0;
- char *key_val_ptr = (char*) &key_val;
-
- for (i = 0; i < strlen(key_str); i += step) {
- strncpy(key_val_ptr, (key_str + i), step);
- hash += key_val;
- }
-
- return hash % HASH_N_ELEMENTS;
-}
-
-/*
- * search an element
- *
- * calculates the hash value, accesses the hash table element and
- * follows the linked list if needed
- * data_ptr can be used to access/modify the element data field
- *
- * possible return values:
- * HASH_LABEL_FOUND
- * HASH_ERR_LABEL_NOT_FOUND
- */
-static int contract_hash_find(const char *key, contract_hash_data_t **data_ptr)
-{
- contract_hash_entry_t *curr_entry;
- unsigned int hash_value;
- int result;
-
- /* hash value of the the key */
- hash_value = contract_hash_hash(key);
-#ifdef frsh_enable_service_th_multithread
- /* lock the table */
- fosa_mutex_lock(&contract_hash_table.mutex);
-#endif
- /* start traversing the linked list (if needed) */
- curr_entry = contract_hash_table.table[hash_value];
- while (curr_entry != NULL) {
- if (strncmp(key, curr_entry->contract_label, HASH_KEY_LENGTH) == 0) {
- /* key found! */
- *data_ptr = &(curr_entry->contract_data);
- result = HASH_LABEL_FOUND;
- break;
- }
- /* not found yet, let's try the next element */
- curr_entry = curr_entry->next;
- }
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the table */
- fosa_mutex_unlock(&contract_hash_table.mutex);
-#endif
-
- return result;
-}
-
-/*
- * add an element
- *
- * calculates the hash function and adds the new element at the end
- * of the linked list of the hash table entry, unless one with the same
- * key value already exists
- * data_ptr can be used to access/modify the element data field
- *
- * possible return values:
- * HASH_NO_ERROR
- * HASH_ERR_LABEL_FOUND
- */
-static int contract_hash_add(const char *key, contract_hash_data_t **data_ptr)
-{
- contract_hash_entry_t *new_entry, **curr_entry;
- unsigned int hash_value;
- int result;
-
- /* hash value of the key */
- hash_value = contract_hash_hash(key);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* lock the table */
- fosa_mutex_lock(&contract_hash_table.mutex);
-#endif
- /* traverse the linked list till the end
- * (stop if the key already exists) */
- curr_entry = &contract_hash_table.table[hash_value];
- result = HASH_NO_ERROR;
- while (*curr_entry != NULL) {
- if (strncmp(key, (*curr_entry)->contract_label, HASH_KEY_LENGTH) == 0) {
- result = HASH_ERR_LABEL_FOUND;
- break;
- }
- curr_entry = &(*curr_entry)->next;
- }
- if (result == HASH_NO_ERROR) {
- /* create the new element */
- new_entry = (contract_hash_entry_t*) malloc(sizeof(contract_hash_entry_t));
- strncpy(new_entry->contract_label, key, HASH_KEY_LENGTH);
- /* add it (we're already at the end of the linked list) */
- *data_ptr = &(new_entry->contract_data);
- *curr_entry = new_entry;
- new_entry->next = NULL;
- }
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the table */
- fosa_mutex_unlock(&contract_hash_table.mutex);
-#endif
-
- return result;
-}
-
-/*
- * remove an element
- *
- * calculates the hash function, searches the element in the linked
- * list and remove it
- *
- * possible return values:
- * HASH_NO_ERROR
- * HASH_ERR_LABEL_NOT_FOUND
- */
-static int contract_hash_del(const char *key)
-{
- contract_hash_entry_t *curr_entry, *curr_entry_prev;
- unsigned int hash_value;
- int result;
-
- /* hash value of the key */
- hash_value = contract_hash_hash(key);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* lock the table */
- fosa_mutex_lock(&contract_hash_table.mutex);
-#endif
- /* traverse the list searching for the key */
- curr_entry_prev = NULL;
- curr_entry = contract_hash_table.table[hash_value];
- result = HASH_ERR_LABEL_NOT_FOUND;
- while (curr_entry != NULL) {
- if (strncmp(key, curr_entry->contract_label, HASH_KEY_LENGTH) == 0) {
- /* update the list and remove the element */
- if (curr_entry_prev == NULL)
- contract_hash_table.table[hash_value] = curr_entry->next;
- else
- curr_entry_prev->next = curr_entry->next;
- free((void*) curr_entry);
- result = HASH_NO_ERROR;
- break;
- }
- curr_entry_prev = curr_entry;
- curr_entry = curr_entry->next;
- }
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the table */
- fosa_mutex_unlock(&contract_hash_table.mutex);
-#endif
-
- return result;
-}
+++ /dev/null
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
-/***************************************************************************************************/
-/* W O R K E R T H R E A D S I N I T I A L I Z A T I O N A N D M A I N F U N C T I O N S */
-/***************************************************************************************************/
-
-/*
- * access functions to worker thread pool
- */
-
-/* gives the actual number of active threads in the pool */
-#define get_active_thread_number() \
- ( worker_pool.active_thread_number )
-/* gives the actual number of busy threads in the pool */
-#define get_busy_thread_number() \
- ( worker_pool.busy_thread_number )
-/* gives the actual number of sleeping threads in the pool */
-#define get_sleeping_thread_number() \
- ( worker_pool.active_thread_number - worker_pool.busy_thread_number )
-
-/*
- * FRSH utility function prototypes
- *
- * declared here to be visible to the worker thread code, see each definition
- * (below in the code) for specific infos about each one
- */
-static int negotiate_contract(const frsh_contract_t *contract, frsh_vres_id_t *vres);
-
-static int bind_thread(const frsh_thread_id_t *thread,const frsh_vres_id_t vres_id);
-
-static int unbind_thread(const frsh_thread_id_t *thread);
-
-static int get_thread_vres_id(const frsh_thread_id_t *thread, frsh_vres_id_t *vres);
-
-static int get_contract(const frsh_vres_id_t vres_id, frsh_contract_t *contract);
-
-static int get_label_vres_id(const frsh_contract_label_t contract_label,frsh_vres_id_t *vres);
-
-static int cancel_contract(const frsh_vres_id_t vres);
-
-static int renegotiate_contract(const frsh_contract_t *new_contract, const frsh_vres_id_t vres_id);
-
-static int get_renegotiation_status(const frsh_vres_id_t vres_id,frsh_renegotiation_status_t *renegotiation_status);
-
-static int negotiate_group(int vres_down_number, frsh_vres_id_t vres_down[], int vres_down_status[],
- int contracts_up_number, frsh_contract_t contract_up[], frsh_vres_id_t vres_up[], int contracts_up_status[]);
-
-static int change_mode(int vres_down_number, frsh_vres_id_t vres_down[], int vres_down_status[],
- int contracts_touch_number, frsh_contract_t contracts_touch[], frsh_vres_id_t vres_touch[], int vres_touch_status[],
- int contracts_up_number, frsh_contract_t contracts_up[], frsh_vres_id_t vres_up[], int contracts_up_status[]);
-
-static int get_cputime(const frsh_vres_id_t vres_id, struct timespec *cputime);
-
-static int get_current_budget(const frsh_vres_id_t vres_id, struct timespec *current_budget);
-
-static int get_budget_and_period(const frsh_vres_id_t vres_id,struct timespec *budget,struct timespec *period);
-
-static int reserve_feedback(frsh_contract_t *spare_contract);
-
-#endif
+++ /dev/null
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
-static service_th_queue_t service_th_queue; /* job (form clients) queueing for multithreaded implementation */
-#endif
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
-
-/***********************************************************************************************/
-/* S E R V I C E T H R E A D R E Q U E S T Q U E U E U T I L I T Y F U N C T I O N S */
-/***********************************************************************************************/
-
-/*
- * access functions to service thread jobs queue
- */
-
-/* gives the actual number of queued jobs */
-#define get_queued_jobs_number() \
- ( service_th_queue.jobs_number )
-
-/*
- * consistency and status checks
- *
- * common used checkings and tests about the accesses to the queue (is the
- * index value in the correct range?), the status of each entry (is it free?,
- * non-free?) and of the whole queue (is it full?, is it empty?)
- */
-
-/* are we accessing the queue with a valid index value ? */
-#define check_service_th_queue_ind(ind) \
- ( (ind >=0 && ind < FRSH_MAX_N_SERVICE_JOBS) ? true : false )
-/* is the queue element (correctly accessed and) free ? */
-#define check_service_th_queue_isfree(ind) \
- ( ((check_service_th_queue(ind) && service_th_queue.queue[ind].valid == 1) ? true : false )
-/* is the queue element (correctly accessed and) non free ? */
-#define check_service_th_queue_nonfree(ind) \
- ( (check_service_th_queue(ind) && service_th_queue.queue[ind].valid == 0) ? true : false )
-/* is the queue still empty ? */
-#define check_service_th_queue_empty() \
- ( (service_th_queue.jobs_number == 0) ? true : false )
-/* is the queue already full ? */
-#define check_service_th_queue_full() \
- ( (service_th_queue.jobs_number >= FRSH_MAX_N_SERVICE_JOBS) ? true: false )
-
-/*
- * initialize the queue
- *
- * sets all elements to free and init the mutex
- *
- * possible return values:
- * true (all ok)
- * false (something wrong with the mutex)
- */
-static inline bool service_th_queue_init()
-{
- int i;
-
- service_th_queue.jobs_number = 0;
- service_th_queue.first = service_th_queue.last = 0;
- if (fosa_mutex_init(&service_th_queue.mutex, 0))
- return false;
- for (i = 0; i < FRSH_MAX_N_SERVICE_JOBS; i++) {
- service_th_queue.queue[i].conn = 0;
- service_th_queue.queue[i].valid = 0;
- }
-
- return true;
-}
-
-/*
- * add an element into the queue
- *
- * if possible (there is enough free space) adds a new element into the queue
- * according to the FIFO policy (so the new element it's inserted after the
- * actual last one).
- * Note all is done while holding an atomic lock on the whole queue
- *
- * possible return values:
- * true (all ok, element added)
- * false (element not added, no more room in the queue!)
- */
-static bool enqueue_service_th_request(int conn, frsh_in_msg_t *request)
-{
- int last;
-
- /* lock the queue */
- fosa_mutex_lock(&service_th_queue.mutex);
- if (check_service_th_queue_full()) {
- fosa_mutex_unlock(&service_th_queue.mutex);
- return false;
- }
- last = service_th_queue.last;
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined(FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- /* if we need to be sure the choosen element is really free... */
- assert(service_th_queue.queue[last].valid == 0);
-#endif
- /* fill the new element with provided data and mark it as no longer free */
- service_th_queue.queue[last].msg = *request;
- service_th_queue.queue[last].conn = conn;
- service_th_queue.queue[last].valid = 1;
- /* update queue (last) pointer and counter */
- service_th_queue.last = (service_th_queue.last + 1) % FRSH_MAX_N_SERVICE_JOBS;
- service_th_queue.jobs_number++;
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined(FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- /* if we need to be sure there was at least a free element in the queue... */
- assert(service_th_queue.jobs_number > 0 && service_th_queue.jobs_number <= FRSH_MAX_N_SERVICE_JOBS);
-#endif
- /* unlock the queue */
- fosa_mutex_unlock(&service_th_queue.mutex);
-
- return true;
-}
-
-/*
- * remove an element from the queue
- *
- * if possible (there is at least one element) remove an (the first, FIFO
- * policy) element from the queue.
- * Note all is done while holding an atomic lock on the whole queue
- *
- * possible return values:
- * true (all ok, element added)
- * false (element not added, no more room in the queue!)
- */
-static bool dequeue_service_th_request(int *conn, frsh_in_msg_t *request)
-{
- int first;
-
- /* lock the queue */
- fosa_mutex_lock(&service_th_queue.mutex);
- if (check_service_th_queue_empty()) {
- fosa_mutex_unlock(&service_th_queue.mutex);
- return false;
- }
- first = service_th_queue.first;
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined(FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- /* if we need to be sure the element is really not free... */
- assert(service_th_queue.queue[first].valid == 1);
-#endif
- /* provide the user for the element datas and mark it as again free */
- *request = service_th_queue.queue[first].msg;
- *conn = service_th_queue.queue[first].conn;
- service_th_queue.queue[first].valid = 0;
- /* update queue (first) pointer and counter */
- service_th_queue.first = (service_th_queue.first + 1) % FRSH_MAX_N_SERVICE_JOBS;
- service_th_queue.jobs_number--;
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined(FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- /* if we need to be sure there was at least one element in the queue... */
- assert(service_th_queue.jobs_number >= 0 && service_th_queue.jobs_number <= FRSH_MAX_N_SERVICE_JOBS);
- /* if we need to be sure the pointers have always been correctly updated... */
- if (!check_service_th_queue_empty())
- assert(service_th_queue.first != service_th_queue.last);
- else
- assert(service_th_queue.first == service_th_queue.last);
-#endif
- /* unlock the queue */
- fosa_mutex_unlock(&service_th_queue.mutex);
-
- return true;
-}
-#endif
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
-
+++ /dev/null
-static thread_repo_t thread_repo; /* registered thread repository */
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
-static worker_thread_pool_t worker_pool; /* thread pool for multithreaded implementation */
-#endif
-
-/***************************************************************************/
-/* T H R E A D S R E P O S I T O R Y U T I L I T Y F U N C T I O N S */
-/***************************************************************************/
-
-/*
- * access functions to thread repository
- *
- * some simple subsitutions macro which help keep thread_repo_t opaque and
- * improve code cleanness and look & feel
- */
-
-/* given the index of a registered thread in the repository returns
- * a pointer to its entry () */
-#define get_thread_entry(thread_ind) \
- ( & ( thread_repo.repo[(thread_ind)] ) )
-/* gives the actual number of threads in the repository */
-#define get_threads_number() \
- ( thread_repo.threads_number )
-
-/*
- * consistency and status checks
- *
- * common used checkings and tests about the access to the thread repository
- * (is the index value in the correct range?) and the status of each entry
- * (is it free?, non-free?, equal to an external one?, ecc.)
- */
-
-/* are we accessing the repository with a valid index value ? */
-#define check_thread_repo_ind(ind) \
- ( ( ind >= 0 && ind < FRSH_MAX_N_THREADS ) ? true : false )
-/* is the thread repository entry (correctly accessed and) free ? */
-#define check_thread_repo_entry_free(ind) \
- ( ( ( check_thread_repo_ind(ind) ) && \
- thread_repo.repo[(ind)].thread.pthread_id == FRSH_NOT_VALID_THREAD_ID && \
- thread_repo.repo[(ind)].thread.linux_pid == FRSH_NOT_VALID_THREAD_ID && \
- thread_repo.repo[(ind)].thread.linux_tid == FRSH_NOT_VALID_THREAD_ID ) ? true : false )
-/* is the thread repository entry (correctly accessed and) non free ? */
-#define check_thread_repo_entry_nonfree(ind) \
- ( ( ( check_thread_repo_ind(ind) ) && \
- thread_repo.repo[(ind)].thread.pthread_id != FRSH_NOT_VALID_THREAD_ID && \
- thread_repo.repo[(ind)].thread.linux_pid != FRSH_NOT_VALID_THREAD_ID && \
- thread_repo.repo[(ind)].thread.linux_tid != FRSH_NOT_VALID_THREAD_ID ) ? true : false )
-/* does the thread repository entry contain a thread equal to the one provided ? */
-#define check_thread_repo_entry_equal(th, th_ind) \
- ( ( ( check_thread_repo_ind(th_ind) ) && \
- ( thread_repo.repo[(th_ind)].thread.pthread_id == (th).pthread_id ) && \
- ( thread_repo.repo[(th_ind)].thread.linux_pid == (th).linux_pid ) && \
- ( thread_repo.repo[(th_ind)].thread.linux_tid == (th).linux_tid ) ) ? true : false ) \
-
-/*
- * initialize the repository
- *
- * sets all entries to invalid (that is, free) and init the mutex
- * (if a multithreaded service thread has been configured)
- *
- * possible return values:
- * true (all ok)
- * false (something wrong with the mutex)
- */
-static inline bool thread_repo_init()
-{
- int i;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- if (fosa_mutex_init(&thread_repo.mutex, 0) != 0)
- return false;
-#endif
- thread_repo.threads_number = 0;
- for (i = 0; i < FRSH_MAX_N_THREADS; i++) {
- thread_repo.repo[i].thread.pthread_id = FRSH_NOT_VALID_THREAD_ID;
- thread_repo.repo[i].thread.linux_pid = FRSH_NOT_VALID_THREAD_ID;
- thread_repo.repo[i].thread.linux_tid = FRSH_NOT_VALID_THREAD_ID;
- thread_repo.repo[i].vres = FRSH_NOT_VALID_VRES_ID;
- thread_repo.repo[i].next_in_vres = -1; /* no other thread in vres */
- }
-
- return true;
-}
-
-/*
- * add an entry
- *
- * adds an entry into the repository. If successful the index of the entry is
- * returned in thread_ind.
- *
- * We "accept suggestions", i.e. we suppose the caller knows the location of
- * a free entry in the repository and ask us to insert the new entry exactly
- * there, at thread_ind position.
- * So we check if that location is really free and, if yes, we can add the
- * entry right there. If, on the other way, the entry is not free we need to
- * search the repository for a different place.
- *
- * Note we also keep updated the repository entry (see below) of the vres the
- * thread is bound to.
- *
- * possible return values:
- * true (entry correctly added)
- * false (entry not added, maybe no more room in the repository!)
- */
-static bool thread_repo_put(const frsh_thread_id_t *thread,
- const frsh_vres_id_t vres_id,
- int *thread_ind)
-{
- int i;
- bool result;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* lock the repository */
- fosa_mutex_lock(&thread_repo.mutex);
-#endif
- /* try to place the new entry in the caller provided position (if any)
- * and, only if it's not free, scan all the repository for
- * a different and suitable place */
- if (thread_ind != NULL &&
- check_thread_repo_entry_free(*thread_ind % FRSH_MAX_N_THREADS))
- i = *thread_ind % FRSH_MAX_N_THREADS;
- else {
- i = 0;
- while (i < FRSH_MAX_N_THREADS && !check_thread_repo_entry_free(i))
- i++;
- }
- /* if we're sure it's valid and free we place the
- * thread entry into the repository in position 'i' */
- result = false;
- if (check_thread_repo_entry_free(i)) {
- /* update the provided vres repository entry */
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* we need to lock the vres repository too */
- fosa_mutex_lock(&vres_repo.mutex);
-#endif
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined(FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- assert(FRSH_HIERARCHICAL_MODULE_SUPPORTED ||
- get_vres_entry(vres_id)->processor.threads_number == 0);
-#endif
- get_vres_entry(vres_id)->processor.threads_number++;
- /* keep updated the chain of thread of the vres repository entry */
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined(FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- assert(FRSH_HIERARCHICAL_MODULE_SUPPORTED ||
- get_vres_entry(vres_id)->processor.first_thread_index == -1);
-#endif
- thread_repo.repo[i].next_in_vres = get_vres_entry(vres_id)->processor.first_thread_index;
- get_vres_entry(vres_id)->processor.first_thread_index = i;
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the vres repository */
- fosa_mutex_unlock(&vres_repo.mutex);
-#endif
- thread_repo.repo[i].thread = *thread;
- thread_repo.repo[i].vres = vres_id;
- if (thread_ind != NULL)
- *thread_ind = i;
- thread_repo.threads_number++;
- result = true;
- }
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the repository */
- fosa_mutex_unlock(&thread_repo.mutex);
-#endif
-
- return result;
-}
-
-/*
- * remove an entry
- *
- * sets the entry as free (if it is not) and decrement the thread count.
- *
- * Note we also keep updated the repository entry (see below) of the vres the
- * thread is bound to.
- *
- * possible return values:
- * true (all ok, entry war non-free and is now free)
- * false (something wrong, entry was already free or index is out of renge)
- */
-static bool thread_repo_free(const int thread_ind)
-{
- vres_repo_entry_t *thread_vres;
- thread_repo_entry_t *thread_p;
- bool result;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* lock the repository */
- fosa_mutex_lock(&thread_repo.mutex);
-#endif
- result = false;
- if (check_thread_repo_entry_nonfree(thread_ind)) {
- thread_p = &thread_repo.repo[thread_ind];
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined(FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- assert(!vres_repo_isfree(vres_id_2_index(thread_p->vres)));
-#endif
- thread_vres = get_vres_entry(thread_p->vres);
- /* update the bound vres repository entry */
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* we need to lock the vres repository too */
- fosa_mutex_lock(&vres_repo.mutex);
-#endif
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined(FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- assert(FRSH_HIERARCHICAL_MODULE_SUPPORTED ||
- get_vres_entry(thread_p->vres)->processor.threads_number == 1);
-#endif
- thread_vres->processor.threads_number--;
- /* keep the chain of thread in the vres updated */
- if (thread_vres->processor.first_thread_index == thread_ind)
- thread_vres->processor.first_thread_index = thread_p->next_in_vres;
- else
- while (thread_p->next_in_vres != thread_ind)
- thread_p = &thread_repo.repo[thread_p->next_in_vres];
- thread_p->next_in_vres = thread_repo.repo[thread_ind].next_in_vres;
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the vres repository */
- fosa_mutex_unlock(&vres_repo.mutex);
-#endif
- /* set the repository entry as free */
- thread_repo.repo[thread_ind].thread.pthread_id = FRSH_NOT_VALID_THREAD_ID;
- thread_repo.repo[thread_ind].thread.linux_pid = FRSH_NOT_VALID_THREAD_ID;
- thread_repo.repo[thread_ind].thread.linux_tid = FRSH_NOT_VALID_THREAD_ID;
- thread_repo.repo[thread_ind].vres = FRSH_NOT_VALID_VRES_ID;
- thread_repo.repo[thread_ind].next_in_vres = -1;
- thread_repo.threads_number--;
- result = true;
- }
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the repository */
- fosa_mutex_unlock(&thread_repo.mutex);
-#endif
-
- return result;
-}
-
-/*
- * is an entry free ?
- *
- * check if a specific entry of the repository can be considered free.
- * The needed check is very simple and reduces itself to one of the
- * test macro define d above... Note if a multithreaded service thread is
- * configured we do it with an atomic lock
- *
- * possible return values:
- * true (entry is free)
- * false (entry is not free or index is out of range)
- */
-static bool thread_repo_isfree(const int thread_ind)
-{
- bool result;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* lock the repository */
- fosa_mutex_lock(&thread_repo.mutex);
-#endif
- result = check_thread_repo_entry_free(thread_ind);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the repository */
- fosa_mutex_unlock(&thread_repo.mutex);
-#endif
- return result;
-}
-
-/*
- * search for an entry
- *
- * tries to find an entry in the repository containing a the thread descriptor
- * provided as (first) argument. If successful the index of the entry is
- * returned in thread_ind.
- *
- * We "accept suggestions" (as in the entry add function), i.e. we suppose the
- * caller knows the entry he's searching for is in the repository and its
- * index is exactly thread_ind, so we check if this is true and, if yes,
- * we're done! If, on the other way, we can't find the searched entry at
- * thread_ind position we start a complete scan of the repository
- *
- * possible return values:
- * true (entry found)
- * false (entry not found)
- */
-static bool thread_repo_find(const frsh_thread_id_t *thread, int *thread_ind)
-{
- int i;
- bool result;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* lock the repository */
- fosa_mutex_lock(&thread_repo.mutex);
-#endif
- /* check if the caller provides us (we hope _intentionally_!) the
- * correct position in the repository of the entry he's searching */
- if (thread_ind != NULL &&
- check_thread_repo_entry_equal(*thread, (*thread_ind) % FRSH_MAX_N_THREADS))
- /* if yes we've finished our search before starting it! */
- i = (*thread_ind) % FRSH_MAX_N_THREADS;
- else {
- /* if no we scan the repository till we find the entry (or till its end) */
- i = 0;
- while (i < FRSH_MAX_N_THREADS && !check_thread_repo_entry_equal(*thread, i))
- i++;
- }
- /* check again and definitively decide the entry is in the repository or not */
- result = false;
- if (check_thread_repo_entry_equal(*thread, i)) {
- if (thread_ind != NULL)
- *thread_ind = i;
- result = true;
- }
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the repository */
- fosa_mutex_unlock(&thread_repo.mutex);
-#endif
-
- return result;
-}
-
-/*
- * thread pool initialization
- *
- * initialize the worker thread pool (a couple of counters, a mutex and a
- * condition variable) and create the minimum number of worker thread
- * configured
- *
- * possible return values:
- * true (all ok, pool initialized and all thread created)
- * false (something wrong in mutex or condition initialization or in thread creation)
- */
-
-static void* worker_thread_code();
-
-static inline bool worker_thread_pool_init()
-{
- int i;
- frsh_thread_id_t new_thread;
-
- worker_pool.active_thread_number = 0;
- worker_pool.busy_thread_number = 0;
- if (fosa_mutex_init(&worker_pool.mutex, 0) != 0)
- return false;
- if (fosa_cond_init(&worker_pool.sleep) != 0)
- return false;
- for (i = 0; i < MIN_N_WORKER_THREAD; i++)
- if (fosa_thread_create(&new_thread, NULL, worker_thread_code, NULL) != 0)
- return false;
-
- return true;
-}
-
-/*
- * worker thread code
- *
- * code executed by all the worker thread activated by the service thread to
- * effectively serve the client(s) requests.
- * Basically we check if there are queued requests and if the service thread
- * is useful or, if not, it has to die.
- * If "in service" a worker thread processes a request from a client and sends
- * back the results (if requested) then check again if it's time to sleep or
- * to die!
- *
- * possible exit status:
- * EXIT_SUCCESS (normal exit, the thread is no longer usefull)
- * EXIT_FAILURE (abnormal exit, something has gone severely wrong!)
- */
-static void* worker_thread_code(void *p)
-{
- frsh_in_msg_t request;
- frsh_out_msg_t reply;
- int conn;
- frsh_thread_id_t thread_self;
-
- /* lock the pool and say everyone we're a new
- * living (active) and working (busy) thread */
- fosa_mutex_lock(&worker_pool.mutex);
- worker_pool.active_thread_number++;
- worker_pool.busy_thread_number++;
- /* done, unlock the pool */
- fosa_mutex_unlock(&worker_pool.mutex);
- thread_self = fosa_thread_self();
- /* directly attach ourself to the service contract vres
- * (no need fo negotiation or any other FRSH operation!)*/
- if (qres_attach_thread(get_vres_entry(service_th_vres_id)->processor.sid,
- thread_self.linux_pid,
- thread_self.linux_tid) != QOS_OK) {
- syslog(LOG_ERR, "can't attach the worker thread to the vres");
-
- return (void*)EXIT_FAILURE;
- }
- /* main worker thread cycle */
- while (1) {
- /* check if there are new requests to serve */
- while (!dequeue_service_th_request(&conn, &request)) {
- fosa_mutex_lock(&worker_pool.mutex);
- /* sleeping or exiting depends on how many worker
- * thread the system has been configured to keep alive */
- if (worker_pool.active_thread_number <= MIN_N_WORKER_THREAD) {
- /* we're still alive, we only go to sleep */
- worker_pool.busy_thread_number--;
- fosa_cond_wait(&worker_pool.sleep, &worker_pool.mutex);
- /* the service thread wake up us,
- * go and check again for queued requests */
- worker_pool.busy_thread_number++;
- fosa_mutex_unlock(&worker_pool.mutex);
- } else {
- /* our work is no longer needed, we're dying! */
- worker_pool.busy_thread_number--;
- worker_pool.active_thread_number--;
- fosa_mutex_unlock(&worker_pool.mutex);
- if (qres_detach_thread(get_vres_entry(service_th_vres_id)->processor.sid,
- thread_self.linux_pid,
- thread_self.linux_tid) != QOS_OK) {
- syslog(LOG_ERR, "can't detach the worker thread from the vres");
-
- return (void*)EXIT_FAILURE;
- }
-
- return (void*)EXIT_SUCCESS;
- }
- }
- switch (request.type) {
- /* process client(s) requests according to the operation and
- * (simply?) colling one (or a little more) of the FRSH utility
- * function defined down in the code */
- case FRSH_MT_NEGOTIATE_CONTRACT:
- {
- syslog(LOG_DEBUG, "operation requested: NEGOTIATE_CONTRACT");
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_lock(&contract_mutex);
-#endif
- reply.error = negotiate_contract(&request.val.negotiate_contract.contract,
- &reply.val.negotiate_contract.vres_id);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&contract_mutex);
-#endif
- goto answer_and_close;
- }
- case FRSH_MT_BIND_THREAD:
- {
- syslog(LOG_DEBUG, "operation requested: BIND_THREAD");
- reply.error = bind_thread(&request.val.bind_thread.thread_id,
- request.val.bind_thread.vres_id);
- goto answer_and_close;
- }
- case FRSH_MT_UNBIND_THREAD:
- {
- syslog(LOG_DEBUG, "operation requested: UNBIND_THREAD");
- reply.error = unbind_thread(&request.val.unbind_thread.thread_id);
- goto answer_and_close;
- }
- case FRSH_MT_GET_THREAD_VRES_ID:
- {
- syslog(LOG_DEBUG, "operation requested: GET_THREAD_VRES_ID");
- reply.error = get_thread_vres_id(&request.val.get_thread_vres_id.thread_id,
- &reply.val.get_thread_vres_id.vres_id);
- goto answer_and_close;
- }
- case FRSH_MT_GET_CONTRACT:
- {
- syslog(LOG_DEBUG, "operation requested: GET_CONTRACT");
- reply.error = get_contract(request.val.get_contract.vres_id,
- &reply.val.get_contract.contract);
- goto answer_and_close;
- }
- case FRSH_MT_GET_LABEL_VRES_ID:
- {
- syslog(LOG_DEBUG, "operation requested: GET_LABEL_VRES_ID");
- reply.error = get_label_vres_id(request.val.get_label_vres_id.contract_label,
- &reply.val.get_label_vres_id.vres_id);
- goto answer_and_close;
- }
- case FRSH_MT_CANCEL_CONTRACT:
- {
- syslog(LOG_DEBUG, "operation requested: CANCEL_CONTRACT");
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_lock(&contract_mutex);
-#endif
- reply.error = cancel_contract(request.val.cancel_contract.vres_id);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&contract_mutex);
-#endif
- goto answer_and_close;
- }
- case FRSH_MT_RENEGOTIATE_CONTRACT:
- {
- syslog(LOG_DEBUG, "operation requested: RENEGOTIATE_CONTRACT");
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_lock(&contract_mutex);
-#endif
- reply.error =
- renegotiate_contract(&request.val.renegotiate_contract.new_contract,
- request.val.renegotiate_contract.vres_id);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&contract_mutex);
-#endif
- goto answer_and_close;
- }
- case FRSH_MT_REQUEST_CONTRACT_RENEGOTIATION:
- {
- syslog(LOG_DEBUG, "operation requested: REQUEST_CONTRACT_RENEGOTIATION");
- close(conn);
- syslog(LOG_DEBUG, "aync. operation, do not wait for completion");
- syslog(LOG_INFO, "connection closed");
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_lock(&contract_mutex);
-#endif
- reply.error =
- renegotiate_contract(&request.val.request_contract_renegotiation.new_contract,
- request.val.request_contract_renegotiation.vres_id);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&contract_mutex);
-#endif
-#ifdef FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE
- /* signals the completion of the operation with a signal */
- if (request.val.request_contract_renegotiation.signal != FRSH_NULL_SIGNAL)
- if (fosa_signal_queue(request.val.request_contract_renegotiation.signal,
- request.val.request_contract_renegotiation.siginfo,
- request.val.request_contract_renegotiation.thread_to_signal) != 0)
- syslog(LOG_ERR,
- "can't signal process %d with signal %d to notify the completion of the renegotiation",
- request.val.request_contract_renegotiation.thread_to_signal.linux_pid,
- request.val.request_contract_renegotiation.signal);
-#endif
- goto end_cycle;
- }
- case FRSH_MT_GET_RENEGOTIATION_STATUS:
- {
- syslog(LOG_DEBUG, "operation requested: GET_RENEGOTIATION_STATUS");
- reply.error = get_renegotiation_status(request.val.get_renegotiation_status.vres_id,
- &reply.val.get_renegotiation_status.renegotiation_status);
- goto answer_and_close;
- }
- case FRSH_MT_NEGOTIATE_GROUP:
- {
- syslog(LOG_DEBUG, "operation requested: NEGOTIATE_GROUP");
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_lock(&contract_mutex);
-#endif
- reply.error =
- negotiate_group(request.val.negotiate_group.vres_down_number,
- request.val.negotiate_group.vres_down,
- reply.val.negotiate_group.vres_down_status,
- request.val.negotiate_group.contracts_up_number,
- request.val.negotiate_group.contracts_up,
- reply.val.negotiate_group.vres_up,
- reply.val.negotiate_group.contracts_up_status);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&contract_mutex);
-#endif
-
- //reply.error = FRSH_NO_ERROR;
- //for (i = 0; i < request.val.negotiate_group.vres_down_number; i++)
- // reply.error = reply.val.negotiate_group.vres_down_status[i] =
- // cancel_contract(request.val.negotiate_group.vres_down[i]);
- //for (i = 0; i < request.val.negotiate_group.contracts_up_number; i++)
- // reply.error = reply.val.negotiate_group.contracts_up_status[i] =
- // negotiate_contract(&request.val.negotiate_group.contracts_up[i],
- // &reply.val.negotiate_group.vres_up[i]);
-
- goto answer_and_close;
- }
- case FRSH_MT_CHANGE_MODE_SYNC:
- case FRSH_MT_CHANGE_MODE_ASYNC:
- {
- syslog(LOG_DEBUG, "operation requested: NEGOTIATE_GROUP");
- reply.error = FRSH_NO_ERROR;
- if (request.type == FRSH_MT_CHANGE_MODE_ASYNC) {
- close(conn);
- syslog(LOG_DEBUG, "aync. operation, do not wait for completion");
- syslog(LOG_INFO, "connection closed");
-
- }
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_lock(&contract_mutex);
-#endif
- reply.error =
- change_mode(request.val.change_mode.vres_down_number,
- request.val.change_mode.vres_down,
- reply.val.change_mode.vres_down_status,
- request.val.change_mode.contracts_touch_number,
- request.val.change_mode.contracts_touch,
- request.val.change_mode.vres_touch,
- reply.val.change_mode.vres_touch_status,
- request.val.change_mode.contracts_up_number,
- request.val.change_mode.contracts_up,
- reply.val.change_mode.vres_up,
- reply.val.change_mode.contracts_up_status);
-
- //for (i = 0; i < request.val.change_mode.vres_down_number; i++)
- // reply.error = reply.val.change_mode.vres_down_status[i] =
- // cancel_contract(request.val.change_mode.vres_down[i]);
- //for (i = 0; i < request.val.change_mode.contracts_touch_number; i++)
- // reply.error = reply.val.change_mode.vres_touch_status[i] =
- // renegotiate_contract(&request.val.change_mode.contracts_touch[i],
- // request.val.change_mode.vres_touch[i]);
- //for (i = 0; i < request.val.change_mode.contracts_up_number; i++)
- // reply.error = reply.val.change_mode.contracts_up_status[i] =
- // negotiate_contract(&request.val.change_mode.contracts_up[i],
- // &reply.val.change_mode.vres_up[i]);
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&contract_mutex);
-#endif
-#ifdef FRSH_CONFIG_SERVICE_TH_LOCAL_MACHINE
- /* signals the completion of the operation with a signal */
- if (request.val.change_mode.signal != FRSH_NULL_SIGNAL)
- if (fosa_signal_queue(request.val.change_mode.signal,
- request.val.change_mode.siginfo,
- request.val.change_mode.thread_to_signal) != 0)
- syslog(LOG_ERR,
- "can't signal process %d with signal %d to notify the completion of the renegotiation",
- request.val.change_mode.thread_to_signal.linux_pid,
- request.val.change_mode.signal);
-#endif
- if (request.type == FRSH_MT_CHANGE_MODE_SYNC)
- goto answer_and_close;
- else
- goto end_cycle;
- }
- case FRSH_MT_GET_CPUTIME:
- {
- syslog(LOG_DEBUG, "operation requested: GET_CPUTIME");
- reply.error = get_cputime(request.val.get_cputime.vres_id,
- &reply.val.get_cputime.cputime);
- goto answer_and_close;
- }
- case FRSH_MT_GET_CURRENTBUDGET:
- {
- syslog(LOG_DEBUG, "operation requested: GET_CURRENTBUDGET");
- reply.error = get_current_budget(request.val.get_currentbudget.vres_id,
- &reply.val.get_currentbudget.currentbudget);
- goto answer_and_close;
- }
- case FRSH_MT_GET_BUDGET_AND_PERIOD:
- {
- syslog(LOG_DEBUG, "operation requested: GET_BUDGET_AND_PERIOD");
- reply.error = get_budget_and_period(request.val.get_budget_and_period.vres_id,
- &reply.val.get_budget_and_period.budget,
- &reply.val.get_budget_and_period.period);
- goto answer_and_close;
- }
- case FRSH_MT_GET_SERVICE_THREAD_DATA:
- {
- syslog(LOG_DEBUG, "operation requested: GET_SERVICE_THREAD_DATA");
- reply.error = get_budget_and_period(service_th_vres_id,
- &reply.val.get_service_thread_data.budget,
- &reply.val.get_service_thread_data.period);
- goto answer_and_close;
- }
- case FRSH_MT_SET_SERVICE_THREAD_DATA:
- {
- struct timespec old_budget, old_period;
- syslog(LOG_DEBUG, "operation requested: SET_SERVICE_THREAD_DATA");
- old_budget = service_th_contract.budget_min;
- old_period = service_th_contract.period_max;
- service_th_contract.budget_min =
- request.val.set_service_thread_data.budget;
- service_th_contract.period_max =
- request.val.set_service_thread_data.period;
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_lock(&contract_mutex);
-#endif
- reply.error =
- renegotiate_contract(&service_th_contract, service_th_vres_id);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_MULTITHREAD
- fosa_mutex_unlock(&contract_mutex);
-#endif
- if (reply.error == FRSH_NO_ERROR)
- reply.val.set_service_thread_data.accepted = true;
- else {
- reply.val.set_service_thread_data.accepted = false;
- service_th_contract.budget_min = old_budget;
- service_th_contract.period_max = old_period;
- }
- goto answer_and_close;
- }
- case FRSH_MT_FEEDBACK_SET_SPARE:
- {
- syslog(LOG_DEBUG, "operation requested: FEEDBACK_SET_SPARE");
- reply.error = reserve_feedback(&request.val.set_feedback_spare.spare_contract);
- goto answer_and_close;
- }
- case FRSH_MT_FEEDBACK_GET_SPARE:
- {
- syslog(LOG_DEBUG, "operation requested: FEEDBACK_GET_SPARE");
- if (feedback_spare_contract == NULL)
- reply.error = FRSH_ERR_NOT_CONTRACTED_VRES;
- else {
- reply.val.get_feedback_spare.spare_contract = *feedback_spare_contract;
- reply.error = FRSH_NO_ERROR;
- }
- goto answer_and_close;
- }
- default:
- syslog(LOG_ERR, "operation requested: unknown !!");
- reply.error = FRSH_SERVICE_TH_ERR_SOCKET;
- goto answer_and_close;
- }
-answer_and_close:
- if (send(conn, (void*) &reply, sizeof(frsh_out_msg_t), 0) < sizeof(frsh_out_msg_t))
- syslog(LOG_ERR, "can't send reply message (ERROR 0x%x)", FRSH_SERVICE_TH_ERR_SOCKET);
- else
- syslog(LOG_DEBUG, "command reply sent (exit status 0x%x)", reply.error);
- close(conn);
- syslog(LOG_INFO, "connection closed");
-end_cycle:
- ;
- }
-
- return EXIT_SUCCESS;
-}
-
-#endif /* FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD */
+++ /dev/null
-
-
-/*********************************************************************/
-/* V R E S R E P O S I T O R Y U T I L I T Y F U N C T I O N S */
-/*********************************************************************/
-
-/*
- * access functions to vres repository
- *
- * some simple subsitutions macro which help keep vres_repo_t opaque and
- * improve code cleanness and look & feel (exactly as such as
- * with thread_repo_t a few lines above)
- */
-
-/* given the id of a contracted vres stored in the repository returns
- * a pointer to its entry */
-#define get_vres_entry(vres_id) \
- ( & ( vres_repo.repo[vres_id_2_index(vres_id)] ) )
-/* gives the actual number of thread bound to a vres */
-#define get_vres_threads_number(vres_id) \
- ( vres_repo.repo[vres_id_2_index(vres_id)].threads_number )
-/* gives the actual number of vres in the repository */
-#define get_vres_number() \
- ( vres_repo.vres_number )
-/* gives the actual number of dummy vres in the repository */
-#define get_dummy_vres_number() \
- ( vres_repo.dummy_vres_number )
-
-/*
- * consistency and status checks
- *
- * common used checkings and tests about the access to the vres repository
- * (is the index value in the correct range?) and the status of each entry
- * (is it free?, non-free?, ecc.)
- */
-
-/* are we accessing the repository with a valid index value ? */
-#define check_vres_repo_ind(ind) \
- ( (ind >= 0 && ind < 2 * FRSH_MAX_N_VRES) ? true : false )
-/* is the vres repository entry (correctly accessed and) free ? */
-#define check_vres_repo_entry_free(ind) \
- ( check_vres_repo_ind(ind) && ( vres_repo.repo[(ind)].processor.sid == FRSH_QRES_NOT_VALID_SID ) && ( vres_repo.repo[(ind)].disk.weight == FRSH_QRES_NOT_VALID_DISK ) )
-
-/* is the vres repository entry (correctly accessed and) non free ? */
-#define check_vres_repo_entry_nonfree(ind) \
- ( check_vres_repo_ind(ind) && \
- ( ( vres_repo.repo[(ind)].processor.sid != FRSH_QRES_NOT_VALID_SID ) || \
- ( vres_repo.repo[(ind)].disk.weight != FRSH_QRES_NOT_VALID_DISK ) ) ) \
-
-/*
- * initialize the repository
- *
- * sets all entries to invalid (that is, free) and init the mutex
- * (if a multithreaded service thread has been configured)
- *
- * possible return values:
- * true (all ok)
- * false (something wrong with the mutex)
- */
-static inline bool vres_repo_init()
-{
- int i;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- if (fosa_mutex_init(&vres_repo.mutex, 0) != 0)
- return false;
-#endif
- vres_repo.vres_number = 0;
- vres_repo.dummy_vres_number = 0;
- for (i = 0; i < 2 * FRSH_MAX_N_VRES; i++) {
- /* vres_repo.repo[i].contract untouched */
- vres_repo.repo[i].processor.sid = FRSH_QRES_NOT_VALID_SID;
- vres_repo.repo[i].processor.threads_number = 0;
- vres_repo.repo[i].processor.first_thread_index = -1;
- vres_repo.repo[i].disk.weight = FRSH_QRES_NOT_VALID_DISK;
- vres_repo.repo[i].renegotiation_status = FRSH_RS_NOT_REQUESTED;
- }
-
- return true;
-}
-
-/*
- * add an entry
- *
- * adds an entry into the repository. If successful the index of the entry is
- * returned in vres_ind.
- *
- * We (again) "accept suggestions" and we implement this exaclty as previously
- * described for the thread repository utility functions
- *
- * possible return values:
- * true (entry correctly added)
- * false (entry not added, maybe no more room in the repository!)
- */
-static bool vres_repo_put(const frsh_contract_t *contract,
- const unsigned int vres_data,
- int *vres_ind)
-{
- int i;
- int start;
- bool result;
-
- /* depending by the contract type we must place the new entry
- * if the "first half" (0 <= vres_ind < FRSH_MAX_N_VRES) of in the
- * second half (FRSH_MAX_N_VRES <= vres_ind < 2*FRSH_MAX_N_VRES) of
- * the repository */
- switch (contract->contract_type) {
- default:
- case FRSH_CT_REGULAR:
- case FRSH_CT_BACKGROUND:
- {
- start = 0;
- break;
- }
- case FRSH_CT_DUMMY:
- {
- start = FRSH_MAX_N_VRES;
- break;
- }
- }
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* lock the repository */
- fosa_mutex_lock(&vres_repo.mutex);
-#endif
- /* try to allocate the vres entry in the caller provided
- * position (if any) and, only if it's not free, scan all
- * the repository for a different suitable place */
- if (vres_ind != NULL &&
- check_vres_repo_entry_free((start + *vres_ind) % FRSH_MAX_N_VRES))
- i = (start + *vres_ind) % FRSH_MAX_N_VRES;
- else {
- i = start;
- while (i < FRSH_MAX_N_VRES && !check_vres_repo_entry_free(i))
- i++;
- }
- /* if we're sure it's valid and free we place the
- * vres entry into the repository in position 'i' */
- result = false;
- if (check_vres_repo_entry_free(i)) {
- vres_repo.repo[i].contract = *contract;
- switch (contract->resource_type) {
- case FRSH_RT_PROCESSOR:
- {
- vres_repo.repo[i].processor.sid = (qres_sid_t) vres_data;
- vres_repo.repo[i].processor.threads_number = 0;
- vres_repo.repo[i].processor.first_thread_index = -1;
- break;
- }
- case FRSH_RT_DISK:
- {
- vres_repo.repo[i].disk.weight = (unsigned int) vres_data;
- break;
- }
- default:
- return false;
- }
- vres_repo.repo[i].renegotiation_status = FRSH_RS_NOT_REQUESTED;
- if (vres_ind != NULL)
- *vres_ind = i;
- if (start == 0)
- vres_repo.vres_number++;
- else
- vres_repo.dummy_vres_number++;
- result = true;
- }
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the repository */
- fosa_mutex_unlock(&vres_repo.mutex);
-#endif
-
- return result;
-}
-
-/*
- * remove an entry
- *
- * sets the entry as free (if it is not) and decrement the (dummy?) vres count
- *
- * possible return values:
- * true (all ok, entry war non-free and is now free)
- * false (something wrong, entry was already free or index is out of renge)
- */
-static bool vres_repo_free(const int vres_ind)
-{
- thread_repo_entry_t *curr_thread;
- int next_thread_ind;
- bool result;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* lock the repository */
- fosa_mutex_lock(&vres_repo.mutex);
-#endif
- result = false;
- if (check_vres_repo_entry_nonfree(vres_ind)) {
- /* detach all the bound threads */
- curr_thread = &thread_repo.repo[vres_repo.repo[vres_ind].processor.first_thread_index];
- while (vres_repo.repo[vres_ind].processor.threads_number--) {
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* we need to lock the thread repository too */
- fosa_mutex_lock(&thread_repo.mutex);
-#endif
-#if defined(FRSH_CONFIG_ENABLE_DEBUG) && defined(FRSH_CONFIG_ENABLE_DEBUG_ASSERTS)
- /* if no hierarchical scheduling only one thread per vres is correct */
- assert(FRSH_HIERARCHICAL_MODULE_SUPPORTED ||
- vres_repo.repo[vres_ind].processor.threads_number == 0);
- /* no threads in DUMMY contracts */
- assert(vres_repo.repo[vres_ind].contract.contract_type != FRSH_CT_DUMMY);
-#endif
- /* only REGULAR contract type case handled since
- * dummy vres _always_ has no bound thread and BACKGROUND
- * thread need no detaching (they're not attachet to any server) */
- if (vres_repo.repo[vres_ind].contract.contract_type == FRSH_CT_REGULAR)
- /* do not care the return value since the thread
- * could exist no more and the call could fail
- * quite easily and frequently! */
- qres_detach_thread(vres_repo.repo[vres_ind].processor.sid,
- curr_thread->thread.linux_pid,
- curr_thread->thread.linux_tid);
- /* free the thread repository entry too */
- curr_thread->thread.pthread_id = FRSH_NOT_VALID_THREAD_ID;
- curr_thread->thread.linux_pid = FRSH_NOT_VALID_THREAD_ID;
- curr_thread->thread.linux_tid = FRSH_NOT_VALID_THREAD_ID;
- curr_thread->vres = FRSH_NOT_VALID_VRES_ID;
- next_thread_ind = curr_thread->next_in_vres;
- curr_thread->next_in_vres = -1;
- thread_repo.threads_number--;
- /* move along the chain */
- if (next_thread_ind != -1)
- curr_thread = &thread_repo.repo[next_thread_ind];
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the thread repository */
- fosa_mutex_unlock(&thread_repo.mutex);
-#endif
- }
- /* set the repository entry as free */
- /* vres_repo.repo[vres_id].contract untouched */
- vres_repo.repo[vres_ind].processor.sid = FRSH_QRES_NOT_VALID_SID;
- vres_repo.repo[vres_ind].processor.threads_number = 0;
- vres_repo.repo[vres_ind].processor.first_thread_index = -1;
- vres_repo.repo[vres_ind].renegotiation_status = FRSH_RS_NOT_REQUESTED;
- if (vres_ind < FRSH_MAX_N_VRES)
- vres_repo.vres_number--;
- else
- vres_repo.dummy_vres_number--;
- result = true;
- }
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- /* unlock the repository */
- fosa_mutex_unlock(&vres_repo.mutex);
-#endif
-
- return result;
-}
-
-/*
- * an entry is free ?
- *
- * check if a specific entry of the repository can be considered free.
- * The needed check is very simple and reduces itself to one of the
- * test macro defined above... Note if a multithreaded service thread is
- * configured we do it with an atomic lock
- *
- * possible return values:
- * true (entry is free)
- * false (entry is not free or index is out of range)
- */
-static inline bool vres_repo_isfree(const int vres_ind)
-{
- bool result;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- fosa_mutex_lock(&vres_repo.mutex);
-#endif
- result = check_vres_repo_entry_free(vres_ind);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- fosa_mutex_unlock(&vres_repo.mutex);
-#endif
- return result;
-}
-
-/*
- * an entry is "dummy" ?
- *
- * check if a specific entry of the repository (is not free!) and contains
- * a dummy vres, created as a consequence of the negotiation of a CT_DUMMY
- * contract.
- * If a multithreaded service thread is configured the needed checkins are
- * performed holding an atomic lock
- *
- * possible return values:
- * true (entry contains a dummy vres)
- * false (entry does not contains a dummy vres or index is out of range)
- */
-static inline bool vres_repo_isdummy(const int vres_ind)
-{
- bool result;
-
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- fosa_mutex_lock(&vres_repo.mutex);
-#endif
- result = (check_vres_repo_ind(vres_ind) && vres_ind >= FRSH_MAX_N_VRES);
-#ifdef FRSH_CONFIG_ENABLE_SERVICE_TH_MULTITHREAD
- fosa_mutex_unlock(&vres_repo.mutex);
-#endif
- return result;
-}
-bin_PROGRAMS = cpumngr
-cpumngr_SOURCES = contract_ops.c main.c
-lib_LOADLIBES+= ulut
+bin_PROGRAMS = aqcpumngr
+aqcpumngr_SOURCES = aqcpu_mngr.c
+aqcpumngr_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 AQCPU (Aquosa CPU) */
+/* */
+/* 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 <fwp_res.h>
+#include <stdio.h>
+
+UL_LOG_CUST(ulogd_frm_aqcpu);
+ul_log_domain_t ulogd_fra_fwp = {UL_LOGL_DEB, "frm_aqcpu"};
+
+static int aqcpu_dummy_admtest(struct fres_sa_scenario *scenario, void *priv,
+ bool *schedulable)
+{
+ struct fres_sa_contract *c;
+
+ 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);
+
+ ul_logdeb("processing : id=%s, period=%ld ms, budget=%ld ms\n",
+ id,
+ fosa_rel_time_to_msec(basic->period),
+ fosa_rel_time_to_msec(basic->budget));
+
+ }
+ *schedulable = scenario->num_contracts <= 3;
+ 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 = aqcpu_dummy_admtest,
+ .priv = NULL
+};
+
+int main(int argc, char *argv[])
+{
+ forb_orb orb;
+ int ret;
+
+ orb = forb_init(&argc, &argv, "frm_aqcpu");
+ if (!orb) error(1, errno, "forb_init");
+
+ ret = frm_register_and_run(orb, &frm);
+
+ if (ret != 0) {
+ error(1, errno, "frm_generic_run");
+ }
+
+ return 0;
+}
+++ /dev/null
-
-int reserve_cpu_contract(contract_t *contract)
-{
- if ((contract->contract_type == FRSH_CT_REGULAR) ||
- (contract->contract_type == FRSH_CT_DUMMY)){
-
- /* call admission test
- * if test == OK
- * cpu_contract_table(contract);
- * set_contract_status(contract, RESERVED);
- * */
- return 0;
- }
-
- if (contract->contract_type == FRSH_CT_BACKGROUND) {
- return 0;
- }
-
- return -1;
-}
-
-int commit_cpu_contract(contract_t contract)
-{
- cpu_params_t cpu_params;
-
- if ((contract->contract_type == FRSH_CT_REGULAR) ||
- (contract->contract_type == FRSH_CT_DUMMY)){
- /* create a FRSH_CT_REGULAR or FRSH_CT_DUMMY */
-
- /* mark contract as negotiated */
-
-
- return 0;
- }
-
- if (contract->contract_type == FRSH_CT_BACKGROUND) {
- return 0;
- }
-
- return -1;
-}
-
-int reserve_contract(contract_t contract)
-{
- if (contract->resource_type == FRSH_RT_PROCESSOR) {
- return reserve_cpu_contract(contract);
- }
-
- return -1;
-}
+++ /dev/null
-
-int aquosa_cpu_init()
-{
- /* (try to) initialize the AQuoSA Framework */
- if (qres_init() != QOS_OK || qsup_init() != QOS_OK)
- FRSH_ERR_RET(FRSH_ERR_INTERNAL_ERROR,
- "can't initialize AQuoSA framework");
- /* connect to DTM manager */
- return 0;
-
-}
-
-int main_loop()
-{
-
-
- return 0;
-
-}
-
-int main()
-{
- if (aquosa_cpu_init() != 0)
- exit(1);
- main_loop();
- return 0;
-}