Skip to content

Commit 8e03991

Browse files
committed
schedulers: added new low-latency scheduling (postpone)
1 parent e35e5a7 commit 8e03991

File tree

4 files changed

+134
-111
lines changed

4 files changed

+134
-111
lines changed

picoRTOS.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ picoRTOS_priority_t picoRTOS_get_last_available_priority(void); /* get l
4343
void picoRTOS_suspend(void); /* suspends the scheduling */
4444
void picoRTOS_resume(void); /* resumes the scheduling */
4545

46-
void picoRTOS_schedule(void); /* move to next task */
46+
void picoRTOS_postpone(void); /* move to next task, put back in FIFO */
4747
void picoRTOS_sleep(picoRTOS_tick_t delay); /* put current task to sleep */
4848
void picoRTOS_sleep_until(picoRTOS_tick_t *ref, /* put current task to sleep until */
4949
picoRTOS_tick_t period);
@@ -53,6 +53,11 @@ void picoRTOS_sleep_until(picoRTOS_tick_t *ref, /* put c
5353
picoRTOS_pid_t picoRTOS_self(void); /* gets the current thread priority */
5454
/*@unused@*/ picoRTOS_tick_t picoRTOS_get_tick(void); /* get current tick */
5555

56+
/* Macro: picoRTOS_schedule()
57+
* Puts the current task to sleep until next tick
58+
*/
59+
#define picoRTOS_schedule() picoRTOS_sleep((picoRTOS_tick_t)1)
60+
5661
/* TIME MANAGEMENT */
5762

5863
/* Macro: PICORTOS_DELAY_SEC(x)

scheduler/picoRTOS-SMP.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,11 @@ struct picoRTOS_task_sub {
6767
#define L1_CACHE_ALIGN(x, a) L1_CACHE_ALIGN_MASK((x), ((a) - 1))
6868
#define L1_CACHE_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
6969

70+
#define F_RUNNING (1 << 0)
71+
#define F_POSTPONED (1 << 1)
72+
7073
struct picoRTOS_SMP_core {
71-
bool is_running;
74+
int flags;
7275
picoRTOS_pid_t index[CONFIG_SMP_CORES];
7376
picoRTOS_tick_t tick;
7477
picoRTOS_pid_t pid_count;
@@ -243,7 +246,7 @@ void picoRTOS_init(void)
243246
picoRTOS.main_core = arch_core();
244247

245248
/* RTOS status */
246-
picoRTOS.is_running = false;
249+
picoRTOS.flags = 0;
247250
}
248251

249252
void picoRTOS_add_task(struct picoRTOS_task *task, picoRTOS_priority_t prio)
@@ -382,7 +385,7 @@ void picoRTOS_start(void)
382385
core_arrange_shared_priorities();
383386

384387
arch_smp_init();
385-
picoRTOS.is_running = true;
388+
picoRTOS.flags |= F_RUNNING;
386389

387390
/* start auxiliary cores first */
388391
picoRTOS_core_t i;
@@ -401,26 +404,24 @@ void picoRTOS_start(void)
401404

402405
void picoRTOS_suspend(void)
403406
{
404-
picoRTOS_assert_fatal(picoRTOS.is_running, return );
407+
picoRTOS_assert_fatal((picoRTOS.flags & F_RUNNING) != 0, return );
405408

406409
arch_suspend();
407410
arch_spin_lock();
408411
}
409412

410413
void picoRTOS_resume(void)
411414
{
412-
picoRTOS_assert_fatal(picoRTOS.is_running, return );
415+
picoRTOS_assert_fatal((picoRTOS.flags & F_RUNNING) != 0, return );
413416

414417
arch_spin_unlock();
415418
arch_resume();
416419
}
417420

418-
void picoRTOS_schedule(void)
421+
void picoRTOS_postpone(void)
419422
{
420-
static const struct syscall_sleep delay = { (picoRTOS_tick_t)1 };
421-
422423
picoRTOS_assert_fatal(TASK_CURRENT().state == PICORTOS_TASK_STATE_BUSY, return );
423-
arch_syscall(SYSCALL_SLEEP, (struct syscall_sleep*)&delay);
424+
arch_syscall(SYSCALL_SWITCH_CONTEXT, NULL);
424425
}
425426

