Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sched-rr: A round-robin scheduler for normal thread #129

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ includes = \
board/$(BOARD) \
include \
include/platform \
include/sched-rr \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't name it after sched-rr. Instead, use include/sched and manipulate each scheduling policy through dedicated file.

.\
$(eval BOARD_$(BOARD)=y)

Expand All @@ -64,6 +65,7 @@ include platform/$(CHIP)/build.mk
include platform/$(PLATFORM)-common/build.mk
include platform/build.mk
include kernel/lib/build.mk
include kernel/sched-rr/build.mk
include kernel/build.mk
include user/build.mk
include loader/build.mk
Expand All @@ -80,6 +82,7 @@ all-y += $(call objs_from_dir,platform/$(PLATFORM)-common,platform-common)
all-y += $(call objs_from_dir,board/$(BOARD),board)
all-y += $(call objs_from_dir,platform,platform)
all-y += $(call objs_from_dir,kernel/lib,kernel-lib)
all-y += $(call objs_from_dir,kernel/sched-rr,kernel-sched-rr)
all-y += $(call objs_from_dir,kernel,kernel)
all-y += $(call objs_from_dir,user,user)

Expand All @@ -93,6 +96,7 @@ loader-all-y += $(call objs_from_dir,kernel,loader-kernel)

dirs = \
kernel/lib \
kernel/sched-rr \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

kernel \
platform/$(CHIP) \
platform/$(PLATFORM)-common \
Expand Down
1 change: 1 addition & 0 deletions board/discoveryf4/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ CONFIG_SMALLEST_FPAGE_SHIFT=8
# Thread tweaks
#
CONFIG_INTR_THREAD_MAX=256
CONFIG_THREAD_TIME_SLICE=4096

#
# KIP tweaks
Expand Down
1 change: 1 addition & 0 deletions board/discoveryf429/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ CONFIG_SMALLEST_FPAGE_SHIFT=8
# Thread tweaks
#
CONFIG_INTR_THREAD_MAX=256
CONFIG_THREAD_TIME_SLICE=4096

#
# KIP tweaks
Expand Down
1 change: 1 addition & 0 deletions board/stm32p103/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ CONFIG_SMALLEST_FPAGE_SHIFT=8
# Thread tweaks
#
CONFIG_INTR_THREAD_MAX=256
CONFIG_THREAD_TIME_SLICE=4096

#
# KIP tweaks
Expand Down
31 changes: 31 additions & 0 deletions include/sched-rr/sched_rr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Copyright (c) 2016 The F9 Microkernel Project. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/


#ifndef SCHED_RR_H_
#define SCHED_RR_H_

#define MAX_QUEUE (CONFIG_MAX_THREADS + 1)
#define TIME_SLICE CONFIG_THREAD_TIME_SLICE

typedef struct cqueue {
uint32_t Queue[MAX_QUEUE];
int front;
int rear;
int count;

void (*put)(struct cqueue *q, void *data);
void *(*get)(struct cqueue *q);
int (*is_empty)(struct cqueue *q);
int (*is_full)(struct cqueue *q);
int (*length)(struct cqueue *q);
} cqueue_t;


tcb_t *rr_select(void);
void rr_init_thread(tcb_t *thr);
uint32_t rr_exhaust_timeslice(void *data);

#endif
7 changes: 5 additions & 2 deletions include/thread.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2013 The F9 Microkernel Project. All rights reserved.
/* Copyright (c) 2013, 2016 The F9 Microkernel Project. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
Expand Down Expand Up @@ -54,7 +54,9 @@ typedef enum {
T_RUNNABLE,
T_SVC_BLOCKED,
T_RECV_BLOCKED,
T_SEND_BLOCKED
T_SEND_BLOCKED,
T_WAIT_SCHEDULE, /* Wait to append to scheduler */
T_PENDING_SCHED, /* Wait for execute in scheculer */
} thread_state_t;

