Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2012. 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: 3555 $
  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.         mov     ecx, [TASK_COUNT]
  93.         mov     edi, TASK_DATA
  94.   .newupdate:
  95.         xor     eax, eax
  96.         xchg    eax, [edi+TASKDATA.counter_sum]
  97.         mov     [edi+TASKDATA.cpu_usage], eax
  98.         add     edi, 0x20
  99.         loop    .newupdate
  100.         ret
  101.  
  102. ;TODO: Надо бы убрать использование do_change_task из V86...
  103. ; и после этого перенести обработку TASKDATA.counter_add/sum в do_change_task
  104.  
  105. align 4
  106. do_change_task:
  107. ;param:
  108. ;   ebx = address of the APPDATA for incoming task (new)
  109. ;warning:
  110. ;   [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task)
  111. ;   [current_slot] is the outcoming (old), and set here to a new value (ebx)
  112. ;scratched: eax,ecx,esi
  113.         mov     esi, ebx
  114.         xchg    esi, [current_slot]
  115. ; set new stack after saving old
  116.         mov     [esi+APPDATA.saved_esp], esp
  117.         mov     esp, [ebx+APPDATA.saved_esp]
  118. ; set new thread io-map
  119.         Mov     dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map]
  120.         Mov     dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4]
  121. ; set new thread memory-map
  122.         mov     ecx, APPDATA.dir_table
  123.         mov     eax, [ebx+ecx]      ;offset>0x7F
  124.         cmp     eax, [esi+ecx]      ;offset>0x7F
  125.         je      @f
  126.         mov     cr3, eax
  127. @@:
  128. ; set tss.esp0
  129.  
  130.         Mov     [tss._esp0],eax,[ebx+APPDATA.saved_esp0]
  131.  
  132.         mov     edx, [ebx+APPDATA.tls_base]
  133.         cmp     edx, [esi+APPDATA.tls_base]
  134.         je      @f
  135.  
  136.         mov     [tls_data_l+2], dx
  137.         shr     edx, 16
  138.         mov     [tls_data_l+4], dl
  139.         mov     [tls_data_l+7], dh
  140.  
  141.         mov     dx, app_tls
  142.         mov     fs, dx
  143. @@:
  144. ; set gs selector unconditionally
  145.         Mov     gs,ax,graph_data
  146.       ; set CR0.TS
  147.         cmp     bh, byte[fpu_owner] ;bh == incoming task (new)
  148.         clts                        ;clear a task switch flag
  149.         je      @f
  150.         mov     eax, cr0            ;and set it again if the owner
  151.         or      eax, CR0_TS         ;of a fpu has changed
  152.         mov     cr0, eax
  153.   @@: ; set context_counter (only for user pleasure ???)
  154.         inc     [context_counter]   ;noname & halyavin
  155.       ; set debug-registers, if it's necessary
  156.         test    byte[ebx+APPDATA.dbg_state], 1
  157.         jz      @f
  158.         xor     eax, eax
  159.         mov     dr6, eax
  160.         lea     esi, [ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table];offset>0x7F
  161.         cld
  162.   macro lodsReg [reg] {
  163.         lodsd
  164.         mov     reg, eax
  165.   }     lodsReg dr0, dr1, dr2, dr3, dr7
  166.   purge lodsReg
  167.   @@:
  168.         ret
  169. ;end.
  170.  
  171.  
  172.  
  173. struct  MUTEX_WAITER
  174.         list    LHEAD
  175.         task    dd ?
  176. ends
  177.  
  178. ;void  __fastcall mutex_init(struct mutex *lock)
  179.  
  180. align 4
  181. mutex_init:
  182.         mov     [ecx+MUTEX.lhead.next], ecx
  183.         mov     [ecx+MUTEX.lhead.prev], ecx
  184.         mov     [ecx+MUTEX.count], 1
  185.         ret
  186.  
  187.  
  188. ;void  __fastcall mutex_lock(struct mutex *lock)
  189.  
  190. align 4
  191. mutex_lock:
  192.  
  193.         dec     [ecx+MUTEX.count]
  194.         jns     .done
  195.  
  196.         pushfd
  197.         cli
  198.  
  199.         sub     esp, sizeof.MUTEX_WAITER
  200.  
  201.         list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
  202.  
  203.         mov     edx, [TASK_BASE]
  204.         mov     [esp+MUTEX_WAITER.task], edx
  205.  
  206. .forever:
  207.  
  208.         mov     eax, -1
  209.         xchg    eax, [ecx+MUTEX.count]
  210.         dec     eax
  211.         jz      @F
  212.  
  213.         mov     [edx+TASKDATA.state], 1
  214.         call    change_task
  215.         jmp     .forever
  216. @@:
  217.         mov     edx, [esp+MUTEX_WAITER.list.next]
  218.         mov     eax, [esp+MUTEX_WAITER.list.prev]
  219.  
  220.         mov     [eax+MUTEX_WAITER.list.next], edx
  221.         mov     [edx+MUTEX_WAITER.list.prev], eax
  222.         cmp     [ecx+MUTEX.lhead.next], ecx
  223.         jne     @F
  224.  
  225.         mov     [ecx+MUTEX.count], 0
  226. @@:
  227.         add     esp, sizeof.MUTEX_WAITER
  228.  
  229.         popfd
  230. .done:
  231.         ret
  232.  
  233. ;void  __fastcall mutex_unlock(struct mutex *lock)
  234.  
  235. align 4
  236. mutex_unlock:
  237.  
  238.         pushfd
  239.         cli
  240.  
  241.         mov     eax, [ecx+MUTEX.lhead.next]
  242.         cmp     eax, ecx
  243.         mov     [ecx+MUTEX.count], 1
  244.         je      @F
  245.  
  246.         mov     eax, [eax+MUTEX_WAITER.task]
  247.         mov     [eax+TASKDATA.state], 0
  248. @@:
  249.         popfd
  250.         ret
  251.  
  252.  
  253. purge MUTEX_WAITER
  254.  
  255. MAX_PRIORITY      = 0   ; highest, used for kernel tasks
  256. USER_PRIORITY     = 1   ; default
  257. IDLE_PRIORITY     = 2   ; lowest, only IDLE thread goes here
  258. NR_SCHED_QUEUES   = 3   ; MUST equal IDLE_PRIORYTY + 1
  259.  
  260. uglobal
  261. ; [scheduler_current + i*4] = zero if there are no threads with priority i,
  262. ;  pointer to APPDATA of the current thread with priority i otherwise.
  263. align 4
  264. scheduler_current       rd      NR_SCHED_QUEUES
  265. endg
  266.  
  267. ; Add the given thread to the given priority list for the scheduler.
  268. ; in: edx -> APPDATA, ecx = priority
  269. proc scheduler_add_thread
  270. ; 1. Acquire the lock.
  271.         spin_lock_irqsave SchedulerLock
  272. ; 2. Store the priority in APPDATA structure.
  273.         mov     [edx+APPDATA.priority], ecx
  274. ; 3. There are two different cases: the given list is empty or not empty.
  275. ; In first case, go to 6. Otherwise, advance to 4.
  276.         mov     eax, [scheduler_current+ecx*4]
  277.         test    eax, eax
  278.         jz      .new_list
  279. ; 4. Insert the new item immediately before the current item.
  280.         mov     ecx, [eax+APPDATA.in_schedule.prev]
  281.         mov     [edx+APPDATA.in_schedule.next], eax
  282.         mov     [edx+APPDATA.in_schedule.prev], ecx
  283.         mov     [eax+APPDATA.in_schedule.prev], edx
  284.         mov     [ecx+APPDATA.in_schedule.next], edx
  285. ; 5. Release the lock and return.
  286.         spin_unlock_irqrestore SchedulerLock
  287.         ret
  288. .new_list:
  289. ; 6. Initialize the list with one item and make it the current item.
  290.         mov     [edx+APPDATA.in_schedule.next], edx
  291.         mov     [edx+APPDATA.in_schedule.prev], edx
  292.         mov     [scheduler_current+ecx*4], edx
  293. ; 7. Release the lock and return.
  294.         spin_unlock_irqrestore SchedulerLock
  295.         ret
  296. endp
  297.  
  298. ; Remove the given thread from the corresponding priority list for the scheduler.
  299. ; in: edx -> APPDATA
  300. proc scheduler_remove_thread
  301. ; 1. Acquire the lock.
  302.         spin_lock_irqsave SchedulerLock
  303. ; 2. Remove the item from the corresponding list.
  304.         mov     eax, [edx+APPDATA.in_schedule.next]
  305.         mov     ecx, [edx+APPDATA.in_schedule.prev]
  306.         mov     [eax+APPDATA.in_schedule.prev], ecx
  307.         mov     [ecx+APPDATA.in_schedule.next], eax
  308. ; 3. If the given thread is the current item in the list,
  309. ; advance the current item.
  310. ; 3a. Check whether the given thread is the current item;
  311. ; if no, skip the rest of this step.
  312.         mov     ecx, [edx+APPDATA.priority]
  313.         cmp     [scheduler_current+ecx*4], edx
  314.         jnz     .return
  315. ; 3b. Set the current item to eax; step 2 has set eax = next item.
  316.         mov     [scheduler_current+ecx*4], eax
  317. ; 3c. If there were only one item in the list, zero the current item.
  318.         cmp     eax, edx
  319.         jnz     .return
  320.         mov     [scheduler_current+ecx*4], 0
  321. .return:
  322. ; 4. Release the lock and return.
  323.         spin_unlock_irqrestore SchedulerLock
  324.         ret
  325. endp
  326.  
  327. ;info:
  328. ;   Find next task to execute
  329. ;retval:
  330. ;   ebx = address of the APPDATA for the selected task (slot-base)
  331. ;   edi = address of the TASKDATA for the selected task
  332. ;   ZF  = 1  if the task is the same
  333. ;warning:
  334. ;   [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result
  335. ;   [current_slot] is not set to new value (ebx)!!!
  336. ;scratched: eax,ecx
  337. proc find_next_task
  338.         call    update_counters
  339.         spin_lock_irqsave SchedulerLock
  340.         xor     ecx, ecx
  341. .priority_loop:
  342.         mov     ebx, [scheduler_current+ecx*4]
  343.         test    ebx, ebx
  344.         jz      .priority_next
  345. .task_loop:
  346.         mov     ebx, [ebx+APPDATA.in_schedule.next]
  347.         mov     edi, ebx
  348.         shr     edi, 3
  349.         add     edi, CURRENT_TASK - (SLOT_BASE shr 3)
  350.         mov     al, [edi+TASKDATA.state]
  351.         test    al, al
  352.         jz      .task_found     ; state == 0
  353.         cmp     al, 5
  354.         jne     .task_next      ; state == 1,2,3,4,9
  355.       ; state == 5
  356.         pushad  ; more freedom for [APPDATA.wait_test]
  357.         call    [ebx+APPDATA.wait_test]
  358.         mov     [esp+28], eax
  359.         popad
  360.         or      eax, eax
  361.         jnz     @f
  362.       ; testing for timeout
  363.         mov     eax, [timer_ticks]
  364.         sub     eax, [ebx+APPDATA.wait_begin]
  365.         cmp     eax, [ebx+APPDATA.wait_timeout]
  366.         jb      .task_next
  367.         xor     eax, eax
  368. @@:
  369.         mov     [ebx+APPDATA.wait_param], eax  ; retval for wait
  370.         mov     [edi+TASKDATA.state], 0
  371. .task_found:
  372.         mov     [scheduler_current+ecx*4], ebx
  373.         spin_unlock_irqrestore SchedulerLock
  374. .found:
  375.         mov     [CURRENT_TASK], bh
  376.         mov     [TASK_BASE], edi
  377.         rdtsc   ;call  _rdtsc
  378.         mov     [edi+TASKDATA.counter_add], eax; for next using update_counters
  379.         cmp     ebx, [current_slot]
  380.         ret
  381. .task_next:
  382.         cmp     ebx, [scheduler_current+ecx*4]
  383.         jnz     .task_loop
  384. .priority_next:
  385.         inc     ecx
  386.         cmp     ecx, NR_SCHED_QUEUES
  387.         jb      .priority_loop
  388.         hlt
  389.         jmp     $-1
  390. endp
  391.  
  392. if 0
  393.  
  394. struc TIMER
  395. {
  396.   .next      dd ?
  397.   .exp_time  dd ?
  398.   .func      dd ?
  399.   .arg       dd ?
  400. }
  401.  
  402.  
  403. uglobal
  404. rdy_head   rd 16
  405. endg
  406.  
  407. align 4
  408. pick_task:
  409.  
  410.         xor     eax, eax
  411.   .pick:
  412.         mov     ebx, [rdy_head+eax*4]
  413.         test    ebx, ebx
  414.         jz      .next
  415.  
  416.         mov     [next_task], ebx
  417.         test    [ebx+flags.billable]
  418.         jz      @F
  419.         mov     [bill_task], ebx
  420.   @@:
  421.         ret
  422.   .next:
  423.         inc     eax
  424.         jmp     .pick
  425.  
  426. ; param
  427. ;  eax= task
  428. ;
  429. ; retval
  430. ;  eax= task
  431. ;  ebx= queue
  432. ;  ecx= front if 1 or back if 0
  433. align 4
  434. shed:
  435.         cmp     [eax+.tics_left], 0;signed compare
  436.         mov     ebx, [eax+.priority]
  437.         setg    ecx
  438.         jg      @F
  439.  
  440.         mov     edx, [eax+.tics_quantum]
  441.         mov     [eax+.ticks_left], edx
  442.         cmp     ebx, (IDLE_PRIORITY-1)
  443.         je      @F
  444.         inc     ebx
  445.   @@:
  446.         ret
  447.  
  448. ; param
  449. ;  eax= task
  450. align 4
  451. enqueue:
  452.         call    shed;eax
  453.         cmp     [rdy_head+ebx*4], 0
  454.         jnz     @F
  455.  
  456.         mov     [rdy_head+ebx*4], eax
  457.         mov     [rdy_tail+ebx*4], eax
  458.         mov     [eax+.next_ready], 0
  459.         jmp     .pick
  460.   @@:
  461.         test    ecx, ecx
  462.         jz      .back
  463.  
  464.         mov     ecx, [rdy_head+ebx*4]
  465.         mov     [eax+.next_ready], ecx
  466.         mov     [rdy_head+ebx*4], eax
  467.         jmp     .pick
  468.   .back:
  469.         mov     ecx, [rdy_tail+ebx*4]
  470.         mov     [ecx+.next_ready], eax
  471.         mov     [rdy_tail+ebx*4], eax
  472.         mov     [eax+.next_ready], 0
  473.   .pick:
  474.         call    pick_proc;select next task
  475.         ret
  476.  
  477. end if
  478.