Subversion Repositories Kolibri OS

Rev

Rev 2150 | Rev 2434 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
  4. ;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa      ;;
  5. ;; Distributed under terms of the GNU General Public License    ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 2166 $
  9.  
  10.  
  11. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  12. ;; IRQ0 HANDLER (TIMER INTERRUPT) ;;
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14.  
  15.  
  16. align 32
  17. irq0:
  18.         pushad
  19.         Mov     ds, ax, app_data
  20.         mov     es, ax
  21.         inc     [timer_ticks]
  22.         mov     eax, [timer_ticks]
  23.         call    playNote       ; <<<--- Speaker driver
  24.         sub     eax,[next_usage_update]
  25.         cmp     eax,100
  26.         jb      .nocounter
  27.         add     [next_usage_update],100
  28.         call    updatecputimes
  29.   .nocounter:
  30.             xor     ecx, ecx    ; send End Of Interrupt signal
  31.         call    irq_eoi
  32.         btr     dword[DONT_SWITCH], 0
  33.         jc      .return
  34.         call    find_next_task
  35.         jz      .return  ; if there is only one running process
  36.         call    do_change_task
  37.   .return:
  38.         popad
  39.         iretd
  40.  
  41. align 4
  42. change_task:
  43.         pushfd
  44.         cli
  45.         pushad
  46. if 0
  47. ; \begin{Mario79} ; <- must be refractoried, if used...
  48.         cmp     [dma_task_switched], 1
  49.         jne     .find_next_task
  50.         mov     [dma_task_switched], 0
  51.         mov     ebx, [dma_process]
  52.         cmp     [CURRENT_TASK], ebx
  53.         je      .return
  54.         mov     edi, [dma_slot_ptr]
  55.         mov     [CURRENT_TASK], ebx
  56.         mov     [TASK_BASE], edi
  57.         jmp     @f
  58. .find_next_task:
  59. ; \end{Mario79}
  60. end if
  61.         call    find_next_task
  62.         jz      .return  ; the same task -> skip switch
  63.   @@:   mov     byte[DONT_SWITCH], 1
  64.         call    do_change_task
  65.   .return:
  66.         popad
  67.         popfd
  68.         ret
  69.  
  70. uglobal
  71. align 4
  72. ;  far_jump:
  73. ;   .offs dd ?
  74. ;   .sel  dw ?
  75.    context_counter     dd 0 ;noname & halyavin
  76.    next_usage_update   dd 0
  77.    timer_ticks         dd 0
  78. ;  prev_slot           dd ?
  79. ;  event_sched         dd ?
  80. endg
  81.  
  82. align 4
  83. update_counters:
  84.         mov     edi, [TASK_BASE]
  85.         rdtsc
  86.         sub     eax, [edi+TASKDATA.counter_add] ; time stamp counter add
  87.         add     [edi+TASKDATA.counter_sum], eax ; counter sum
  88.         ret
  89. align 4
  90. updatecputimes:
  91.         xor     eax,eax
  92.         xchg    eax,[idleuse]
  93.         mov     [idleusesec],eax
  94.         mov     ecx, [TASK_COUNT]
  95.         mov     edi, TASK_DATA
  96.   .newupdate:
  97.         xor     eax,eax
  98.         xchg    eax,[edi+TASKDATA.counter_sum]
  99.         mov     [edi+TASKDATA.cpu_usage],eax
  100.         add     edi,0x20
  101.         loop    .newupdate
  102.         ret
  103.  
  104. align 4
  105. find_next_task:
  106. ;info:
  107. ;   Find next task to execute
  108. ;retval:
  109. ;   ebx = address of the APPDATA for the selected task (slot-base)
  110. ;   esi = previous slot-base ([current_slot] at the begin)
  111. ;   edi = address of the TASKDATA for the selected task
  112. ;   ZF  = 1  if the task is the same
  113. ;warning:
  114. ;   [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result
  115. ;   [current_slot] is not set to new value (ebx)!!!
  116. ;scratched: eax,ecx
  117.         call    update_counters ; edi := [TASK_BASE]
  118.         Mov     esi, ebx, [current_slot]
  119.   .loop:
  120.         cmp     bh,[TASK_COUNT]
  121.         jb      @f
  122.         xor     bh, bh
  123.         mov     edi,CURRENT_TASK
  124.   @@:   inc     bh       ; ebx += APPDATA.size
  125.         add     edi,0x20 ; edi += TASKDATA.size
  126.         mov     al, [edi+TASKDATA.state]
  127.         test    al, al
  128.         jz      .found   ; state == 0
  129.         cmp     al, 5
  130.         jne     .loop    ; state == 1,2,3,4,9
  131.       ; state == 5
  132.         pushad  ; more freedom for [APPDATA.wait_test]
  133.         call    [ebx+APPDATA.wait_test]
  134.         mov     [esp+28],eax
  135.         popad
  136.         or      eax,eax
  137.         jnz     @f
  138.       ; testing for timeout
  139.         mov     ecx, [timer_ticks]
  140.         sub     ecx, [ebx+APPDATA.wait_begin]
  141.         cmp     ecx, [ebx+APPDATA.wait_timeout]
  142.         jb      .loop
  143.   @@:   mov     [ebx+APPDATA.wait_param], eax  ; retval for wait
  144.         mov     [edi+TASKDATA.state], 0
  145.   .found:
  146.         mov     [CURRENT_TASK],bh
  147.         mov     [TASK_BASE],edi
  148.         rdtsc   ;call  _rdtsc
  149.         mov     [edi+TASKDATA.counter_add],eax ; for next using update_counters
  150.         cmp     ebx, esi ;esi - previous slot-base
  151.         ret
  152. ;TODO: Íàäî áû óáðàòü èñïîëüçîâàíèå do_change_task èç V86...
  153. ; è ïîñëå ýòîãî ïåðåíåñòè îáðàáîòêó TASKDATA.counter_add/sum â do_change_task
  154.  
  155. align 4
  156. do_change_task:
  157. ;param:
  158. ;   ebx = address of the APPDATA for incoming task (new)
  159. ;warning:
  160. ;   [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task)
  161. ;   [current_slot] is the outcoming (old), and set here to a new value (ebx)
  162. ;scratched: eax,ecx,esi
  163.         mov     esi,ebx
  164.         xchg    esi,[current_slot]
  165. ; set new stack after saving old
  166.         mov     [esi+APPDATA.saved_esp], esp
  167.         mov     esp, [ebx+APPDATA.saved_esp]
  168. ; set new thread io-map
  169.         Mov     dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map]
  170.         Mov     dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4]
  171. ; set new thread memory-map
  172.         mov     ecx, APPDATA.dir_table
  173.         mov     eax, [ebx+ecx]      ;offset>0x7F
  174.         cmp     eax, [esi+ecx]      ;offset>0x7F
  175.         je      @f
  176.         mov     cr3, eax
  177. @@:
  178. ; set tss.esp0
  179.  
  180.         Mov     [tss._esp0],eax,[ebx+APPDATA.saved_esp0]
  181.  
  182.         mov edx, [ebx+APPDATA.tls_base]
  183.         cmp edx, [esi+APPDATA.tls_base]
  184.         je @f
  185.  
  186.         mov     [tls_data_l+2],dx
  187.         shr     edx,16
  188.         mov     [tls_data_l+4],dl
  189.         mov     [tls_data_l+7],dh
  190.  
  191.         mov dx, app_tls
  192.         mov fs, dx
  193. @@:
  194. ; set gs selector unconditionally
  195.         Mov     gs,ax,graph_data
  196.       ; set CR0.TS
  197.         cmp     bh, byte[fpu_owner] ;bh == incoming task (new)
  198.         clts                        ;clear a task switch flag
  199.         je      @f
  200.         mov     eax, cr0            ;and set it again if the owner
  201.         or      eax, CR0_TS         ;of a fpu has changed
  202.         mov     cr0, eax
  203.   @@: ; set context_counter (only for user pleasure ???)
  204.         inc     [context_counter]   ;noname & halyavin
  205.       ; set debug-registers, if it's necessary
  206.         test    byte[ebx+APPDATA.dbg_state], 1
  207.         jz      @f
  208.         xor     eax, eax
  209.         mov     dr6, eax
  210.         lea     esi,[ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table] ;offset>0x7F
  211.         cld
  212.   macro lodsReg [reg] {
  213.         lodsd
  214.         mov     reg,eax
  215.   }     lodsReg dr0, dr1, dr2, dr3, dr7
  216.   purge lodsReg
  217.   @@:   ret
  218. ;end.
  219.  
  220.  
  221.  
  222. struc MUTEX_WAITER
  223. {
  224.     .list   LHEAD
  225.     .task   rd 1
  226.     .sizeof:
  227. };
  228.  
  229. virtual at 0
  230.  MUTEX_WAITER MUTEX_WAITER
  231. end virtual
  232.  
  233. ;void  __fastcall mutex_init(struct mutex *lock)
  234.  
  235. align 4
  236. mutex_init:
  237.         mov [ecx+MUTEX.wait.next], ecx
  238.         mov [ecx+MUTEX.wait.prev], ecx
  239.         mov [ecx+MUTEX.count],1
  240.         ret
  241.  
  242.  
  243. ;void  __fastcall mutex_lock(struct mutex *lock)
  244.  
  245. align 4
  246. mutex_lock:
  247.  
  248.         dec [ecx+MUTEX.count]
  249.         jns .done
  250.  
  251.         pushfd
  252.         cli
  253.  
  254.         sub esp, MUTEX_WAITER.sizeof
  255.  
  256.         list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
  257.  
  258.         mov edx, [TASK_BASE]
  259.         mov [esp+MUTEX_WAITER.task], edx
  260.  
  261. .forever:
  262.  
  263.         mov eax, -1
  264.         xchg eax, [ecx+MUTEX.count]
  265.         dec eax
  266.         jz @F
  267.  
  268.         mov [edx+TASKDATA.state], 1
  269.         call change_task
  270.         jmp .forever
  271. @@:
  272.         mov edx, [esp+MUTEX_WAITER.list.next]
  273.         mov eax, [esp+MUTEX_WAITER.list.prev]
  274.  
  275.         mov [eax+MUTEX_WAITER.list.next], edx
  276.         mov [edx+MUTEX_WAITER.list.prev], eax
  277.         cmp [ecx+MUTEX.wait.next], ecx
  278.         jne @F
  279.  
  280.         mov [ecx+MUTEX.count], 0
  281. @@:
  282.         add  esp, MUTEX_WAITER.sizeof
  283.  
  284.         popfd
  285. .done:
  286.         ret
  287.  
  288. ;void  __fastcall mutex_unlock(struct mutex *lock)
  289.  
  290. align 4
  291. mutex_unlock:
  292.  
  293.         pushfd
  294.         cli
  295.  
  296.         mov eax, [ecx+MUTEX.wait.next]
  297.         cmp eax, ecx
  298.         mov [ecx+MUTEX.count], 1
  299.         je @F
  300.  
  301.         mov eax, [eax+MUTEX_WAITER.task]
  302.         mov [eax+TASKDATA.state], 0
  303. @@:
  304.         popfd
  305.         ret
  306.  
  307.  
  308. purge MUTEX_WAITER
  309.  
  310. if 0
  311.  
  312. struc TIMER
  313. {
  314.   .next      dd ?
  315.   .exp_time  dd ?
  316.   .func      dd ?
  317.   .arg       dd ?
  318. }
  319.  
  320.  
  321. MAX_PROIRITY         0   ; highest, used for kernel tasks
  322. MAX_USER_PRIORITY    0   ; highest priority for user processes
  323. USER_PRIORITY        7   ; default (should correspond to nice 0)
  324. MIN_USER_PRIORITY   14   ; minimum priority for user processes
  325. IDLE_PRIORITY       15   ; lowest, only IDLE process goes here
  326. NR_SCHED_QUEUES     16   ; MUST equal IDLE_PRIORYTY + 1
  327.  
  328. uglobal
  329. rdy_head   rd 16
  330. endg
  331.  
  332. align 4
  333. pick_task:
  334.  
  335.        xor eax, eax
  336.   .pick:
  337.        mov ebx, [rdy_head+eax*4]
  338.        test ebx, ebx
  339.        jz .next
  340.  
  341.        mov [next_task], ebx
  342.        test [ebx+flags.billable]
  343.        jz @F
  344.        mov [bill_task], ebx
  345.   @@:
  346.        ret
  347.   .next:
  348.        inc eax
  349.        jmp .pick
  350.  
  351. ; param
  352. ;  eax= task
  353. ;
  354. ; retval
  355. ;  eax= task
  356. ;  ebx= queue
  357. ;  ecx= front if 1 or back if 0
  358. align 4
  359. shed:
  360.        cmp [eax+.tics_left], 0 ;signed compare
  361.        mov ebx, [eax+.priority]
  362.        setg ecx
  363.        jg @F
  364.  
  365.        mov edx, [eax+.tics_quantum]
  366.        mov [eax+.ticks_left], edx
  367.        cmp ebx, (IDLE_PRIORITY-1)
  368.        je @F
  369.        inc ebx
  370.   @@:
  371.        ret
  372.  
  373. ; param
  374. ;  eax= task
  375. align 4
  376. enqueue:
  377.       call shed  ;eax
  378.       cmp [rdy_head+ebx*4],0
  379.       jnz @F
  380.  
  381.       mov [rdy_head+ebx*4], eax
  382.       mov [rdy_tail+ebx*4], eax
  383.       mov [eax+.next_ready], 0
  384.       jmp .pick
  385.   @@:
  386.       test ecx, ecx
  387.       jz .back
  388.  
  389.       mov ecx, [rdy_head+ebx*4]
  390.       mov [eax+.next_ready], ecx
  391.       mov [rdy_head+ebx*4], eax
  392.       jmp .pick
  393.   .back:
  394.       mov ecx, [rdy_tail+ebx*4]
  395.       mov [ecx+.next_ready], eax
  396.       mov [rdy_tail+ebx*4], eax
  397.       mov [eax+.next_ready], 0
  398.   .pick:
  399.       call pick_proc     ;select next task
  400.       ret
  401.  
  402. end if
  403.