1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners: */
5 /* Universidad de Cantabria, SPAIN */
6 /* University of York, UK */
7 /* Scuola Superiore Sant'Anna, ITALY */
8 /* Kaiserslautern University, GERMANY */
9 /* Univ. Politécnica Valencia, SPAIN */
10 /* Czech Technical University in Prague, CZECH REPUBLIC */
12 /* Thales Communication S.A. FRANCE */
13 /* Visual Tools S.A. SPAIN */
14 /* Rapita Systems Ltd UK */
17 /* See http://www.frescor.org for a link to partners' websites */
19 /* FRESCOR project (FP6/2005/IST/5-034026) is funded */
20 /* in part by the European Union Sixth Framework Programme */
21 /* The European Union is not liable of any use that may be */
22 /* made of this code. */
25 /* This file is part of FRESCOR CPUCG (cpu control group) */
27 /* FWP is free software; you can redistribute it and/or modify it */
28 /* under terms of the GNU General Public License as published by the */
29 /* Free Software Foundation; either version 2, or (at your option) any */
30 /* later version. FWP is distributed in the hope that it will be */
31 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
32 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
33 /* General Public License for more details. You should have received a */
34 /* copy of the GNU General Public License along with FWP; see file */
35 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
36 /* Cambridge, MA 02139, USA. */
38 /* As a special exception, including AQCPU header files in a file, */
39 /* instantiating FWP generics or templates, or linking other files */
40 /* with FWP objects to produce an executable application, does not */
41 /* by itself cause the resulting executable application to be covered */
42 /* by the GNU General Public License. This exception does not */
43 /* however invalidate any other reasons why the executable file might be */
44 /* covered by the GNU Public License. */
45 /**************************************************************************/
49 * @author Dario Faggiolir <faggioli@gandalf.sssup.it>
58 #include <ul_logreg.h>
59 #include <fra_generic.h>
60 #include "diskbfq_contract.h"
63 UL_LOG_CUST(ulogd_fra_diskbfq);
64 ul_log_domain_t ulogd_fra_diskbfq = {UL_LOGL_MSG, "fra_diskbfq"};
65 UL_LOGREG_SINGLE_DOMAIN_INIT_FUNCTION(fra_diskbfq_logreg_domains, ulogd_fra_diskbfq);
67 static int diskbfq_initialized = 0; /* initialization flag */
70 * Test whether BFQ disk scheduler modue is initialized
72 static inline int diskbfq_is_initialized()
74 return (diskbfq_initialized == 1);
77 static int diskbfq_create_vres(fres_vres_t *vres, void *priv)
79 fres_block_basic *basic;
80 fres_block_disk_sched *disk_sched;
84 * for disk, reserving the bandwidth does not
87 * All that we must do is prepare the
88 * vres storing the I/O priority the thread that
89 * will be bound to it will acquire.
91 fres_contract_id_to_string(id, &vres->id, sizeof(id));
92 basic = fres_contract_get_basic(vres->new);
93 disk_sched = fres_contract_get_disk_sched(vres->new);
94 if (!(vres->priv = malloc(sizeof(int))))
97 memcpy(vres->priv, &disk_sched->ioprio, sizeof(int));
98 printf("Created BFQ VRES (ioprio=%d budget=%ld ms, period=%ld ms)\n",
100 fosa_rel_time_to_msec(basic->budget),
101 fosa_rel_time_to_msec(basic->period));
106 static int diskbfq_cancel_vres(fres_vres_t *vres, void *priv)
114 * As before, it is not possible to "free" disk
117 * All that we do is free vres memory, the bandwidth
118 * is automatically released when the thread is unbound
119 * from the vres itself.
121 printf("Canceled DISK VRES (ioprio=%d)\n", *((int*)vres->priv));
128 int diskbfq_change_vres(fres_vres_t *vres, void *priv)
130 fres_block_disk_sched *disk_sched;
137 disk_sched = fres_contract_get_disk_sched(vres->new);
138 printf("Changed BFQ VRES from ioprio=%d to ioprio=%d\n",
139 *((int*)vres->priv), (int) disk_sched->ioprio);
140 memcpy(vres->priv, &disk_sched->ioprio, sizeof(int));
145 int diskbfq_fra_exit()
151 int fra_DISK_bind_thread
153 const fosa_thread_id_t thread)
156 int ret, ioprio = *((int*)vres->priv);
157 struct fres_contract *contract = vres->perceived;
159 b = fres_contract_get_basic(contract);
160 if (b->contract_type == FRSH_CT_REGULAR)
161 ioprio = DISKBFQ_IOPRIO_DEFAULT;
162 else if (b->contract_type == FRSH_CT_BACKGROUND)
163 ioprio |= IOPRIO_CLASS_IDLE << IOPRIO_CLASS_SHIFT;
167 /* ret = ioprio_set(IOPRIO_WHO_PROCESS, gettid(), ioprio); */
168 ret = syscall(__NR_ioprio_set, IOPRIO_WHO_PROCESS,
169 syscall(__NR_gettid), ioprio);
178 int fra_DISK_unbind_thread(const fosa_thread_id_t thread)
182 /* ret = ioprio_set(IOPRIO_WHO_PROCESS, gettid(), IOPRIO_DEFAULT); */
183 ret = syscall(__NR_ioprio_set, IOPRIO_WHO_PROCESS,
184 syscall(__NR_gettid), IOPRIO_PRIO_DEFAULT);
192 int fra_DISK_get_usage
193 (const fres_vres_t *vres,
194 fosa_rel_time_t *spent)
200 int fra_DISK_get_job_usage
201 (const fres_vres_t *vres,
202 fosa_rel_time_t *spent)
208 int fra_DISK_get_remaining_budget
209 (const fres_vres_t *vres,
210 fosa_rel_time_t *budget)
216 int fra_DISK_set_spare_bandwidth
223 int fra_DISK_get_desired_budget
225 frsh_rel_time_t *p_budget_out)
231 int fra_DISK_set_desired_budget
233 fosa_rel_time_t *p_budget_in)
239 int fra_DISK_get_actual_budget
241 fosa_rel_time_t *budget)
246 static struct fres_allocator diskbfq_allocator = {
247 .res_type = FRSH_RT_DISK,
248 .res_id = 0, /* DISK ID 0 */
249 .create_vres = diskbfq_create_vres,
250 .cancel_vres = diskbfq_cancel_vres,
251 .change_vres = diskbfq_change_vres,
253 .bind_thread = fra_DISK_bind_thread,
254 .unbind_thread = fra_DISK_unbind_thread,
256 .vres_get_usage = fra_DISK_get_usage,
257 .vres_get_job_usage = fra_DISK_get_job_usage,
258 .vres_get_remaining_budget = fra_DISK_get_remaining_budget,
260 .set_spare_bandwidth = fra_DISK_set_spare_bandwidth,
261 .get_desired_budget = fra_DISK_get_desired_budget,
262 .set_desired_budget = fra_DISK_set_desired_budget,
263 .get_actual_budget = fra_DISK_get_actual_budget,
271 * initialize FRSH for the calling process
273 * Must be called before starting using the framework.
274 * No FRSH call will be successful if this routine is not invoked
276 * Note that no BACKGROUND is created and negotiated and the caller thread
277 * is bound to no BACKGROUND vres, since no way is provided in order of
278 * specifying the contract label and get back the vres id!
280 * Note also that, since in this implementation the threads/processes with
281 * backgound contracts are left into the default Linux scheduler hands' and
282 * not attached to any AQuoSA server, while we're violating what D-AC2v1
283 * (pag. 14) says, we achieve exactly the same behaviour!!
285 * possible return values:
287 * FRSH_ERR_ALREADY_INITIALIZED
288 * FRSH_ERR_INTERNAL_ERROR (something, different from the previous case, gone wrong)
290 int diskbfq_fra_init(void)
292 if (diskbfq_is_initialized()) {
296 fres_block_register_disk_sched();
297 if (fra_register(&diskbfq_allocator)) {
301 diskbfq_initialized = 1;