2014-01-08 05:03:52 +01:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; ;;
|
|
|
|
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
|
|
|
|
;; Distributed under terms of the GNU General Public License ;;
|
|
|
|
;; ;;
|
|
|
|
;; queue.inc ;;
|
|
|
|
;; ;;
|
|
|
|
;; Written by hidnplayr@kolibrios.org ;;
|
|
|
|
;; ;;
|
|
|
|
;; GNU GENERAL PUBLIC LICENSE ;;
|
|
|
|
;; Version 2, June 1991 ;;
|
|
|
|
;; ;;
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
2014-09-12 21:16:32 +02:00
|
|
|
$Revision: 4850 $
|
2014-01-08 05:03:52 +01:00
|
|
|
|
|
|
|
; The Queues implemented by these macros form a ring-buffer.
|
|
|
|
; The data to these queue's always looks like this:
|
|
|
|
;
|
|
|
|
; At top, you have the queue struct, wich has the size (number of currently queued packets, read and write pointers.
|
|
|
|
; This struct is followed by a number of slots wich you can read and write to using the macros.
|
|
|
|
; 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.
|
|
|
|
; (you can see some examples below)
|
|
|
|
|
|
|
|
|
|
|
|
struct queue
|
|
|
|
|
|
|
|
size dd ? ; number of queued packets in this queue
|
|
|
|
w_ptr dd ? ; current writing pointer in queue
|
|
|
|
r_ptr dd ? ; current reading pointer
|
|
|
|
|
|
|
|
ends
|
|
|
|
|
|
|
|
; The following macros share these inputs:
|
|
|
|
|
|
|
|
; ptr = pointer to where the queue data is located
|
|
|
|
; size = number of slots/entrys in the queue
|
|
|
|
; entry_size = size of one slot, in bytes
|
|
|
|
; failaddr = the address where macro will jump to when there is no data in the queue
|
|
|
|
|
|
|
|
; additionally, add_to_queue requires you to set esi to the data wich you want to queue
|
|
|
|
; get_from_queue on the other hand will return a pointer in esi, to the entry you're interessed in
|
|
|
|
; PS: macros WILL destroy ecx and edi
|
|
|
|
|
|
|
|
macro add_to_queue ptr, size, entry_size, failaddr {
|
|
|
|
|
|
|
|
local .ok, .no_wrap
|
|
|
|
|
2014-02-22 12:39:11 +01:00
|
|
|
spin_lock_irqsave
|
2014-01-08 05:03:52 +01:00
|
|
|
|
|
|
|
cmp [ptr + queue.size], size ; Check if queue isnt full
|
|
|
|
jb .ok
|
|
|
|
|
2014-02-22 12:39:11 +01:00
|
|
|
spin_unlock_irqrestore
|
2014-01-08 05:03:52 +01:00
|
|
|
jmp failaddr
|
|
|
|
|
|
|
|
.ok:
|
|
|
|
inc [ptr + queue.size] ; if not full, queue one more
|
|
|
|
|
|
|
|
mov edi, [ptr + queue.w_ptr] ; Current write pointer (FIFO!)
|
|
|
|
mov ecx, entry_size/4 ; Write the queue entry
|
|
|
|
rep movsd ;
|
|
|
|
|
|
|
|
lea ecx, [size*entry_size+ptr+sizeof.queue]
|
|
|
|
cmp edi, ecx ; entry size
|
|
|
|
jb .no_wrap
|
|
|
|
|
|
|
|
sub edi, size*entry_size
|
|
|
|
.no_wrap:
|
|
|
|
mov [ptr + queue.w_ptr], edi
|
|
|
|
|
2014-02-22 12:39:11 +01:00
|
|
|
spin_unlock_irqrestore
|
2014-01-08 05:03:52 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
macro get_from_queue ptr, size, entry_size, failaddr {
|
|
|
|
|
|
|
|
local .ok, .no_wrap
|
|
|
|
|
2014-02-22 12:39:11 +01:00
|
|
|
spin_lock_irqsave
|
2014-01-08 05:03:52 +01:00
|
|
|
|
|
|
|
cmp [ptr + queue.size], 0 ; any packets queued?
|
|
|
|
ja .ok
|
|
|
|
|
2014-02-22 12:39:11 +01:00
|
|
|
spin_unlock_irqrestore
|
2014-01-08 05:03:52 +01:00
|
|
|
jmp failaddr
|
|
|
|
|
|
|
|
.ok:
|
|
|
|
dec [ptr + queue.size] ; if so, dequeue one
|
|
|
|
|
|
|
|
mov esi, [ptr + queue.r_ptr]
|
|
|
|
push esi
|
|
|
|
|
|
|
|
add esi, entry_size
|
|
|
|
|
|
|
|
lea ecx, [size*entry_size+ptr+sizeof.queue]
|
|
|
|
cmp esi, ecx ; entry size
|
|
|
|
jb .no_wrap
|
|
|
|
|
|
|
|
sub esi, size*entry_size
|
|
|
|
|
|
|
|
.no_wrap:
|
|
|
|
mov dword [ptr + queue.r_ptr], esi
|
|
|
|
|
|
|
|
pop esi
|
|
|
|
|
2014-02-22 12:39:11 +01:00
|
|
|
spin_unlock_irqrestore
|
2014-01-08 05:03:52 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
macro init_queue ptr {
|
|
|
|
|
|
|
|
mov [ptr + queue.size] , 0
|
|
|
|
lea edi, [ptr + sizeof.queue]
|
|
|
|
mov [ptr + queue.w_ptr], edi
|
|
|
|
mov [ptr + queue.r_ptr], edi
|
|
|
|
|
|
|
|
}
|