POK(kernelpart)
|
00001 /* 00002 * POK header 00003 * 00004 * The following file is a part of the POK project. Any modification should 00005 * made according to the POK licence. You CANNOT use this file or a part of 00006 * this file is this part of a file for your own project 00007 * 00008 * For more information on the POK licence, please see our LICENCE FILE 00009 * 00010 * Please follow the coding guidelines described in doc/CODING_GUIDELINES 00011 * 00012 * Copyright (c) 2007-2009 POK team 00013 * 00014 * Created by julien on Thu Jan 15 23:34:13 2009 00015 */ 00016 00024 #include <types.h> 00025 00026 #include <arch.h> 00027 #include <core/debug.h> 00028 #include <core/error.h> 00029 #include <core/thread.h> 00030 #include <core/sched.h> 00031 #include <core/partition.h> 00032 #include <core/time.h> 00033 00034 #include <core/instrumentation.h> 00035 00036 #ifdef POK_NEEDS_THREADS 00037 00044 pok_thread_t pok_threads[POK_CONFIG_NB_THREADS]; 00045 00046 extern pok_partition_t pok_partitions[POK_CONFIG_NB_PARTITIONS]; 00047 00048 #ifdef POK_NEEDS_SCHED_RMS 00049 00054 void pok_thread_insert_sort(uint16_t index_low, uint16_t index_high) 00055 { 00056 uint32_t i=index_high,j=0; 00057 pok_thread_t val; 00058 00059 val=pok_threads[i]; 00060 j=i-1; 00061 while ( j>= index_low && pok_threads[j].period > val.period) 00062 { 00063 pok_threads[j+1] = pok_threads[j]; 00064 j--; 00065 } 00066 pok_threads[j+1]=val; 00067 } 00068 #endif 00069 00070 00075 void pok_thread_init(void) 00076 { 00077 uint32_t i; 00078 00079 #ifdef POK_NEEDS_PARTITIONS 00080 uint32_t total_threads; 00081 uint8_t j; 00082 00083 total_threads = 0; 00084 00085 for (j = 0 ; j < POK_CONFIG_NB_PARTITIONS ; j++) 00086 { 00087 total_threads = total_threads + pok_partitions[j].nthreads; 00088 } 00089 00090 #if defined (POK_NEEDS_DEBUG) || defined (POK_NEEDS_ERROR_HANDLING) 00091 if (total_threads != (POK_CONFIG_NB_THREADS - 2)) 00092 { 00093 #ifdef POK_NEEDS_DEBUG 00094 printf ("Error in configuration, bad number of threads\n"); 00095 #endif 00096 #ifdef POK_NEEDS_ERROR_HANDLING 00097 pok_kernel_error (POK_ERROR_KIND_KERNEL_CONFIG); 00098 #endif 00099 } 00100 #endif 00101 #endif 00102 00103 pok_threads[KERNEL_THREAD].priority = pok_sched_get_priority_min(0); 00104 pok_threads[KERNEL_THREAD].base_priority = pok_sched_get_priority_min(0); 00105 pok_threads[KERNEL_THREAD].state = POK_STATE_RUNNABLE; 00106 pok_threads[KERNEL_THREAD].next_activation = 0; 00107 00108 pok_threads[IDLE_THREAD].period = 0; 00109 pok_threads[IDLE_THREAD].deadline = 0; 00110 pok_threads[IDLE_THREAD].time_capacity = 0; 00111 pok_threads[IDLE_THREAD].next_activation = 0; 00112 pok_threads[IDLE_THREAD].remaining_time_capacity = 0; 00113 pok_threads[IDLE_THREAD].wakeup_time = 0; 00114 pok_threads[IDLE_THREAD].entry = pok_arch_idle; 00115 pok_threads[IDLE_THREAD].base_priority = pok_sched_get_priority_min(0); 00116 pok_threads[IDLE_THREAD].state = POK_STATE_RUNNABLE; 00117 00118 pok_threads[IDLE_THREAD].sp = pok_context_create 00119 (IDLE_THREAD, IDLE_STACK_SIZE, 00120 (uint32_t)pok_arch_idle); 00121 00122 for (i = 0; i < POK_CONFIG_NB_THREADS; ++i) 00123 { 00124 pok_threads[i].period = 0; 00125 pok_threads[i].deadline = 0; 00126 pok_threads[i].time_capacity = 0; 00127 pok_threads[i].remaining_time_capacity = 0; 00128 pok_threads[i].next_activation = 0; 00129 pok_threads[i].wakeup_time = 0; 00130 pok_threads[i].state = POK_STATE_STOPPED; 00131 } 00132 } 00133 00134 #ifdef POK_NEEDS_PARTITIONS 00135 00141 pok_ret_t pok_partition_thread_create (uint32_t* thread_id, 00142 const pok_thread_attr_t* attr, 00143 const uint8_t partition_id) 00144 { 00145 uint32_t id; 00146 uint32_t stack_vaddr; 00150 if ( (pok_partitions[partition_id].mode != POK_PARTITION_MODE_INIT_COLD) && 00151 (pok_partitions[partition_id].mode != POK_PARTITION_MODE_INIT_WARM) ) 00152 { 00153 return POK_ERRNO_MODE; 00154 } 00155 00156 if (pok_partitions[partition_id].thread_index >= pok_partitions[partition_id].thread_index_high) 00157 { 00158 #ifdef POK_NEEDS_ERROR_HANDLING 00159 POK_ERROR_CURRENT_PARTITION (POK_ERROR_KIND_PARTITION_CONFIGURATION); 00160 #endif 00161 return POK_ERRNO_TOOMANY; 00162 } 00163 00164 id = pok_partitions[partition_id].thread_index_low + pok_partitions[partition_id].thread_index; 00165 pok_partitions[partition_id].thread_index = pok_partitions[partition_id].thread_index + 1; 00166 00167 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))) 00168 { 00169 pok_threads[id].priority = attr->priority; 00170 pok_threads[id].base_priority = attr->priority; 00171 } 00172 00173 if (attr->period > 0) 00174 { 00175 pok_threads[id].period = attr->period; 00176 pok_threads[id].next_activation = attr->period; 00177 } 00178 00179 if (attr->deadline > 0) 00180 { 00181 pok_threads[id].deadline = attr->deadline; 00182 } 00183 00184 #ifdef POK_NEEDS_SCHED_HFPPS 00185 pok_threads[id].payback = 0; 00186 #endif /* POK_NEEDS_SCHED_HFPPS */ 00187 00188 if (attr->time_capacity > 0) 00189 { 00190 pok_threads[id].time_capacity = attr->time_capacity; 00191 pok_threads[id].remaining_time_capacity = attr->time_capacity; 00192 } 00193 else 00194 { 00195 pok_threads[id].remaining_time_capacity = POK_THREAD_DEFAULT_TIME_CAPACITY; 00196 pok_threads[id].time_capacity = POK_THREAD_DEFAULT_TIME_CAPACITY; 00197 } 00198 00199 stack_vaddr = pok_thread_stack_addr (partition_id, pok_partitions[partition_id].thread_index); 00200 00201 pok_threads[id].state = POK_STATE_RUNNABLE; 00202 pok_threads[id].wakeup_time = 0; 00203 pok_threads[id].sp = pok_space_context_create (partition_id, 00204 (uint32_t)attr->entry, 00205 stack_vaddr, 00206 0xdead, 00207 0xbeaf); 00208 /* 00209 * FIXME : current debug session about exceptions-handled 00210 printf ("thread sp=0x%x\n", pok_threads[id].sp); 00211 printf ("thread stack vaddr=0x%x\n", stack_vaddr); 00212 */ 00213 pok_threads[id].partition = partition_id; 00214 pok_threads[id].entry = attr->entry; 00215 pok_threads[id].init_stack_addr = stack_vaddr; 00216 *thread_id = id; 00217 00218 #ifdef POK_NEEDS_SCHED_RMS 00219 if ((pok_partitions[partition_id].sched == POK_SCHED_RMS) && (id > pok_partitions[partition_id].thread_index_low)) 00220 { 00221 pok_thread_insert_sort(pok_partitions[partition_id].thread_index_low+1,id); 00222 } 00223 #endif 00224 00225 #ifdef POK_NEEDS_INSTRUMENTATION 00226 pok_instrumentation_task_archi (id); 00227 #endif 00228 00229 return POK_ERRNO_OK; 00230 } 00231 #endif 00232 00233 00238 void pok_thread_start(void (*entry)(), unsigned int id) 00239 { 00240 (void) id; 00241 entry(); 00242 } 00243 00244 #ifdef POK_NEEDS_THREAD_SLEEP 00245 pok_ret_t pok_thread_sleep (uint32_t time) 00246 { 00247 uint64_t mytime; 00248 mytime = time + POK_GETTICK(); 00249 pok_sched_lock_current_thread_timed (mytime); 00250 pok_sched (); 00251 return POK_ERRNO_OK; 00252 } 00253 #endif 00254 00255 #ifdef POK_NEEDS_THREAD_SLEEP_UNTIL 00256 pok_ret_t pok_thread_sleep_until (uint32_t time) 00257 { 00258 pok_sched_lock_current_thread_timed ((uint64_t)time); 00259 pok_sched (); 00260 return POK_ERRNO_OK; 00261 } 00262 #endif 00263 00264 #if defined (POK_NEEDS_THREAD_SUSPEND) || defined (POK_NEEDS_ERROR_HANDLING) 00265 pok_ret_t pok_thread_suspend (void) 00266 { 00267 pok_sched_stop_self (); 00268 pok_sched (); 00269 return POK_ERRNO_OK; 00270 } 00271 #endif 00272 00273 #ifdef POK_NEEDS_ERROR_HANDLING 00274 pok_ret_t pok_thread_restart (const uint32_t tid) 00275 { 00280 pok_threads[tid].remaining_time_capacity = pok_threads[tid].time_capacity; 00281 pok_threads[tid].state = POK_STATE_WAIT_NEXT_ACTIVATION; 00282 pok_threads[tid].wakeup_time = 0; 00283 00295 pok_threads[tid].sp = pok_space_context_create (pok_threads[tid].partition, 00296 (uint32_t)pok_threads[tid].entry, 00297 pok_threads[tid].init_stack_addr, 00298 0xdead, 00299 0xbeaf); 00300 00301 return POK_ERRNO_OK; 00302 } 00303 #endif 00304 00305 pok_ret_t pok_thread_delayed_start (const uint32_t id, const uint32_t ms) 00306 { 00307 if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id) 00308 return POK_ERRNO_THREADATTR; 00309 pok_threads[id].priority = pok_threads[id].base_priority; 00310 //reset stack 00311 pok_context_reset(POK_USER_STACK_SIZE,pok_threads[id].init_stack_addr); 00312 if ((long long)pok_threads[id].period == -1) //-1 <==> ARINC INFINITE_TIME_VALUE 00313 { 00314 if (pok_partitions[pok_threads[id].partition].mode == POK_PARTITION_MODE_NORMAL) 00315 { 00316 if (ms == 0) 00317 { 00318 pok_threads[id].state = POK_STATE_RUNNABLE; 00319 pok_threads[id].end_time = POK_GETTICK() + pok_threads[id].time_capacity; 00320 } 00321 else 00322 { 00323 pok_threads[id].state = POK_STATE_WAITING; 00324 pok_threads[id].wakeup_time = POK_GETTICK() + ms; 00325 } 00326 //the preemption is always enabled so 00327 pok_sched(); 00328 } 00329 else //the partition mode is cold or warm start 00330 { 00331 pok_threads[id].state = POK_STATE_DELAYED_START; 00332 pok_threads[id].wakeup_time = ms; 00333 } 00334 } 00335 else 00336 { 00337 if (pok_partitions[pok_threads[id].partition].mode == POK_PARTITION_MODE_NORMAL) 00338 { // set the first release point 00339 pok_threads[id].next_activation = ms + POK_GETTICK(); 00340 pok_threads[id].end_time = pok_threads[id].deadline + pok_threads[id].next_activation; 00341 } 00342 else 00343 { 00344 pok_threads[id].state = POK_STATE_DELAYED_START; 00345 pok_threads[id].wakeup_time = ms; // temporarly storing the delay, see set_partition_mode 00346 } 00347 } 00348 return POK_ERRNO_OK; 00349 } 00350 00351 pok_ret_t pok_thread_get_status (const uint32_t id, pok_thread_attr_t *attr) 00352 { 00353 if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id) 00354 return POK_ERRNO_PARAM; 00355 attr->deadline = pok_threads[id].end_time; 00356 attr->state = pok_threads[id].state; 00357 attr->priority = pok_threads[id].priority; 00358 attr->entry = pok_threads[id].entry; 00359 attr->period = pok_threads[id].period; 00360 attr->time_capacity = pok_threads[id].time_capacity; 00361 attr->stack_size = POK_USER_STACK_SIZE; 00362 return POK_ERRNO_OK; 00363 } 00364 00365 pok_ret_t pok_thread_set_priority (const uint32_t id, const uint32_t priority) 00366 { 00367 if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id) 00368 return POK_ERRNO_PARAM; 00369 pok_threads[id].priority = priority; 00370 /* preemption is always enabled so ... */ 00371 pok_sched(); 00372 return POK_ERRNO_OK; 00373 } 00374 00375 pok_ret_t pok_thread_resume (const uint32_t id) 00376 { 00377 if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id) 00378 return POK_ERRNO_THREADATTR; 00379 pok_threads[id].wakeup_time = POK_GETTICK(); 00380 pok_threads[id].state = POK_STATE_RUNNABLE; 00381 /* preemption is always enabled */ 00382 pok_sched(); 00383 return POK_ERRNO_OK; 00384 } 00385 00386 pok_ret_t pok_thread_suspend_target (const uint32_t id) 00387 { 00388 if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id || id == POK_SCHED_CURRENT_THREAD) 00389 return POK_ERRNO_THREADATTR; 00390 pok_threads[id].state = POK_STATE_STOPPED; 00391 return POK_ERRNO_OK; 00392 } 00393 00394 #endif