00001 #include <linux/aquosa/qres_config.h>
00002
00003
00004 #include "qres_lib.h"
00005
00006 #include <linux/aquosa/qos_types.h>
00007
00008 #include <sys/ioctl.h>
00009 #include <sys/types.h>
00010 #include <sys/stat.h>
00011 #include <fcntl.h>
00012
00013 #include <string.h>
00014 #include <errno.h>
00015
00019 #define IOCTL_OP_CREATE_SERVER _IOR (QRES_MAJOR_NUM, QRES_OP_CREATE_SERVER, qres_iparams_t)
00020 #define IOCTL_OP_DESTROY_SERVER _IOR (QRES_MAJOR_NUM, QRES_OP_DESTROY_SERVER, qres_sid_t)
00021 #define IOCTL_OP_ATTACH_TO_SERVER _IOR (QRES_MAJOR_NUM, QRES_OP_ATTACH_TO_SERVER, qres_attach_iparams_t)
00022 #define IOCTL_OP_DETACH_FROM_SERVER _IOR (QRES_MAJOR_NUM, QRES_OP_DETACH_FROM_SERVER, qres_attach_iparams_t)
00023 #define IOCTL_OP_SET_PARAMS _IOR (QRES_MAJOR_NUM, QRES_OP_SET_PARAMS, qres_iparams_t)
00024 #define IOCTL_OP_GET_PARAMS _IOWR(QRES_MAJOR_NUM, QRES_OP_GET_PARAMS, qres_iparams_t)
00025 #define IOCTL_OP_GET_SERVER_ID _IOWR(QRES_MAJOR_NUM, QRES_OP_GET_SERVER_ID, qres_attach_iparams_t)
00026 #define IOCTL_OP_GET_EXEC_TIME _IOWR(QRES_MAJOR_NUM, QRES_OP_GET_EXEC_TIME, qres_time_iparams_t)
00027 #define IOCTL_OP_GET_CURR_BUDGET _IOWR(QRES_MAJOR_NUM, QRES_OP_GET_CURR_BUDGET, qres_time_iparams_t)
00028 #define IOCTL_OP_GET_NEXT_BUDGET _IOWR(QRES_MAJOR_NUM, QRES_OP_GET_NEXT_BUDGET, qres_time_iparams_t)
00029 #define IOCTL_OP_GET_APPR_BUDGET _IOWR(QRES_MAJOR_NUM, QRES_OP_GET_APPR_BUDGET, qres_time_iparams_t)
00030 #define IOCTL_OP_GET_DEADLINE _IOWR(QRES_MAJOR_NUM, QRES_OP_GET_DEADLINE, qres_timespec_iparams_t)
00031 #define IOCTL_OP_SET_WEIGHT _IOR (QRES_MAJOR_NUM, QRES_OP_SET_WEIGHT, qres_weight_iparams_t)
00032 #define IOCTL_OP_GET_WEIGHT _IOWR(QRES_MAJOR_NUM, QRES_OP_GET_WEIGHT, qres_weight_iparams_t)
00033
00035 int qres_fd = -1;
00036
00038 qres_params_t server_params = {
00039 .Q = 0,
00040 .Q_min = 0,
00041 .P = 0,
00042 .flags = 0,
00043 .timeout = 0
00044 };
00045
00046
00048 static inline qos_rv check_open() {
00049 if (qres_fd == -1) {
00050 return qres_init();
00051 }
00052 return QOS_OK;
00053 }
00054
00055
00056 qos_rv qres_get_sid(pid_t pid, tid_t tid, qres_sid_t *p_sid) {
00057 qres_attach_iparams_t iparams;
00058
00059 qos_rv rv = check_open();
00060 qos_chk_rv(rv == QOS_OK, rv);
00061
00062 iparams.pid = pid;
00063 iparams.tid = tid;
00064
00065 if (ioctl(qres_fd, IOCTL_OP_GET_SERVER_ID, &iparams) < 0)
00066 return qos_int_rv(-errno);
00067
00068 *p_sid = iparams.server_id;
00069
00070 return QOS_OK;
00071 }
00072
00073
00074 qos_rv qres_create_server(qres_params_t * p_params, qres_sid_t *p_sid) {
00075 qres_iparams_t iparams;
00076
00077 qos_rv rv = check_open();
00078 qos_chk_rv(rv == QOS_OK, rv);
00079
00080 iparams.params = *p_params;
00081
00082 if (ioctl(qres_fd, IOCTL_OP_CREATE_SERVER, &iparams) < 0)
00083 return qos_int_rv(-errno);
00084
00085 if (p_sid != NULL)
00086 *p_sid = iparams.server_id;
00087
00088 server_params = *p_params;
00089 return QOS_OK;
00090 }
00091
00092
00093 qos_rv qres_destroy_server(qres_sid_t sid) {
00094 qos_rv rv = check_open();
00095 qos_chk_rv(rv == QOS_OK, rv);
00096
00097 if (ioctl(qres_fd, IOCTL_OP_DESTROY_SERVER, &sid) < 0)
00098 return qos_int_rv(-errno);
00099
00100 return QOS_OK;
00101 }
00102
00103
00104 qos_rv qres_attach_thread(qres_sid_t sid, pid_t pid, tid_t tid) {
00105 qres_attach_iparams_t iparams;
00106
00107 qos_rv rv = check_open();
00108 qos_chk_rv(rv == QOS_OK, rv);
00109
00110 iparams.server_id = sid;
00111 iparams.pid = pid;
00112 iparams.tid = tid;
00113
00114 if (ioctl(qres_fd, IOCTL_OP_ATTACH_TO_SERVER, &iparams) < 0)
00115 return qos_int_rv(-errno);
00116
00117 return QOS_OK;
00118 }
00119
00120
00121 qos_rv qres_detach_thread(qres_sid_t sid, pid_t pid, tid_t tid) {
00122 qres_attach_iparams_t iparams;
00123
00124 qos_rv rv = check_open();
00125 qos_chk_rv(rv == QOS_OK, rv);
00126
00127 iparams.server_id = sid;
00128 iparams.pid = pid;
00129 iparams.tid = tid;
00130
00131 if (ioctl(qres_fd, IOCTL_OP_DETACH_FROM_SERVER, &iparams) < 0)
00132 return qos_int_rv(-errno);
00133
00134 return QOS_OK;
00135 }
00136
00137
00138 #define QRES_DEV_PATHNAME QOS_DEV_PATH "/" QRES_DEV_NAME
00139
00140 qos_rv qres_init() {
00141 qres_fd = open(QRES_DEV_PATHNAME, O_RDONLY);
00142 if (qres_fd < 0) {
00143 qos_log_debug("Failed to open device %s", QRES_DEV_PATHNAME);
00144 return QOS_E_MISSING_COMPONENT;
00145 }
00146 return QOS_OK;
00147 }
00148
00149
00150 qos_rv qres_cleanup() {
00151 int fd = qres_fd;
00152
00153 if (qres_fd == -1)
00154 return QOS_E_INCONSISTENT_STATE;
00155
00156 qres_fd = -1;
00157 if (close(fd) < 0)
00158 return QOS_E_GENERIC;
00159
00160 return QOS_OK;
00161 }
00162
00163
00164 qos_rv qres_module_exists ()
00165 {
00166 FILE* module_file;
00167 char buffer[1024];
00168
00169 module_file = fopen ("/proc/modules", "r");
00170
00171 while (fgets (buffer, 1024, module_file) != NULL)
00172 {
00173 if (strstr (buffer, "qresmod") != NULL)
00174 return QOS_OK;
00175 }
00176 return QOS_E_GENERIC;
00177 }
00178
00179
00180 qos_rv qres_get_exec_time(qres_sid_t sid, qres_time_t *p_exec_time, qres_atime_t *p_abs_time) {
00181 qres_time_iparams_t iparams;
00182
00183 qos_rv rv = check_open();
00184 qos_chk_rv(rv == QOS_OK, rv);
00185
00186 iparams.server_id = sid;
00187 if (ioctl(qres_fd, IOCTL_OP_GET_EXEC_TIME, &iparams) < 0) {
00188 qos_log_err("Got error: %s", qos_strerror(qos_int_rv(-errno)));
00189 return qos_int_rv(-errno);
00190 }
00191 if (p_exec_time != NULL)
00192 *p_exec_time = iparams.exec_time;
00193 if (p_abs_time != NULL)
00194 *p_abs_time = iparams.abs_time;
00195 return QOS_OK;
00196 }
00197
00198
00199 qos_rv qres_get_curr_budget(qres_sid_t sid, qres_time_t *p_curr_budget) {
00200 qres_time_iparams_t iparams;
00201 qos_rv rv;
00202
00203 qos_chk_ok_do(rv = check_open(), return rv);
00204 if (p_curr_budget == NULL)
00205 return QOS_E_INVALID_PARAM;
00206
00207 iparams.server_id = sid;
00208 if (ioctl(qres_fd, IOCTL_OP_GET_CURR_BUDGET, &iparams) < 0) {
00209 rv = qos_int_rv(-errno);
00210 qos_log_err("Got error: %s", qos_strerror(rv));
00211 return rv;
00212 }
00213 *p_curr_budget = iparams.exec_time;
00214 return QOS_OK;
00215 }
00216
00217
00218 qos_rv qres_get_next_budget(qres_sid_t sid, qres_time_t *p_next_budget) {
00219 qres_time_iparams_t iparams;
00220 qos_rv rv;
00221
00222 qos_chk_ok_do(rv = check_open(), return rv);
00223 if (p_next_budget == NULL)
00224 return QOS_E_INVALID_PARAM;
00225
00226 iparams.server_id = sid;
00227 if (ioctl(qres_fd, IOCTL_OP_GET_NEXT_BUDGET, &iparams) < 0) {
00228 rv = qos_int_rv(-errno);
00229 qos_log_err("Got error: %s", qos_strerror(rv));
00230 return rv;
00231 }
00232 *p_next_budget = iparams.exec_time;
00233 return QOS_OK;
00234 }
00235
00236
00237 qos_rv qres_get_appr_budget(qres_sid_t sid, qres_time_t *p_appr_budget) {
00238 qres_time_iparams_t iparams;
00239 qos_rv rv;
00240
00241 qos_chk_ok_do(rv = check_open(), return rv);
00242 if (p_appr_budget == NULL)
00243 return QOS_E_INVALID_PARAM;
00244
00245 iparams.server_id = sid;
00246 if (ioctl(qres_fd, IOCTL_OP_GET_APPR_BUDGET, &iparams) < 0) {
00247 rv = qos_int_rv(-errno);
00248 qos_log_err("Got error: %s", qos_strerror(rv));
00249 return rv;
00250 }
00251 *p_appr_budget = iparams.exec_time;
00252 return QOS_OK;
00253 }
00254
00255
00256 qos_rv qres_set_params(qres_sid_t sid, qres_params_t * p_params) {
00257 qres_iparams_t iparams;
00258 int err;
00259
00260 qos_rv rv = check_open();
00261 qos_chk_rv(rv == QOS_OK, rv);
00262
00263 iparams.server_id = sid;
00264 iparams.params = *p_params;
00265 err = ioctl(qres_fd, IOCTL_OP_SET_PARAMS, &iparams);
00266 if (err == -1)
00267 rv = qos_int_rv(-errno);
00268 else
00269 server_params = *p_params;
00270 return rv;
00271 }
00272
00273
00274 qos_rv qres_get_params(qres_sid_t sid, qres_params_t * qres_p) {
00275 qres_iparams_t iparams;
00276 int err;
00277
00278 qos_rv rv = check_open();
00279 qos_chk_rv(rv == QOS_OK, rv);
00280
00281 iparams.server_id = sid;
00282 err = ioctl(qres_fd, IOCTL_OP_GET_PARAMS, &iparams);
00283 if (err == 0) {
00284 memcpy(qres_p, &iparams.params, sizeof(qres_params_t));
00285 return QOS_OK;
00286 } else
00287 return qos_int_rv(-errno);
00288 }
00289
00290
00291 qos_rv qres_set_bandwidth(qres_sid_t sid, qos_bw_t bw) {
00292 qres_iparams_t iparams;
00293 int err;
00294
00295 qos_rv rv = check_open();
00296 qos_chk_rv(rv == QOS_OK, rv);
00297
00298 iparams.server_id = sid;
00299 iparams.params = server_params;
00300 iparams.params.Q = bw2Q(bw, server_params.P);
00301 err = ioctl(qres_fd, IOCTL_OP_SET_PARAMS, &iparams);
00302 if (err == -1) {
00303 qos_log_debug("ioctl() FAILED: %s", qos_strerror(qos_int_rv(-errno)));
00304 return qos_int_rv(-errno);
00305 }
00306 return QOS_OK;
00307 }
00308
00309
00310 qos_rv qres_get_bandwidth(qres_sid_t sid, float *bw) {
00311 qres_iparams_t iparams;
00312 int err;
00313
00314 qos_chk_ok_ret(check_open());
00315
00316 iparams.server_id = sid;
00317 err = ioctl(qres_fd, IOCTL_OP_GET_PARAMS, &iparams);
00318 if (err == 0)
00319 *bw = ((float) iparams.params.Q) / ((float) iparams.params.P);
00320 else
00321 return qos_int_rv(-errno);
00322 return QOS_OK;
00323 }
00324
00325 qos_rv qres_get_deadline(qres_sid_t sid, struct timespec *p_deadline) {
00326 qres_timespec_iparams_t iparams;
00327 qos_rv rv;
00328
00329 qos_chk_ok_do(rv = check_open(), return rv);
00330 if (p_deadline == NULL)
00331 return QOS_E_INVALID_PARAM;
00332
00333 iparams.server_id = sid;
00334 if (ioctl(qres_fd, IOCTL_OP_GET_DEADLINE, &iparams) < 0) {
00335 rv = qos_int_rv(-errno);
00336 qos_log_err("Got error: %s", qos_strerror(rv));
00337 return rv;
00338 }
00339 *p_deadline = iparams.timespec;
00340 return QOS_OK;
00341 }
00342
00343 qos_rv qres_set_weight(qres_sid_t sid, unsigned int weight) {
00344 qres_weight_iparams_t iparams;
00345 int err;
00346
00347 qos_rv rv = check_open();
00348 qos_chk_rv(rv == QOS_OK, rv);
00349
00350 iparams.server_id = sid;
00351 iparams.weight = weight;
00352 err = ioctl(qres_fd, IOCTL_OP_SET_WEIGHT, &iparams);
00353 if (err == -1) {
00354 qos_log_debug("ioctl() FAILED: %s", qos_strerror(qos_int_rv(-errno)));
00355 return qos_int_rv(-errno);
00356 }
00357 return QOS_OK;
00358 }
00359
00360 qos_rv qres_get_weight(qres_sid_t sid, unsigned int *p_weight) {
00361 qres_weight_iparams_t iparams;
00362 qos_rv rv;
00363
00364 qos_chk_ok_do(rv = check_open(), return rv);
00365 if (p_weight == NULL)
00366 return QOS_E_INVALID_PARAM;
00367
00368 iparams.server_id = sid;
00369 if (ioctl(qres_fd, IOCTL_OP_GET_WEIGHT, &iparams) < 0) {
00370 rv = qos_int_rv(-errno);
00371 qos_log_err("Got error: %s", qos_strerror(rv));
00372 return rv;
00373 }
00374 *p_weight = iparams.weight;
00375 return QOS_OK;
00376 }
00377
00378 qos_rv qres_get_servers(qres_sid_t *sids, size_t *n) {
00379 FILE* proc_scheduler_file;
00380 char buffer[1024];
00381 int dim = 0;
00382
00383 proc_scheduler_file = fopen ("/proc/aquosa/qres/scheduler", "r");
00384 if (proc_scheduler_file == NULL)
00385 return QOS_E_MISSING_COMPONENT;
00386
00387 if (fgets (buffer, sizeof(buffer), proc_scheduler_file) == NULL
00388 || fgets (buffer, sizeof(buffer), proc_scheduler_file) == NULL
00389 || fgets (buffer, sizeof(buffer), proc_scheduler_file) == NULL) {
00390 *n = 0;
00391 return QOS_OK;
00392 }
00393
00394 while (dim < *n && fgets (buffer, sizeof(buffer), proc_scheduler_file) != NULL)
00395 if (sscanf(buffer, "%d", &sids[dim]) == 1)
00396 dim++;
00397 else
00398 qos_log_err("Could not parse line: %s", buffer);
00399
00400 fclose(proc_scheduler_file);
00401
00402 *n = dim;
00403
00404 return QOS_OK;
00405 }