Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;  queue.inc                                                   ;;
  7. ;;                                                              ;;
  8. ;;    Written by hidnplayr@kolibrios.org                        ;;
  9. ;;                                                              ;;
  10. ;;          GNU GENERAL PUBLIC LICENSE                          ;;
  11. ;;             Version 2, June 1991                             ;;
  12. ;;                                                              ;;
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14.  
  15. $Revision: 2305 $
  16.  
  17. ; The Queues implemented by these macros form a ring-buffer.
  18. ; The data to these queue's always looks like this:
  19. ;
  20. ; At top, you have the queue struct, wich has the size (number of currently queued packets, read and write pointers.
  21. ; This struct is followed by a number of slots wich you can read and write to using the macros.
  22. ; How these slots look like is up to you to chose, normally they should have at least a pointer to where the real data is.
  23. ; (you can see some examples below)
  24.  
  25.  
  26. struct  queue
  27.  
  28.         size            dd ?    ; number of queued packets in this queue
  29.         w_ptr           dd ?    ; current writing pointer in queue
  30.         r_ptr           dd ?    ; current reading pointer
  31.         mutex           MUTEX
  32.  
  33. ends
  34.  
  35. ; The following macros share these inputs:
  36.  
  37. ; ptr           = pointer to where the queue data is located
  38. ; size          = number of slots/entrys in the queue
  39. ; entry_size    = size of one slot, in bytes
  40. ; failaddr      = the address where macro will jump to when there is no data in the queue
  41.  
  42. ; additionally, add_to_queue requires you to set esi to the data wich you want to queue
  43. ; get_from_queue on the other hand will return a pointer in esi, to the entry you're interessed in
  44. ; PS: macros WILL destroy ecx and edi
  45.  
  46. macro add_to_queue ptr, size, entry_size, failaddr {
  47.  
  48. local .ok, .no_wrap
  49.  
  50.         pusha
  51.         lea     ecx, [ptr + queue.mutex]
  52.         call    mutex_lock
  53.         popa
  54.  
  55.         cmp     [ptr + queue.size], size        ; Check if queue isnt full
  56.         jb      .ok
  57.  
  58.         pusha
  59.         lea     ecx, [ptr + queue.mutex]
  60.         call    mutex_unlock
  61.         popa
  62.         jmp     failaddr
  63.  
  64.   .ok:
  65.         inc     [ptr + queue.size]              ; if not full, queue one more
  66.  
  67.         mov     edi, [ptr + queue.w_ptr]        ; Current write pointer (FIFO!)
  68.         mov     ecx, entry_size/4               ; Write the queue entry
  69.         rep movsd                               ;
  70.  
  71.         lea     ecx, [size*entry_size+ptr+sizeof.queue]
  72.         cmp     edi, ecx                        ; entry size
  73.         jb      .no_wrap
  74.  
  75.         sub     edi, size*entry_size
  76.   .no_wrap:
  77.         mov     [ptr + queue.w_ptr], edi
  78.  
  79.         pusha
  80.         lea     ecx, [ptr + queue.mutex]
  81.         call    mutex_unlock
  82.         popa
  83.  
  84. }
  85.  
  86.  
  87.  
  88. macro get_from_queue ptr, size, entry_size,  failaddr {
  89.  
  90. local .ok, .no_wrap
  91.  
  92.         pusha
  93.         lea     ecx, [ptr + queue.mutex]
  94.         call    mutex_lock
  95.         popa
  96.  
  97.         cmp     [ptr + queue.size], 0           ; any packets queued?
  98.         ja      .ok
  99.  
  100.         pusha
  101.         lea     ecx, [ptr + queue.mutex]
  102.         call    mutex_unlock
  103.         popa
  104.         jmp     failaddr
  105.  
  106.   .ok:
  107.         dec     [ptr + queue.size]              ; if so, dequeue one
  108.  
  109.         mov     esi, [ptr + queue.r_ptr]
  110.         push    esi
  111.  
  112.         add     esi, entry_size
  113.  
  114.         lea     ecx, [size*entry_size+ptr+sizeof.queue]
  115.         cmp     esi, ecx                        ; entry size
  116.         jb      .no_wrap
  117.  
  118.         sub     esi, size*entry_size
  119.  
  120.   .no_wrap:
  121.         mov     dword [ptr + queue.r_ptr], esi
  122.  
  123.         pop     esi
  124.  
  125.         pusha
  126.         lea     ecx, [ptr + queue.mutex]
  127.         call    mutex_unlock
  128.         popa
  129.  
  130. }
  131.  
  132. macro init_queue ptr {
  133.  
  134.         mov     [ptr + queue.size] , 0
  135.         lea     edi, [ptr + sizeof.queue]
  136.         mov     [ptr + queue.w_ptr], edi
  137.         mov     [ptr + queue.r_ptr], edi
  138.  
  139.         lea     ecx, [ptr + queue.mutex]
  140.         call    mutex_init
  141. }