|
63 | 63 | #include <sched.h>
|
64 | 64 | #include <sys/sysinfo.h>
|
65 | 65 | #include <vector>
|
| 66 | +#include <set> |
| 67 | +#include <sstream> |
66 | 68 | #include <string>
|
67 | 69 | #include <utility>
|
68 | 70 |
|
@@ -465,6 +467,50 @@ void output_exit_time(int exitcode, double cpudiff)
|
465 | 467 | write_meta("time-result","%s",output_timelimit_str[timelimit_reached]);
|
466 | 468 | }
|
467 | 469 |
|
| 470 | +std::set<unsigned> parse_cpuset(std::string cpus) |
| 471 | +{ |
| 472 | + std::stringstream ss(cpus); |
| 473 | + std::set<unsigned> result; |
| 474 | + |
| 475 | + std::string token; |
| 476 | + while ( getline(ss, token, ',') ) { |
| 477 | + size_t split = token.find('-'); |
| 478 | + if ( split!=std::string::npos ) { |
| 479 | + std::string token1 = token.substr(0, split); |
| 480 | + std::string token2 = token.substr(split+1); |
| 481 | + size_t len; |
| 482 | + unsigned cpu1 = std::stoul(token1, &len); |
| 483 | + if ( len<token1.length() ) error(0, "failed to parse cpuset `%s'", cpus.c_str()); |
| 484 | + unsigned cpu2 = std::stoul(token2, &len); |
| 485 | + if ( len<token2.length() ) error(0, "failed to parse cpuset `%s'", cpus.c_str()); |
| 486 | + for(unsigned i=cpu1; i<=cpu2; i++) result.insert(i); |
| 487 | + } else { |
| 488 | + size_t len; |
| 489 | + unsigned cpu = std::stoul(token, &len); |
| 490 | + if ( len<token.length() ) error(0, "failed to parse cpuset `%s'", cpus.c_str()); |
| 491 | + result.insert(cpu); |
| 492 | + } |
| 493 | + } |
| 494 | + |
| 495 | + return result; |
| 496 | +} |
| 497 | + |
| 498 | +std::set<unsigned> read_cpuset(const char *path) |
| 499 | +{ |
| 500 | + FILE *file = fopen(path, "r"); |
| 501 | + if (file == nullptr) error(errno, "opening file `%s'", path); |
| 502 | + |
| 503 | + char cpuset[1024]; |
| 504 | + if (fgets(cpuset, 1024, file) == nullptr) error(errno, "reading from file `%s'", path); |
| 505 | + |
| 506 | + size_t len = strlen(cpuset); |
| 507 | + if (len > 0 && cpuset[len-1] == '\n') cpuset[len-1] = 0; |
| 508 | + |
| 509 | + if (fclose(file) != 0) error(errno, "closing file `%s'", path); |
| 510 | + |
| 511 | + return parse_cpuset(cpuset); |
| 512 | +} |
| 513 | + |
468 | 514 | void check_remaining_procs()
|
469 | 515 | {
|
470 | 516 | char path[1024];
|
@@ -1296,14 +1342,12 @@ int main(int argc, char **argv)
|
1296 | 1342 | }
|
1297 | 1343 |
|
1298 | 1344 | if ( cpuset!=nullptr && strlen(cpuset)>0 ) {
|
1299 | | - int ret = strtol(cpuset, &ptr, 10); |
1300 | | - /* check if input is only a single integer */ |
1301 | | - if ( *ptr == '0円' ) { |
1302 | | - /* check if we have enough cores available */ |
1303 | | - int nprocs = get_nprocs_conf(); |
1304 | | - if ( ret < 0 || ret >= nprocs ) { |
1305 | | - error(0, "processor ID %d given as cpuset, but only %d cores configured", |
1306 | | - ret, nprocs); |
| 1345 | + std::set<unsigned> cpus = parse_cpuset(cpuset); |
| 1346 | + std::set<unsigned> online_cpus = read_cpuset("/sys/devices/system/cpu/online"); |
| 1347 | + |
| 1348 | + for(unsigned cpu : cpus) { |
| 1349 | + if ( !online_cpus.count(cpu) ) { |
| 1350 | + error(0, "requested pinning on CPU %u which is not online", cpu); |
1307 | 1351 | }
|
1308 | 1352 | }
|
1309 | 1353 | }
|
|
0 commit comments