Changeset 648
- Timestamp:
- Jul 22, 2015, 1:11:08 PM (9 years ago)
- Location:
- soft/giet_vm/giet_kernel
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_kernel/ctx_handler.c
r629 r648 109 109 // makes context switch 110 110 _task_switch( curr_ctx_vaddr , next_ctx_vaddr ); 111 112 111 } 113 112 } //end _ctx_switch() -
soft/giet_vm/giet_kernel/ctx_handler.h
r629 r648 33 33 // ctx[34]<- SR |ctx[42]<- CMA_RX |ctx[50]<- NORUN |ctx[58]<- *** 34 34 // ctx[35]<- BVAR |ctx[43]<- CMA_TX |ctx[51]<- COPROC |ctx[59]<- *** 35 // ctx[36]<- PTAB |ctx[44]<- NIC_RX |ctx[52]<- ***|ctx[60]<- ***35 // ctx[36]<- PTAB |ctx[44]<- NIC_RX |ctx[52]<- ENTRY |ctx[60]<- *** 36 36 // ctx[37]<- LTID |ctx[45]<- NIC_TX |ctx[53]<- *** |ctx[61]<- *** 37 37 // ctx[38]<- VSID |ctx[46]<- TIM |ctx[54]<- *** |ctx[62]<- *** … … 73 73 #define CTX_NORUN_ID 50 // bit-vector : task runable if all zero 74 74 #define CTX_COPROC_ID 51 // cluster_xy : coprocessor coordinates 75 #define CTX_ENTRY_ID 52 // Virtual address of task entry point 75 76 76 77 ///////////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/giet_kernel/irq_handler.c
r547 r648 252 252 unsigned int x = cluster_xy >> Y_WIDTH; 253 253 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 254 unsigned int lpid= gpid & ((1<<P_WIDTH)-1);254 unsigned int p = gpid & ((1<<P_WIDTH)-1); 255 255 unsigned int irq_id; 256 256 unsigned int irq_type; 257 257 258 258 // get the highest priority active IRQ index 259 unsigned int icu_out_index = lpid* IRQ_PER_PROCESSOR;259 unsigned int icu_out_index = p * IRQ_PER_PROCESSOR; 260 260 261 261 _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type ); … … 283 283 _nolock_printf("\n[DEBUG IRQS] _irq_demux() Processor[%d,%d,%d] enters at cycle %d\n" 284 284 " irq_type = %s / irq_id = %d / isr_type = %s / channel = %d\n", 285 x , y , lpid, _get_proctime() ,285 x , y , p , _get_proctime() , 286 286 _irq_type_str[irq_type] , irq_id , _isr_type_str[isr_type] , channel ); 287 287 #endif … … 309 309 " - irq_id = %d\n" 310 310 " - isr_type = %s\n", 311 x, y, lpid, _get_proctime(),311 x, y, p, _get_proctime(), 312 312 _irq_type_str[irq_type] , irq_id , _isr_type_str[isr_type] ); 313 313 _exit(); … … 327 327 unsigned int x = cluster_xy >> Y_WIDTH; 328 328 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 329 unsigned int lpid= gpid & ((1<<P_WIDTH)-1);329 unsigned int p = gpid & ((1<<P_WIDTH)-1); 330 330 331 331 _printf("\n[GIET WARNING] IRQ handler called but no active IRQ " 332 332 "on processor[%d,%d,%d] at cycle %d\n", 333 x, y, lpid, _get_proctime() );333 x, y, p, _get_proctime() ); 334 334 } 335 335 -
soft/giet_vm/giet_kernel/kernel_init.c
r629 r648 266 266 // initialisation, from values stored in the tasks contexts. 267 267 // - set CTX_RA slot with the kernel _ctx_eret() virtual address. 268 // - set CTX_E PCslot that must contain the task entry point,268 // - set CTX_ENTRY slot that must contain the task entry point, 269 269 // and contain only at this point the virtual address of the 270 // memory slotcontaining this entry point.270 // memory word containing this entry point. 271 271 //////////////////////////////////////////////////////////////////////////// 272 272 … … 283 283 _ptabs_ptprs[vsid][x][y] = ptpr; 284 284 285 // set the ptprto use the local page table285 // set the PTPR to use the local page table 286 286 asm volatile( "mtc2 %0, $0" 287 287 : : "r" (ptpr) ); 288 288 289 // compute ctx_ra289 // set CTX_RA slot 290 290 unsigned int ctx_ra = (unsigned int)(&_ctx_eret); 291 291 _set_task_slot( x, y, p, ltid, CTX_RA_ID, ctx_ra ); 292 292 293 // compute ctx_epc 294 unsigned int* ptr = (unsigned int*)_get_task_slot(x,y,p,ltid,CTX_EPC_ID); 295 _set_task_slot( x , y , p , ltid , CTX_EPC_ID , *ptr ); 293 // set CTX_ENTRY slot 294 unsigned int* ptr = (unsigned int*)_get_task_slot(x , y , p , ltid , CTX_ENTRY_ID); 295 unsigned int ctx_entry = *ptr; 296 _set_task_slot( x , y , p , ltid , CTX_ENTRY_ID , ctx_entry ); 296 297 297 298 #if GIET_DEBUG_INIT … … 300 301 " - ptabs_vaddr[%d][%d][%d] = %x\n" 301 302 " - ptabs_paddr[%d][%d][%d] = %l\n" 302 " - ctx_e pc= %x\n"303 " - ctx_entry = %x\n" 303 304 " - ctx_ra = %x\n", 304 305 x , y , p , ltid , 305 306 vsid , x , y , ptab , 306 307 vsid , x , y , ((unsigned long long)ptpr)<<13 , 307 _get_task_slot( x, y, p, ltid, CTX_EPC_ID ), 308 _get_task_slot( x, y, p, ltid, CTX_RA_ID ) ); 308 ctx_entry, ctx_ra ); 309 309 #endif 310 310 … … 316 316 317 317 //////////////////////////////////////////////////////////////////////////// 318 // step 3 : - Each processor complete idle task context initialisation ,319 // (only the CTX_SP, CTX_RA, CTX_EPC slot, because the CTX_PTPR320 // and CTX_PTAB slotshave been initialised in boot code)318 // step 3 : - Each processor complete idle task context initialisation. 319 // Only CTX_SP, CTX_RA, CTX_EPC slots, because other slots 320 // have been initialised in boot code) 321 321 // The 4 Kbytes idle stack is implemented in the scheduler itself. 322 // - Each processor starts TICK timer, as soon as at least one task 323 // is allocated. 322 // - Each processor starts TICK timer, if at least one task. 324 323 // - P[0,0,0] initialises FAT (not done before, because it must 325 324 // be done after the _ptabs_vaddr[v][x][y] array initialisation, … … 327 326 //////////////////////////////////////////////////////////////////////////// 328 327 329 unsigned int sp = ((unsigned int)psched) + 0x2000;330 unsigned int ra = (unsigned int)(&_ctx_eret);331 unsigned int e pc= (unsigned int)(&_idle_task);332 333 _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_SP_ID , sp );334 _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_RA_ID , ra );335 _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_E PC_ID , epc);328 unsigned int sp = ((unsigned int)psched) + 0x2000; 329 unsigned int ra = (unsigned int)(&_ctx_eret); 330 unsigned int entry = (unsigned int)(&_idle_task); 331 332 _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_SP_ID , sp ); 333 _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_RA_ID , ra ); 334 _set_task_slot( x , y , p , IDLE_TASK_INDEX , CTX_ENTRY_ID , entry ); 336 335 337 336 if (tasks > 0) _xcu_timer_start( cluster_xy, p, GIET_TICK_VALUE ); … … 358 357 359 358 //////////////////////////////////////////////////////////////////////////// 360 // step 4 : Each processor compute values for registers SP, SR, PTPR, EPC, 361 // corresponding to the first allocated task (can be idle task) 362 // and jumps to user code. 359 // step 4 : Each processor computes the task index (ltid), and the values 360 // to initialize the SP, SR, PTPR, EPC registers. 361 // It jumps to a runable task if possible, and jumps to IDLE-TASK 362 // if no task allocated or no runable task. 363 363 //////////////////////////////////////////////////////////////////////////// 364 364 … … 366 366 x, y, p ); 367 367 368 if (tasks == 0) ltid = IDLE_TASK_INDEX; 369 else ltid = 0; 370 368 // default value for ltid 369 ltid = IDLE_TASK_INDEX; 370 371 // scan allocated tasks to find a runable task 372 unsigned int task_id; 373 for ( task_id = 0 ; task_id < tasks ; task_id++ ) 374 { 375 if ( _get_task_slot( x, y, p, task_id, CTX_NORUN_ID ) == 0 ) 376 { 377 ltid = task_id; 378 break; 379 } 380 } 381 382 // update scheduler 383 psched->current = ltid; 384 385 // get values from selected task context 371 386 unsigned int sp_value = _get_task_slot( x, y, p, ltid, CTX_SP_ID); 372 387 unsigned int sr_value = _get_task_slot( x, y, p, ltid, CTX_SR_ID); 373 388 unsigned int ptpr_value = _get_task_slot( x, y, p, ltid, CTX_PTPR_ID); 374 unsigned int epc_value = _get_task_slot( x, y, p, ltid, CTX_E PC_ID);375 376 #if GIET_DEBUG_INIT 377 _printf("\n[DEBUG KINIT] P[%d,%d,%d] jumps to user codeat cycle %d\n"389 unsigned int epc_value = _get_task_slot( x, y, p, ltid, CTX_ENTRY_ID); 390 391 #if GIET_DEBUG_INIT 392 _printf("\n[DEBUG KINIT] P[%d,%d,%d] completes kernel_init at cycle %d\n" 378 393 " ltid = %d / sp = %x / sr = %x / ptpr = %x / epc = %x\n", 379 394 x , y , p , _get_proctime() , -
soft/giet_vm/giet_kernel/sys_handler.c
r629 r648 206 206 }; 207 207 208 209 ////////////////////////////////////////////////////////////////////////////// 210 // Applications related syscall handlers 211 ////////////////////////////////////////////////////////////////////////////// 212 213 /////////////////////////////////////// 214 int _sys_kill_application( char* name ) 215 { 216 mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 217 mapping_vspace_t * vspace = _get_vspace_base(header); 218 mapping_task_t * task = _get_task_base(header); 219 220 unsigned int vspace_id; 221 unsigned int task_id; 222 unsigned int y_size = header->y_size; 223 224 #if GIET_DEBUG_EXEC 225 if ( _get_proctime() > GIET_DEBUG_EXEC ) 226 _printf("\n[DEBUG EXEC] enters _sys_kill_application() for %s\n", name ); 227 #endif 228 229 // scan vspaces 230 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 231 { 232 if ( _strcmp( vspace[vspace_id].name, name ) == 0 ) 233 { 234 // check if pplication can be killed 235 if ( vspace[vspace_id].active ) return -2; 236 237 // scan tasks in vspace 238 for (task_id = vspace[vspace_id].task_offset; 239 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks); 240 task_id++) 241 { 242 unsigned int cid = task[task_id].clusterid; 243 unsigned int x = cid / y_size; 244 unsigned int y = cid % y_size; 245 unsigned int p = task[task_id].proclocid; 246 unsigned int ltid = task[task_id].ltid; 247 248 // get scheduler pointer for processor running the task 249 static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p]; 250 251 // release private TTY peripheral if required 252 if ( psched->context[ltid][CTX_TTY_ID] < NB_TTY_CHANNELS ) 253 { 254 psched->context[ltid][CTX_TTY_ID] = 0xFFFFFFFF; 255 _atomic_increment( &_tty_channel_allocator , 0xFFFFFFFF ); 256 } 257 258 // set NORUN_MASK_TASK bit 259 unsigned int* ptr = &psched->context[ltid][CTX_NORUN_ID]; 260 _atomic_or( ptr , NORUN_MASK_TASK ); 261 } 262 263 #if GIET_DEBUG_EXEC 264 if ( _get_proctime() > GIET_DEBUG_EXEC ) 265 _printf("\n[DEBUG EXEC] exit _sys_kill_application() : %s desactivated\n", name ); 266 #endif 267 268 return 0; 269 } 270 } 271 272 #if GIET_DEBUG_EXEC 273 if ( _get_proctime() > GIET_DEBUG_EXEC ) 274 _printf("\n[DEBUG EXEC] exit _sys_kill_application() : %s not found\n", name ); 275 #endif 276 277 return -1; // not found 278 279 } // end _sys_kill_application() 280 281 /////////////////////////////////////// 282 int _sys_exec_application( char* name ) 283 { 284 mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 285 mapping_vspace_t * vspace = _get_vspace_base(header); 286 mapping_task_t * task = _get_task_base(header); 287 mapping_vseg_t * vseg = _get_vseg_base(header); 288 289 unsigned int vspace_id; 290 unsigned int task_id; 291 unsigned int vseg_id; 292 293 unsigned int y_size = header->y_size; 294 295 #if GIET_DEBUG_EXEC 296 if ( _get_proctime() > GIET_DEBUG_EXEC ) 297 _printf("\n[DEBUG EXEC] enters _sys_exec_application() at cycle %d for %s\n", 298 _get_proctime() , name ); 299 #endif 300 301 // scan vspaces 302 for (vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++) 303 { 304 if ( _strcmp( vspace[vspace_id].name, name ) == 0 ) 305 { 306 // scan tasks in vspace 307 for (task_id = vspace[vspace_id].task_offset; 308 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks); 309 task_id++) 310 { 311 unsigned int cid = task[task_id].clusterid; 312 unsigned int x = cid / y_size; 313 unsigned int y = cid % y_size; 314 unsigned int p = task[task_id].proclocid; 315 unsigned int ltid = task[task_id].ltid; 316 317 // get scheduler pointer for the processor running the task 318 static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p]; 319 320 // sp_value : initial stack pointer 321 vseg_id = task[task_id].stack_vseg_id; 322 unsigned int sp_value = vseg[vseg_id].vbase + vseg[vseg_id].length; 323 324 // epc value : task entry point 325 unsigned int epc_value = psched->context[ltid][CTX_ENTRY_ID]; 326 327 // ra_value : initial return address 328 unsigned int ra_value = (unsigned int)(&_ctx_eret); 329 330 // initialise task context: RA / SR / EPC / SP / NORUN slots 331 psched->context[ltid][CTX_RA_ID] = ra_value; 332 psched->context[ltid][CTX_SR_ID] = GIET_SR_INIT_VALUE; 333 psched->context[ltid][CTX_SP_ID] = sp_value; 334 psched->context[ltid][CTX_EPC_ID] = epc_value; 335 psched->context[ltid][CTX_NORUN_ID] = 0; 336 337 #if GIET_DEBUG_EXEC 338 if ( _get_proctime() > GIET_DEBUG_EXEC ) 339 _printf("\n[DEBUG EXEC] _sys_exec_application() start task %d on P[%d,%d,%d]\n" 340 " - ctx_ra = %x\n" 341 " - ctx_sp = %x\n" 342 " - ctx_epc = %x\n", 343 task_id , x , y , p , ra_value , sp_value , epc_value ); 344 #endif 345 } 346 347 #if GIET_DEBUG_EXEC 348 if ( _get_proctime() > GIET_DEBUG_EXEC ) 349 _printf("\n[DEBUG EXEC] exit _sys_exec_application() at cycle %d : %s activated\n", 350 _get_proctime() , name ); 351 #endif 352 353 return 0; // application found and activated 354 } 355 } 356 357 #if GIET_DEBUG_EXEC 358 if ( _get_proctime() > GIET_DEBUG_EXEC ) 359 _printf("\n[DEBUG EXEC] exit _sys_exec_application() at cycle %d : %s not found\n", 360 _get_proctime() , name ); 361 #endif 362 363 return -1; // not found 364 365 } // end _sys_exec_application() 366 208 367 209 368 ////////////////////////////////////////////////////////////////////////////// … … 624 783 if ( channel >= NB_TTY_CHANNELS ) 625 784 { 785 _atomic_increment( &_tty_channel_allocator , 0xFFFFFFFF ); 626 786 _printf("\n[GIET_ERROR] in _sys_tty_alloc() : not enough TTY channels\n"); 627 787 return -1; 628 788 } 629 else 630 {631 }789 790 // reset kernel buffer for allocated TTY channel 791 _tty_rx_full[channel] = 0; 632 792 633 793 // allocate a WTI mailbox to the calling proc if external IRQ … … 1425 1585 1426 1586 1427 //////////////////////// 1428 int _sys_fbf_cma_init_buf( void* buf0_vbase,1429 void* buf1_vbase,1430 void* sts0_vaddr,1431 void* sts1_vaddr )1587 /////////////////////////////////////////////////// 1588 int _sys_fbf_cma_init_buf( void* buf0_vbase, 1589 void* buf1_vbase, 1590 void* sts0_vaddr, 1591 void* sts1_vaddr ) 1432 1592 { 1433 1593 #if NB_CMA_CHANNELS > 0 … … 1447 1607 if ( channel >= NB_CMA_CHANNELS ) 1448 1608 { 1449 _printf("\n[GIET ERROR] in _ fbf_cma_init_buf() : CMA channel index too large\n");1609 _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : CMA channel index too large\n"); 1450 1610 return -1; 1451 1611 } … … 1469 1629 ((unsigned int)buf1_vbase & 0x3F) ) 1470 1630 { 1471 _printf("\n[GIET ERROR] in _ fbf_cma_inti_buf() : user buffer not aligned\n");1631 _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user buffer not aligned\n"); 1472 1632 return -1; 1473 1633 } … … 1477 1637 ((unsigned int)sts1_vaddr & 0x3F) ) 1478 1638 { 1479 _printf("\n[GIET ERROR] in _ fbf_cma_init_buf() : user buffer status not aligned\n");1639 _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user status not aligned\n"); 1480 1640 return -1; 1481 1641 } … … 1496 1656 if ((flags & PTE_U) == 0) 1497 1657 { 1498 _printf("\n[GIET ERROR] in _ fbf_cma_start() : buf0 not in user space\n");1658 _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf0 not in user space\n"); 1499 1659 return -1; 1500 1660 } … … 1504 1664 if ((flags & PTE_U) == 0) 1505 1665 { 1506 _printf("\n[GIET ERROR] in _ fbf_cma_start() : sts0 not in user space\n");1666 _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts0 not in user space\n"); 1507 1667 return -1; 1508 1668 } … … 1517 1677 if ((flags & PTE_U) == 0) 1518 1678 { 1519 _printf("\n[GIET ERROR] in _ fbf_cma_start() : buf1 not in user space\n");1679 _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf1 not in user space\n"); 1520 1680 return -1; 1521 1681 } … … 1525 1685 if ((flags & PTE_U) == 0) 1526 1686 { 1527 _printf("\n[GIET ERROR] in _ fbf_cma_start() : sts1 not in user space\n");1687 _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts1 not in user space\n"); 1528 1688 return -1; 1529 1689 } … … 1696 1856 while ( full ) 1697 1857 { 1698 // INVAL L2 cache copy of user buffer descriptor,1858 // INVAL L2 cache copy of user buffer status 1699 1859 // because it has been modified in RAM by the CMA component 1700 1860 _mmc_inval( buf_sts_paddr , 4 ); … … 1810 1970 } 1811 1971 1812 ///////////////////////////////////////1813 int _sys_kill_application( char* name )1814 {1815 mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;1816 mapping_vspace_t * vspace = _get_vspace_base(header);1817 mapping_task_t * task = _get_task_base(header);1818 1819 unsigned int vspace_id;1820 unsigned int task_id;1821 unsigned int y_size = header->y_size;1822 1823 // scan vspaces1824 for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++)1825 {1826 if ( _strcmp( vspace[vspace_id].name, name ) == 0 )1827 {1828 // scan tasks in vspace1829 for (task_id = vspace[vspace_id].task_offset;1830 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);1831 task_id++)1832 {1833 unsigned int cid = task[task_id].clusterid;1834 unsigned int x = cid / y_size;1835 unsigned int y = cid % y_size;1836 unsigned int p = task[task_id].proclocid;1837 unsigned int ltid = task[task_id].ltid;1838 1839 // set NORUN_MASK_TASK bit1840 static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];1841 unsigned int* ptr = &psched->context[ltid][CTX_NORUN_ID];1842 _atomic_or( ptr , NORUN_MASK_TASK );1843 }1844 return 0;1845 }1846 }1847 return -1; // not found1848 }1849 1850 ///////////////////////////////////////1851 int _sys_exec_application( char* name )1852 {1853 mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;1854 mapping_vspace_t * vspace = _get_vspace_base(header);1855 mapping_task_t * task = _get_task_base(header);1856 mapping_vseg_t * vseg = _get_vseg_base(header);1857 1858 unsigned int vspace_id;1859 unsigned int task_id;1860 unsigned int vseg_id;1861 1862 unsigned int y_size = header->y_size;1863 1864 // scan vspaces1865 for (vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++)1866 {1867 if ( _strcmp( vspace[vspace_id].name, name ) == 0 )1868 {1869 // scan tasks in vspace1870 for (task_id = vspace[vspace_id].task_offset;1871 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);1872 task_id++)1873 {1874 unsigned int cid = task[task_id].clusterid;1875 unsigned int x = cid / y_size;1876 unsigned int y = cid % y_size;1877 unsigned int p = task[task_id].proclocid;1878 unsigned int ltid = task[task_id].ltid;1879 1880 // compute stack pointer value (sp_value)1881 vseg_id = task[task_id].stack_vseg_id;1882 unsigned int sp_value = vseg[vseg_id].vbase + vseg[vseg_id].length;1883 1884 // compute task entry point value (epc_value)1885 vseg_id = vspace[vspace_id].start_vseg_id;1886 unsigned int* vaddr = (unsigned int*)( vseg[vseg_id].vbase +1887 ((task[task_id].startid)<<2) );1888 unsigned int epc_value = *vaddr;1889 1890 // compute reurn address value (ra_value)1891 unsigned int ra_value = (unsigned int)(&_ctx_eret);1892 1893 // get scheduler pointer1894 static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];1895 1896 // initialise task context: RA / SR / EPC / SP / NORUN slots1897 psched->context[ltid][CTX_RA_ID] = ra_value;1898 psched->context[ltid][CTX_SR_ID] = GIET_SR_INIT_VALUE;1899 psched->context[ltid][CTX_SP_ID] = sp_value;1900 psched->context[ltid][CTX_EPC_ID] = epc_value;1901 psched->context[ltid][CTX_NORUN_ID] = 0;1902 }1903 return 0;1904 }1905 }1906 return -1; // not found1907 }1908 1909 1972 ///////////////////////// 1910 1973 int _sys_context_switch()
Note: See TracChangeset
for help on using the changeset viewer.