Subversion Repositories Kolibri OS

Rev

Rev 3555 | Rev 5201 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3555 Serge 3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
3555 Serge 6
;;  queue.inc                                                   ;;
431 serge 7
;;                                                              ;;
3555 Serge 8
;;    Written by hidnplayr@kolibrios.org                        ;;
431 serge 9
;;                                                              ;;
3555 Serge 10
;;          GNU GENERAL PUBLIC LICENSE                          ;;
11
;;             Version 2, June 1991                             ;;
431 serge 12
;;                                                              ;;
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1 ha 14
 
593 mikedld 15
$Revision: 3725 $
1 ha 16
 
3555 Serge 17
; The Queues implemented by these macros form a ring-buffer.
18
; The data to these queue's always looks like this:
1 ha 19
;
3555 Serge 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)
1 ha 24
 
25
 
3725 Serge 26
struct  queue
1 ha 27
 
3725 Serge 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
1 ha 32
 
3555 Serge 33
ends
1 ha 34
 
3555 Serge 35
; The following macros share these inputs:
1 ha 36
 
3555 Serge 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
1 ha 41
 
3555 Serge 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
1 ha 45
 
3555 Serge 46
macro add_to_queue ptr, size, entry_size, failaddr {
1 ha 47
 
3725 Serge 48
local .ok, .no_wrap
1 ha 49
 
3725 Serge 50
        pusha
51
        lea     ecx, [ptr + queue.mutex]
52
        call    mutex_lock
53
        popa
1 ha 54
 
3725 Serge 55
        cmp     [ptr + queue.size], size        ; Check if queue isnt full
56
        jb      .ok
1 ha 57
 
3725 Serge 58
        pusha
59
        lea     ecx, [ptr + queue.mutex]
60
        call    mutex_unlock
61
        popa
62
        jmp     failaddr
1 ha 63
 
3725 Serge 64
  .ok:
65
        inc     [ptr + queue.size]              ; if not full, queue one more
1 ha 66
 
3725 Serge 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
3555 Serge 76
  .no_wrap:
3725 Serge 77
        mov     [ptr + queue.w_ptr], edi
1 ha 78
 
3725 Serge 79
        pusha
80
        lea     ecx, [ptr + queue.mutex]
81
        call    mutex_unlock
82
        popa
83
 
3555 Serge 84
}
1 ha 85
 
86
 
87
 
3555 Serge 88
macro get_from_queue ptr, size, entry_size,  failaddr {
1 ha 89
 
3725 Serge 90
local .ok, .no_wrap
1 ha 91
 
3725 Serge 92
        pusha
93
        lea     ecx, [ptr + queue.mutex]
94
        call    mutex_lock
95
        popa
1 ha 96
 
3725 Serge 97
        cmp     [ptr + queue.size], 0           ; any packets queued?
98
        ja      .ok
1 ha 99
 
3725 Serge 100
        pusha
101
        lea     ecx, [ptr + queue.mutex]
102
        call    mutex_unlock
103
        popa
104
        jmp     failaddr
1 ha 105
 
3725 Serge 106
  .ok:
107
        dec     [ptr + queue.size]              ; if so, dequeue one
1 ha 108
 
3725 Serge 109
        mov     esi, [ptr + queue.r_ptr]
110
        push    esi
1 ha 111
 
3725 Serge 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
 
3555 Serge 120
  .no_wrap:
3725 Serge 121
        mov     dword [ptr + queue.r_ptr], esi
1 ha 122
 
3725 Serge 123
        pop     esi
1 ha 124
 
3725 Serge 125
        pusha
126
        lea     ecx, [ptr + queue.mutex]
127
        call    mutex_unlock
128
        popa
129
 
3555 Serge 130
}
1 ha 131
 
3555 Serge 132
macro init_queue ptr {
1 ha 133
 
3725 Serge 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
3555 Serge 141
}