diff options
| -rw-r--r-- | kernel/sched/litmus.c | 2 | ||||
| -rw-r--r-- | litmus/polling_reservations.c | 28 | ||||
| -rw-r--r-- | litmus/reservation.c | 98 | ||||
| -rw-r--r-- | litmus/sched_mc2.c | 337 |
4 files changed, 187 insertions, 278 deletions
diff --git a/kernel/sched/litmus.c b/kernel/sched/litmus.c index b84361f03f60..29cd69d5aa0c 100644 --- a/kernel/sched/litmus.c +++ b/kernel/sched/litmus.c | |||
| @@ -73,7 +73,7 @@ litmus_schedule(struct rq *rq, struct task_struct *prev) | |||
| 73 | if (next->rt_param.stack_in_use == NO_CPU) | 73 | if (next->rt_param.stack_in_use == NO_CPU) |
| 74 | TRACE_TASK(next,"descheduled. Proceeding.\n"); | 74 | TRACE_TASK(next,"descheduled. Proceeding.\n"); |
| 75 | 75 | ||
| 76 | if (lt_before(_maybe_deadlock + 1000000000L, | 76 | if (lt_before(_maybe_deadlock + 5000000000L, |
| 77 | litmus_clock())) { | 77 | litmus_clock())) { |
| 78 | /* We've been spinning for 1s. | 78 | /* We've been spinning for 1s. |
| 79 | * Something can't be right! | 79 | * Something can't be right! |
diff --git a/litmus/polling_reservations.c b/litmus/polling_reservations.c index a3125ebf5273..df1aeb0a113f 100644 --- a/litmus/polling_reservations.c +++ b/litmus/polling_reservations.c | |||
| @@ -383,11 +383,7 @@ static lt_t td_time_remaining_until_end(struct table_driven_reservation *tdres) | |||
| 383 | { | 383 | { |
| 384 | lt_t now = tdres->res.env->current_time; | 384 | lt_t now = tdres->res.env->current_time; |
| 385 | lt_t end = tdres->cur_interval.end; | 385 | lt_t end = tdres->cur_interval.end; |
| 386 | TRACE("td_remaining(%u): start=%llu now=%llu end=%llu state=%d\n", | 386 | //TRACE("td_remaining(%u): start=%llu now=%llu end=%llu state=%d\n", tdres->res.id, tdres->cur_interval.start, now, end, tdres->res.state); |
| 387 | tdres->res.id, | ||
| 388 | tdres->cur_interval.start, | ||
| 389 | now, end, | ||
| 390 | tdres->res.state); | ||
| 391 | if (now >= end) | 387 | if (now >= end) |
| 392 | return 0; | 388 | return 0; |
| 393 | else | 389 | else |
| @@ -400,24 +396,22 @@ static void td_replenish( | |||
| 400 | struct table_driven_reservation *tdres = | 396 | struct table_driven_reservation *tdres = |
| 401 | container_of(res, struct table_driven_reservation, res); | 397 | container_of(res, struct table_driven_reservation, res); |
| 402 | 398 | ||
| 403 | TRACE("td_replenish(%u): expected_replenishment=%llu\n", res->id, | 399 | //TRACE("td_replenish(%u): expected_replenishment=%llu\n", res->id, res->next_replenishment); |
| 404 | res->next_replenishment); | ||
| 405 | 400 | ||
| 406 | /* figure out current interval */ | 401 | /* figure out current interval */ |
| 407 | tdres->cur_interval.start = tdres->major_cycle_start + | 402 | tdres->cur_interval.start = tdres->major_cycle_start + |
| 408 | tdres->intervals[tdres->next_interval].start; | 403 | tdres->intervals[tdres->next_interval].start; |
| 409 | tdres->cur_interval.end = tdres->major_cycle_start + | 404 | tdres->cur_interval.end = tdres->major_cycle_start + |
| 410 | tdres->intervals[tdres->next_interval].end; | 405 | tdres->intervals[tdres->next_interval].end; |
| 411 | TRACE("major_cycle_start=%llu => [%llu, %llu]\n", | 406 | /* TRACE("major_cycle_start=%llu => [%llu, %llu]\n", |
| 412 | tdres->major_cycle_start, | 407 | tdres->major_cycle_start, |
| 413 | tdres->cur_interval.start, | 408 | tdres->cur_interval.start, |
| 414 | tdres->cur_interval.end); | 409 | tdres->cur_interval.end); |
| 415 | 410 | */ | |
| 416 | /* reset budget */ | 411 | /* reset budget */ |
| 417 | res->cur_budget = td_time_remaining_until_end(tdres); | 412 | res->cur_budget = td_time_remaining_until_end(tdres); |
| 418 | res->budget_consumed = 0; | 413 | res->budget_consumed = 0; |
| 419 | TRACE("td_replenish(%u): %s budget=%llu\n", res->id, | 414 | //TRACE("td_replenish(%u): %s budget=%llu\n", res->id, res->cur_budget ? "" : "WARNING", res->cur_budget); |
| 420 | res->cur_budget ? "" : "WARNING", res->cur_budget); | ||
| 421 | 415 | ||
| 422 | /* prepare next slot */ | 416 | /* prepare next slot */ |
| 423 | tdres->next_interval = (tdres->next_interval + 1) % tdres->num_intervals; | 417 | tdres->next_interval = (tdres->next_interval + 1) % tdres->num_intervals; |
| @@ -428,8 +422,7 @@ static void td_replenish( | |||
| 428 | /* determine next time this reservation becomes eligible to execute */ | 422 | /* determine next time this reservation becomes eligible to execute */ |
| 429 | res->next_replenishment = tdres->major_cycle_start; | 423 | res->next_replenishment = tdres->major_cycle_start; |
| 430 | res->next_replenishment += tdres->intervals[tdres->next_interval].start; | 424 | res->next_replenishment += tdres->intervals[tdres->next_interval].start; |
| 431 | TRACE("td_replenish(%u): next_replenishment=%llu\n", res->id, | 425 | //TRACE("td_replenish(%u): next_replenishment=%llu\n", res->id, res->next_replenishment); |
| 432 | res->next_replenishment); | ||
| 433 | 426 | ||
| 434 | 427 | ||
| 435 | switch (res->state) { | 428 | switch (res->state) { |
| @@ -465,7 +458,7 @@ static void td_drain_budget( | |||
| 465 | * how much time is left in this allocation interval. */ | 458 | * how much time is left in this allocation interval. */ |
| 466 | 459 | ||
| 467 | /* sanity check: we should never try to drain from future slots */ | 460 | /* sanity check: we should never try to drain from future slots */ |
| 468 | TRACE("TD_DRAIN STATE(%d) [%llu,%llu] %llu ?\n", res->state, tdres->cur_interval.start, tdres->cur_interval.end, res->env->current_time); | 461 | //TRACE("TD_DRAIN STATE(%d) [%llu,%llu] %llu ?\n", res->state, tdres->cur_interval.start, tdres->cur_interval.end, res->env->current_time); |
| 469 | //BUG_ON(tdres->cur_interval.start > res->env->current_time); | 462 | //BUG_ON(tdres->cur_interval.start > res->env->current_time); |
| 470 | if (tdres->cur_interval.start > res->env->current_time) | 463 | if (tdres->cur_interval.start > res->env->current_time) |
| 471 | TRACE("TD_DRAIN BUG!!!!!!!!!!\n"); | 464 | TRACE("TD_DRAIN BUG!!!!!!!!!!\n"); |
| @@ -480,8 +473,7 @@ static void td_drain_budget( | |||
| 480 | case RESERVATION_ACTIVE_IDLE: | 473 | case RESERVATION_ACTIVE_IDLE: |
| 481 | case RESERVATION_ACTIVE: | 474 | case RESERVATION_ACTIVE: |
| 482 | res->cur_budget = td_time_remaining_until_end(tdres); | 475 | res->cur_budget = td_time_remaining_until_end(tdres); |
| 483 | TRACE("td_drain_budget(%u): drained to budget=%llu\n", | 476 | //TRACE("td_drain_budget(%u): drained to budget=%llu\n", res->id, res->cur_budget); |
| 484 | res->id, res->cur_budget); | ||
| 485 | if (!res->cur_budget) { | 477 | if (!res->cur_budget) { |
| 486 | res->env->change_state(res->env, res, | 478 | res->env->change_state(res->env, res, |
| 487 | RESERVATION_DEPLETED); | 479 | RESERVATION_DEPLETED); |
| @@ -489,6 +481,10 @@ static void td_drain_budget( | |||
| 489 | /* sanity check budget calculation */ | 481 | /* sanity check budget calculation */ |
| 490 | //BUG_ON(res->env->current_time >= tdres->cur_interval.end); | 482 | //BUG_ON(res->env->current_time >= tdres->cur_interval.end); |
| 491 | //BUG_ON(res->env->current_time < tdres->cur_interval.start); | 483 | //BUG_ON(res->env->current_time < tdres->cur_interval.start); |
| 484 | if (res->env->current_time >= tdres->cur_interval.end) | ||
| 485 | printk(KERN_ALERT "TD_DRAIN_BUDGET WARNING1\n"); | ||
| 486 | if (res->env->current_time < tdres->cur_interval.start) | ||
| 487 | printk(KERN_ALERT "TD_DRAIN_BUDGET WARNING2\n"); | ||
| 492 | } | 488 | } |
| 493 | 489 | ||
| 494 | break; | 490 | break; |
diff --git a/litmus/reservation.c b/litmus/reservation.c index 3ec18a23f588..86d2f6e65382 100644 --- a/litmus/reservation.c +++ b/litmus/reservation.c | |||
| @@ -4,6 +4,9 @@ | |||
| 4 | #include <litmus/litmus.h> | 4 | #include <litmus/litmus.h> |
| 5 | #include <litmus/reservation.h> | 5 | #include <litmus/reservation.h> |
| 6 | 6 | ||
| 7 | #define TRACE(fmt, args...) do {} while (false) | ||
| 8 | #define TRACE_TASK(fmt, args...) do {} while (false) | ||
| 9 | |||
| 7 | void reservation_init(struct reservation *res) | 10 | void reservation_init(struct reservation *res) |
| 8 | { | 11 | { |
| 9 | memset(res, sizeof(*res), 0); | 12 | memset(res, sizeof(*res), 0); |
| @@ -376,43 +379,6 @@ struct next_timer_event* gmp_find_event_by_time(struct gmp_reservation_environme | |||
| 376 | return NULL; | 379 | return NULL; |
| 377 | } | 380 | } |
| 378 | 381 | ||
| 379 | /* | ||
| 380 | static void gmp_scheduler_update_at( | ||
| 381 | struct gmp_reservation_environment* gmp_env, unsigned int id, | ||
| 382 | event_type_t type, lt_t when) | ||
| 383 | { | ||
| 384 | struct next_timer_event *nevent, *queued; | ||
| 385 | struct list_head *pos; | ||
| 386 | int found = 0; | ||
| 387 | |||
| 388 | nevent = gmp_find_event_by_id(gmp_env, id); | ||
| 389 | |||
| 390 | if (!nevent) { | ||
| 391 | nevent = kzalloc(sizeof(*nevent), GFP_KERNEL); | ||
| 392 | nevent->next_update = when; | ||
| 393 | nevent->id = id; | ||
| 394 | nevent->timer_armed_on = NO_CPU; | ||
| 395 | nevent->type = type; | ||
| 396 | |||
| 397 | list_for_each(pos, &gmp_env->next_events) { | ||
| 398 | queued = list_entry(pos, struct next_timer_event, list); | ||
| 399 | if (queued->next_update > nevent->next_update) { | ||
| 400 | list_add(&nevent->list, pos->prev); | ||
| 401 | found = 1; | ||
| 402 | TRACE("NEXT_EVENT ADDED after %llu\n", queued->next_update); | ||
| 403 | break; | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 407 | if (!found) { | ||
| 408 | list_add_tail(&nevent->list, &gmp_env->next_events); | ||
| 409 | TRACE("NEXT_EVENT ADDED at [0]\n"); | ||
| 410 | } | ||
| 411 | } else { | ||
| 412 | TRACE("EVENT FOUND at %llu T(%d), NEW EVENT %llu T(%d)\n", nevent->next_update, nevent->type, when, type); | ||
| 413 | } | ||
| 414 | } | ||
| 415 | */ | ||
| 416 | #define TIMER_RESOLUTION 100000L | 382 | #define TIMER_RESOLUTION 100000L |
| 417 | 383 | ||
| 418 | static void gmp_add_event( | 384 | static void gmp_add_event( |
| @@ -425,11 +391,12 @@ static void gmp_add_event( | |||
| 425 | 391 | ||
| 426 | //when = div64_u64(when, TIMER_RESOLUTION); | 392 | //when = div64_u64(when, TIMER_RESOLUTION); |
| 427 | //when *= TIMER_RESOLUTION; | 393 | //when *= TIMER_RESOLUTION; |
| 428 | 394 | //printk(KERN_ALERT "GMP_ADD id=%d type=%d when=%llu\n", id, type, when); | |
| 429 | nevent = gmp_find_event_by_id(gmp_env, id); | 395 | nevent = gmp_find_event_by_id(gmp_env, id); |
| 430 | 396 | ||
| 431 | if (!nevent || nevent->type != type) { | 397 | if (!nevent || nevent->type != type) { |
| 432 | nevent = kzalloc(sizeof(*nevent), GFP_ATOMIC); | 398 | nevent = kzalloc(sizeof(*nevent), GFP_ATOMIC); |
| 399 | BUG_ON(!nevent); | ||
| 433 | nevent->next_update = when; | 400 | nevent->next_update = when; |
| 434 | nevent->id = id; | 401 | nevent->id = id; |
| 435 | nevent->type = type; | 402 | nevent->type = type; |
| @@ -450,17 +417,19 @@ static void gmp_add_event( | |||
| 450 | TRACE("NEXT_EVENT id=%d type=%d update=%llu ADDED at TAIL\n", nevent->id, nevent->type, nevent->next_update); | 417 | TRACE("NEXT_EVENT id=%d type=%d update=%llu ADDED at TAIL\n", nevent->id, nevent->type, nevent->next_update); |
| 451 | } | 418 | } |
| 452 | } else { | 419 | } else { |
| 453 | TRACE("EVENT FOUND id = %d type=%d when=%llu, NEW EVENT type=%d when=%llu\n", nevent->id, nevent->type, nevent->next_update, type, when); | 420 | //TRACE("EVENT FOUND id = %d type=%d when=%llu, NEW EVENT type=%d when=%llu\n", nevent->id, nevent->type, nevent->next_update, type, when); |
| 421 | ; //printk(KERN_ALERT "EVENT FOUND id = %d type=%d when=%llu, NEW EVENT type=%d when=%llu\n", nevent->id, nevent->type, nevent->next_update, type, when); | ||
| 454 | } | 422 | } |
| 455 | 423 | ||
| 456 | TRACE("======START PRINTING EVENT LIST======\n"); | 424 | //TRACE("======START PRINTING EVENT LIST======\n"); |
| 457 | gmp_print_events(gmp_env, litmus_clock()); | 425 | //gmp_print_events(gmp_env, litmus_clock()); |
| 458 | TRACE("======FINISH PRINTING EVENT LIST======\n"); | 426 | //TRACE("======FINISH PRINTING EVENT LIST======\n"); |
| 459 | } | 427 | } |
| 460 | 428 | ||
| 461 | void gmp_add_event_after( | 429 | void gmp_add_event_after( |
| 462 | struct gmp_reservation_environment* gmp_env, lt_t timeout, unsigned int id, event_type_t type) | 430 | struct gmp_reservation_environment* gmp_env, lt_t timeout, unsigned int id, event_type_t type) |
| 463 | { | 431 | { |
| 432 | //printk(KERN_ALERT "ADD_EVENT_AFTER id = %d\n", id); | ||
| 464 | gmp_add_event(gmp_env, gmp_env->env.current_time + timeout, id, type); | 433 | gmp_add_event(gmp_env, gmp_env->env.current_time + timeout, id, type); |
| 465 | } | 434 | } |
| 466 | 435 | ||
| @@ -472,19 +441,24 @@ static void gmp_queue_depleted( | |||
| 472 | struct reservation *queued; | 441 | struct reservation *queued; |
| 473 | int found = 0; | 442 | int found = 0; |
| 474 | 443 | ||
| 444 | //printk(KERN_ALERT "R%d request to enqueue depleted_list\n", res->id); | ||
| 445 | |||
| 475 | list_for_each(pos, &gmp_env->depleted_reservations) { | 446 | list_for_each(pos, &gmp_env->depleted_reservations) { |
| 476 | queued = list_entry(pos, struct reservation, list); | 447 | queued = list_entry(pos, struct reservation, list); |
| 477 | if (queued && queued->next_replenishment > res->next_replenishment) { | 448 | if (queued && (queued->next_replenishment > res->next_replenishment)) { |
| 449 | //printk(KERN_ALERT "QUEUED R%d %llu\n", queued->id, queued->next_replenishment); | ||
| 478 | list_add(&res->list, pos->prev); | 450 | list_add(&res->list, pos->prev); |
| 479 | found = 1; | 451 | found = 1; |
| 452 | break; | ||
| 480 | } | 453 | } |
| 481 | } | 454 | } |
| 482 | 455 | ||
| 483 | if (!found) | 456 | if (!found) |
| 484 | list_add_tail(&res->list, &gmp_env->depleted_reservations); | 457 | list_add_tail(&res->list, &gmp_env->depleted_reservations); |
| 458 | |||
| 485 | TRACE("R%d queued to depleted_list\n", res->id); | 459 | TRACE("R%d queued to depleted_list\n", res->id); |
| 460 | //printk(KERN_ALERT "R%d queued to depleted_list\n", res->id); | ||
| 486 | gmp_add_event(gmp_env, res->next_replenishment, res->id, EVENT_REPLENISH); | 461 | gmp_add_event(gmp_env, res->next_replenishment, res->id, EVENT_REPLENISH); |
| 487 | res->event_added = 1; | ||
| 488 | } | 462 | } |
| 489 | 463 | ||
| 490 | static void gmp_queue_active( | 464 | static void gmp_queue_active( |
| @@ -520,10 +494,8 @@ static void gmp_queue_reservation( | |||
| 520 | struct gmp_reservation_environment* gmp_env, | 494 | struct gmp_reservation_environment* gmp_env, |
| 521 | struct reservation *res) | 495 | struct reservation *res) |
| 522 | { | 496 | { |
| 523 | if (res == NULL) { | 497 | |
| 524 | BUG(); | 498 | //printk(KERN_ALERT "DEBUG: Passed %s %d %p R%d STATE %d\n",__FUNCTION__,__LINE__, gmp_env, res->id, res->state); |
| 525 | return; | ||
| 526 | } | ||
| 527 | switch (res->state) { | 499 | switch (res->state) { |
| 528 | case RESERVATION_INACTIVE: | 500 | case RESERVATION_INACTIVE: |
| 529 | list_add(&res->list, &gmp_env->inactive_reservations); | 501 | list_add(&res->list, &gmp_env->inactive_reservations); |
| @@ -584,8 +556,7 @@ static void gmp_charge_budget( | |||
| 584 | { | 556 | { |
| 585 | /* make sure scheduler is invoked when this reservation expires | 557 | /* make sure scheduler is invoked when this reservation expires |
| 586 | * its remaining budget */ | 558 | * its remaining budget */ |
| 587 | TRACE("requesting gmp_scheduler update for reservation %u in %llu nanoseconds\n", | 559 | TRACE("requesting gmp_scheduler update for reservation %u in %llu nanoseconds\n", res->id, res->cur_budget); |
| 588 | res->id, res->cur_budget); | ||
| 589 | gmp_add_event_after(gmp_env, res->cur_budget, res->id, EVENT_DRAIN); | 560 | gmp_add_event_after(gmp_env, res->cur_budget, res->id, EVENT_DRAIN); |
| 590 | res->event_added = 1; | 561 | res->event_added = 1; |
| 591 | } | 562 | } |
| @@ -593,7 +564,7 @@ static void gmp_charge_budget( | |||
| 593 | /* stop at the first ACTIVE reservation */ | 564 | /* stop at the first ACTIVE reservation */ |
| 594 | // break; | 565 | // break; |
| 595 | } | 566 | } |
| 596 | //TRACE("finished charging budgets\n"); | 567 | TRACE("finished charging budgets\n"); |
| 597 | } | 568 | } |
| 598 | 569 | ||
| 599 | static void gmp_replenish_budgets(struct gmp_reservation_environment* gmp_env) | 570 | static void gmp_replenish_budgets(struct gmp_reservation_environment* gmp_env) |
| @@ -611,24 +582,6 @@ static void gmp_replenish_budgets(struct gmp_reservation_environment* gmp_env) | |||
| 611 | } | 582 | } |
| 612 | } | 583 | } |
| 613 | TRACE("finished replenishing budgets\n"); | 584 | TRACE("finished replenishing budgets\n"); |
| 614 | |||
| 615 | /* request a scheduler update at the next replenishment instant */ | ||
| 616 | list_for_each_safe(pos, next, &gmp_env->depleted_reservations) { | ||
| 617 | res = list_entry(pos, struct reservation, list); | ||
| 618 | if (res->event_added == 0) { | ||
| 619 | gmp_add_event(gmp_env, res->next_replenishment, res->id, EVENT_REPLENISH); | ||
| 620 | res->event_added = 1; | ||
| 621 | } | ||
| 622 | } | ||
| 623 | |||
| 624 | /* | ||
| 625 | res = list_first_entry_or_null(&gmp_env->depleted_reservations, | ||
| 626 | struct reservation, list); | ||
| 627 | if (res && res->event_added == 0) { | ||
| 628 | gmp_add_event(gmp_env, res->next_replenishment, res->id, EVENT_REPLENISH); | ||
| 629 | res->event_added = 1; | ||
| 630 | } | ||
| 631 | */ | ||
| 632 | } | 585 | } |
| 633 | 586 | ||
| 634 | #define EPSILON 50 | 587 | #define EPSILON 50 |
| @@ -644,7 +597,7 @@ int gmp_update_time( | |||
| 644 | /* If the time didn't advance, there is nothing to do. | 597 | /* If the time didn't advance, there is nothing to do. |
| 645 | * This check makes it safe to call sup_advance_time() potentially | 598 | * This check makes it safe to call sup_advance_time() potentially |
| 646 | * multiple times (e.g., via different code paths. */ | 599 | * multiple times (e.g., via different code paths. */ |
| 647 | TRACE("(gmp_update_time) now: %llu, current_time: %llu\n", now, gmp_env->env.current_time); | 600 | //TRACE("(gmp_update_time) now: %llu, current_time: %llu\n", now, gmp_env->env.current_time); |
| 648 | if (unlikely(now <= gmp_env->env.current_time + EPSILON)) | 601 | if (unlikely(now <= gmp_env->env.current_time + EPSILON)) |
| 649 | return 0; | 602 | return 0; |
| 650 | 603 | ||
| @@ -660,12 +613,15 @@ int gmp_update_time( | |||
| 660 | /* check if any budgets where replenished */ | 613 | /* check if any budgets where replenished */ |
| 661 | //TRACE("REPLENISH###\n"); | 614 | //TRACE("REPLENISH###\n"); |
| 662 | gmp_replenish_budgets(gmp_env); | 615 | gmp_replenish_budgets(gmp_env); |
| 616 | |||
| 663 | 617 | ||
| 664 | list_for_each_entry_safe(event, next, &gmp_env->next_events, list) { | 618 | list_for_each_entry_safe(event, next, &gmp_env->next_events, list) { |
| 665 | if (event->next_update < now) { | 619 | if (event->next_update < now) { |
| 666 | list_del(&event->list); | 620 | list_del(&event->list); |
| 667 | TRACE("EVENT at %llu IS DELETED\n", event->next_update); | 621 | TRACE("EVENT at %llu IS DELETED\n", event->next_update); |
| 668 | kfree(event); | 622 | kfree(event); |
| 623 | } else { | ||
| 624 | break; | ||
| 669 | } | 625 | } |
| 670 | } | 626 | } |
| 671 | 627 | ||
| @@ -673,7 +629,7 @@ int gmp_update_time( | |||
| 673 | 629 | ||
| 674 | ret = min(gmp_env->schedule_now, NR_CPUS); | 630 | ret = min(gmp_env->schedule_now, NR_CPUS); |
| 675 | gmp_env->schedule_now = 0; | 631 | gmp_env->schedule_now = 0; |
| 676 | 632 | ||
| 677 | return ret; | 633 | return ret; |
| 678 | } | 634 | } |
| 679 | 635 | ||
diff --git a/litmus/sched_mc2.c b/litmus/sched_mc2.c index b3390dc87d47..f7758f2aff58 100644 --- a/litmus/sched_mc2.c +++ b/litmus/sched_mc2.c | |||
| @@ -62,7 +62,6 @@ struct mc2_task_state { | |||
| 62 | struct crit_entry { | 62 | struct crit_entry { |
| 63 | enum crit_level level; | 63 | enum crit_level level; |
| 64 | struct task_struct *running; | 64 | struct task_struct *running; |
| 65 | //struct hrtimer ghost_timer; | ||
| 66 | }; | 65 | }; |
| 67 | 66 | ||
| 68 | /* mc2_cpu_state - maintain the scheduled state and ghost jobs | 67 | /* mc2_cpu_state - maintain the scheduled state and ghost jobs |
| @@ -74,7 +73,6 @@ struct mc2_cpu_state { | |||
| 74 | 73 | ||
| 75 | struct sup_reservation_environment sup_env; | 74 | struct sup_reservation_environment sup_env; |
| 76 | struct hrtimer timer; | 75 | struct hrtimer timer; |
| 77 | //struct hrtimer g_timer; | ||
| 78 | 76 | ||
| 79 | int cpu; | 77 | int cpu; |
| 80 | struct task_struct* scheduled; | 78 | struct task_struct* scheduled; |
| @@ -221,7 +219,9 @@ static int get_lowest_prio_cpu(lt_t priority) | |||
| 221 | raw_spin_unlock(&_lowest_prio_cpu.lock); | 219 | raw_spin_unlock(&_lowest_prio_cpu.lock); |
| 222 | TRACE("CPU %d (local) is the lowest!\n", ce->cpu); | 220 | TRACE("CPU %d (local) is the lowest!\n", ce->cpu); |
| 223 | return ce->cpu; | 221 | return ce->cpu; |
| 224 | } | 222 | } else { |
| 223 | TRACE("Local CPU will_schedule=%d, scheduled=(%s/%d)\n", ce->will_schedule, ce->scheduled ? (ce->scheduled)->comm : "null", ce->scheduled ? (ce->scheduled)->pid : 0); | ||
| 224 | } | ||
| 225 | 225 | ||
| 226 | for_each_online_cpu(cpu) { | 226 | for_each_online_cpu(cpu) { |
| 227 | ce = &_lowest_prio_cpu.cpu_entries[cpu]; | 227 | ce = &_lowest_prio_cpu.cpu_entries[cpu]; |
| @@ -287,6 +287,10 @@ static void mc2_update_timer_and_unlock(struct mc2_cpu_state *state) | |||
| 287 | list_for_each_entry_safe(event, next, &_global_env.next_events, list) { | 287 | list_for_each_entry_safe(event, next, &_global_env.next_events, list) { |
| 288 | /* If the event time is already passed, we call schedule() on | 288 | /* If the event time is already passed, we call schedule() on |
| 289 | the lowest priority cpu */ | 289 | the lowest priority cpu */ |
| 290 | if (event->next_update >= update) { | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | |||
| 290 | if (event->next_update < litmus_clock()) { | 294 | if (event->next_update < litmus_clock()) { |
| 291 | if (event->timer_armed_on == NO_CPU) { | 295 | if (event->timer_armed_on == NO_CPU) { |
| 292 | struct reservation *res = gmp_find_by_id(&_global_env, event->id); | 296 | struct reservation *res = gmp_find_by_id(&_global_env, event->id); |
| @@ -351,70 +355,33 @@ static void mc2_update_timer_and_unlock(struct mc2_cpu_state *state) | |||
| 351 | litmus_reschedule(state->cpu); | 355 | litmus_reschedule(state->cpu); |
| 352 | } | 356 | } |
| 353 | } | 357 | } |
| 354 | |||
| 355 | #if 0 | ||
| 356 | raw_spin_lock(&_global_env.lock); | ||
| 357 | list_for_each_entry_safe(event, next, &_global_env.next_events, list) { | ||
| 358 | if (event->timer_armed_on == NO_CPU) { | ||
| 359 | /* If the event time is already passed, we call schedule() on | ||
| 360 | the lowest priority cpu */ | ||
| 361 | if (event->next_update < litmus_clock()) { | ||
| 362 | int cpu = get_lowest_prio_cpu(); | ||
| 363 | TRACE("GLOBAL EVENT PASSED!! poking CPU %d to reschedule\n", cpu); | ||
| 364 | list_del(&event->list); | ||
| 365 | kfree(event); | ||
| 366 | if (cpu != NO_CPU) { | ||
| 367 | raw_spin_lock(&_lowest_prio_cpu.lock); | ||
| 368 | _lowest_prio_cpu.cpu_entries[cpu].will_schedule = true; | ||
| 369 | raw_spin_unlock(&_lowest_prio_cpu.lock); | ||
| 370 | litmus_reschedule(cpu); | ||
| 371 | } | ||
| 372 | } else if (!hrtimer_active(&state->g_timer)) { | ||
| 373 | int ret; | ||
| 374 | |||
| 375 | raw_spin_unlock(&_global_env.lock); | ||
| 376 | found_event = 1; | ||
| 377 | |||
| 378 | TRACE("setting global scheduler timer for %llu\n", | ||
| 379 | event->next_update); | ||
| 380 | ret = __hrtimer_start_range_ns(&state->g_timer, | ||
| 381 | ns_to_ktime(event->next_update), | ||
| 382 | 0 /* timer coalescing slack */, | ||
| 383 | HRTIMER_MODE_ABS_PINNED, | ||
| 384 | 0 /* wakeup */); | ||
| 385 | if (!ret) { | ||
| 386 | event->timer_armed_on = state->cpu; | ||
| 387 | break; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | } | ||
| 391 | } | ||
| 392 | if (found_event == 0) | ||
| 393 | raw_spin_unlock(&_global_env.lock); | ||
| 394 | #endif | ||
| 395 | } | 358 | } |
| 396 | 359 | ||
| 397 | /* mc2_update_ghost_state - Update crit_entries[] to track ghost jobs | 360 | /* mc2_update_ghost_state - Update crit_entries[] to track ghost jobs |
| 398 | * If the budget of a ghost is exhausted, | 361 | * If the budget of a ghost is exhausted, |
| 399 | * clear is_ghost and reschedule | 362 | * clear is_ghost and reschedule |
| 400 | */ | 363 | */ |
| 401 | static void mc2_update_ghost_state(struct mc2_cpu_state *state) | 364 | static lt_t mc2_update_ghost_state(struct mc2_cpu_state *state) |
| 402 | { | 365 | { |
| 403 | int lv = 0; | 366 | int lv = 0; |
| 404 | struct crit_entry* ce; | 367 | struct crit_entry* ce; |
| 405 | struct reservation *res; | 368 | struct reservation *res; |
| 406 | struct mc2_task_state *tinfo; | 369 | struct mc2_task_state *tinfo; |
| 407 | 370 | lt_t ret = ULLONG_MAX; | |
| 371 | |||
| 408 | BUG_ON(!state); | 372 | BUG_ON(!state); |
| 409 | 373 | ||
| 410 | for (lv = 0; lv < NUM_CRIT_LEVELS; lv++) { | 374 | for (lv = 0; lv < NUM_CRIT_LEVELS; lv++) { |
| 411 | ce = &state->crit_entries[lv]; | 375 | ce = &state->crit_entries[lv]; |
| 412 | if (ce->running != NULL) { | 376 | if (ce->running != NULL) { |
| 377 | //printk(KERN_ALERT "P%d ce->running : %s/%d\n", state->cpu, ce->running ? (ce->running)->comm : "null", ce->running ? (ce->running)->pid : 0); | ||
| 413 | tinfo = get_mc2_state(ce->running); | 378 | tinfo = get_mc2_state(ce->running); |
| 414 | if (!tinfo) | 379 | if (!tinfo) |
| 415 | continue; | 380 | continue; |
| 416 | 381 | ||
| 417 | res = res_find_by_id(state, tinfo->mc2_param.res_id); | 382 | res = res_find_by_id(state, tinfo->mc2_param.res_id); |
| 383 | BUG_ON(!res); | ||
| 384 | //printk(KERN_ALERT "R%d found!\n", res->id); | ||
| 418 | TRACE("LV %d running id %d budget %llu\n", | 385 | TRACE("LV %d running id %d budget %llu\n", |
| 419 | lv, tinfo->mc2_param.res_id, res->cur_budget); | 386 | lv, tinfo->mc2_param.res_id, res->cur_budget); |
| 420 | /* If the budget is exhausted, clear is_ghost and reschedule */ | 387 | /* If the budget is exhausted, clear is_ghost and reschedule */ |
| @@ -432,7 +399,7 @@ static void mc2_update_ghost_state(struct mc2_cpu_state *state) | |||
| 432 | struct reservation, list); | 399 | struct reservation, list); |
| 433 | if (res) | 400 | if (res) |
| 434 | litmus_reschedule_local(); | 401 | litmus_reschedule_local(); |
| 435 | } else { | 402 | } else if (lv == CRIT_LEVEL_C) { |
| 436 | res = list_first_entry_or_null( | 403 | res = list_first_entry_or_null( |
| 437 | &_global_env.active_reservations, | 404 | &_global_env.active_reservations, |
| 438 | struct reservation, list); | 405 | struct reservation, list); |
| @@ -440,11 +407,16 @@ static void mc2_update_ghost_state(struct mc2_cpu_state *state) | |||
| 440 | litmus_reschedule(state->cpu); | 407 | litmus_reschedule(state->cpu); |
| 441 | } | 408 | } |
| 442 | } else { | 409 | } else { |
| 443 | TRACE("GHOST NOT FINISH id %d budget %llu\n", res->id, res->cur_budget); | 410 | //TRACE("GHOST NOT FINISH id %d budget %llu\n", res->id, res->cur_budget); |
| 444 | gmp_add_event_after(&_global_env, res->cur_budget, res->id, EVENT_DRAIN); | 411 | //gmp_add_event_after(&_global_env, res->cur_budget, res->id, EVENT_DRAIN); |
| 412 | if (ret > res->cur_budget) { | ||
| 413 | ret = res->cur_budget; | ||
| 414 | } | ||
| 445 | } | 415 | } |
| 446 | } | 416 | } |
| 447 | } | 417 | } |
| 418 | |||
| 419 | return ret; | ||
| 448 | } | 420 | } |
| 449 | 421 | ||
| 450 | /* update_cpu_prio - Update cpu's priority | 422 | /* update_cpu_prio - Update cpu's priority |
| @@ -474,84 +446,6 @@ static void update_cpu_prio(struct mc2_cpu_state *state) | |||
| 474 | } | 446 | } |
| 475 | }; | 447 | }; |
| 476 | 448 | ||
| 477 | #if 0 | ||
| 478 | /* on_global_scheduling_timer - Process the budget accounting (replenish | ||
| 479 | * and charge) | ||
| 480 | */ | ||
| 481 | static enum hrtimer_restart on_global_scheduling_timer(struct hrtimer *timer) | ||
| 482 | { | ||
| 483 | unsigned long flags; | ||
| 484 | enum hrtimer_restart restart = HRTIMER_NORESTART; | ||
| 485 | struct mc2_cpu_state *state; | ||
| 486 | struct next_timer_event *event, *next; | ||
| 487 | int schedule_now; | ||
| 488 | lt_t update, now; | ||
| 489 | int found_event = 0; | ||
| 490 | |||
| 491 | state = container_of(timer, struct mc2_cpu_state, g_timer); | ||
| 492 | |||
| 493 | raw_spin_lock_irqsave(&state->lock, flags); | ||
| 494 | |||
| 495 | /* The scheduling timer should only fire on the local CPU, because | ||
| 496 | * otherwise deadlocks via timer_cancel() are possible. | ||
| 497 | * Note: this does not interfere with dedicated interrupt handling, as | ||
| 498 | * even under dedicated interrupt handling scheduling timers for | ||
| 499 | * budget enforcement must occur locally on each CPU. | ||
| 500 | */ | ||
| 501 | //BUG_ON(state->cpu != raw_smp_processor_id()); | ||
| 502 | if (state->cpu != raw_smp_processor_id()) | ||
| 503 | TRACE("BUG!!!!!!!!!!!!! TIMER FIRED ON THE OTHER CPU\n"); | ||
| 504 | |||
| 505 | raw_spin_lock(&_global_env.lock); | ||
| 506 | |||
| 507 | update = litmus_clock(); | ||
| 508 | TRACE("GLOBAL TIMER FIRED at %llu\n", update); | ||
| 509 | |||
| 510 | /* The event can be processed by the other cpus. So, if there is no | ||
| 511 | events to process, we do nothing */ | ||
| 512 | list_for_each_entry_safe(event, next, &_global_env.next_events, list) { | ||
| 513 | if (event->next_update < update) { | ||
| 514 | found_event = 1; | ||
| 515 | list_del(&event->list); | ||
| 516 | TRACE("EVENT at %llu IS DELETED\n", event->next_update); | ||
| 517 | kfree(event); | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | if (!found_event) { | ||
| 522 | goto unlock; | ||
| 523 | } | ||
| 524 | |||
| 525 | /* gmp_update_timer returns how many tasks become ACTIVE */ | ||
| 526 | schedule_now = gmp_update_time(&_global_env, update); | ||
| 527 | |||
| 528 | mc2_update_ghost_state(state); | ||
| 529 | |||
| 530 | now = _global_env.env.current_time; | ||
| 531 | |||
| 532 | TRACE_CUR("on_global_scheduling_timer at %llu, upd:%llu (for cpu=%d) SCHEDULE_NOW = %d\n", | ||
| 533 | now, update, state->cpu, schedule_now); | ||
| 534 | |||
| 535 | /* Find the lowest cpu, and call reschedule */ | ||
| 536 | while (schedule_now--) { | ||
| 537 | int cpu = get_lowest_prio_cpu(); | ||
| 538 | if (cpu != NO_CPU) { | ||
| 539 | raw_spin_lock(&_lowest_prio_cpu.lock); | ||
| 540 | _lowest_prio_cpu.cpu_entries[cpu].will_schedule = true; | ||
| 541 | raw_spin_unlock(&_lowest_prio_cpu.lock); | ||
| 542 | TRACE("LOWEST CPU = P%d\n", cpu); | ||
| 543 | litmus_reschedule(cpu); | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | unlock: | ||
| 548 | raw_spin_unlock(&_global_env.lock); | ||
| 549 | raw_spin_unlock_irqrestore(&state->lock, flags); | ||
| 550 | |||
| 551 | return restart; | ||
| 552 | } | ||
| 553 | #endif | ||
| 554 | |||
| 555 | /* on_scheduling_timer - timer event for partitioned tasks | 449 | /* on_scheduling_timer - timer event for partitioned tasks |
| 556 | */ | 450 | */ |
| 557 | static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) | 451 | static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) |
| @@ -561,7 +455,8 @@ static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) | |||
| 561 | struct mc2_cpu_state *state; | 455 | struct mc2_cpu_state *state; |
| 562 | lt_t update, now; | 456 | lt_t update, now; |
| 563 | int global_schedule_now; | 457 | int global_schedule_now; |
| 564 | 458 | lt_t remain_budget; | |
| 459 | |||
| 565 | state = container_of(timer, struct mc2_cpu_state, timer); | 460 | state = container_of(timer, struct mc2_cpu_state, timer); |
| 566 | 461 | ||
| 567 | /* The scheduling timer should only fire on the local CPU, because | 462 | /* The scheduling timer should only fire on the local CPU, because |
| @@ -575,18 +470,22 @@ static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) | |||
| 575 | TRACE("TIMER FIRED at %llu\n", litmus_clock()); | 470 | TRACE("TIMER FIRED at %llu\n", litmus_clock()); |
| 576 | raw_spin_lock_irqsave(&_global_env.lock, flags); | 471 | raw_spin_lock_irqsave(&_global_env.lock, flags); |
| 577 | raw_spin_lock(&state->lock); | 472 | raw_spin_lock(&state->lock); |
| 578 | 473 | //printk(KERN_ALERT "P%d on_scheduling_timer() hold lock %s/%d\n", state->cpu, current ? (current)->comm : "null", current ? (current)->pid : 0); | |
| 579 | sup_update_time(&state->sup_env, litmus_clock()); | 474 | now = litmus_clock(); |
| 580 | global_schedule_now = gmp_update_time(&_global_env, litmus_clock()); | 475 | sup_update_time(&state->sup_env, now); |
| 581 | 476 | global_schedule_now = gmp_update_time(&_global_env, now); | |
| 582 | mc2_update_ghost_state(state); | 477 | //printk(KERN_ALERT "P%d update_time in timer() %s/%d\n", state->cpu, current ? (current)->comm : "null", current ? (current)->pid : 0); |
| 478 | remain_budget = mc2_update_ghost_state(state); | ||
| 583 | 479 | ||
| 584 | update = state->sup_env.next_scheduler_update; | 480 | update = state->sup_env.next_scheduler_update; |
| 585 | now = state->sup_env.env.current_time; | 481 | now = state->sup_env.env.current_time; |
| 586 | 482 | ||
| 587 | TRACE_CUR("on_scheduling_timer at %llu, upd:%llu (for cpu=%d) g_schedule_now:%d\n", | 483 | if (remain_budget != ULLONG_MAX && update > now + remain_budget) { |
| 588 | now, update, state->cpu, global_schedule_now); | 484 | update = now + remain_budget; |
| 589 | 485 | } | |
| 486 | |||
| 487 | //TRACE_CUR("on_scheduling_timer at %llu, upd:%llu (for cpu=%d) g_schedule_now:%d\n", now, update, state->cpu, global_schedule_now); | ||
| 488 | //printk(KERN_ALERT "on_scheduling_timer at %llu, upd:%llu (for cpu=%d) g_schedule_now:%d\n", now, update, state->cpu, global_schedule_now); | ||
| 590 | if (update <= now) { | 489 | if (update <= now) { |
| 591 | litmus_reschedule_local(); | 490 | litmus_reschedule_local(); |
| 592 | } else if (update != SUP_NO_SCHEDULER_UPDATE) { | 491 | } else if (update != SUP_NO_SCHEDULER_UPDATE) { |
| @@ -594,6 +493,8 @@ static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) | |||
| 594 | restart = HRTIMER_RESTART; | 493 | restart = HRTIMER_RESTART; |
| 595 | } | 494 | } |
| 596 | 495 | ||
| 496 | BUG_ON(global_schedule_now < 0 || global_schedule_now > 4); | ||
| 497 | |||
| 597 | /* Find the lowest cpu, and call reschedule */ | 498 | /* Find the lowest cpu, and call reschedule */ |
| 598 | while (global_schedule_now--) { | 499 | while (global_schedule_now--) { |
| 599 | int cpu = get_lowest_prio_cpu(0); | 500 | int cpu = get_lowest_prio_cpu(0); |
| @@ -601,14 +502,14 @@ static enum hrtimer_restart on_scheduling_timer(struct hrtimer *timer) | |||
| 601 | raw_spin_lock(&_lowest_prio_cpu.lock); | 502 | raw_spin_lock(&_lowest_prio_cpu.lock); |
| 602 | _lowest_prio_cpu.cpu_entries[cpu].will_schedule = true; | 503 | _lowest_prio_cpu.cpu_entries[cpu].will_schedule = true; |
| 603 | raw_spin_unlock(&_lowest_prio_cpu.lock); | 504 | raw_spin_unlock(&_lowest_prio_cpu.lock); |
| 604 | TRACE("LOWEST CPU = P%d\n", cpu); | 505 | //TRACE("LOWEST CPU = P%d\n", cpu); |
| 605 | litmus_reschedule(cpu); | 506 | litmus_reschedule(cpu); |
| 606 | } | 507 | } |
| 607 | } | 508 | } |
| 608 | 509 | ||
| 609 | raw_spin_unlock(&state->lock); | 510 | raw_spin_unlock(&state->lock); |
| 610 | raw_spin_unlock_irqrestore(&_global_env.lock, flags); | 511 | raw_spin_unlock_irqrestore(&_global_env.lock, flags); |
| 611 | 512 | //printk(KERN_ALERT "P%d on_scheduling_timer() release lock %s/%d\n", state->cpu, current ? (current)->comm : "null", current ? (current)->pid : 0); | |
| 612 | return restart; | 513 | return restart; |
| 613 | } | 514 | } |
| 614 | 515 | ||
| @@ -651,6 +552,13 @@ struct task_struct* mc2_dispatch(struct sup_reservation_environment* sup_env, st | |||
| 651 | } | 552 | } |
| 652 | 553 | ||
| 653 | /* no eligible level A or B tasks exists */ | 554 | /* no eligible level A or B tasks exists */ |
| 555 | /* check the ghost job */ | ||
| 556 | ce = &state->crit_entries[CRIT_LEVEL_C]; | ||
| 557 | if (ce->running) { | ||
| 558 | TRACE_TASK(ce->running," is GHOST\n"); | ||
| 559 | return NULL; | ||
| 560 | } | ||
| 561 | |||
| 654 | cur_priority = _lowest_prio_cpu.cpu_entries[state->cpu].deadline; | 562 | cur_priority = _lowest_prio_cpu.cpu_entries[state->cpu].deadline; |
| 655 | 563 | ||
| 656 | TRACE("****** ACTIVE LIST ******\n"); | 564 | TRACE("****** ACTIVE LIST ******\n"); |
| @@ -663,21 +571,24 @@ struct task_struct* mc2_dispatch(struct sup_reservation_environment* sup_env, st | |||
| 663 | lv = get_task_crit_level(tsk); | 571 | lv = get_task_crit_level(tsk); |
| 664 | if (lv == NUM_CRIT_LEVELS) { | 572 | if (lv == NUM_CRIT_LEVELS) { |
| 665 | gmp_add_event_after(&_global_env, res->cur_budget, res->id, EVENT_DRAIN); | 573 | gmp_add_event_after(&_global_env, res->cur_budget, res->id, EVENT_DRAIN); |
| 666 | res->event_added = 1; | 574 | //res->event_added = 1; |
| 667 | return tsk; | 575 | return tsk; |
| 668 | } else { | 576 | } else if (lv == CRIT_LEVEL_C) { |
| 669 | ce = &state->crit_entries[lv]; | 577 | //ce = &state->crit_entries[lv]; |
| 670 | if (likely(!ce->running)) { | 578 | //if (likely(!ce->running)) { |
| 671 | gmp_add_event_after(&_global_env, res->cur_budget, res->id, EVENT_DRAIN); | 579 | gmp_add_event_after(&_global_env, res->cur_budget, res->id, EVENT_DRAIN); |
| 672 | res->event_added = 1; | 580 | res->event_added = 1; |
| 673 | res->blocked_by_ghost = 0; | 581 | res->blocked_by_ghost = 0; |
| 674 | res->is_ghost = 0; | 582 | res->is_ghost = 0; |
| 675 | res->scheduled_on = state->cpu; | 583 | res->scheduled_on = state->cpu; |
| 676 | return tsk; | 584 | return tsk; |
| 677 | } else { | 585 | //} else { |
| 678 | res->blocked_by_ghost = 1; | 586 | // res->blocked_by_ghost = 1; |
| 679 | TRACE_TASK(ce->running, " is GHOST\n"); | 587 | // TRACE_TASK(ce->running, " is GHOST\n"); |
| 680 | } | 588 | // return NULL; |
| 589 | //} | ||
| 590 | } else { | ||
| 591 | BUG(); | ||
| 681 | } | 592 | } |
| 682 | } | 593 | } |
| 683 | } | 594 | } |
| @@ -711,8 +622,9 @@ static void post_schedule(struct task_struct *next) | |||
| 711 | static struct task_struct* mc2_schedule(struct task_struct * prev) | 622 | static struct task_struct* mc2_schedule(struct task_struct * prev) |
| 712 | { | 623 | { |
| 713 | /* next == NULL means "schedule background work". */ | 624 | /* next == NULL means "schedule background work". */ |
| 625 | lt_t now; | ||
| 714 | struct mc2_cpu_state *state = local_cpu_state(); | 626 | struct mc2_cpu_state *state = local_cpu_state(); |
| 715 | 627 | ||
| 716 | pre_schedule(prev); | 628 | pre_schedule(prev); |
| 717 | 629 | ||
| 718 | raw_spin_lock(&_global_env.lock); | 630 | raw_spin_lock(&_global_env.lock); |
| @@ -721,17 +633,18 @@ static struct task_struct* mc2_schedule(struct task_struct * prev) | |||
| 721 | //BUG_ON(state->scheduled && state->scheduled != prev); | 633 | //BUG_ON(state->scheduled && state->scheduled != prev); |
| 722 | //BUG_ON(state->scheduled && !is_realtime(prev)); | 634 | //BUG_ON(state->scheduled && !is_realtime(prev)); |
| 723 | if (state->scheduled && state->scheduled != prev) | 635 | if (state->scheduled && state->scheduled != prev) |
| 724 | TRACE("BUG1!!!!!!!!\n"); | 636 | printk(KERN_ALERT "BUG1!!!!!!!! %s %s\n", state->scheduled ? (state->scheduled)->comm : "null", prev ? (prev)->comm : "null"); |
| 725 | if (state->scheduled && !is_realtime(prev)) | 637 | if (state->scheduled && !is_realtime(prev)) |
| 726 | TRACE("BUG2!!!!!!!!\n"); | 638 | printk(KERN_ALERT "BUG2!!!!!!!! \n"); |
| 727 | 639 | ||
| 728 | /* update time */ | 640 | /* update time */ |
| 729 | state->sup_env.will_schedule = true; | 641 | state->sup_env.will_schedule = true; |
| 730 | 642 | ||
| 731 | sup_update_time(&state->sup_env, litmus_clock()); | 643 | now = litmus_clock(); |
| 732 | gmp_update_time(&_global_env, litmus_clock()); | 644 | sup_update_time(&state->sup_env, now); |
| 733 | 645 | gmp_update_time(&_global_env, now); | |
| 734 | mc2_update_ghost_state(state); | 646 | |
| 647 | mc2_update_ghost_state(state); | ||
| 735 | 648 | ||
| 736 | /* remove task from reservation if it blocks */ | 649 | /* remove task from reservation if it blocks */ |
| 737 | if (is_realtime(prev) && !is_running(prev)) | 650 | if (is_realtime(prev) && !is_running(prev)) |
| @@ -767,14 +680,17 @@ static struct task_struct* mc2_schedule(struct task_struct * prev) | |||
| 767 | TRACE_TASK(prev, "descheduled.\n"); | 680 | TRACE_TASK(prev, "descheduled.\n"); |
| 768 | /* if prev is preempted and a global task, find the lowest cpu and reschedule */ | 681 | /* if prev is preempted and a global task, find the lowest cpu and reschedule */ |
| 769 | if (tinfo->has_departed == false && get_task_crit_level(prev) == CRIT_LEVEL_C) { | 682 | if (tinfo->has_departed == false && get_task_crit_level(prev) == CRIT_LEVEL_C) { |
| 770 | int cpu = get_lowest_prio_cpu(res?res->priority:0); | 683 | int cpu; |
| 771 | TRACE("LEVEL-C TASK PREEMPTED!! poking CPU %d to reschedule\n", cpu); | 684 | raw_spin_lock(&_global_env.lock); |
| 685 | cpu = get_lowest_prio_cpu(res?res->priority:0); | ||
| 686 | //TRACE("LEVEL-C TASK PREEMPTED!! poking CPU %d to reschedule\n", cpu); | ||
| 772 | if (cpu != NO_CPU) { | 687 | if (cpu != NO_CPU) { |
| 773 | raw_spin_lock(&_lowest_prio_cpu.lock); | 688 | raw_spin_lock(&_lowest_prio_cpu.lock); |
| 774 | _lowest_prio_cpu.cpu_entries[cpu].will_schedule = true; | 689 | _lowest_prio_cpu.cpu_entries[cpu].will_schedule = true; |
| 775 | raw_spin_unlock(&_lowest_prio_cpu.lock); | 690 | raw_spin_unlock(&_lowest_prio_cpu.lock); |
| 776 | litmus_reschedule(cpu); | 691 | litmus_reschedule(cpu); |
| 777 | } | 692 | } |
| 693 | raw_spin_unlock(&_global_env.lock); | ||
| 778 | } | 694 | } |
| 779 | } | 695 | } |
| 780 | if (state->scheduled) { | 696 | if (state->scheduled) { |
| @@ -814,12 +730,14 @@ static void mc2_task_resume(struct task_struct *tsk) | |||
| 814 | 730 | ||
| 815 | TRACE_TASK(tsk, "thread wakes up at %llu\n", litmus_clock()); | 731 | TRACE_TASK(tsk, "thread wakes up at %llu\n", litmus_clock()); |
| 816 | 732 | ||
| 733 | local_irq_save(flags); | ||
| 817 | if (tinfo->cpu != -1) | 734 | if (tinfo->cpu != -1) |
| 818 | state = cpu_state_for(tinfo->cpu); | 735 | state = cpu_state_for(tinfo->cpu); |
| 819 | else | 736 | else |
| 820 | state = local_cpu_state(); | 737 | state = local_cpu_state(); |
| 821 | 738 | ||
| 822 | raw_spin_lock_irqsave(&_global_env.lock, flags); | 739 | raw_spin_lock(&_global_env.lock); |
| 740 | //printk(KERN_ALERT "P%d resume() hold lock\n", state->cpu); | ||
| 823 | /* Requeue only if self-suspension was already processed. */ | 741 | /* Requeue only if self-suspension was already processed. */ |
| 824 | if (tinfo->has_departed) | 742 | if (tinfo->has_departed) |
| 825 | { | 743 | { |
| @@ -830,22 +748,25 @@ static void mc2_task_resume(struct task_struct *tsk) | |||
| 830 | if (tinfo->cpu != -1) { | 748 | if (tinfo->cpu != -1) { |
| 831 | sup_update_time(&state->sup_env, litmus_clock()); | 749 | sup_update_time(&state->sup_env, litmus_clock()); |
| 832 | } else { | 750 | } else { |
| 833 | TRACE("RESUME UPDATE ####\n"); | 751 | //TRACE("RESUME UPDATE ####\n"); |
| 834 | gmp_update_time(&_global_env, litmus_clock()); | 752 | gmp_update_time(&_global_env, litmus_clock()); |
| 835 | TRACE("RESUME UPDATE $$$$\n"); | 753 | //TRACE("RESUME UPDATE $$$$\n"); |
| 836 | } | 754 | } |
| 837 | 755 | ||
| 838 | mc2_update_ghost_state(state); | 756 | mc2_update_ghost_state(state); |
| 839 | task_arrives(state, tsk); | 757 | task_arrives(state, tsk); |
| 840 | /* NOTE: drops state->lock */ | 758 | /* NOTE: drops state->lock */ |
| 841 | TRACE_TASK(tsk, "mc2_resume()\n"); | 759 | TRACE_TASK(tsk, "mc2_resume()\n"); |
| 842 | mc2_update_timer_and_unlock(state); | 760 | mc2_update_timer_and_unlock(state); |
| 843 | local_irq_restore(flags); | 761 | //printk(KERN_ALERT "P%d resume() dropped lock\n", state->cpu); |
| 844 | } else { | 762 | } else { |
| 845 | TRACE_TASK(tsk, "resume event ignored, still scheduled\n"); | 763 | TRACE_TASK(tsk, "resume event ignored, still scheduled\n"); |
| 846 | raw_spin_unlock_irqrestore(&_global_env.lock, flags); | 764 | raw_spin_unlock(&_global_env.lock); |
| 765 | //printk(KERN_ALERT "P%d resume() release lock\n", state->cpu); | ||
| 847 | } | 766 | } |
| 848 | 767 | ||
| 768 | local_irq_restore(flags); | ||
| 769 | |||
| 849 | resume_legacy_task_model_updates(tsk); | 770 | resume_legacy_task_model_updates(tsk); |
| 850 | } | 771 | } |
| 851 | 772 | ||
| @@ -870,6 +791,7 @@ static long mc2_complete_job(void) | |||
| 870 | struct reservation *res; | 791 | struct reservation *res; |
| 871 | unsigned long flags; | 792 | unsigned long flags; |
| 872 | 793 | ||
| 794 | preempt_disable(); | ||
| 873 | local_irq_save(flags); | 795 | local_irq_save(flags); |
| 874 | 796 | ||
| 875 | tinfo = get_mc2_state(current); | 797 | tinfo = get_mc2_state(current); |
| @@ -881,7 +803,7 @@ static long mc2_complete_job(void) | |||
| 881 | 803 | ||
| 882 | raw_spin_lock(&_global_env.lock); | 804 | raw_spin_lock(&_global_env.lock); |
| 883 | raw_spin_lock(&state->lock); | 805 | raw_spin_lock(&state->lock); |
| 884 | 806 | //printk(KERN_ALERT "P%d complete() hold lock\n", state->cpu); | |
| 885 | env = &(state->sup_env.env); | 807 | env = &(state->sup_env.env); |
| 886 | 808 | ||
| 887 | res = res_find_by_id(state, tinfo->mc2_param.res_id); | 809 | res = res_find_by_id(state, tinfo->mc2_param.res_id); |
| @@ -905,12 +827,13 @@ static long mc2_complete_job(void) | |||
| 905 | res->cur_budget = 0; | 827 | res->cur_budget = 0; |
| 906 | res->env->change_state(res->env, res, RESERVATION_DEPLETED); | 828 | res->env->change_state(res->env, res, RESERVATION_DEPLETED); |
| 907 | 829 | ||
| 908 | TRACE_CUR("CHANGE NEXT_REP = %llu\n NEXT_UPDATE = %llu\n", res->next_replenishment, state->sup_env.next_scheduler_update); | 830 | //TRACE_CUR("CHANGE NEXT_REP = %llu\n NEXT_UPDATE = %llu\n", res->next_replenishment, state->sup_env.next_scheduler_update); |
| 909 | 831 | ||
| 910 | raw_spin_unlock(&state->lock); | 832 | raw_spin_unlock(&state->lock); |
| 911 | raw_spin_unlock(&_global_env.lock); | 833 | raw_spin_unlock(&_global_env.lock); |
| 912 | 834 | //printk(KERN_ALERT "P%d complete() release lock\n", state->cpu); | |
| 913 | local_irq_restore(flags); | 835 | local_irq_restore(flags); |
| 836 | preempt_enable(); | ||
| 914 | } | 837 | } |
| 915 | sched_trace_task_completion(current, 0); | 838 | sched_trace_task_completion(current, 0); |
| 916 | 839 | ||
| @@ -937,6 +860,7 @@ static long mc2_complete_job(void) | |||
| 937 | } | 860 | } |
| 938 | 861 | ||
| 939 | TRACE_CUR("mc2_complete_job returns at %llu\n", litmus_clock()); | 862 | TRACE_CUR("mc2_complete_job returns at %llu\n", litmus_clock()); |
| 863 | |||
| 940 | return err; | 864 | return err; |
| 941 | } | 865 | } |
| 942 | 866 | ||
| @@ -988,6 +912,7 @@ static long mc2_admit_task(struct task_struct *tsk) | |||
| 988 | raw_spin_unlock_irqrestore(&state->lock, flags); | 912 | raw_spin_unlock_irqrestore(&state->lock, flags); |
| 989 | } else if (lv == CRIT_LEVEL_C) { | 913 | } else if (lv == CRIT_LEVEL_C) { |
| 990 | raw_spin_lock_irqsave(&_global_env.lock, flags); | 914 | raw_spin_lock_irqsave(&_global_env.lock, flags); |
| 915 | //printk(KERN_ALERT "admit() hold lock\n"); | ||
| 991 | state = local_cpu_state(); | 916 | state = local_cpu_state(); |
| 992 | 917 | ||
| 993 | raw_spin_lock(&state->lock); | 918 | raw_spin_lock(&state->lock); |
| @@ -1012,6 +937,7 @@ static long mc2_admit_task(struct task_struct *tsk) | |||
| 1012 | 937 | ||
| 1013 | raw_spin_unlock(&state->lock); | 938 | raw_spin_unlock(&state->lock); |
| 1014 | raw_spin_unlock_irqrestore(&_global_env.lock, flags); | 939 | raw_spin_unlock_irqrestore(&_global_env.lock, flags); |
| 940 | //printk(KERN_ALERT "admit() release lock\n"); | ||
| 1015 | } | 941 | } |
| 1016 | 942 | ||
| 1017 | preempt_enable(); | 943 | preempt_enable(); |
| @@ -1033,25 +959,30 @@ static void mc2_task_new(struct task_struct *tsk, int on_runqueue, | |||
| 1033 | struct mc2_cpu_state *state; // = cpu_state_for(tinfo->cpu); | 959 | struct mc2_cpu_state *state; // = cpu_state_for(tinfo->cpu); |
| 1034 | struct reservation *res; | 960 | struct reservation *res; |
| 1035 | enum crit_level lv = get_task_crit_level(tsk); | 961 | enum crit_level lv = get_task_crit_level(tsk); |
| 962 | lt_t release = 0; | ||
| 1036 | 963 | ||
| 1037 | TRACE_TASK(tsk, "new RT task %llu (on_rq:%d, running:%d)\n", | 964 | TRACE_TASK(tsk, "new RT task %llu (on_rq:%d, running:%d)\n", |
| 1038 | litmus_clock(), on_runqueue, is_running); | 965 | litmus_clock(), on_runqueue, is_running); |
| 1039 | 966 | ||
| 967 | local_irq_save(flags); | ||
| 1040 | if (tinfo->cpu == -1) | 968 | if (tinfo->cpu == -1) |
| 1041 | state = local_cpu_state(); | 969 | state = local_cpu_state(); |
| 1042 | else | 970 | else |
| 1043 | state = cpu_state_for(tinfo->cpu); | 971 | state = cpu_state_for(tinfo->cpu); |
| 1044 | 972 | ||
| 1045 | /* acquire the lock protecting the state and disable interrupts */ | 973 | /* acquire the lock protecting the state and disable interrupts */ |
| 1046 | raw_spin_lock_irqsave(&_global_env.lock, flags); | 974 | raw_spin_lock(&_global_env.lock); |
| 1047 | raw_spin_lock(&state->lock); | 975 | raw_spin_lock(&state->lock); |
| 1048 | 976 | //printk(KERN_ALERT "new() hold lock R%d\n", tinfo->mc2_param.res_id); | |
| 1049 | if (is_running) { | 977 | if (is_running) { |
| 1050 | state->scheduled = tsk; | 978 | state->scheduled = tsk; |
| 1051 | /* make sure this task should actually be running */ | 979 | /* make sure this task should actually be running */ |
| 1052 | litmus_reschedule_local(); | 980 | litmus_reschedule_local(); |
| 1053 | } | 981 | } |
| 1054 | 982 | ||
| 983 | res = res_find_by_id(state, tinfo->mc2_param.res_id); | ||
| 984 | release = res->next_replenishment; | ||
| 985 | |||
| 1055 | if (on_runqueue || is_running) { | 986 | if (on_runqueue || is_running) { |
| 1056 | /* Assumption: litmus_clock() is synchronized across cores | 987 | /* Assumption: litmus_clock() is synchronized across cores |
| 1057 | * [see comment in pres_task_resume()] */ | 988 | * [see comment in pres_task_resume()] */ |
| @@ -1062,18 +993,20 @@ static void mc2_task_new(struct task_struct *tsk, int on_runqueue, | |||
| 1062 | TRACE("mc2_new()\n"); | 993 | TRACE("mc2_new()\n"); |
| 1063 | 994 | ||
| 1064 | mc2_update_timer_and_unlock(state); | 995 | mc2_update_timer_and_unlock(state); |
| 1065 | local_irq_restore(flags); | 996 | //printk(KERN_ALERT "new() dropped lock R%d\n",tinfo->mc2_param.res_id); |
| 1066 | } else | 997 | } else { |
| 1067 | raw_spin_unlock_irqrestore(&_global_env.lock, flags); | 998 | raw_spin_unlock(&state->lock); |
| 1068 | 999 | raw_spin_unlock(&_global_env.lock); | |
| 1069 | res = res_find_by_id(state, tinfo->mc2_param.res_id); | 1000 | //printk(KERN_ALERT "new() release lock R%d\n",tinfo->mc2_param.res_id); |
| 1001 | } | ||
| 1002 | local_irq_restore(flags); | ||
| 1070 | 1003 | ||
| 1071 | if (res) { | 1004 | if (!release) { |
| 1072 | TRACE_TASK(tsk, "mc2_task_new() next_replenishment = %llu\n", res->next_replenishment); | 1005 | TRACE_TASK(tsk, "mc2_task_new() next_release = %llu\n", release); |
| 1073 | release_at(tsk, res->next_replenishment); | 1006 | release_at(tsk, release); |
| 1074 | } | 1007 | } |
| 1075 | else | 1008 | else |
| 1076 | TRACE_TASK(tsk, "mc2_task_new() next_replenishment = NULL\n"); | 1009 | TRACE_TASK(tsk, "mc2_task_new() next_release = NULL\n"); |
| 1077 | } | 1010 | } |
| 1078 | 1011 | ||
| 1079 | /* mc2_reservation_destroy - reservation_destroy system call backend | 1012 | /* mc2_reservation_destroy - reservation_destroy system call backend |
| @@ -1196,14 +1129,16 @@ static void mc2_task_exit(struct task_struct *tsk) | |||
| 1196 | struct mc2_task_state* tinfo = get_mc2_state(tsk); | 1129 | struct mc2_task_state* tinfo = get_mc2_state(tsk); |
| 1197 | struct mc2_cpu_state *state; | 1130 | struct mc2_cpu_state *state; |
| 1198 | enum crit_level lv = tinfo->mc2_param.crit; | 1131 | enum crit_level lv = tinfo->mc2_param.crit; |
| 1199 | struct crit_entry* ce; | 1132 | struct crit_entry* ce; |
| 1133 | int cpu; | ||
| 1200 | 1134 | ||
| 1135 | local_irq_save(flags); | ||
| 1201 | if (tinfo->cpu != -1) | 1136 | if (tinfo->cpu != -1) |
| 1202 | state = cpu_state_for(tinfo->cpu); | 1137 | state = cpu_state_for(tinfo->cpu); |
| 1203 | else | 1138 | else |
| 1204 | state = local_cpu_state(); | 1139 | state = local_cpu_state(); |
| 1205 | 1140 | ||
| 1206 | raw_spin_lock_irqsave(&_global_env.lock, flags); | 1141 | raw_spin_lock(&_global_env.lock); |
| 1207 | raw_spin_lock(&state->lock); | 1142 | raw_spin_lock(&state->lock); |
| 1208 | 1143 | ||
| 1209 | if (state->scheduled == tsk) | 1144 | if (state->scheduled == tsk) |
| @@ -1226,11 +1161,30 @@ static void mc2_task_exit(struct task_struct *tsk) | |||
| 1226 | /* NOTE: drops state->lock */ | 1161 | /* NOTE: drops state->lock */ |
| 1227 | TRACE("mc2_exit()\n"); | 1162 | TRACE("mc2_exit()\n"); |
| 1228 | 1163 | ||
| 1229 | mc2_update_timer_and_unlock(state); | 1164 | mc2_update_timer_and_unlock(state); |
| 1230 | local_irq_restore(flags); | 1165 | } else { |
| 1231 | } else | 1166 | raw_spin_unlock(&state->lock); |
| 1232 | raw_spin_unlock_irqrestore(&_global_env.lock, flags); | 1167 | raw_spin_unlock(&_global_env.lock); |
| 1168 | } | ||
| 1233 | 1169 | ||
| 1170 | for_each_online_cpu(cpu) { | ||
| 1171 | state = cpu_state_for(cpu); | ||
| 1172 | if (state == local_cpu_state()) | ||
| 1173 | continue; | ||
| 1174 | raw_spin_lock(&state->lock); | ||
| 1175 | |||
| 1176 | if (state->scheduled == tsk) | ||
| 1177 | state->scheduled = NULL; | ||
| 1178 | |||
| 1179 | ce = &state->crit_entries[lv]; | ||
| 1180 | if (ce->running == tsk) | ||
| 1181 | ce->running = NULL; | ||
| 1182 | |||
| 1183 | raw_spin_unlock(&state->lock); | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | local_irq_restore(flags); | ||
| 1187 | |||
| 1234 | kfree(tsk_rt(tsk)->plugin_state); | 1188 | kfree(tsk_rt(tsk)->plugin_state); |
| 1235 | tsk_rt(tsk)->plugin_state = NULL; | 1189 | tsk_rt(tsk)->plugin_state = NULL; |
| 1236 | kfree(tsk_rt(tsk)->mc2_data); | 1190 | kfree(tsk_rt(tsk)->mc2_data); |
| @@ -1539,16 +1493,11 @@ static long mc2_activate_plugin(void) | |||
| 1539 | struct crit_entry *cr_entry = &state->crit_entries[lv]; | 1493 | struct crit_entry *cr_entry = &state->crit_entries[lv]; |
| 1540 | cr_entry->level = lv; | 1494 | cr_entry->level = lv; |
| 1541 | cr_entry->running = NULL; | 1495 | cr_entry->running = NULL; |
| 1542 | //hrtimer_init(&ce->ghost_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); | ||
| 1543 | //ce->ghost_timer.function = on_ghost_timer; | ||
| 1544 | } | 1496 | } |
| 1545 | sup_init(&state->sup_env); | 1497 | sup_init(&state->sup_env); |
| 1546 | 1498 | ||
| 1547 | hrtimer_init(&state->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); | 1499 | hrtimer_init(&state->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); |
| 1548 | state->timer.function = on_scheduling_timer; | 1500 | state->timer.function = on_scheduling_timer; |
| 1549 | |||
| 1550 | // hrtimer_init(&state->g_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); | ||
| 1551 | // state->g_timer.function = on_global_scheduling_timer; | ||
| 1552 | } | 1501 | } |
| 1553 | 1502 | ||
| 1554 | mc2_setup_domain_proc(); | 1503 | mc2_setup_domain_proc(); |
| @@ -1561,7 +1510,7 @@ static void mc2_finish_switch(struct task_struct *prev) | |||
| 1561 | struct mc2_cpu_state *state = local_cpu_state(); | 1510 | struct mc2_cpu_state *state = local_cpu_state(); |
| 1562 | 1511 | ||
| 1563 | state->scheduled = is_realtime(current) ? current : NULL; | 1512 | state->scheduled = is_realtime(current) ? current : NULL; |
| 1564 | TRACE_TASK(prev, "FINISH CXS! complete=%d\n", tsk_rt(prev)->completed); | 1513 | TRACE("FINISH CXS! from %s/%d to %s/%d\n", prev ? (prev)->comm : "null", prev ? (prev)->pid : 0, current ? (current)->comm : "null", current ? (current)->pid : 0); |
| 1565 | } | 1514 | } |
| 1566 | 1515 | ||
| 1567 | static long mc2_deactivate_plugin(void) | 1516 | static long mc2_deactivate_plugin(void) |
| @@ -1570,7 +1519,8 @@ static long mc2_deactivate_plugin(void) | |||
| 1570 | struct mc2_cpu_state *state; | 1519 | struct mc2_cpu_state *state; |
| 1571 | struct reservation *res; | 1520 | struct reservation *res; |
| 1572 | struct next_timer_event *event; | 1521 | struct next_timer_event *event; |
| 1573 | 1522 | struct cpu_entry *ce; | |
| 1523 | |||
| 1574 | raw_spin_lock(&_global_env.lock); | 1524 | raw_spin_lock(&_global_env.lock); |
| 1575 | 1525 | ||
| 1576 | for_each_online_cpu(cpu) { | 1526 | for_each_online_cpu(cpu) { |
| @@ -1578,7 +1528,14 @@ static long mc2_deactivate_plugin(void) | |||
| 1578 | raw_spin_lock(&state->lock); | 1528 | raw_spin_lock(&state->lock); |
| 1579 | 1529 | ||
| 1580 | hrtimer_cancel(&state->timer); | 1530 | hrtimer_cancel(&state->timer); |
| 1581 | // hrtimer_cancel(&state->g_timer); | 1531 | |
| 1532 | ce = &_lowest_prio_cpu.cpu_entries[cpu]; | ||
| 1533 | |||
| 1534 | ce->cpu = cpu; | ||
| 1535 | ce->scheduled = NULL; | ||
| 1536 | ce->deadline = ULLONG_MAX; | ||
| 1537 | ce->lv = NUM_CRIT_LEVELS; | ||
| 1538 | ce->will_schedule = false; | ||
| 1582 | 1539 | ||
| 1583 | /* Delete all reservations --- assumes struct reservation | 1540 | /* Delete all reservations --- assumes struct reservation |
| 1584 | * is prefix of containing struct. */ | 1541 | * is prefix of containing struct. */ |
