00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <unistd.h>
00004 #include <string.h>
00005
00006 #include <aquosa/qres_lib.h>
00007 #include <linux/aquosa/qos_debug.h>
00008 #include <aquosa/qsup_lib.h>
00009
00010 extern char **environ;
00011
00012 static inline void qos_assert(int cond, const char *msg) {
00013 if (! cond) {
00014 printf("%s\n", msg);
00015 exit(-1);
00016 }
00017 }
00018
00019 static inline unsigned int str2flags(char str_flags[5]) {
00020 unsigned int flags = 0x0000;
00021 if (index(str_flags, 'd') != NULL)
00022 flags |= QOS_F_DEFAULT;
00023 if (index(str_flags, 's') != NULL)
00024 flags |= QOS_F_SOFT;
00025 if (index(str_flags, 'p') != NULL)
00026 flags |= QOS_F_PERSISTENT;
00027 return flags;
00028 }
00029
00030 static inline void flags2str(unsigned int flags, char str_flags[5]) {
00031 sprintf(str_flags, "----");
00032 if (flags & QOS_F_DEFAULT)
00033 str_flags[3] = 'd';
00034 if (flags & QOS_F_SOFT)
00035 str_flags[2] = 's';
00036 if (flags & QOS_F_PERSISTENT)
00037 str_flags[1] = 'p';
00038 }
00039
00041 FILE *fproc = NULL;
00042 char fname[32];
00043
00045 int proc_begin(pid_t pid) {
00046 sprintf(fname, "ls /proc/%d/task", pid);
00047 fproc = popen(fname, "r");
00048 return (fproc != NULL);
00049 }
00050
00052 tid_t proc_next(void) {
00053 qos_assert(fproc != NULL, "");
00054 if (feof(fproc)) {
00055 pclose(fproc);
00056 return 0;
00057 }
00058 int tid;
00059 if (fscanf(fproc, "%d", &tid) != 1) {
00060 pclose(fproc);
00061 return 0;
00062 }
00063 return (tid_t) tid;
00064 }
00065
00066 int main(int argc, char *argv[]) {
00067 int Q_min = -1, Q = -1, P = -1;
00068 unsigned int flags = -1, weight = 0;
00069 char str_flags[5] = "NONE";
00070 qos_bw_t bw_min = -1, bw = -1;
00071 int create = 0;
00072 int destroy = 0;
00073 int attach = 0;
00074 int detach = 0;
00075 int wrap = 0;
00076 int getparams = 0;
00077 int gettime = 0;
00078 int getbudgets = 0;
00079 int setparams = 0;
00080 int setspare = 0;
00081 pid_t pid = -1;
00082 tid_t tid = -1;
00083 qres_sid_t sid = -1;
00084 double spare_bw = -1;
00085 qres_params_t params;
00086 char *argv0 = argv[0];
00087
00088 argc--; argv++;
00089 while (argc > 0 && ! wrap) {
00090 if (0) {
00091 } else if (sscanf(*argv, "q-min=%d", &Q_min) == 1 || sscanf(*argv, "q_min=%d", &Q_min) == 1) {
00092 } else if (strcmp(*argv, "-q-min") == 0) {
00093 qos_assert(argc > 1, "Missing option parameter");
00094 argc--; argv++;
00095 Q_min = atoi(*argv);
00096 } else if (sscanf(*argv, "q=%d", &Q) == 1) {
00097 } else if (strcmp(*argv, "-q") == 0) {
00098 qos_assert(argc > 1, "Missing option parameter");
00099 argc--; argv++;
00100 Q = atoi(*argv);
00101 } else if (sscanf(*argv, "p=%d", &P) == 1) {
00102 } else if (strcmp(*argv, "-p") == 0) {
00103 qos_assert(argc > 1, "Missing option parameter");
00104 argc--; argv++;
00105 P = atoi(*argv);
00106 } else if (sscanf(*argv, "w=%d", &weight) == 1) {
00107 } else if (strcmp(*argv, "-w") == 0) {
00108 qos_assert(argc > 1, "Missing option parameter");
00109 argc--; argv++;
00110 weight = atoi(*argv);
00111 } else if (strcmp(*argv, "-b-min") == 0) {
00112 qos_assert(argc > 1, "Missing option parameter");
00113 argc--; argv++;
00114 bw_min = d2bw(atof(*argv));
00115 } else if (strcmp(*argv, "-b") == 0) {
00116 qos_assert(argc > 1, "Missing option parameter");
00117 argc--; argv++;
00118 bw = d2bw(atof(*argv));
00119 } else if (sscanf(*argv, "spare=%lg", &spare_bw) == 1) {
00120 qos_assert(spare_bw >= 0.0 && spare_bw <= 1.0,
00121 "Spare bandwidth must be in the [0.0 1.0] range\n");
00122 } else if (strcmp(*argv, "-spare") == 0) {
00123 qos_assert(argc > 1, "Missing option parameter");
00124 argc--; argv++;
00125 spare_bw = atof(*argv);
00126 qos_assert(spare_bw >= 0.0 && spare_bw <= 1.0,
00127 "Spare bandwidth must be in the [0.0 1.0] range\n");
00128 } else if (sscanf(*argv, "pid=%d", &pid) == 1) {
00129 } else if (strcmp(*argv, "-pid") == 0) {
00130 qos_assert(argc > 1, "Missing option parameter");
00131 argc--; argv++;
00132 pid = atoi(*argv);
00133 } else if (sscanf(*argv, "tid=%d", &tid) == 1) {
00134 } else if (strcmp(*argv, "-tid") == 0) {
00135 qos_assert(argc > 1, "Missing option parameter");
00136 argc--; argv++;
00137 tid = atoi(*argv);
00138 } else if (sscanf(*argv, "sid=%d", &sid) == 1) {
00139 } else if (strcmp(*argv, "-sid") == 0) {
00140 qos_assert(argc > 1, "Missing option parameter");
00141 argc--; argv++;
00142 sid = atoi(*argv);
00143 } else if (sscanf(*argv, "f=%x", &flags) == 1) {
00144 } else if (sscanf(*argv, "f=%4s", str_flags) == 1) {
00145 } else if (strcmp(*argv, "-f") == 0) {
00146 qos_assert(argc > 1, "Missing option parameter");
00147 argc--; argv++;
00148 qos_assert((sscanf(*argv, "%x", &flags) == 1)
00149 || (sscanf(*argv, "%4s", str_flags) == 1),
00150 "Wrong option syntax");
00151 } else if (strcmp(*argv, "-create") == 0 || strcmp(*argv, "create") == 0) {
00152 create = 1;
00153 } else if (strcmp(*argv, "-destroy") == 0 || strcmp(*argv, "destroy") == 0) {
00154 destroy = 1;
00155 } else if (strcmp(*argv, "-attach") == 0 || strcmp(*argv, "attach") == 0) {
00156 attach = 1;
00157 } else if (strcmp(*argv, "-detach") == 0 || strcmp(*argv, "detach") == 0) {
00158 detach = 1;
00159 } else if (strcmp(*argv, "-getparams") == 0 || strcmp(*argv, "getparams") == 0) {
00160 getparams = 1;
00161 } else if (strcmp(*argv, "-gettime") == 0 || strcmp(*argv, "gettime") == 0) {
00162 gettime = 1;
00163 } else if (strcmp(*argv, "-getbudgets") == 0 || strcmp(*argv, "getbudgets") == 0) {
00164 getbudgets = 1;
00165 } else if (strcmp(*argv, "-setparams") == 0 || strcmp(*argv, "setparams") == 0) {
00166 setparams = 1;
00167 } else if (strcmp(*argv, "-setspare") == 0 || strcmp(*argv, "setspare") == 0) {
00168 setspare = 1;
00169 } else if (strcmp(*argv, "-h") == 0 || strcmp(*argv, "--help") == 0 || strcmp(*argv, "help") == 0) {
00170 printf("Usage: %s [ options... ]\n", argv0);
00171 printf(" -q-min Q_min : set minimum guaranteed budget per server period\n");
00172 printf(" -q Q_max : set required budget per server period\n");
00173 printf(" -p P : set server period\n");
00174 printf(" -w W : set server weight\n");
00175 printf(" -f flags : set flags\n");
00176
00177
00178 printf(" -pid pid : set process id to affect or 0 for self (defaults to first tid)\n");
00179 printf(" -tid tid : set thread id to affect or 0 for self (if omitted, all process threads are affected)\n");
00180 printf(" -sid sid : set id of existing server to affect\n");
00181 printf(" -create : create server (requires q, p, q_min=0)\n");
00182 printf(" -destroy : destroy server (requires sid)\n");
00183 printf(" -attach : attach thread to server (requires sid, pid, tid)\n");
00184 printf(" -detach : detach thread from server (requires sid, pid/tid)\n");
00185 printf(" -setparams : set server params (requires sid, q, p, q_min=0)\n");
00186 printf(" -getparams : get server params (requires sid or pid/tid)\n");
00187 printf(" -gettime : get server time figures (requires sid or pid/tid)\n");
00188 printf(" -getbudgets : get dynamic budget values (requires sid or pid/tid)\n");
00189 printf(" -setspare : set spare bandwidth (requires -spare)\n");
00190 printf(" -spare bw : specify the spare bw to be set (range 0..1)\n");
00191 printf(" -wrap cmd [args]: command to wrap (followed by its args, thus this needs to be last option)\n");
00192 printf("\n");
00193 printf("Sample usage : qres -create -q 10000 -p 30000 -attach -tid 44021\n");
00194 printf(" : qres create q=10000 p=30000 wrap /usr/bin/yes\n");
00195 printf(" : qres attach sid=2 pid=`pidof qemu-kvm`\n");
00196 printf("Altern. syntax : qres create q=10000 p=30000 attach tid=44021\n");
00197 exit(0);
00198 } else if (strcmp(*argv, "-wrap") == 0 || strcmp(*argv, "wrap") == 0) {
00199
00200 wrap = 1;
00201 } else {
00202 printf("Unknown option: %s\n", *argv);
00203 exit(-1);
00204 }
00205
00206 argc--; argv++;
00207 }
00208
00209 qos_chk_ok_exit(qres_init());
00210 qos_chk_ok_exit(qsup_init());
00211
00212 tid_t def_tid = tid;
00213 if (def_tid == -1 && pid != -1)
00214 def_tid = pid;
00215 if (pid == -1 && tid != -1)
00216 pid = tid;
00217
00218 if (sid == -1 && pid != -1 && def_tid != -1) {
00219 if (qres_get_sid(pid, def_tid, &sid) == QOS_OK) {
00220 printf("sid of attached server: %d\n", sid);
00221 }
00222 }
00223
00224 if (flags == -1) {
00225 if (strcmp(str_flags, "NONE") != 0)
00226 flags = str2flags(str_flags);
00227 else
00228 flags = 0x0000;
00229 }
00230
00231 if (create == 1 && Q != -1 && P != -1) {
00232 params.Q = Q;
00233 params.P = P;
00234 params.Q_min = (Q_min != -1) ? Q_min : 0;
00235 params.flags = flags;
00236 qos_chk_ok_exit(qres_create_server(¶ms, &sid));
00237 printf("SID of new server: %d\n", sid);
00238 }
00239
00240 if (sid != -1 && weight != 0)
00241 qos_chk_ok_exit(qres_set_weight(sid, weight));
00242
00243 if (attach == 1 && sid != -1 && pid != -1 && tid != -1)
00244 qos_chk_ok_exit(qres_attach_thread(sid, pid, tid));
00245 else if (attach == 1 && sid != -1 && pid != -1) {
00246 qos_assert(proc_begin(pid), "No such pid");
00247 tid_t mytid = proc_next();
00248 while (mytid != 0) {
00249 qos_chk_ok_exit(qres_attach_thread(sid, pid, mytid));
00250 mytid = proc_next();
00251 }
00252 }
00253
00254 if (detach == 1 && sid != -1 && pid != -1 && tid != -1)
00255 qos_chk_ok_exit(qres_detach_thread(sid, pid, tid));
00256 else if (detach == 1 && sid != -1 && pid != -1) {
00257 qos_assert(proc_begin(pid), "No such pid");
00258 tid_t mytid = proc_next();
00259 while (mytid != 0) {
00260 qos_chk_ok_exit(qres_detach_thread(sid, pid, mytid));
00261 mytid = proc_next();
00262 }
00263 }
00264
00265 if (setparams == 1 && sid != -1) {
00266 qos_chk_ok_exit(qres_get_params(sid, ¶ms));
00267 if (Q != -1) params.Q = Q;
00268 if (Q_min != -1) params.Q_min = Q_min;
00269 if (P != -1) params.P = P;
00270 qos_chk_ok_exit(qres_set_params(sid, ¶ms));
00271 }
00272
00273 if (destroy == 1 && sid != -1)
00274 qos_chk_ok_exit(qres_destroy_server(sid));
00275
00276 if (getparams == 1 && sid != -1) {
00277 qos_chk_ok_exit(qres_get_params(sid, ¶ms));
00278 flags2str(params.flags, str_flags);
00279 printf("sid: %d, Q: " QRES_TIME_FMT
00280 ", Q_min: " QRES_TIME_FMT
00281 ", P: " QRES_TIME_FMT
00282 ", f: %s (%04x)"
00283 "\n", sid, params.Q, params.Q_min, params.P, str_flags, params.flags);
00284 }
00285
00286 if (getbudgets == 1 && sid != -1) {
00287 qres_time_t curr_budget, next_budget, appr_budget;
00288 qos_chk_ok_exit(qres_get_curr_budget(sid, &curr_budget));
00289 qos_chk_ok_exit(qres_get_next_budget(sid, &next_budget));
00290 qos_chk_ok_exit(qres_get_appr_budget(sid, &appr_budget));
00291 printf("sid: %d, Q_curr: " QRES_TIME_FMT
00292 ", Q_next: " QRES_TIME_FMT
00293 ", Q_appr: " QRES_TIME_FMT
00294 "\n", sid, curr_budget, next_budget, appr_budget);
00295 }
00296
00297 if (gettime == 1 && sid != -1) {
00298 qres_time_t exec_time;
00299 qres_atime_t abs_time;
00300 qos_chk_ok_exit(qres_get_exec_time(sid, &exec_time, &abs_time));
00301 printf("sid: %d"
00302 ", exec_time: " QRES_TIME_FMT
00303 ", abs_time: " QRES_ATIME_FMT
00304 "\n", sid, exec_time, abs_time);
00305 }
00306
00307 if (setspare == 1) {
00308 qos_assert(spare_bw != -1, "Need to specify the spare bandwidth to be set (through -spare)");
00309 qos_chk_ok_exit(qsup_reserve_spare(d2bw(spare_bw)));
00310 printf("Set spare bandwidth for QoS manager\n");
00311 }
00312
00313 if (wrap == 1) {
00314 qos_assert(sid != -1, "Need to specify server either by sid or by creating a new one");
00315 const char *cmd = argv[0];
00316 qos_chk_ok_exit(qres_attach_thread(sid, 0, 0));
00317 qos_chk_ok_exit(qsup_cleanup());
00318 qos_chk_ok_exit(qres_cleanup());
00319 execvp(cmd, argv);
00320 }
00321
00322 qos_chk_ok_exit(qsup_cleanup());
00323 qos_chk_ok_exit(qres_cleanup());
00324
00325 return 0;
00326 }