BRISCITS  0.1
RISC "Real-Time" Scheduler
brisc_thread.c
Go to the documentation of this file.
1 /******************************************************************************
2  ________ ________ ___ ________ ________ ___ _________ ________
3 |\ __ \|\ __ \|\ \|\ ____\|\ ____\|\ \|\___ ___\\ ____\
4 \ \ \|\ /\ \ \|\ \ \ \ \ \___|\ \ \___|\ \ \|___ \ \_\ \ \___|_
5  \ \ __ \ \ _ _\ \ \ \_____ \ \ \ \ \ \ \ \ \ \ \_____ \
6  \ \ \|\ \ \ \\ \\ \ \|____|\ \ \ \____\ \ \ \ \ \ \|____|\ \
7  \ \_______\ \__\\ _\\ \__\____\_\ \ \_______\ \__\ \ \__\ ____\_\ \
8  \|_______|\|__|\|__|\|__|\_________\|_______|\|__| \|__| |\_________\
9  \|_________| \|_________|
10 
11 MIT License
12 
13 Copyright (c) 2021 Mike Sharkey
14 
15 Permission is hereby granted, free of charge, to any person obtaining a copy
16 of this software and associated documentation files (the "Software"), to deal
17 in the Software without restriction, including without limitation the rights
18 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19 copies of the Software, and to permit persons to whom the Software is
20 furnished to do so, subject to the following conditions:
21 
22 The above copyright notice and this permission notice shall be included in all
23 copies or substantial portions of the Software.
24 
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 SOFTWARE.
32 
33 ******************************************************************************/
34 #include <brisc_thread.h>
35 #include <brisc_sched.h>
36 #include <string.h>
37 
38 static int thread_new_id( void );
39 static void thread_exit ( void );
40 
41 int b_thread_init( const char* name )
42 {
43  memset((void*)&brisc_scheduler_state,0,sizeof(brisc_scheduler_state));
44  for(int n=0; n < BRISC_THREAD_MAX; n++)
46 
47  /* insert the 'main' thread into the scheduler */
48  return b_thread_create( name, NULL, NULL, NULL, 0 );
49 }
50 
51 extern void b_thread_set_systick_fn(void (*systick_fn)(void))
52 {
53  brisc_scheduler_state.systick_fn = systick_fn;
54 }
55 
56 extern void b_thread_set_yield_fn(void (*yield_fn)(void))
57 {
59 }
60 
61 
63 {
64  return brisc_scheduler_state.systick;
65 }
66 
67 void b_thread_stop(int id)
68 {
70 }
71 
72 void b_thread_start(int id)
73 {
75 }
76 
77 void b_thread_lock( void )
78 {
79  ++brisc_scheduler_state.lock;
80 }
81 
82 void b_thread_unlock( void )
83 {
84  --brisc_scheduler_state.lock;
85 }
86 
87 void b_thread_yield( void )
88 {
89  cpu_yield();
90 }
91 
92 static void thread_exit( void )
93 {
94  // wait to die
95  for(;;);
96 }
97 
98 int b_thread_create( const char* name, void (*thread_fn)(void*), void* arg, cpu_reg_t* stack, size_t n_stack_words )
99 {
100  int id = thread_new_id();
101  if ( id >= 0 )
102  {
103  volatile brisc_thread_t* thread = b_thread_state(id);
104  if ( thread_fn == NULL && stack == NULL )
105  {
106  /* 'main' thread already has 'context' */
107  thread->prio = BRISC_THREAD_PRIO_MIN;
108  }
109  else
110  {
111  uint8_t* stack_uint8 = (uint8_t*)stack;
112 
113  /* initialize the cpu state initial stack frame */
114  cpu_state_t* cpu_state = (cpu_state_t*) &stack_uint8 [ (n_stack_words*sizeof(cpu_reg_t)) - sizeof(cpu_state_t) ];
115  memset( cpu_state, 0, sizeof(cpu_state_t) );
116 
117  cpu_state->reg.x[CPU_A0_XREG] = (cpu_reg_t)arg;
118  cpu_state->reg.x[CPU_RA_XREG] = (cpu_reg_t)thread_exit;
119  cpu_state->reg.x[CPU_PC_XREG] = (cpu_reg_t)thread_fn;
120  cpu_set_initial_state(cpu_state);
121 
122  /* initialize the initial thread state */
123  thread->cpu_state = cpu_state;
124  thread->prio = BRISC_THREAD_PRIO_SUSPEND;
125  }
126  strncpy( (void*)thread->name, name, BRISC_THREAD_NAME_MAX );
127  }
128  return id;
129 }
130 
131 
132 int b_thread_set_prio ( int id, int8_t prio )
133 {
134  volatile brisc_thread_t* thread = b_thread_state(id);
135  if ( thread )
136  {
137  thread->prio = prio;
138  return id;
139  }
140  return -1;
141 }
142 
143 int8_t b_thread_priority( int id )
144 {
145  volatile brisc_thread_t* thread = b_thread_state(id);
146  if ( thread )
147  {
148  return thread->prio;
149  }
151 }
152 
153 
154 static int thread_new_id( void )
155 {
156  for(int id=0; id < BRISC_THREAD_MAX; id++)
157  {
158  if ( brisc_scheduler_state.threads[id].prio == BRISC_THREAD_PRIO_INVALID )
159  {
161  return id;
162  }
163  }
164  return -1;
165 }
166 
167 volatile brisc_thread_t* b_thread_current( void )
168 {
169  return &brisc_scheduler_state.threads[brisc_scheduler_state.thread_id];
170 }
void(* yield_fn)(void)
Definition: brisc_sched.h:83
#define brisc_systick_t
Definition: brisc_thread.h:160
int b_thread_set_prio(int id, int8_t prio)
set a thread priority. < 0 is inactive, = 0 is active but suspended. > 0 indicates the maximum number...
Definition: brisc_thread.c:132
char name[BRISC_THREAD_NAME_MAX+1]
Definition: brisc_thread.h:88
void b_thread_lock(void)
Lock the scheduler such that the current thread will nut yield until thread_unlock() is called...
Definition: brisc_thread.c:77
volatile brisc_thread_t * b_thread_current(void)
Definition: brisc_thread.c:167
brisc_systick_t b_thread_systick(void)
Definition: brisc_thread.c:62
void b_thread_set_systick_fn(void(*systick_fn)(void))
Insert a callback on systick interrupt.
Definition: brisc_thread.c:51
void b_thread_start(int id)
Start a thread with the default priority of BRISC_THREAD_PRIO_MIN. TO start thread with other priorit...
Definition: brisc_thread.c:72
#define BRISC_THREAD_NAME_MAX
Definition: brisc_thread.h:152
#define BRISC_THREAD_PRIO_INVALID
Definition: brisc_thread.h:155
volatile brisc_scheduler_t brisc_scheduler_state
Definition: brisc_sched.c:37
void b_thread_stop(int id)
Stop a thread. The thread remains active in the run queue, yet receives no run time.
Definition: brisc_thread.c:67
#define BRISC_THREAD_MAX
Definition: brisc_thread.h:148
void b_thread_set_yield_fn(void(*yield_fn)(void))
Insert a callback on yield interrupt.
Definition: brisc_thread.c:56
#define BRISC_THREAD_PRIO_MIN
Definition: brisc_thread.h:157
void b_thread_yield(void)
Yield the remainder of the current thread&#39;s time slice(s).
Definition: brisc_thread.c:87
#define BRISC_THREAD_PRIO_SUSPEND
Definition: brisc_thread.h:156
int8_t prio
Definition: brisc_sched.h:80
int b_thread_create(const char *name, void(*thread_fn)(void *), void *arg, cpu_reg_t *stack, size_t n_stack_words)
Allocate a new thread in the run queue.
Definition: brisc_thread.c:98
cpu_state_t * cpu_state
Definition: brisc_thread.h:90
void b_thread_unlock(void)
Unlock the current thread (see thread_lock())
Definition: brisc_thread.c:82
volatile brisc_thread_t * b_thread_state(uint8_t id)
Definition: brisc_sched.c:63
void(* systick_fn)(void)
Definition: brisc_sched.h:82
int8_t b_thread_priority(int id)
Definition: brisc_thread.c:143
int b_thread_init(const char *name)
Called by the "main()" thread, initializes briscits and inserts an entry in the thread table for the ...
Definition: brisc_thread.c:41