Subversion Repositories Kolibri OS

Rev

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