Subversion Repositories Kolibri OS

Rev

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