POK(kernelpart)
thread.c
Go to the documentation of this file.
1 /*
2  * POK header
3  *
4  * The following file is a part of the POK project. Any modification should
5  * made according to the POK licence. You CANNOT use this file or a part of
6  * this file is this part of a file for your own project
7  *
8  * For more information on the POK licence, please see our LICENCE FILE
9  *
10  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
11  *
12  * Copyright (c) 2007-2009 POK team
13  *
14  * Created by julien on Thu Jan 15 23:34:13 2009
15  */
16 
24 #include <types.h>
25 
26 #include <arch.h>
27 #include <core/debug.h>
28 #include <core/error.h>
29 #include <core/thread.h>
30 #include <core/sched.h>
31 #include <core/partition.h>
32 #include <core/time.h>
33 
34 #include <core/instrumentation.h>
35 
36 #ifdef POK_NEEDS_THREADS
37 
44 pok_thread_t pok_threads[POK_CONFIG_NB_THREADS];
45 
46 extern pok_partition_t pok_partitions[POK_CONFIG_NB_PARTITIONS];
47 
48 #ifdef POK_NEEDS_SCHED_RMS
49 
54 void pok_thread_insert_sort(uint16_t index_low, uint16_t index_high)
55 {
56  uint32_t i=index_high,j=0;
57  pok_thread_t val;
58 
59  val=pok_threads[i];
60  j=i-1;
61  while ( j>= index_low && pok_threads[j].period > val.period)
62  {
63  pok_threads[j+1] = pok_threads[j];
64  j--;
65  }
66  pok_threads[j+1]=val;
67 }
68 #endif
69 
70 
75 void pok_thread_init(void)
76 {
77  uint32_t i;
78 
79 #ifdef POK_NEEDS_PARTITIONS
80  uint32_t total_threads;
81  uint8_t j;
82 
83  total_threads = 0;
84 
85  for (j = 0 ; j < POK_CONFIG_NB_PARTITIONS ; j++)
86  {
87  total_threads = total_threads + pok_partitions[j].nthreads;
88  }
89 
90 #if defined (POK_NEEDS_DEBUG) || defined (POK_NEEDS_ERROR_HANDLING)
91  if (total_threads != (POK_CONFIG_NB_THREADS - 2))
92  {
93 #ifdef POK_NEEDS_DEBUG
94  printf ("Error in configuration, bad number of threads\n");
95 #endif
96 #ifdef POK_NEEDS_ERROR_HANDLING
97  pok_kernel_error (POK_ERROR_KIND_KERNEL_CONFIG);
98 #endif
99  }
100 #endif
101 #endif
102 
103  pok_threads[KERNEL_THREAD].priority = pok_sched_get_priority_min(0);
104  pok_threads[KERNEL_THREAD].state = POK_STATE_RUNNABLE;
105  pok_threads[KERNEL_THREAD].next_activation = 0;
106 
107  pok_threads[IDLE_THREAD].period = 0;
108  pok_threads[IDLE_THREAD].deadline = 0;
109  pok_threads[IDLE_THREAD].time_capacity = 0;
110  pok_threads[IDLE_THREAD].next_activation = 0;
111  pok_threads[IDLE_THREAD].remaining_time_capacity = 0;
112  pok_threads[IDLE_THREAD].wakeup_time = 0;
113  pok_threads[IDLE_THREAD].entry = pok_arch_idle;
114  pok_threads[IDLE_THREAD].priority = pok_sched_get_priority_min(0);
115  pok_threads[IDLE_THREAD].state = POK_STATE_RUNNABLE;
116 
117  pok_threads[IDLE_THREAD].sp = pok_context_create
118  (IDLE_THREAD, IDLE_STACK_SIZE,
120 
121  for (i = 0; i < POK_CONFIG_NB_THREADS; ++i)
122  {
123  pok_threads[i].period = 0;
124  pok_threads[i].deadline = 0;
125  pok_threads[i].time_capacity = 0;
126  pok_threads[i].remaining_time_capacity = 0;
127  pok_threads[i].next_activation = 0;
128  pok_threads[i].wakeup_time = 0;
129  pok_threads[i].state = POK_STATE_STOPPED;
130  }
131 }
132 
133 #ifdef POK_NEEDS_PARTITIONS
134 
140 pok_ret_t pok_partition_thread_create (uint32_t* thread_id,
141  const pok_thread_attr_t* attr,
142  const uint8_t partition_id)
143 {
144  uint32_t id;
145  uint32_t stack_vaddr;
149  if ( (pok_partitions[partition_id].mode != POK_PARTITION_MODE_INIT_COLD) &&
150  (pok_partitions[partition_id].mode != POK_PARTITION_MODE_INIT_WARM) )
151  {
152  return POK_ERRNO_MODE;
153  }
154 
155  if (pok_partitions[partition_id].thread_index >= pok_partitions[partition_id].thread_index_high)
156  {
157 #ifdef POK_NEEDS_ERROR_HANDLING
158  POK_ERROR_CURRENT_PARTITION (POK_ERROR_KIND_PARTITION_CONFIGURATION);
159 #endif
160  return POK_ERRNO_TOOMANY;
161  }
162 
163  id = pok_partitions[partition_id].thread_index_low + pok_partitions[partition_id].thread_index;
164  pok_partitions[partition_id].thread_index = pok_partitions[partition_id].thread_index + 1;
165 
166  if ((attr->priority <= pok_sched_get_priority_max (pok_partitions[partition_id].sched)) && (attr->priority >= pok_sched_get_priority_min (pok_partitions[partition_id].sched)))
167  {
168  pok_threads[id].priority = attr->priority;
169  }
170 
171  if (attr->period > 0)
172  {
173  pok_threads[id].period = attr->period;
174  pok_threads[id].next_activation = attr->period;
175  }
176 
177  if (attr->deadline > 0)
178  {
179  pok_threads[id].deadline = attr->deadline;
180  }
181 
182 #ifdef POK_NEEDS_SCHED_HFPPS
183  pok_threads[id].payback = 0;
184 #endif /* POK_NEEDS_SCHED_HFPPS */
185 
186  if (attr->time_capacity > 0)
187  {
188  pok_threads[id].time_capacity = attr->time_capacity;
189  pok_threads[id].remaining_time_capacity = attr->time_capacity;
190  }
191  else
192  {
193  pok_threads[id].remaining_time_capacity = POK_THREAD_DEFAULT_TIME_CAPACITY;
194  pok_threads[id].time_capacity = POK_THREAD_DEFAULT_TIME_CAPACITY;
195  }
196 
197  stack_vaddr = pok_thread_stack_addr (partition_id, pok_partitions[partition_id].thread_index);
198 
199  pok_threads[id].state = POK_STATE_RUNNABLE;
200  pok_threads[id].wakeup_time = 0;
201  pok_threads[id].sp = pok_space_context_create (partition_id,
202  (uint32_t)attr->entry,
203  stack_vaddr,
204  0xdead,
205  0xbeaf);
206  /*
207  * FIXME : current debug session about exceptions-handled
208  printf ("thread sp=0x%x\n", pok_threads[id].sp);
209  printf ("thread stack vaddr=0x%x\n", stack_vaddr);
210  */
211  pok_threads[id].partition = partition_id;
212  pok_threads[id].entry = attr->entry;
213  pok_threads[id].init_stack_addr = stack_vaddr;
214  *thread_id = id;
215 
216 #ifdef POK_NEEDS_SCHED_RMS
217  if ((pok_partitions[partition_id].sched == POK_SCHED_RMS) && (id > pok_partitions[partition_id].thread_index_low))
218  {
219  pok_thread_insert_sort(pok_partitions[partition_id].thread_index_low+1,id);
220  }
221 #endif
222 
223 #ifdef POK_NEEDS_INSTRUMENTATION
224  pok_instrumentation_task_archi (id);
225 #endif
226 
227  return POK_ERRNO_OK;
228 }
229 #endif
230 
231 
236 void pok_thread_start(void (*entry)(), unsigned int id)
237 {
238  (void) id;
239  entry();
240 }
241 
242 #ifdef POK_NEEDS_THREAD_SLEEP
243 pok_ret_t pok_thread_sleep (uint32_t time)
244 {
245  uint64_t mytime;
246  mytime = time + POK_GETTICK();
247  pok_sched_lock_current_thread_timed (mytime);
248  pok_sched ();
249  return POK_ERRNO_OK;
250 }
251 #endif
252 
253 #ifdef POK_NEEDS_THREAD_SLEEP_UNTIL
254 pok_ret_t pok_thread_sleep_until (uint32_t time)
255 {
256  pok_sched_lock_current_thread_timed ((uint64_t)time);
257  pok_sched ();
258  return POK_ERRNO_OK;
259 }
260 #endif
261 
262 #if defined (POK_NEEDS_THREAD_SUSPEND) || defined (POK_NEEDS_ERROR_HANDLING)
263 pok_ret_t pok_thread_suspend (void)
264 {
265  pok_sched_stop_self ();
266  pok_sched ();
267  return POK_ERRNO_OK;
268 }
269 #endif
270 
271 #ifdef POK_NEEDS_ERROR_HANDLING
272 pok_ret_t pok_thread_restart (const uint32_t tid)
273 {
278  pok_threads[tid].remaining_time_capacity = pok_threads[tid].time_capacity;
279  pok_threads[tid].state = POK_STATE_WAIT_NEXT_ACTIVATION;
280  pok_threads[tid].wakeup_time = 0;
281 
293  pok_threads[tid].sp = pok_space_context_create (pok_threads[tid].partition,
294  (uint32_t)pok_threads[tid].entry,
295  pok_threads[tid].init_stack_addr,
296  0xdead,
297  0xbeaf);
298 
299  return POK_ERRNO_OK;
300 }
301 #endif
302 
303 pok_ret_t pok_thread_get_status (const uint32_t id, pok_thread_attr_t *attr)
304 {
305  if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id)
306  return POK_ERRNO_THREADATTR;
307  attr->deadline = pok_threads[id].end_time;
308  attr->state = pok_threads[id].state;
309  attr->priority = pok_threads[id].priority;
310  attr->entry = pok_threads[id].entry;
311  attr->period = pok_threads[id].period;
312  attr->time_capacity = pok_threads[id].time_capacity;
313  attr->stack_size = POK_USER_STACK_SIZE;
314  return POK_ERRNO_OK;
315 }
316 #endif