3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 // Copyright (C) 2006 Daniel Hokka Zakrisson <daniel@hozac.com>
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; version 2 of the License.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #define ENSC_WRAPPERS_PREFIX "vsched: "
37 #define ENSC_WRAPPERS_VSERVER 1
38 #define ENSC_WRAPPERS_UNISTD 1
39 #define ENSC_WRAPPERS_FCNTL 1
40 #define ENSC_WRAPPERS_DIRENT 1
41 #define ENSC_WRAPPERS_STAT 1
44 #define CMD_HELP 0x1000
45 #define CMD_VERSION 0x1001
46 #define CMD_XID 0x4000
47 #define CMD_FRATE 0x4001
48 #define CMD_INTERVAL 0x4002
49 #define CMD_TOKENS 0x4003
50 #define CMD_TOK_MIN 0x4004
51 #define CMD_TOK_MAX 0x4005
52 #define CMD_CPU_MASK 0x4006
53 #define CMD_PRIO_BIAS 0x4007
54 #define CMD_FRATE2 0x4008
55 #define CMD_INTERVAL2 0x4009
56 #define CMD_CPUID 0x400a
57 #define CMD_BUCKETID 0x400b
58 #define CMD_FORCE 0x400c
59 #define CMD_IDLE_TIME 0x400d
60 #define CMD_DIR 0x400e
61 #define CMD_MISSING 0x400f
63 int wrapper_exit_code = 255;
67 { "help", no_argument, 0, CMD_HELP },
68 { "version", no_argument, 0, CMD_VERSION },
69 { "ctx", required_argument, 0, CMD_XID },
70 { "xid", required_argument, 0, CMD_XID },
71 { "fill-rate", required_argument, 0, CMD_FRATE },
72 { "interval", required_argument, 0, CMD_INTERVAL },
73 { "tokens", required_argument, 0, CMD_TOKENS },
74 { "tokens_min", required_argument, 0, CMD_TOK_MIN },
75 { "tokens-min", required_argument, 0, CMD_TOK_MIN },
76 { "tokens_max", required_argument, 0, CMD_TOK_MAX },
77 { "tokens-max", required_argument, 0, CMD_TOK_MAX },
78 { "prio_bias", required_argument, 0, CMD_PRIO_BIAS },
79 { "prio-bias", required_argument, 0, CMD_PRIO_BIAS },
80 { "priority_bias", required_argument, 0, CMD_PRIO_BIAS },
81 { "priority-bias", required_argument, 0, CMD_PRIO_BIAS },
82 { "cpu_mask", required_argument, 0, CMD_CPU_MASK },
83 { "fill-rate2", required_argument, 0, CMD_FRATE2 },
84 { "interval2", required_argument, 0, CMD_INTERVAL2 },
85 { "cpu-id", required_argument, 0, CMD_CPUID },
86 { "bucket-id", required_argument, 0, CMD_BUCKETID },
87 { "force", no_argument, 0, CMD_FORCE },
88 { "idle-time", no_argument, 0, CMD_IDLE_TIME },
89 { "dir", required_argument, 0, CMD_DIR },
90 { "missingok", no_argument, 0, CMD_MISSING },
95 const char * const name;
99 #define FOPT(NAME,MASK,FIELD) { #NAME, MASK, offsetof(struct vc_set_sched, FIELD) }
100 static struct sched_opt FILE_OPTIONS[] = {
101 FOPT(fill-rate, VC_VXSM_FILL_RATE, fill_rate),
102 FOPT(interval, VC_VXSM_INTERVAL, interval),
103 FOPT(tokens, VC_VXSM_TOKENS, tokens),
104 FOPT(tokens-min, VC_VXSM_TOKENS_MIN, tokens_min),
105 FOPT(tokens-max, VC_VXSM_TOKENS_MAX, tokens_max),
106 FOPT(prio-bias, VC_VXSM_PRIO_BIAS, priority_bias),
107 FOPT(priority-bias, VC_VXSM_PRIO_BIAS, priority_bias),
108 FOPT(fill-rate2, VC_VXSM_FILL_RATE2|VC_VXSM_IDLE_TIME, fill_rate2),
109 FOPT(interval2, VC_VXSM_INTERVAL2|VC_VXSM_IDLE_TIME, interval2),
110 FOPT(cpu-id, VC_VXSM_CPU_ID, cpu_id),
111 FOPT(bucket-id, VC_VXSM_BUCKET_ID, bucket_id),
112 FOPT(idle-time, VC_VXSM_IDLE_TIME, set_mask),
117 showHelp(int fd, char const *cmd, int res)
119 VSERVER_DECLARE_CMD(cmd);
121 WRITE_MSG(fd, "Usage:\n ");
124 " [--xid <xid>] <sched options>* [--dir <dir>] [--] [<command> <args>*]\n"
127 " --fill-rate <rate>\n"
128 " --interval <interval>\n"
129 " --tokens <tokens>\n"
130 " --tokens-min <tokens>\n"
131 " --tokens-max <tokens>\n"
132 " --prio-bias <bias>\n"
133 " --fill-rate2 <rate>\n"
134 " --interval2 <interval>\n"
135 " --cpu-id <CPU id>\n"
136 " --bucket-id <bucket id>\n"
137 " --idle-time ... set the idle time flag; this is required for\n"
138 " all updates to the scheduler to keep it enabled\n"
139 " --force ... force update of all per-CPU schedulers now\n"
140 " --dir <dir> ... read settings from <dir>\n"
141 " --missingok ... do not fail when <dir> does not exist\n"
142 "\nPlease report bugs to " PACKAGE_BUGREPORT "\n");
151 "vsched " VERSION " -- modifies scheduling parameters\n"
152 "This program is part of " PACKAGE_STRING "\n\n"
153 "Copyright (C) 2003,2004 Enrico Scholz\n"
154 "Copyright (C) 2006 Daniel Hokka Zakrisson\n"
155 VERSION_COPYRIGHT_DISCLAIMER);
159 static void do_dir_entry(struct vc_set_sched *sched, const char *name)
164 struct sched_opt *opt;
168 for (opt = FILE_OPTIONS; opt->name != 0; opt++) {
169 if (strcmp(name, opt->name) == 0)
175 fd = Eopen(name, O_RDONLY, 0);
176 len = Eread(fd, buf, sizeof(buf)-1);
179 if ((newline=strchr(buf, '\n')) != NULL)
182 if (!isNumber(buf, &val, true)) {
183 WRITE_MSG(2, ENSC_WRAPPERS_PREFIX);
185 WRITE_MSG(2, ": is not a number\n");
189 if (opt->offset != offsetof(struct vc_set_sched, set_mask))
190 *(int_least32_t *)(((char *)sched)+opt->offset) = (int_least32_t) val;
192 sched->set_mask |= opt->mask;
195 static void do_dir(xid_t xid, struct vc_set_sched *sched, const char *dir, int missing_ok, int per_cpu)
199 int cur_fd = Eopen(".", O_RDONLY, 0);
202 if (chdir(dir)!=-1) {
204 while ((de = Ereaddir(dp)) != NULL) {
205 if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
207 Estat(de->d_name, &st);
208 if (S_ISDIR(st.st_mode))
210 do_dir_entry(sched, de->d_name);
213 /* set the values now */
214 if (vc_set_sched(xid, sched) == -1) {
215 perror(ENSC_WRAPPERS_PREFIX "vc_set_sched()");
220 struct vc_set_sched per_cpu_sched;
223 while ((de = Ereaddir(dp)) != NULL) {
224 if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
226 Estat(de->d_name, &st);
227 if (S_ISDIR(st.st_mode)) {
228 per_cpu_sched.set_mask = sched->set_mask & (VC_VXSM_IDLE_TIME|VC_VXSM_FORCE);
229 do_dir(xid, &per_cpu_sched, de->d_name, 0, 1);
236 else if (!missing_ok) {
237 perror(ENSC_WRAPPERS_PREFIX "chdir()");
238 exit(wrapper_exit_code);
244 #define SETVAL(ATTR,MASK) \
245 if (!isNumber(optarg, &tmp, false)) { \
246 WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "non-numeric value specified for '--" #ATTR "'\n"); \
247 exit(wrapper_exit_code); \
251 sched.set_mask |= MASK; \
254 int main(int argc, char *argv[])
256 xid_t xid = VC_NOCTX;
258 struct vc_set_sched sched = {
261 const char *dir = NULL;
265 int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
269 case CMD_HELP : showHelp(1, argv[0], 0);
270 case CMD_VERSION : showVersion();
271 case CMD_XID : xid = Evc_xidopt2xid(optarg,true); break;
272 case CMD_FRATE : SETVAL(fill_rate, VC_VXSM_FILL_RATE); break;
273 case CMD_INTERVAL : SETVAL(interval, VC_VXSM_INTERVAL); break;
274 case CMD_TOKENS : SETVAL(tokens, VC_VXSM_TOKENS); break;
275 case CMD_TOK_MIN : SETVAL(tokens_min, VC_VXSM_TOKENS_MIN); break;
276 case CMD_TOK_MAX : SETVAL(tokens_max, VC_VXSM_TOKENS_MAX); break;
277 case CMD_PRIO_BIAS: SETVAL(priority_bias, VC_VXSM_PRIO_BIAS); break;
279 WRITE_MSG(2, "vsched: WARNING: the '--cpu_mask' parameter is deprecated and will not have any effect\n");
281 case CMD_FRATE2 : SETVAL(fill_rate2, VC_VXSM_FILL_RATE2); break;
282 case CMD_INTERVAL2: SETVAL(interval2, VC_VXSM_INTERVAL2); break;
283 case CMD_CPUID : SETVAL(cpu_id, VC_VXSM_CPU_ID); break;
284 case CMD_BUCKETID : SETVAL(bucket_id, VC_VXSM_BUCKET_ID); break;
285 case CMD_DIR : dir = optarg; break;
286 case CMD_MISSING : missing_ok = 1; break;
287 case CMD_FORCE : sched.set_mask |= VC_VXSM_FORCE; break;
288 case CMD_IDLE_TIME: sched.set_mask |= VC_VXSM_IDLE_TIME; break;
290 WRITE_MSG(2, "Try '");
291 WRITE_STR(2, argv[0]);
292 WRITE_MSG(2, " --help' for more information.\n");
298 if (xid==VC_NOCTX && optind==argc) {
299 WRITE_MSG(2, "Without a program, '--xid' must be used; try '--help' for more information\n");
300 exit(wrapper_exit_code);
303 if (sched.set_mask==0 && dir==NULL && optind==argc) {
304 WRITE_MSG(2, "Neither an option nor a program was specified; try '--help' for more information\n");
305 exit(wrapper_exit_code);
309 xid = Evc_get_task_xid(0);
312 do_dir(xid, &sched, dir, missing_ok, 0);
315 if (sched.set_mask!=0 && vc_set_sched(xid, &sched)==-1) {
316 perror("vc_set_sched()");
322 EexecvpD(argv[optind],argv+optind);