426427
void picoRTOS_sleep(picoRTOS_tick_t delay)
@@ -506,6 +507,7 @@ static void syscall_kill(struct picoRTOS_task_core *task)
506507
static struct picoRTOS_task_core *
507508
syscall_switch_context(struct picoRTOS_task_core *task)
508509
{
510+
int count = 2;
509511
picoRTOS_core_t core = arch_core();
510512
picoRTOS_mask_t mask = (picoRTOS_mask_t)(1u << core);
511513

@@ -516,18 +518,32 @@ syscall_switch_context(struct picoRTOS_task_core *task)
516518
if (task->state == PICORTOS_TASK_STATE_BUSY)
517519
task->state = PICORTOS_TASK_STATE_DONE;
518520

519-
do {
520-
picoRTOS.index[core]++;
521-
picoRTOS_assert_void_fatal(picoRTOS.index[core] < (picoRTOS_pid_t)TASK_COUNT);
522-
/* ignore sleeping, empty tasks & out-of-round sub-tasks */
523-
} while (!task_core_is_available(&TASK_CURRENT_CORE(core), mask));
524-
525-
/* refresh current task pointer & state */
526-
task = &TASK_CURRENT_CORE(core);
527-
task->state = PICORTOS_TASK_STATE_BUSY;
521+
while (count-- != 0) {
522+
/* choose next task to run */
523+
do {
524+
picoRTOS.index[core]++;
525+
picoRTOS_assert_void_fatal(picoRTOS.index[core] < (picoRTOS_pid_t)TASK_COUNT);
526+
/* ignore sleeping, empty tasks & out-of-round sub-tasks */
527+
} while (!task_core_is_available(&TASK_CURRENT_CORE(core), mask));
528+
529+
/* refresh current task pointer & state */
530+
task = &TASK_CURRENT_CORE(core);
531+
532+
/* postponed tasks management */
533+
if (picoRTOS.index[core] >= (picoRTOS_pid_t)TASK_IDLE_PID &&
534+
(picoRTOS.flags & F_POSTPONED) != 0) {
535+
/* reset flags & index */
536+
picoRTOS.flags &= ~F_POSTPONED;
537+
picoRTOS.index[core] = (picoRTOS_pid_t)-1;
538+
}else{
539+
/* next task or idle */
540+
task->state = PICORTOS_TASK_STATE_BUSY;
541+
break;
542+
}
543+
}
528544

529-
/* stats */
530-
task_core_stat_start(task);
545+
picoRTOS_assert_void_fatal(count != -1); /* check */
546+
task_core_stat_start(task); /* stats */
531547

532548
return task;
533549
}
@@ -565,6 +581,8 @@ picoRTOS_stack_t *picoRTOS_syscall(picoRTOS_stack_t *sp, syscall_t syscall, void
565581

566582
default:
567583
/* SYSCALL_SWITCH_CONTEXT */
584+
picoRTOS.flags |= F_POSTPONED;
585+
task->state = PICORTOS_TASK_STATE_READY;
568586
break;
569587
}
570588