typedef struct {
Expand Down Expand Up @@ -95,6 +97,7 @@ struct tcb {
struct tcb *t_child;

uint32_t timeout_event;
uint32_t (*timeslice_event)(void *);
};
typedef struct tcb tcb_t;

Expand Down
4 changes: 4 additions & 0 deletions kernel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ menu "Thread tweaks"
config INTR_THREAD_MAX
int "Maximum of interrupt threads"
default 256

config THREAD_TIME_SLICE
int "Maximum timeslice for threads"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve the descriptions.

default 4096
endmenu

menu "KIP tweaks"
Expand Down
11 changes: 7 additions & 4 deletions kernel/ipc.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2013, 2014 The F9 Microkernel Project. All rights reserved.
/* Copyright (c) 2013, 2014, 2016 The F9 Microkernel Project. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
Expand All @@ -16,6 +16,7 @@
#include <user-log.h>
#include <ktimer.h>
#include <interrupt.h>
#include <sched-rr/sched_rr.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto. It is not elegant!


extern tcb_t *caller;

Expand Down Expand Up @@ -241,7 +242,6 @@ void sys_ipc(uint32_t *param1)
/* mr1: thread func, mr2: stack addr, mr3: stack size*/
/* mr4: thread entry, mr5: thread args */
/* thread start protocol */

memptr_t sp = ipc_read_mr(caller, 2);
size_t stack_size = ipc_read_mr(caller, 3);
uint32_t regs[4]; /* r0, r1, r2, r3 */
Expand All @@ -260,8 +260,11 @@ void sys_ipc(uint32_t *param1)

caller->state = T_RUNNABLE;

/* Start thread */
to_thr->state = T_RUNNABLE;
/* make a timeslice for thread*/
dbg_printf(DL_IPC, "IPC: making timeslice for: %x @[%x]\n",
to_tid,
to_thr);
rr_init_thread(to_thr);

return;
} else {
Expand Down
1 change: 1 addition & 0 deletions kernel/ktimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ void ktimer_enter_tickless()
uint32_t tickless_delta;
uint32_t reload;

dbg_printf(DL_KTIMER, "KTE: Handle ticklesss event\n");
irq_disable();

if (ktimer_enabled && ktimer_delta <= KTIMER_MAXTICKS) {
Expand Down
6 changes: 6 additions & 0 deletions kernel/sched-rr/build.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright (c) 2016 The F9 Microkernel Project. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

kernel-sched-rr-y = \
sched_rr.o
103 changes: 103 additions & 0 deletions kernel/sched-rr/sched_rr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* Copyright (c) 2016 The F9 Microkernel Project. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include <types.h>
#include <thread.h>
#include <ktimer.h>
#include <sched-rr/sched_rr.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.


void put(cqueue_t *q, void *data)
{
if (!q->is_full(q)) {
q->count++;
q->rear = (q->rear + 1) % (MAX_QUEUE);
q->Queue[q->rear] = (uint32_t) data;
}
}

void *get(cqueue_t *q)
{
uint32_t ret;

if (!q->is_empty(q)) {
q->count--;
ret = q->Queue[++q->front % MAX_QUEUE];
if (q->front % MAX_QUEUE == 0) {
q->front = 0;
}

return (void *) ret;
}

return NULL;
}

int is_empty(cqueue_t *q)
{
return q->count == 0;
}

int is_full(cqueue_t *q)
{
return q->count == MAX_QUEUE - 1;
}

int length(cqueue_t *q)
{
return q->count;
}

cqueue_t schedQueue = {
.Queue = { 0 },
.front = -1,
.rear = -1,
.count = 0,
.put = put,
.get = get,
.is_empty = is_empty,
.is_full = is_full,
.length = length,
};

void rr_init_thread(tcb_t *thr)
{
thr->timeslice_event = rr_exhaust_timeslice;
thr->state = T_WAIT_SCHEDULE;
schedQueue.put(&schedQueue, (void *) thr);
}

uint32_t rr_exhaust_timeslice(void *data)
{
/* Get thread in data */
tcb_t *thr = (tcb_t *) ((ktimer_event_t *)data)->data;

/* Check thread state to schedule */
if (thr->state == T_RUNNABLE) {
thr->state = T_WAIT_SCHEDULE;
schedQueue.put(&schedQueue, (void *) thr);
}

return 0;
}

tcb_t *rr_select(void)
{
tcb_t *thr = NULL;

while (!schedQueue.is_empty(&schedQueue)) {
thr = (tcb_t *) schedQueue.get(&schedQueue);

if (thr->state == T_WAIT_SCHEDULE) {
thr->state = T_PENDING_SCHED;
schedQueue.put(&schedQueue, (void *) thr);
} else if (thr->state == T_PENDING_SCHED) {
thr->state = T_RUNNABLE;
ktimer_event_create(TIME_SLICE, thr->timeslice_event, thr);
return thr;
}
}

return NULL;
}
8 changes: 6 additions & 2 deletions kernel/thread.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2013, 2014 The F9 Microkernel Project. All rights reserved.
/* Copyright (c) 2013, 2014, 2016 The F9 Microkernel Project. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
Expand All @@ -12,6 +12,7 @@
#include <platform/armv7m.h>
#include <fpage_impl.h>
#include <init_hook.h>
#include <sched-rr/sched_rr.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.


/**
* @file thread.c
Expand Down Expand Up @@ -411,6 +412,9 @@ static tcb_t *thread_select(tcb_t *parent)
if (thr == NULL)
return NULL;

if ((thr = rr_select()) != NULL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make scheduling policy pluggable as Linux kernel does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is like insmod/rmmod or config in make config?

Thanks.

Also, Linux kernel scheduler is pluggable!? Ain't they choose when config?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OMg is pluggable....since 2004!

https://lwn.net/Articles/109458/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant pluggable scheduler framework.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If rr_select returns NULL, thrwill be modified as NULL and unexpected result
will happen in the following code.

return thr;

while (1) {
if (thread_isrunnable(thr))
return thr;
Expand Down Expand Up @@ -467,7 +471,7 @@ void kdb_dump_threads(void)
tcb_t *thr;
int idx;

char *state[] = { "FREE", "RUN", "SVC", "RECV", "SEND" };
char *state[] = { "FREE", "RUN", "SVC", "RECV", "SEND", "SCHED", "PEND"};

dbg_printf(DL_KDB, "%5s %8s %8s %6s %s\n",
"type", "global", "local", "state", "parent");
Expand Down