Subversion Repositories Kolibri OS

Rev

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