scheduler/picoRTOS.c

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,11 @@ struct picoRTOS_task_sub {
5757
#define L1_CACHE_ALIGN(x, a) L1_CACHE_ALIGN_MASK((x), ((a) - 1))
5858
#define L1_CACHE_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
5959

60+
#define F_RUNNING (1 << 0)
61+
#define F_POSTPONED (1 << 1)
62+
6063
struct picoRTOS_core {
61-
bool is_running;
64+
int flags;
6265
picoRTOS_pid_t index;
6366
picoRTOS_tick_t tick;
6467
picoRTOS_pid_t pid_count;
@@ -192,7 +195,7 @@ void picoRTOS_init(void)
192195
picoRTOS.tick = (picoRTOS_tick_t)-1; /* 1st tick will be 0 */
193196

194197
/* RTOS status */
195-
picoRTOS.is_running = false;
198+
picoRTOS.flags = 0;
196199
}
197200

198201
/* Function: picoRTOS_task_init
@@ -395,7 +398,7 @@ void picoRTOS_start(void)
395398
core_arrange_shared_priorities();
396399

397400
arch_init();
398-
picoRTOS.is_running = true;
401+
picoRTOS.flags |= F_RUNNING;
399402
arch_start_first_task(TASK_BY_PID(TASK_IDLE_PID).sp);
400403
}
401404

@@ -404,7 +407,7 @@ void picoRTOS_start(void)
404407
*/
405408
void picoRTOS_suspend(void)
406409
{
407-
picoRTOS_assert_fatal(picoRTOS.is_running, return );
410+
picoRTOS_assert_fatal((picoRTOS.flags & F_RUNNING) != 0, return );
408411
arch_suspend();
409412
}
410413

@@ -413,19 +416,17 @@ void picoRTOS_suspend(void)
413416
*/
414417
void picoRTOS_resume(void)
415418
{
416-
picoRTOS_assert_fatal(picoRTOS.is_running, return );
419+
picoRTOS_assert_fatal((picoRTOS.flags & F_RUNNING) != 0, return );
417420
arch_resume();
418421
}
419422

420-
/* Function: picoRTOS_schedule
421-
* Puts the current task to sleep until next tick
423+
/* Function: picoRTOS_postpone
424+
* Puts the current task back in the scheduler's FIFO (don't wait for next tick)
422425
*/
423-
void picoRTOS_schedule(void)
426+
void picoRTOS_postpone(void)
424427
{
425-
static const struct syscall_sleep delay = { (picoRTOS_tick_t)1 };
426-
427-
picoRTOS_assert_fatal(picoRTOS.is_running, return );
428-
arch_syscall(SYSCALL_SLEEP, (struct syscall_sleep*)&delay);
428+
picoRTOS_assert_fatal((picoRTOS.flags & F_RUNNING) != 0, return );
429+
arch_syscall(SYSCALL_SWITCH_CONTEXT, NULL);
429430
}
430431

431432
/* Function: picoRTOS_sleep
@@ -437,7 +438,7 @@ void picoRTOS_schedule(void)
437438
*/
438439
void picoRTOS_sleep(picoRTOS_tick_t delay)
439440
{
440-
picoRTOS_assert_fatal(picoRTOS.is_running, return );
441+
picoRTOS_assert_fatal((picoRTOS.flags & F_RUNNING) != 0, return );
441442
arch_syscall(SYSCALL_SLEEP, (struct syscall_sleep*)&delay);
442443
}
443444

@@ -465,7 +466,7 @@ void picoRTOS_sleep(picoRTOS_tick_t delay)
465466
void picoRTOS_sleep_until(picoRTOS_tick_t *ref, picoRTOS_tick_t period)
466467
{
467468
picoRTOS_assert_fatal(period > 0, return );
468-
picoRTOS_assert_fatal(picoRTOS.is_running, return );
469+
picoRTOS_assert_fatal((picoRTOS.flags & F_RUNNING) != 0, return );
469470

470471
struct syscall_sleep_until sc = { *ref, period };
471472

@@ -478,7 +479,7 @@ void picoRTOS_sleep_until(picoRTOS_tick_t *ref, picoRTOS_tick_t period)
478479
*/
479480
void picoRTOS_kill(void)
480481
{
481-
picoRTOS_assert_fatal(picoRTOS.is_running, return );
482+
picoRTOS_assert_fatal((picoRTOS.flags & F_RUNNING) != 0, return );
482483
arch_syscall(SYSCALL_KILL, NULL);
483484
}
484485

@@ -487,7 +488,7 @@ void picoRTOS_kill(void)
487488
*/
488489
picoRTOS_pid_t picoRTOS_self(void)
489490
{
490-
picoRTOS_assert_fatal(picoRTOS.is_running, return (picoRTOS_pid_t)-1);
491+
picoRTOS_assert_fatal((picoRTOS.flags & F_RUNNING) != 0, return (picoRTOS_pid_t)-1);
491492
return (picoRTOS_pid_t)picoRTOS.index;
492493
}
493494

@@ -496,7 +497,7 @@ picoRTOS_pid_t picoRTOS_self(void)
496497
*/
497498
picoRTOS_tick_t picoRTOS_get_tick(void)
498499
{
499-
picoRTOS_assert_fatal(picoRTOS.is_running, return (picoRTOS_tick_t)-1);
500+
picoRTOS_assert_fatal((picoRTOS.flags & F_RUNNING) != 0, return (picoRTOS_tick_t)-1);
500501
return picoRTOS.tick;
501502
}
502503

@@ -544,21 +545,35 @@ static void syscall_kill(struct picoRTOS_task_core *task)
544545
static struct picoRTOS_task_core *
545546
syscall_switch_context(struct picoRTOS_task_core *task)
546547
{
548+
int count = 2;
549+
547550
/* stats */
548551
task_core_stat_finish(task);
549552

550-
/* choose next task to run */
551-
do {
552-
picoRTOS.index++;
553-
picoRTOS_assert_void_fatal(picoRTOS.index < (picoRTOS_pid_t)TASK_COUNT);
554-
/* ignore sleeping, empty tasks & out-of-round sub-tasks */
555-
} while (!task_core_is_available(&TASK_CURRENT()));
556-
557-
/* refresh current task pointer */
558-
task = &TASK_CURRENT();
553+
while (count-- != 0) {
554+
/* choose next task to run */
555+
do {
556+
picoRTOS.index++;
557+
picoRTOS_assert_void_fatal(picoRTOS.index < (picoRTOS_pid_t)TASK_COUNT);
558+
/* ignore sleeping, empty tasks & out-of-round sub-tasks */
559+
} while (!task_core_is_available(&TASK_CURRENT()));
560+
561+
/* refresh current task pointer */
562+
task = &TASK_CURRENT();
563+
564+
/* postponed tasks management */
565+
if (picoRTOS.index == (picoRTOS_pid_t)TASK_IDLE_PID &&
566+
(picoRTOS.flags & F_POSTPONED) != 0) {
567+
/* reset flags & index */
568+
picoRTOS.flags &= ~F_POSTPONED;
569+
picoRTOS.index = (picoRTOS_pid_t)-1;
570+
}else
571+
/* next task or idle */
572+
break;
573+
}
559574

560-
/* stats */
561-
task_core_stat_start(task);
575+
picoRTOS_assert_void_fatal(count != -1); /* check */
576+
task_core_stat_start(task); /* stats */
562577

563578
return task;
564579
}
@@ -592,6 +607,7 @@ picoRTOS_stack_t *picoRTOS_syscall(picoRTOS_stack_t *sp, syscall_t syscall, void
592607

593608
default:
594609
/* SYSCALL_SWITCH_CONTEXT */
610+
picoRTOS.flags |= F_POSTPONED;
595611
break;
596612
}
597613

0 commit comments

Comments
 (0)