home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / DOOG / CTASK.ZIP / TSKQUE.ASM < prev    next >
Assembly Source File  |  1989-12-20  |  8KB  |  320 lines

  1. ;
  2. ;    --- Version 2.0 89-12-14 17:44 ---
  3. ;
  4. ;    CTask - Queue management
  5. ;
  6. ;    Public Domain Software written by
  7. ;        Thomas Wagner
  8. ;        Patschkauer Weg 31
  9. ;        D-1000 Berlin 33
  10. ;        West Germany
  11. ;
  12. ;    Since managing the queues is one of the most timing critical 
  13. ;    parts of CTask, the main routines have been coded in Assembler.
  14. ;    The corresponding C code is included as a reference.
  15. ;
  16. ;    This file is new with 2.0.
  17. ;
  18.     name    tskque
  19.     .model    large,c
  20. ;
  21.     public    tsk_enqueue
  22.     public    tsk_dequeue
  23.     public    tsk_putqueue
  24.     public    tsk_enqtimer
  25.     public    tsk_deqtimer
  26. ;
  27.     include    tsk.mac
  28. ;
  29.     extrn    tsk_dgroup: word
  30. ;
  31.     .tsk_data
  32. ;
  33.     IF    SINGLE_DATA
  34.     extrn    tsk_glob_rec: byte
  35.     ELSE
  36.     extrn    tsk_global: dword
  37.     ENDIF
  38. ;
  39.     .tsk_edata
  40.     .tsk_code
  41. ;
  42.     extrn    tsk_scheduler: far
  43. ;
  44. ;
  45. ; tsk_enqueue
  46. ;
  47. ;    This routine adds a task (or any other queue element) to a queue
  48. ;    in priority order. The search starts at the queue's tail end so
  49. ;    as to better support the 'yield' operation (which disturbs the
  50. ;    priority order in the queue).
  51. ;
  52. ;void near tsk_enqueue (queheadptr q, queptr elem)
  53. ;{
  54. ;   queptr curr;
  55. ;
  56. ;   while (1)
  57. ;      {
  58. ;      curr = q->prev;
  59. ;      while (curr->kind &&
  60. ;             curr->el.pri.prior < elem->el.pri.prior)
  61. ;         curr = curr->prev;
  62. ;      }
  63. ;   elem->prev = curr;
  64. ;   elem->next = curr->next;
  65. ;   curr->next = elem->next->prev = elem;
  66. ;}
  67. ;
  68. tsk_enqueue    proc    near uses ds di, que: far ptr, elem: far ptr
  69. ;
  70.     les    di,elem
  71.     lds    bx,que
  72.     mov    cx,es:q_el.q_prior[di]    ; load priority into BX
  73.     lds    bx,q_prev[bx]        ; last queue element
  74. ;
  75. enq_loop:
  76.     cmp    q_kind[bx],0        ; at head?
  77.     je    enq_found        ; then insert
  78.     cmp    q_el.q_prior[bx],cx    ; else check priority
  79.     jae    enq_found        ; if above or equal, insert
  80. ;
  81.     lds    bx,q_prev[bx]        ; backup one element
  82.     jmp    enq_loop        ; and try again
  83. ;
  84. enq_found:
  85.     mov    word ptr es:q_prev[di],bx    ; elem->prev = curr
  86.     mov    word ptr es:q_prev+2[di],ds
  87.     mov    ax,word ptr q_next[bx]        ; elem->next = curr->next;
  88.     mov    word ptr es:q_next[di],ax
  89.     mov    dx,word ptr q_next+2[bx]
  90.     mov    word ptr es:q_next+2[di],dx
  91.     mov    word ptr q_next[bx],di        ; curr->next = elem;
  92.     mov    word ptr q_next+2[bx],es
  93.     mov    bx,ax
  94.     mov    ds,dx
  95.     mov    word ptr q_prev[bx],di        ; elem->next->prev = elem
  96.     mov    word ptr q_prev+2[bx],es
  97.     ret
  98. ;
  99. tsk_enqueue    endp
  100. ;
  101. ;
  102. ; tsk_putqueue
  103. ;
  104. ;    This routine adds a queue element to the end of a queue.
  105. ;
  106. ;void near tsk_putqueue (queheadptr q, queptr elem)
  107. ;{
  108. ;   elem->next = q;
  109. ;   elem->prev = q->prev;
  110. ;   q->prev = elem->prev->next = elem;
  111. ;}
  112. ;
  113. tsk_putqueue    proc    near uses ds di, que: far ptr, elem: far ptr
  114. ;
  115.     les    di,elem
  116.     lds    bx,que
  117.     mov    word ptr es:q_next[di],bx    ; elem->next = que
  118.     mov    word ptr es:q_next+2[di],ds
  119.     mov    ax,word ptr q_prev[bx]        ; elem->prev = que->prev;
  120.     mov    word ptr es:q_prev[di],ax
  121.     mov    dx,word ptr q_prev+2[bx]
  122.     mov    word ptr es:q_prev+2[di],dx
  123.     mov    word ptr q_prev[bx],di        ; que->prev = elem;
  124.     mov    word ptr q_prev+2[bx],es
  125.     mov    bx,ax
  126.     mov    ds,dx
  127.     mov    word ptr q_next[bx],di        ; elem->prev->next = elem
  128.     mov    word ptr q_next+2[bx],es
  129.     ret
  130. ;
  131. tsk_putqueue    endp
  132. ;
  133. ;
  134. ;
  135. ; tsk_enqtimer
  136. ;
  137. ;    This routine adds a task (or any other queue element) to
  138. ;    the timeout queue.
  139. ;
  140. ;    This is slightly different from the normal enqueue in that
  141. ;    queue elements are not inserted based on priority, but rather
  142. ;    based on the tick count. Each element's tick counter stores
  143. ;    the difference in ticks to the previous element. This speeds
  144. ;    up the timeout loop, since only the first element has to be
  145. ;    counted down, but it makes insertion a tad more complicated.
  146. ;
  147. ;void near tsk_enqtimer (queptr elem, dword ticks)
  148. ;{
  149. ;   queptr curr, q;
  150. ;
  151. ;   if (!ticks)
  152. ;      return;
  153. ;   q = &GLOBDATA timer_queue;
  154. ;
  155. ;   curr = q->next;
  156. ;   while (curr->kind &&
  157. ;          curr->el.ticks <= ticks)
  158. ;      {
  159. ;      ticks -= curr->el.ticks;
  160. ;      curr = curr->next;
  161. ;      if (!ticks)
  162. ;         break;
  163. ;      }
  164. ;   if (curr->kind)
  165. ;      curr->el.ticks -= ticks;
  166. ;   elem->next = curr;
  167. ;   elem->prev = curr->prev;
  168. ;   curr->prev = elem->prev->next = elem;
  169. ;   elem->el.ticks = ticks;
  170. ;}
  171. ;
  172. tsk_enqtimer    proc    near uses ds di, elem: far ptr, ticks: dword
  173. ;
  174.     les    di,elem
  175.     mov    ds,cs:tsk_dgroup
  176.     IF    SINGLE_DATA
  177.     lea    bx,tsk_glob_rec.timer_queue
  178.     ELSE
  179.     lds    bx,tsk_global
  180.     add    bx,timer_queue
  181.     ENDIF
  182. ;
  183.     mov    ax,word ptr (ticks)    ; load tick count into DX:AX
  184.     mov    dx,word ptr (ticks+2)
  185.     mov    cx,ax
  186.     or    cx,dx
  187.     jz    enqt_ret
  188.     lds    bx,q_first[bx]        ; first queue element
  189. ;
  190. et_loop:
  191.     cmp    q_kind[bx],0        ; at head?
  192.     je    et_found1        ; then insert
  193.     sub    ax,word ptr q_el.q_ticks[bx]    ; else check ticks
  194.     sbb    dx,word ptr q_el.q_ticks+2[bx]
  195.     jc    et_found        ; insert on overflow
  196. ;
  197.     lds    bx,q_next[bx]        ; next element
  198.     jmp    et_loop            ; and try again
  199. ;
  200. et_found:
  201.     add    ax,word ptr q_el.q_ticks[bx]    ; restore ticks
  202.     adc    dx,word ptr q_el.q_ticks+2[bx]
  203. ;
  204. et_found1:
  205.     mov    word ptr es:q_el.q_ticks[di],ax    ; elem->el.ticks = ticks
  206.     mov    word ptr es:q_el.q_ticks+2[di],dx
  207. ;
  208.     cmp    q_kind[bx],0        ; at head?
  209.     je    et_notick        ; no tick mod if yes
  210. ;
  211.     sub    word ptr q_el.q_ticks[bx],ax    ; else curr->el.ticks -= ticks
  212.     sbb    word ptr q_el.q_ticks+2[bx],dx
  213. ;
  214. et_notick:
  215.     mov    word ptr es:q_next[di],bx    ; elem->next = curr
  216.     mov    word ptr es:q_next+2[di],ds
  217.     mov    ax,word ptr q_prev[bx]        ; elem->prev = curr->prev;
  218.     mov    word ptr es:q_prev[di],ax
  219.     mov    dx,word ptr q_prev+2[bx]
  220.     mov    word ptr es:q_prev+2[di],dx
  221.     mov    word ptr q_prev[bx],di        ; curr->prev = elem;
  222.     mov    word ptr q_prev+2[bx],es
  223.     mov    bx,ax
  224.     mov    ds,dx
  225.     mov    word ptr q_next[bx],di        ; elem->prev->next = elem
  226.     mov    word ptr q_next+2[bx],es
  227. ;
  228. enqt_ret:
  229.     ret
  230. ;
  231. tsk_enqtimer    endp
  232. ;
  233. ;
  234. ;  tsk_dequeue
  235. ;
  236. ;    This routine removes an element from a queue.
  237. ;
  238. ;void near tsk_dequeue (queptr elem)
  239. ;{
  240. ;   if (elem->next == NULL)
  241. ;      return;
  242. ;   elem->next->prev = elem->prev;
  243. ;   elem->prev->next = elem->next;
  244. ;   elem->next = NULL;
  245. ;}
  246. ;
  247. tsk_dequeue    proc    near uses ds di, elem: far ptr
  248. ;
  249.     lds    bx,elem
  250.     les    di,q_next[bx]        ; remove from queue
  251.     mov    ax,es            ; check if enqueued
  252.     or    ax,di
  253.     jz    deq_ret            ; nothing to do if not in queue
  254.     xor    ax,ax            ; clear next pointer
  255.     mov    word ptr q_next[bx],ax
  256.     mov    word ptr q_next+2[bx],ax
  257.     lds    bx,q_prev[bx]
  258.     mov    word ptr es:q_prev[di],bx
  259.     mov    word ptr es:q_prev+2[di],ds
  260.     mov    word ptr q_next[bx],di
  261.     mov    word ptr q_next+2[bx],es
  262. ;
  263. deq_ret:
  264.     ret
  265. ;
  266. tsk_dequeue    endp
  267. ;
  268. ;
  269. ;  tsk_deqtimer
  270. ;
  271. ;    This routine removes an element from the timer queue.
  272. ;    It is different from the normal dequeue in that the tick
  273. ;    difference must be updated for the next in line.
  274. ;
  275. ;void near tsk_deqtimer (queptr elem)
  276. ;{
  277. ;   if (elem->next == NULL)
  278. ;      return;
  279. ;
  280. ;   if (elem->next->kind)
  281. ;      elem->next->el.ticks += elem->el.ticks;
  282. ;   elem->next->prev = elem->prev;
  283. ;   elem->prev->next = elem->next;
  284. ;   elem->next = NULL;
  285. ;}
  286. ;
  287. tsk_deqtimer    proc    near uses ds di, elem: far ptr
  288. ;
  289.     lds    bx,elem
  290.     les    di,q_next[bx]
  291.     mov    ax,es
  292.     or    ax,di
  293.     jz    deqtim_ret        ; nothing to do if not in queue
  294.     cmp    es:q_kind[di],0
  295.     je    dqt_notick
  296.     mov    ax,word ptr q_el.q_ticks[bx]    ; first update next tick count
  297.     mov    dx,word ptr q_el.q_ticks+2[bx]
  298.     add    word ptr es:q_el.q_ticks[di],ax
  299.     adc    word ptr es:q_el.q_ticks+2[di],dx
  300. ;
  301. dqt_notick:
  302.     xor    ax,ax
  303.     mov    word ptr q_next[bx],ax
  304.     mov    word ptr q_next+2[bx],ax
  305.     lds    bx,q_prev[bx]
  306.     mov    word ptr es:q_prev[di],bx
  307.     mov    word ptr es:q_prev+2[di],ds
  308.     mov    word ptr q_next[bx],di
  309.     mov    word ptr q_next+2[bx],es
  310. ;
  311. deqtim_ret:
  312.     ret
  313. ;
  314. tsk_deqtimer    endp
  315. ;
  316.     .tsk_ecode
  317.     end
  318.  
  319.  
  320.