windALib.s
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:41k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* windALib.s - I80x86 internal VxWorks kernel assembly library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01q,05dec01,hdn  added PAUSE instruction for Pentium4
  7. 01p,13nov01,ahm  Added AutoHalt mode for idling kenel (SPR#32599)
  8. 01o,26sep01,hdn  added the interrupt stack switch support
  9. 01n,23aug01,hdn  added FUNC/FUNC_LABEL, replaced .align with .balign
  10.  replaced sysCodeSelector with sysCsSuper
  11. 01m,28aug98,hdn  replaced sysIntLevel() with "movl INT29(%edi),%eax"
  12. 01l,10aug98,pr   replaced evtsched with function pointer _func_evtLogTSched
  13. 01k,29apr98,cjtc fix WV instrumentation in idle
  14. 01j,16apr98,pr   cleanup.
  15. 01i,17feb98,pr   added WindView 2.0 code.
  16. 01h,29jul96,sbs  Made windview conditionally compile.
  17. 01g,14jun95,hdn  changed CODE_SELECTOR to sysCodeSelector.
  18. 01f,08aug94,hdn  added support for WindView.
  19. 01e,02jun93,hdn  updated to 5.1.
  20.   - fixed #else and #endif
  21.   - changed VOID to void
  22.   - changed ASMLANGUAGE to _ASMLANGUAGE
  23.   - changed copyright notice
  24. 01d,15oct92,hdn  supported nested interrupt.
  25. 01c,13oct92,hdn  debugged.
  26. 01b,07apr92,hdn  written optimized codes.
  27. 01a,28feb92,hdn  written based on TRON, 68k version.
  28. */
  29. /*
  30. DESCRIPTION
  31. This module contains internals to the VxWorks kernel.
  32. These routines have been coded in assembler because they are either
  33. specific to this processor, or they have been optimized for performance.
  34. */
  35. #define _ASMLANGUAGE
  36. #include "vxWorks.h"
  37. #include "asm.h"
  38. #include "regs.h"
  39. #include "esf.h"
  40. #include "private/eventP.h"
  41. #include "private/trgLibP.h"
  42. #include "private/taskLibP.h"
  43. #include "private/semLibP.h"
  44. #include "private/workQLibP.h"
  45. /* defines */
  46. #define INT_STACK_USE
  47. #define X86_POWER_MANAGEMENT
  48. .data
  49. .globl FUNC(copyright_wind_river)
  50. .long FUNC(copyright_wind_river)
  51. /* internals */
  52. .globl GTEXT(windExit) /* routine to exit mutual exclusion */
  53. .globl GTEXT(windIntStackSet) /* interrupt stack set routine */
  54. .globl GTEXT(vxTaskEntry) /* task entry wrapper */
  55. .globl GTEXT(intEnt) /* interrupt entrance routine */
  56. .globl GTEXT(intExit) /* interrupt exit routine */
  57. .globl GTEXT(intStackEnable) /* interrupt stack usage enabler */
  58. #ifdef X86_POWER_MANAGEMENT
  59.         .globl GTEXT(vxIdleAutoHalt) /* put cpu in AutoHalt when idle */
  60. #endif /* X86_POWER_MANAGEMENT */
  61. #ifdef PORTABLE
  62. .globl GTEXT(windLoadContext) /* needed by portable reschedule () */
  63. #else
  64. .globl GTEXT(reschedule) /* optimized reschedule () routine */
  65. #endif /* PORTABLE */
  66. .globl GDATA(vxIntStackPtr) /* interrupt stack pointer */
  67. .globl GDATA(vxIntStackEnabled) /* interrupt stack enabled */
  68. FUNC_LABEL(vxIntStackPtr) /* interrupt stack pointer */
  69. .long 0x00000000
  70. FUNC_LABEL(vxIntStackEnabled) /* TRUE if interrupt stack is enabled */
  71. .long 0x00000000
  72. FUNC_LABEL(intNest) /* interrupt stack nest counter */
  73. .long 0x00000000
  74. .text
  75. .balign 16
  76. /*******************************************************************************
  77. *
  78. * windExitInt - exit kernel routine from interrupt level
  79. *
  80. * windExit branches here if exiting kernel routine from int level
  81. * No rescheduling is necessary because the ISR will exit via intExit, and
  82. * intExit does the necessary rescheduling.
  83. */
  84. windExitIntWork:
  85. popfl /* pop original level */
  86. call FUNC(workQDoWork) /* empty the work queue */
  87. windExitInt:
  88. pushfl /* push interrupt level to stack */
  89. cli /* LOCK INTERRUPTS */
  90. cmpl $0,FUNC(workQIsEmpty) /* test for work to do */
  91. je windExitIntWork /* workQ is not empty */
  92. #ifdef WV_INSTRUMENTATION
  93. /* windview instrumentation - BEGIN
  94.  * exit windExit with no dispatch; point 1 in the windExit diagram.
  95.  */
  96.         cmpl    $0,FUNC(evtAction) /* is WindView on? */
  97.         je      noInst1
  98. movl $ WV_CLASS_1_ON,%eax
  99.         andl    FUNC(wvEvtClass),%eax /* is event collection on? */
  100.         cmpl    $ WV_CLASS_1_ON,%eax /* is event collection on? */
  101.         jne     trgCheckInst1
  102. movl FUNC(_func_evtLogTSched),%edx /* event log routine */
  103. cmpl $0,%edx
  104.         je      trgCheckInst1
  105.         movl FUNC(taskIdCurrent),%eax /* current task */
  106.         movl WIND_TCB_PRIORITY(%eax),%ecx
  107.         pushl %ecx                         /* WIND_TCB_PRIORITY */
  108.         pushl %eax                         /* taskIdCurrent */
  109.         /* Here we try to determine if the task is running at an
  110.          * inherited priority, if so a different event is generated.
  111.          */
  112.         cmpl WIND_TCB_PRI_NORMAL(%eax),%ecx
  113.         jge     noInst1Inheritance /* no inheritance */
  114.         pushl $ EVENT_WIND_EXIT_NODISPATCH_PI
  115.         jmp     inst1Inheritance /* no inheritance */
  116. noInst1Inheritance:
  117.         pushl $ EVENT_WIND_EXIT_NODISPATCH /* event id */
  118. inst1Inheritance:
  119.         call    *%edx                           /* call evtsched routine */
  120. addl    $12,%esp
  121. trgCheckInst1:
  122. movl $ TRG_CLASS_1,%eax     
  123. orl  $ TRG_ON,%eax
  124.         cmpl    FUNC(trgEvtClass),%eax /* any trigger? */
  125.         jne     noInst1
  126.         movl    FUNC(_func_trgCheck),%edx /* triggering routine */
  127. cmpl $0,%edx
  128.         je      noInst1
  129.         movl FUNC(taskIdCurrent),%eax /* current task */
  130.         movl WIND_TCB_PRIORITY(%eax),%ecx
  131.         pushl   $ 0                     /* 0 */
  132.         pushl   $ 0                     /* 0 */
  133.         pushl   $ 0                     /* 0 */
  134.         pushl %ecx                 /* WIND_TCB_PRIORITY */
  135.         pushl %eax                 /* taskIdCurrent */
  136.         pushl   $ 0                     /* obj */
  137.         pushl   $ 0                     /* TRG_CLASS1_INDEX */
  138.         /* Here we try to determine if the task is running at an
  139.          * inherited priority, if so a different event is generated.
  140.          */
  141.         cmpl WIND_TCB_PRI_NORMAL(%eax),%ecx
  142.         jge     noTrgInst1Inheritance /* no inheritance */
  143.         pushl $ EVENT_WIND_EXIT_NODISPATCH_PI
  144.         jmp     trgInst1Inheritance /* no inheritance */
  145. noTrgInst1Inheritance:
  146.         pushl $ EVENT_WIND_EXIT_NODISPATCH    /* event id */
  147. trgInst1Inheritance:
  148.         call    *%edx                           /* call triggering routine */
  149. addl    $32,%esp
  150. noInst1:
  151. /* windview instrumentation - END */
  152. #endif  /* WV_INSTRUMENTATION */
  153. movl $0,FUNC(kernelState) /* release mutual exclusion to kernel */
  154. popfl /* pop original level */
  155. xorl %eax,%eax /* return OK */
  156. ret /* intExit will do rescheduling */
  157. /*******************************************************************************
  158. *
  159. * checkTaskReady - check that taskIdCurrent is ready to run
  160. *
  161. * This code branched to by windExit when it finds preemption is disabled.
  162. * It is possible that even though preemption is disabled, a context switch
  163. * must occur.  This situation arrises when a task block during a preemption
  164. * lock.  So this routine checks if taskIdCurrent is ready to run, if not it
  165. * branches to save the context of taskIdCurrent, otherwise it falls thru to
  166. * check the work queue for any pending work.
  167. */
  168. .balign 16,0x90
  169. checkTaskReady:
  170. cmpl $0,WIND_TCB_STATUS(%edx) /* is task ready to run */
  171. jne saveTaskContext /* if no, we blocked with preempt off */
  172. /* FALL THRU TO CHECK WORK QUEUE */
  173. /*******************************************************************************
  174. *
  175. * checkWorkQ - check the work queue for any work to do
  176. *
  177. * This code is branched to by windExit.  Currently taskIdCurrent is highest
  178. * priority ready task, but before we can return to it we must check the work
  179. * queue.  If there is work we empty it via doWorkPreSave, otherwise we unlock
  180. * interrupts, clear d0, and return to taskIdCurrent.
  181. */
  182. checkWorkQ:
  183. cli /* LOCK INTERRUPTS */
  184. cmpl $0,FUNC(workQIsEmpty) /* test for work to do */
  185. je doWorkPreSave /* workQueue is not empty */
  186. #ifdef WV_INSTRUMENTATION
  187. /* windview instrumentation - BEGIN
  188.  * exit windExit with no dispatch; point 4 in the windExit diagram.
  189.  */
  190.         cmpl    $0,FUNC(evtAction) /* is WindView on? */
  191.         je      noInst4
  192. movl $ WV_CLASS_1_ON,%eax
  193.         andl    FUNC(wvEvtClass),%eax /* is event collection on? */
  194.         cmpl    $ WV_CLASS_1_ON,%eax /* is event collection on? */
  195.         jne     trgCheckInst4
  196. movl FUNC(_func_evtLogTSched),%edx /* event log routine */
  197. cmpl $0,%edx
  198.         je      trgCheckInst4
  199.         movl FUNC(taskIdCurrent),%eax /* current task */
  200.         movl WIND_TCB_PRIORITY(%eax),%ecx
  201.         pushl %ecx                         /* WIND_TCB_PRIORITY */
  202.         pushl %eax                         /* taskIdCurrent */
  203. /* Here we try to determine if the task is running at an
  204.  * inherited priority, if so a different event is generated.
  205.  */
  206.         cmpl WIND_TCB_PRI_NORMAL(%eax),%ecx
  207.         jge     noInst4Inheritance /* no inheritance */
  208.         pushl $ EVENT_WIND_EXIT_NODISPATCH_PI
  209.         jmp     inst4Inheritance /* no inheritance */
  210. noInst4Inheritance:
  211.         pushl $ EVENT_WIND_EXIT_NODISPATCH /* event id */
  212. inst4Inheritance:
  213.         call    *%edx                           /* call evtsched routine */
  214. addl    $12,%esp
  215. trgCheckInst4:
  216. movl $ TRG_CLASS_1,%eax     
  217. orl  $ TRG_ON,%eax
  218.         cmpl    FUNC(trgEvtClass),%eax /* any trigger? */
  219.         jne     noInst4
  220.         movl    FUNC(_func_trgCheck),%edx /* triggering routine */
  221. cmpl $0,%edx
  222.         je      noInst4
  223.         movl FUNC(taskIdCurrent),%eax /* current task */
  224.         movl WIND_TCB_PRIORITY(%eax),%ecx
  225.         pushl   $ 0                     /* 0 */
  226.         pushl   $ 0                     /* 0 */
  227.         pushl   $ 0                     /* 0 */
  228.         pushl %ecx                 /* WIND_TCB_PRIORITY */
  229.         pushl %eax                 /* taskIdCurrent */
  230.         pushl   $ 0                     /* obj */
  231.         pushl   $ 0                     /* TRG_CLASS1_INDEX */
  232. /* Here we try to determine if the task is running at an
  233.  * inherited priority, if so a different event is generated.
  234.  */
  235.         cmpl WIND_TCB_PRI_NORMAL(%eax),%ecx
  236.         jge     noTrgInst4Inheritance /* no inheritance */
  237.         pushl $ EVENT_WIND_EXIT_NODISPATCH_PI
  238.         jmp     trgInst4Inheritance /* no inheritance */
  239. noTrgInst4Inheritance:
  240.         pushl $ EVENT_WIND_EXIT_NODISPATCH /* event id */
  241. trgInst4Inheritance:
  242.         call    *%edx                   /* call triggering routine */
  243. addl    $32,%esp
  244. noInst4:
  245. /* windview instrumentation - END */
  246. #endif  /* WV_INSTRUMENTATION */
  247. movl $0,FUNC(kernelState) /* else release exclusion */
  248. sti /* UNLOCK INTERRUPTS */
  249. xorl %eax,%eax /* return OK */
  250. ret /* back to calling task */
  251. /*******************************************************************************
  252. *
  253. * doWorkPreSave - empty the work queue with current context not saved
  254. *
  255. * We try to empty the work queue here, rather than let reschedule
  256. * perform the work because there is a strong chance that the
  257. * work we do will not preempt the calling task.  If this is the case, then
  258. * saving the entire context just to restore it in reschedule is a waste of
  259. * time.  Once the work has been emptied, the ready queue must be checked to
  260. * see if reschedule must be called, the check of the ready queue is done by
  261. * branching back up to checkTaskCode.
  262. */
  263. .balign 16,0x90
  264. doWorkPreSave:
  265. sti /* UNLOCK INTERRUPTS */
  266. call FUNC(workQDoWork) /* empty the work queue */
  267. jmp checkTaskSwitch /* back up to test if tasks switched */
  268. /******************************************************************************
  269. *
  270. * windExit - task level exit from kernel
  271. *
  272. * Release kernel mutual exclusion (kernelState) and dispatch any new task if
  273. * necessary.  If a higher priority task than the current task has been made
  274. * ready, then we invoke the rescheduler.  Before releasing mutual exclusion,
  275. * the work queue is checked and emptied if necessary.
  276. *
  277. * If rescheduling is necessary, the context of the calling task is saved in its
  278. * associated TCB with the PC pointing at the next instruction after the jsr to
  279. * this routine.  The SP in the tcb is modified to ignore the return address
  280. * on the stack.  Thus the context saved is as if this routine was never called.
  281. *
  282. * Only the volatile registers e[adc]x are safe to use until the context
  283. * is saved in saveTaskContext.
  284. *
  285. * At the call to reschedule the value of taskIdCurrent must be in edx.
  286. *
  287. * RETURNS: OK or
  288. *    ERROR if semaphore timeout occurs.
  289. *
  290. * NOMANUAL
  291. * STATUS windExit ()
  292. */
  293. .balign 16,0x90
  294. FUNC_LABEL(windExit)
  295. cmpl $0,FUNC(intCnt) /* if intCnt == 0 we're from task */
  296. jne windExitInt /* else we're exiting interrupt code */
  297. /* FALL THRU TO CHECK THAT CURRENT TASK IS STILL HIGHEST */
  298. /*******************************************************************************
  299. *
  300. * checkTaskSwitch - check to see if taskIdCurrent is still highest task
  301. *
  302. * We arrive at this code either as the result of falling thru from windExit,
  303. * or if we have finished emptying the work queue.  We compare taskIdCurrent
  304. * with the highest ready task on the ready queue.  If they are same we
  305. * go to a routine to check the work queue.  If they are different and preemption
  306. * is allowed we branch to a routine to make sure that taskIdCurrent is really
  307. * ready (it may have blocked with preemption disabled).  If they are different
  308. * we save the context of taskIdCurrent and fall thru to reschedule.
  309. */
  310. checkTaskSwitch:
  311. movl FUNC(taskIdCurrent),%edx /* move taskIdCurrent to edx */
  312. cmpl FUNC(readyQHead),%edx /* compare highest ready task */
  313. je checkWorkQ /* if same then time to leave */
  314. cmpl $0,WIND_TCB_LOCK_CNT(%edx) /* is task preemption allowed */
  315. jne checkTaskReady /* if no, check task is ready */
  316. saveTaskContext:
  317. movl (%esp),%eax /* save return address as PC */
  318. movl %eax,WIND_TCB_PC(%edx)
  319. pushfl /* save a eflags */
  320. popl WIND_TCB_EFLAGS(%edx)
  321. bts $9,WIND_TCB_EFLAGS(%edx) /* set IF to enable INT */
  322. movl %ebx,WIND_TCB_EBX(%edx) /* e[adc]x are volatile */
  323. movl %esi,WIND_TCB_ESI(%edx)
  324. movl %edi,WIND_TCB_EDI(%edx)
  325. movl %ebp,WIND_TCB_EBP(%edx)
  326. movl %esp,WIND_TCB_ESP(%edx)
  327. movl $0,WIND_TCB_EAX(%edx) /* clear saved eax for return */
  328. addl $4,WIND_TCB_ESP(%edx) /* fix up SP for no ret adrs */
  329. pushl FUNC(errno) /* save errno */
  330. popl WIND_TCB_ERRNO(%edx)
  331. #ifdef PORTABLE
  332. call FUNC(reschedule)
  333. #else
  334. /* FALL THRU TO RESCHEDULE */
  335. /*******************************************************************************
  336. *
  337. * reschedule - rescheduler for VxWorks kernel
  338. *
  339. * This routine is called when either intExit, or windExit, thinks the
  340. * context might change.  All of the contexts of all of the tasks are
  341. * accurately stored in the task control blocks when entering this function.
  342. * The status register is 0x800f0000. (Supervisor, Stack0, Interrupts UNLOCKED)
  343. *
  344. * The register %edx must contain the value of _taskIdCurrent at the entrance to
  345. * this routine.
  346. *
  347. * At the conclusion of this routine, taskIdCurrent will equal the highest
  348. * priority task eligible to run, and the kernel work queue will be empty.
  349. * If a context switch to a different task is to occur, then the installed
  350. * switch hooks are called.
  351. *
  352. * NOMANUAL
  353. * void reschedule ()
  354. */
  355. .balign 16,0x90
  356. FUNC_LABEL(reschedule)
  357. movl FUNC(readyQHead),%eax /* get highest task to %eax */
  358. cmpl $0,%eax
  359. je idle /* idle if nobody ready */
  360. switchTasks:
  361. movl %eax,FUNC(taskIdCurrent) /* update taskIdCurrent */
  362.   movw WIND_TCB_SWAP_IN(%eax),%bx /* swap hook mask into %bx */
  363.   orw WIND_TCB_SWAP_OUT(%edx),%bx /* or in swap out hook mask */
  364.   jne doSwapHooks /* any swap hooks to do */
  365.   cmpl $0,FUNC(taskSwitchTable) /* any global switch hooks? */
  366. jne doSwitchHooks /* any switch hooks to do */
  367. dispatch:
  368. movl WIND_TCB_ERRNO(%eax),%ecx /* retore errno */
  369. movl %ecx,FUNC(errno)
  370. movl WIND_TCB_ESP(%eax),%esp /* push dummy except */
  371. pushl WIND_TCB_EFLAGS(%eax) /* push EFLAGS */
  372. pushl FUNC(sysCsSuper) /* push CS */
  373. pushl WIND_TCB_PC(%eax)  /* push PC */
  374. movl WIND_TCB_EDX(%eax),%edx /* restore registers */
  375. movl WIND_TCB_ECX(%eax),%ecx
  376. movl WIND_TCB_EBX(%eax),%ebx
  377. movl WIND_TCB_ESI(%eax),%esi
  378. movl WIND_TCB_EDI(%eax),%edi
  379. movl WIND_TCB_EBP(%eax),%ebp
  380. movl WIND_TCB_EAX(%eax),%eax
  381. cli /* LOCK INTERRUPTS */
  382. cmpl $0,FUNC(workQIsEmpty) /* if work q is not empty */
  383. je doWorkUnlock /* then unlock and do work */
  384. #ifdef WV_INSTRUMENTATION
  385. /* windview instrumentation - BEGIN
  386.  * exit windExit with dispatch;
  387.  */
  388.         cmpl    $0,FUNC(evtAction) /* is WindView on? */
  389.         je      noInst3
  390. pushl %eax /* save regs */
  391. pushl %edx
  392. pushl %ecx
  393. movl $ WV_CLASS_1_ON,%eax
  394.         andl    FUNC(wvEvtClass),%eax /* is event collection on? */
  395.         cmpl    $ WV_CLASS_1_ON,%eax /* is event collection on? */
  396.         jne     trgCheckInst3
  397. movl FUNC(_func_evtLogTSched),%edx /* event log routine */
  398. cmpl $0,%edx
  399.         je      trgCheckInst3
  400.         movl FUNC(taskIdCurrent),%eax /* current task */
  401.         movl WIND_TCB_PRIORITY(%eax),%ecx
  402.         pushl %ecx                         /* WIND_TCB_PRIORITY */
  403.         pushl %eax                         /* taskIdCurrent */
  404.         /* Here we try to determine if the task is running at an
  405.          * inherited priority, if so a different event is generated.
  406.          */
  407.         cmpl WIND_TCB_PRI_NORMAL(%eax),%ecx
  408.         jge     noInst3Inheritance /* no inheritance */
  409.         pushl $ EVENT_WIND_EXIT_DISPATCH_PI
  410.         jmp     inst3Inheritance /* no inheritance */
  411. noInst3Inheritance:
  412.         pushl $ EVENT_WIND_EXIT_DISPATCH /* event id */
  413. inst3Inheritance:
  414.         call    *%edx                           /* call evtsched routine */
  415. addl    $12,%esp
  416. trgCheckInst3:
  417. movl $ TRG_CLASS_1,%eax     
  418. orl  $ TRG_ON,%eax
  419.         cmpl    FUNC(trgEvtClass),%eax /* any trigger? */
  420.         jne      inst3Clean
  421.         movl    FUNC(_func_trgCheck),%edx /* triggering routine */
  422. cmpl $0,%edx
  423.         je      inst3Clean
  424.         movl FUNC(taskIdCurrent),%eax /* current task */
  425.         movl WIND_TCB_PRIORITY(%eax),%ecx
  426.         pushl   $ 0                     /* 0 */
  427.         pushl   $ 0                     /* 0 */
  428.         pushl   $ 0                     /* 0 */
  429.         pushl %ecx                 /* WIND_TCB_PRIORITY */
  430.         pushl %eax                 /* taskIdCurrent */
  431.         pushl   $ 0                     /* obj */
  432.         pushl   $ 0                     /* TRG_CLASS1_INDEX */
  433.         /* Here we try to determine if the task is running at an
  434.          * inherited priority, if so a different event is generated.
  435.          */
  436.         cmpl WIND_TCB_PRI_NORMAL(%eax),%ecx
  437.         jge     noTrgInst3Inheritance /* no inheritance */
  438.         pushl $ EVENT_WIND_EXIT_DISPATCH_PI
  439.         jmp     trgInst3Inheritance /* no inheritance */
  440. noTrgInst3Inheritance:
  441.         pushl $ EVENT_WIND_EXIT_DISPATCH /* event id */
  442. trgInst3Inheritance:
  443.         call    *%edx                   /* call triggering routine */
  444. addl    $32,%esp
  445. inst3Clean:
  446. popl %ecx /* restore regs */
  447. popl %edx
  448. popl %eax
  449. noInst3:
  450. /* windview instrumentation - END */
  451. #endif  /* WV_INSTRUMENTATION */
  452. movl $0,FUNC(kernelState) /* release kernel mutex */
  453. iret /* UNLOCK INTERRUPTS */
  454. /*******************************************************************************
  455. *
  456. * idle - spin here until there is more work to do
  457. *
  458. * When the kernel is idle, we spin here continually checking for work to do.
  459. */
  460. .balign 16,0x90
  461. idle:
  462. #ifdef WV_INSTRUMENTATION
  463.         /* windview instrumentation - BEGIN
  464.          * enter idle state
  465.          *
  466.          * NOTE: I am making the assumption here that it is okay to
  467.          * modify the %eax,%edx,%ecx registers. They are not being saved.
  468.          */
  469.         cmpl    $0,FUNC(evtAction) /* is WindView on? */
  470.         je      noInstIdle
  471. pushal
  472. cli /* LOCK INTERRUPTS */
  473. movl $ WV_CLASS_1_ON,%eax
  474.         andl    FUNC(wvEvtClass),%eax /* is event collection on? */
  475.         cmpl    $ WV_CLASS_1_ON,%eax /* is event collection on? */
  476.         jne     trgCheckInstIdle
  477. movl FUNC(_func_evtLogT0),%edx /* event log routine */
  478. cmpl $0,%edx
  479.         je      trgCheckInstIdle
  480.         pushl $ EVENT_WIND_EXIT_IDLE  /* event id */
  481. call *%edx /* call event log routine */
  482. addl    $4,%esp
  483. trgCheckInstIdle:
  484. movl $ TRG_CLASS_1,%eax     
  485. orl  $ TRG_ON,%eax
  486.         cmpl    FUNC(trgEvtClass),%eax /* any trigger? */
  487.         jne     instIdleClean
  488.         movl    FUNC(_func_trgCheck),%edx /* triggering routine */
  489. cmpl $0,%edx
  490. je instIdleClean
  491.         pushl   $ 0                     /* 0 */
  492.         pushl   $ 0                     /* 0 */
  493.         pushl   $ 0                     /* 0 */
  494.         pushl   $ 0                     /* 0 */
  495.         pushl   $ 0                     /* 0 */
  496.         pushl   $ 0                     /* obj */
  497.         pushl   $ 0                     /* TRG_CLASS1_INDEX */
  498.         pushl   $ EVENT_WIND_EXIT_IDLE /* EVENT_WIND_EXIT_IDLE */
  499.         call    *%edx                   /* call triggering routine */
  500. addl  $32,%esp 
  501. instIdleClean:
  502. popal
  503. noInstIdle:
  504. /* windview instrumentation - END */
  505. #endif  /* WV_INSTRUMENTATION */
  506. sti /* UNLOCK INTERRUPTS (just in case) */
  507. movl $1,FUNC(kernelIsIdle) /* set idle flag for spyLib */
  508. idleLoop:
  509.         cmpl    $0,FUNC(workQIsEmpty)   /* if work queue has work to do */
  510.         je      goDoWork /* no more idling */
  511. /* PAUSE instruction operates like a NOP in earlier IA-32 processors */
  512.         .byte   0xf3, 0x90              /* PAUSE should be in the loop */
  513. #ifdef X86_POWER_MANAGEMENT
  514. cmp     $0, FUNC(vxIdleRtn) /* is Power Management enabled ? */
  515. je idleLoop /* no: stay in loop */
  516.         call    *FUNC(vxIdleRtn)        /* call routine set by vxPowerModeSet */
  517. #else
  518.         jmp     idleLoop                /* keep hanging around */
  519. #endif /* X86_POWER_MANAGEMENT */
  520. goDoWork: /* there is some work to do, can't remain idle now */
  521.         movl    $0,FUNC(kernelIsIdle)   /* unset idle flag for spyLib */
  522.         jmp     doWork                  /* go do the work */
  523. #ifdef X86_POWER_MANAGEMENT
  524. /*******************************************************************************
  525. *
  526. * vxIdleAutoHalt - place the processor in AutoHalt mode when nothing to do
  527. */
  528.         .balign 16,0x90
  529. FUNC_LABEL(vxIdleAutoHalt)
  530.         sti                             /* make sure interrupts are enabled */
  531.         nop                             /* delay a bit */
  532.         cmpl    $0,FUNC(workQIsEmpty)   /* if work queue is still empty */
  533.         je      vpdRet                  /* there is work to do - return */
  534.         hlt                             /* nothing to do - go in AutoHalt */
  535. vpdRet:
  536.         ret
  537. #endif /* X86_POWER_MANAGEMENT */
  538. /*******************************************************************************
  539. *
  540. * doSwapHooks - execute the tasks' swap hooks
  541. */
  542. .balign 16,0x90
  543. doSwapHooks:
  544. pushl %eax /* push pointer to new tcb */
  545. pushl %edx /* push pointer to old tcb */
  546. leal FUNC(taskSwapTable),%edi /* get adrs of task switch rtn list */
  547. movl $-4,%esi /* start index at -1, heh heh */
  548. jmp doSwapShift /* jump into the loop */
  549. .balign 16,0x90
  550. doSwapHook:
  551. movl (%esi,%edi,1),%ecx /* call task switch rtn into r3+4*n */
  552. call *%ecx
  553. doSwapShift:
  554. addl $4,%esi /* bump swap table index */
  555. shlw $1,%bx /* shift swapMask bit pattern left */
  556. jc doSwapHook /* if carry bit set then do ix hook */
  557. jne doSwapShift /* any bits still set */
  558. /* no need to clean stack */
  559. movl FUNC(taskIdCurrent),%eax /* restore %eax with taskIdCurrent */
  560. cmpl $0,FUNC(taskSwitchTable) /* any global switch hooks? */
  561. je dispatch /* if no then dispatch taskIdCurrent */
  562. jmp doSwitchFromSwap /* do switch routines from swap */
  563. /*******************************************************************************
  564. *
  565. * doSwitchHooks - execute the global switch hooks
  566. */
  567. .balign 16,0x90
  568. doSwitchHooks:
  569. pushl %eax /* push pointer to new tcb */
  570. pushl %edx /* push pointer to old tcb */
  571. doSwitchFromSwap:
  572. leal FUNC(taskSwitchTable),%edi /* get adrs of task switch rtn list */
  573. movl (%edi),%esi /* get task switch rtn into %esi */
  574. doSwitchHook:
  575. call *%esi /* call routine */
  576. addl $4,%edi /* bump to next task switch routine */
  577. movl (%edi),%esi /* get next task switch rtn */
  578. cmpl $0,%esi
  579. jne doSwitchHook /* check for end of table (NULL) */
  580. /* no need to clean stack */
  581. movl FUNC(taskIdCurrent),%eax /* restore %eax with taskIdCurrent */
  582. jmp dispatch /* dispatch task */
  583. /*******************************************************************************
  584. *
  585. * doWork - empty the work queue
  586. * doWorkUnlock - unlock interrupts and empty the work queue
  587. */
  588. .balign 16,0x90
  589. doWorkUnlock:
  590. sti /* UNLOCK INTERRUPTS */
  591. doWork:
  592. call FUNC(workQDoWork) /* empty the work queue */
  593. movl FUNC(taskIdCurrent),%edx /* %edx = taskIdCurrent */
  594. movl FUNC(readyQHead),%eax /* %eax = highest task */
  595. cmpl $0,%eax
  596. je idle /* nobody is ready so spin */
  597. cmpl %edx,%eax /* compare to last task */
  598. je dispatch /* if the same dispatch */
  599. jmp switchTasks /* not same, do switch */
  600. #endif /* PORTABLE */
  601. #ifdef PORTABLE
  602. /*******************************************************************************
  603. *
  604. * windLoadContext - load the register context from the control block
  605. *
  606. * The registers of the current executing task, (the one reschedule chose),
  607. * are restored from the control block.  Then the appropriate exception frame
  608. * for the architecture being used is constructed.  To unlock interrupts and
  609. * enter the new context we simply use the instruction rte.
  610. *
  611. * NOMANUAL
  612. * void windLoadContext ()
  613. */
  614. .balign 16,0x90
  615. FUNC_LABEL(windLoadContext)
  616. movl FUNC(taskIdCurrent),%eax /* current tid */
  617. movl WIND_TCB_ERRNO(%eax),%ecx /* save errno */
  618. movl %ecx,FUNC(errno)
  619. movl WIND_TCB_ESP(%eax),%esp /* push dummy except. */
  620. pushl WIND_TCB_EFLAGS(%eax) /* push eflags */
  621. pushl FUNC(sysCsSuper) /* push CS */
  622. pushl WIND_TCB_PC(%eax) /* push pc */
  623. movl WIND_TCB_EDX(%eax),%edx /* restore registers */
  624. movl WIND_TCB_ECX(%eax),%ecx
  625. movl WIND_TCB_EBX(%eax),%ebx
  626. movl WIND_TCB_ESI(%eax),%esi
  627. movl WIND_TCB_EDI(%eax),%edi
  628. movl WIND_TCB_EBP(%eax),%ebp
  629. movl WIND_TCB_EAX(%eax),%eax
  630. iret /* enter task's context. */
  631. #endif /* PORTABLE */
  632. /*******************************************************************************
  633. *
  634. * intEnt - enter an interrupt service routine
  635. *
  636. * intEnt must be called at the entrance of an interrupt service routine.
  637. * This normally happens automatically, from the stub built by intConnect (2).
  638. * This routine should NEVER be called from C.
  639. *
  640. * SEE ALSO: intConnect(2)
  641. * void intEnt ()
  642. */
  643. .balign 16,0x90
  644. FUNC_LABEL(intEnt)
  645. cli /* LOCK INTERRUPTS */
  646. pushl (%esp) /* bump return address up a notch */
  647. pushl %eax
  648. movl FUNC(errno),%eax /* save errno where return adress was */
  649. movl %eax,8(%esp)
  650. incl FUNC(intCnt) /* increment the counter */
  651. incl FUNC(intNest) /* increment the private counter */
  652. #ifdef INT_STACK_USE
  653. /*
  654.  * switch to the interrupt stack from the supervisor stack 
  655.  * used by a task running in the supervisor mode
  656.  *
  657.  * if we are already in the interrupt stack, no stack switch will
  658.  * happen.  It happens in the following cases:
  659.  *   int - exc(break/trace) - int
  660.  *   int - int - exc(break/trace) - int
  661.  * To detect if the interrupt stack is already in use, the
  662.  * private counter intNest is used.  Checking the CS in ESF does
  663.  * not work in the above cases.  But the checking the CS in ESF
  664.  * is necessary to detect the nesting interrupt before and after
  665.  * the counter is manipulated.
  666.          *
  667.          * stack growth in the 1st interrupt
  668.  *   (supervisor stack)            (interrupt stack)
  669.  *   ----------------------------------------------
  670.  *     :                 +-----     supervisor SP
  671.  *     ESF(12 bytes)  |          ESF(12 bytes)
  672.  *     errno       <-----+     errno
  673.  *     return addr            : return addr
  674.  *     %eax     : %eax
  675.  *     : %ecx     V
  676.  *     : %esi     
  677.  *     : %edi     
  678.  *     :
  679.  *     V
  680.  *
  681.          * stack growth in the 2nd interrupt (nested interrupt)
  682.  *   (supervisor stack)            (interrupt stack)
  683.  *   ----------------------------------------------
  684.  *     :                 +-----     supervisor SP
  685.  *     ESF(12 bytes)  |          ESF(12 bytes)    --- 1st int
  686.  *     errno       <-----+     errno            --- 1st int
  687.  *     return addr            :
  688.  *     %eax     ESF(12 bytes)    --- 2nd int
  689.  *     : %ecx     errno            --- 2nd int
  690.  *     : %esi     : return addr
  691.  *     : %edi     : %eax
  692.  *     :     V
  693.  *     V
  694.  *
  695.  */
  696. cmpl $0,FUNC(vxIntStackEnabled) /* if vxIntStackEnabled == 0 then */
  697. je intEnt0 /* skip the interrupt stack switch */
  698. movl ESF0_CS+12(%esp), %eax /* get CS in ESF0 */
  699. cmpw FUNC(sysCsInt), %ax /* is it nested interrupt ? */
  700. je intEnt0 /*   yes: skip followings */
  701. cmpl $1,FUNC(intNest) /* already in the interrupt stack? */
  702. jne intEnt0 /* skip the interrupt stack switch */
  703. /* copy the supervisor stack to the interrupt stack. */
  704. intEntStackSwitch:
  705. pushl %ecx /* save %ecx */
  706. pushl %esi /* save %esi */
  707. pushl %edi /* save %edi */
  708. /* copy ESF0(12 bytes), errno, return addr, %eax */
  709. subl $ ESF0_NBYTES+12+4, FUNC(vxIntStackPtr) /* alloc */
  710. movl FUNC(vxIntStackPtr), %eax  /* get int-stack ptr */
  711. leal 20(%esp), %ecx    /* get addr of errno */
  712. movl %ecx, ESF0_NBYTES+12(%eax) /* save the original ESP */
  713. leal 12(%esp), %esi /* set the source addr */
  714. movl %eax, %edi /* set the destination addr */
  715. movl $ ESF0_NLONGS+3, %ecx /* set number of longs to copy */
  716. cld /* set direction ascending order */
  717. rep /* repeat next inst */
  718. movsl /* copy ESF0_NLONGS + 3 longs */
  719. popl %edi /* restore %edi */
  720. popl %esi /* restore %esi */
  721. popl %ecx /* restore %ecx */
  722. movl %eax, %esp /* switch to the interrupt stack */
  723. /* now, we are in the interrupt stack */
  724. #endif /* INT_STACK_USE */
  725. intEnt0:
  726. pushl ESF0_EFLAGS+12(%esp) /* push the saved EFLAGS */
  727. popfl /* UNLOCK INTERRUPT */
  728. popl %eax /* restore %eax */
  729. #ifdef WV_INSTRUMENTATION
  730. /* windview instrumentation - BEGIN
  731.  * enter an interrupt handler. 
  732.  *
  733.  * ALL registers must be saved.  
  734.  */
  735.         cmpl    $0,FUNC(evtAction) /* is WindView on? */
  736.         je noIntEnt
  737. pushal                           /* save regs */
  738. pushfl /* save EFLAGS */
  739. cli /* LOCK INTERRUPTS */
  740. movl 32+4(%esp),%edi /* use %edi to store the return address */
  741. movl $ WV_CLASS_1_ON,%eax
  742.         andl    FUNC(wvEvtClass),%eax /* is event collection on? */
  743.         cmpl    $ WV_CLASS_1_ON,%eax /* is event collection on? */
  744.         jne     trgCheckIntEnt
  745. movl INT_CONNECT_CODE29(%edi), %eax /* get IRQ number */
  746. addl    $ MIN_INT_ID,%eax  /* get event ID */
  747. movl FUNC(_func_evtLogT0),%edx /* event log routine */
  748. cmpl $0,%edx
  749. je trgCheckIntEnt
  750. pushl   %eax
  751. call *%edx /* call event log routine */
  752. addl    $4,%esp
  753. trgCheckIntEnt:
  754. movl $ TRG_CLASS_1,%eax     
  755. orl  $ TRG_ON,%eax
  756.         cmpl    FUNC(trgEvtClass),%eax /* any trigger? */
  757.         jne     intEntClean
  758. movl INT_CONNECT_CODE29(%edi), %eax /* get IRQ number */
  759. addl    $ MIN_INT_ID,%eax  /* get event ID */
  760.         movl    FUNC(_func_trgCheck),%edx /* triggering routine */
  761. cmpl $0,%edx
  762.         je      intEntClean
  763.         pushl   $ 0                      /* 0 */
  764.         pushl   $ 0                      /* 0 */
  765.         pushl   $ 0                      /* 0 */
  766.         pushl   $ 0                      /* 0 */
  767.         pushl   $ 0                      /* 0 */
  768.         pushl   $ 0                      /* obj */
  769.         pushl   $ 0                      /* TRG_CLASS1_INDEX */
  770.         pushl   %eax                     /* push event ID */
  771.         call    *%edx                    /* call triggering routine */
  772. addl    $32,%esp
  773. intEntClean:
  774. popfl /* restore EFLAGS */
  775. popal /* restore regs */
  776. noIntEnt:
  777. /* windview instrumentation - END */
  778. #endif  /* WV_INSTRUMENTATION */
  779. ret
  780. /*******************************************************************************
  781. *
  782. * intExit - exit an interrupt service routine
  783. *
  784. * Check the kernel ready queue to determine if resheduling is necessary.  If
  785. * no higher priority task has been readied, and no kernel work has been queued,
  786. * then we return to the interrupted task.
  787. *
  788. * If rescheduling is necessary, the context of the interrupted task is saved
  789. * in its associated TCB with the PC, EFLAGS and EFLAGS retrieved from the 
  790. * exception frame on the master stack.
  791. *
  792. * This routine must be branched to when exiting an interrupt service routine.
  793. * This normally happens automatically, from the stub built by intConnect (2).
  794. *
  795. * This routine can NEVER be called from C.
  796. *
  797. * It can only be jumped to because a jsr will push a return address on the
  798. * stack.
  799. *
  800. * SEE ALSO: intConnect(2)
  801. * void intExit ()
  802. * INTERNAL
  803. * This routine must preserve all registers up until the context is saved,
  804. * so any registers that are used to check the queues must first be saved on
  805. * the stack.
  806. *
  807. * At the call to reschedule the value of taskIdCurrent must be in edx.
  808. */
  809. .balign 16,0x90
  810. FUNC_LABEL(intExit)
  811. popl FUNC(errno) /* restore errno */
  812. pushl %eax /* push %eax onto the stack */
  813. #ifdef WV_INSTRUMENTATION
  814.         /* windview instrumentation - BEGIN
  815.          * log event if work has been done in the interrupt handler.
  816.          * NOTE: a0 is still on the stack
  817.          */
  818.         cmpl    $0,FUNC(evtAction) /* is WindView on? */
  819.         je noIntExit
  820.         pushl %edx
  821.         pushl %ecx
  822. pushfl /* save EFLAGS */
  823. cli /* LOCK INTERRUPTS */
  824. movl $ WV_CLASS_1_ON,%eax
  825.         andl    FUNC(wvEvtClass),%eax /* is event collection on? */
  826.         cmpl    $ WV_CLASS_1_ON,%eax /* is event collection on? */
  827.         jne     trgCheckIntExit
  828. movl FUNC(_func_evtLogT0),%edx /* event log routine */
  829. cmpl $0,%edx
  830. je trgCheckIntExit
  831.         cmpl $0,FUNC(workQIsEmpty) /* work in work queue? */
  832.         jne     intExitEvent
  833.         pushl $ EVENT_INT_EXIT_K /* event id */
  834.         jmp     intExitCont
  835. intExitEvent:
  836.         pushl $ EVENT_INT_EXIT /* event id */
  837. intExitCont:
  838. call *%edx /* call event log routine */
  839. addl  $4,%esp 
  840. trgCheckIntExit:
  841. movl $ TRG_CLASS_1,%eax     
  842. orl  $ TRG_ON,%eax
  843.         cmpl    FUNC(trgEvtClass),%eax /* any trigger? */
  844.         jne      intExitClean
  845.         movl    FUNC(_func_trgCheck),%edx /* triggering routine */
  846. cmpl $0,%edx
  847.         je      intExitClean
  848.         pushl   $ 0                      /* 0 */
  849.         pushl   $ 0                      /* 0 */
  850.         pushl   $ 0                      /* 0 */
  851.         pushl   $ 0                      /* 0 */
  852.         pushl   $ 0                      /* 0 */
  853.         pushl   $ 0                      /* obj */
  854.         pushl   $ 0                      /* TRG_CLASS1_INDEX */
  855.         cmpl $0,FUNC(workQIsEmpty) /* work in work queue? */
  856.         jne     trgIntExitEvent
  857.         pushl $ EVENT_INT_EXIT_K /* event id */
  858.         jmp     trgIntExitCont
  859. trgIntExitEvent:
  860.         pushl $ EVENT_INT_EXIT /* event id */
  861. trgIntExitCont:
  862.         call    *%edx                    /* call triggering routine */
  863. addl    $32,%esp
  864. intExitClean:
  865. popfl /* UNLOCK INTERRUPTS */
  866.         popl %ecx /* restore regs */
  867.         popl %edx
  868. noIntExit:
  869.         /* windview instrumentation - END */
  870. #endif  /* WV_INSTRUMENTATION */
  871. cli /* LOCK INTERRUPTS */
  872. decl FUNC(intCnt) /* decrement intCnt */
  873. decl FUNC(intNest) /* decrement the private counter */
  874.         movl ESF0_CS+4(%esp),%eax /* if CS on stack is sysCsInt, */
  875.         cmpw FUNC(sysCsInt),%ax /*  then we were in an ISR */
  876.         je intRte /*  so just clean up/rte */
  877. #ifdef INT_STACK_USE
  878. /*
  879.  * switch to the supervisor stack from the interrupt stack
  880.  *
  881.          * stack growth in the 1st interrupt
  882.  *   (supervisor stack)            (interrupt stack)
  883.  *   ----------------------------------------------
  884.  *     :                 +-----     supervisor SP
  885.  *     ESF(12 bytes)  |          ESF(12 bytes)    --- 1st int
  886.  *     errno       <-----+     : errno / %eax   --- 1st int
  887.  *     :                            : %eax
  888.  *     :                            :
  889.  *     V                            V
  890.  *
  891.          * stack growth in the 2nd interrupt
  892.  *   (supervisor stack)            (interrupt stack)
  893.  *   ----------------------------------------------
  894.  *     :                 +-----     supervisor SP
  895.  *     ESF(12 bytes)  |          ESF(12 bytes)    --- 1st int
  896.  *     errno       <-----+     errno            --- 1st int
  897.  *     :                            :
  898.  *     :                            ESF(12 bytes)    --- 2nd int
  899.  *     :                            : errno / %eax   --- 2nd int
  900.  *     V                            : %eax
  901.  *                                  :
  902.  *                                  V
  903.  *
  904.  */
  905. cmpl $0,FUNC(vxIntStackEnabled) /* if vxIntStackEnabled == 0 then */
  906. je intExit0 /* skip the interrupt stack switch */
  907. cmpl    $0, FUNC(intNest) /* is it nested interrupt ? */
  908. jne     intExit0 /*   yes: goto intRteInt */
  909. popl %eax /* restore %eax */
  910. addl $ ESF0_NBYTES+12+4, FUNC(vxIntStackPtr) /* free */
  911. movl ESF0_NBYTES(%esp), %esp /* switch to supervisor stack */
  912. popl FUNC(errno) /* restore errno */
  913. pushl %eax /* save %eax */
  914. #endif /* INT_STACK_USE */
  915. intExit0:
  916. cmpl $0,FUNC(kernelState) /* if kernelState == TRUE then */
  917. jne intRte /*  just clean up and rte */
  918. movl FUNC(taskIdCurrent),%eax /* put current task in %eax */
  919. cmpl FUNC(readyQHead),%eax  /* compare to highest ready task */
  920. je intRte /* if same then don't reschedule */
  921. cmpl $0,WIND_TCB_LOCK_CNT(%eax) /* is task preemption allowed */
  922. je saveIntContext /* if yes, then save context */
  923. cmpl $0,WIND_TCB_STATUS(%eax) /* is task ready to run */
  924. jne saveIntContext /* if no, then save context */
  925. intRte:
  926. popl %eax /* restore %eax */
  927. iret /* UNLOCK INTERRUPTS */
  928. /* We are here if we have decided that rescheduling is a distinct possibility.
  929.  * The context must be gathered and stored in the current task's tcb.
  930.  * The stored stack pointers must be modified to clean up the stacks (SP).
  931.  */
  932. .balign 16,0x90
  933. saveIntContext:
  934. /* interrupts are still locked out */
  935. movl $1,FUNC(kernelState) /* kernelState = TRUE; */
  936. movl FUNC(taskIdCurrent),%eax /* tcb to be fixed up */
  937. popl WIND_TCB_EAX(%eax) /* store %eax in tcb */
  938. popl WIND_TCB_PC(%eax) /* save pc in tcb */
  939. leal 4(%esp),%esp /* do not save %cs in tcb */
  940. popl WIND_TCB_EFLAGS(%eax) /* save eflags in tcb */
  941. sti /* UNLOCK INTERRUPTS */
  942. /* interrupts unlocked and using master stack*/
  943. movl %edx,WIND_TCB_EDX(%eax) /* save %edx */
  944. movl %ecx,WIND_TCB_ECX(%eax) /* save %ecx */
  945. movl %ebx,WIND_TCB_EBX(%eax) /* save %ebx */
  946. movl %esi,WIND_TCB_ESI(%eax) /* save %esi */
  947. movl %edi,WIND_TCB_EDI(%eax) /* save %edi */
  948. movl %ebp,WIND_TCB_EBP(%eax) /* save %ebp */
  949. movl %esp,WIND_TCB_ESP(%eax) /* save %esp */
  950. movl FUNC(errno),%edx /* save errno */
  951. movl %edx,WIND_TCB_ERRNO(%eax)
  952. movl %eax,%edx /* taskIdCurrent into %edx */
  953. jmp FUNC(reschedule) /* goto rescheduler */
  954. /*******************************************************************************
  955. *
  956. * vxTaskEntry - task startup code following spawn
  957. *
  958. * This hunk of code is the initial entry point to every task created via
  959. * the "spawn" routines.  taskCreate(2) has put the true entry point of the
  960. * task into the tcb extension before creating the task,
  961. * and then pushed exactly ten arguments (although the task may use
  962. * fewer) onto the stack.  This code picks up the real entry point and calls it.
  963. * Upon return, the 10 task args are popped, and the result of the main
  964. * routine is passed to "exit" which terminates the task.
  965. * This way of doing things has several purposes.  First a task is easily
  966. * "restartable" via the routine taskRestart(2) since the real
  967. * entry point is available in the tcb extension.  Second, the call to the main
  968. * routine is a normal call including the usual stack clean-up afterwards,
  969. * which means that debugging stack trace facilities will handle the call of
  970. * the main routine properly.
  971. *
  972. * NOMANUAL
  973. * void vxTaskEntry ()
  974. */
  975. .balign 16,0x90
  976. FUNC_LABEL(vxTaskEntry)
  977. xorl %ebp,%ebp /* make sure frame pointer is 0 */
  978. movl FUNC(taskIdCurrent),%eax /* get current task id */
  979. movl WIND_TCB_ENTRY(%eax),%eax /* entry point for task is in tcb */
  980. call *%eax /* call main routine */
  981. addl $40,%esp /* pop args to main routine */
  982. pushl %eax /* pass result to exit */
  983. call FUNC(exit) /* gone for good */
  984. /*******************************************************************************
  985. *
  986. * windIntStackSet - set the interrupt stack pointer
  987. *
  988. * This routine sets the interrupt stack pointer to the specified address.
  989. * It is only valid on architectures with an interrupt stack pointer.
  990. * For I80X86, the switch to/from the interrupt stack is done by software.
  991. *
  992. * NOMANUAL
  993. * void windIntStackSet (pBotStack)
  994. *     char *pBotStack; /* pointer to bottom of interrupt stack *
  995. */
  996. .balign 16,0x90
  997. FUNC_LABEL(windIntStackSet)
  998. movl SP_ARG1(%esp), %eax /* get pBotStack */
  999. movl %eax, FUNC(vxIntStackPtr) /* set it to vxIntStackPtr */
  1000. ret
  1001. /*******************************************************************************
  1002. *
  1003. * intStackEnable - enable the interrupt stack usage
  1004. *
  1005. * This routine enables the interrupt stack usage.
  1006. * This routine is only callable from the task level, returns ERROR otherwise.
  1007. * The interrupt stack usage is disabled in the default configuration 
  1008. * for the backward compatibility.
  1009. *
  1010. * RETURNS: OK, or ERROR if it is not in the task level.
  1011. * STATUS intStackEnable 
  1012. *    (
  1013. *    BOOL enable /@ TRUE to enable, FALSE to disable @/
  1014. *    )
  1015. */
  1016. .balign 16,0x90
  1017. FUNC_LABEL(intStackEnable)
  1018. movl %cs, %eax
  1019. cmpl FUNC(sysCsSuper), %eax /* is the CS for the task level? */
  1020. jne intStackEnableError /*   no: return ERROR */
  1021. xorl %eax, %eax /* zero for OK */
  1022. movl SP_ARG1(%esp), %edx /* get & set the parameter */
  1023. /* next "movl" instruction is atomic, so no intLock/Unlock is needed */
  1024. movl %edx, FUNC(vxIntStackEnabled)
  1025. ret
  1026. intStackEnableError:
  1027. movl $ ERROR, %eax
  1028. ret