227 lines
5.4 KiB
C
227 lines
5.4 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2019 Realtek Corporation.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
*****************************************************************************/
|
|
#include "phl_headers.h"
|
|
#define _PHL_UTIL_C_
|
|
|
|
|
|
/* phl queue general API */
|
|
void pq_init(void *d, struct phl_queue *q)
|
|
{
|
|
INIT_LIST_HEAD(&q->queue);
|
|
_os_spinlock_init(d, &q->lock);
|
|
q->cnt = 0;
|
|
}
|
|
|
|
void pq_deinit(void *d, struct phl_queue *q)
|
|
{
|
|
_os_spinlock_free(d, &q->lock);
|
|
}
|
|
|
|
void pq_reset(void *d, struct phl_queue *q, enum lock_type type)
|
|
{
|
|
_os_spinlockfg sp_flags;
|
|
|
|
_os_spinlock(d, &q->lock, type, &sp_flags);
|
|
INIT_LIST_HEAD(&q->queue);
|
|
q->cnt = 0;
|
|
_os_spinunlock(d, &q->lock, type, &sp_flags);
|
|
}
|
|
|
|
u8 pq_push(void *d, struct phl_queue *q, _os_list *obj, u8 pos, enum lock_type type)
|
|
{
|
|
_os_spinlockfg sp_flags;
|
|
|
|
_os_spinlock(d, &q->lock, type, &sp_flags);
|
|
if(pos == _first)
|
|
list_add(obj, &q->queue);
|
|
else
|
|
list_add_tail(obj, &q->queue);
|
|
q->cnt++;
|
|
_os_spinunlock(d, &q->lock, type, &sp_flags);
|
|
return true;
|
|
}
|
|
|
|
u8 pq_pop(void *d, struct phl_queue *q, _os_list **obj, u8 pos, enum lock_type type)
|
|
{
|
|
_os_spinlockfg sp_flags = 0;
|
|
|
|
(*obj) = NULL;
|
|
_os_spinlock(d, &q->lock, type, &sp_flags);
|
|
if(!list_empty(&q->queue) && (q->cnt > 0)) {
|
|
if(pos == _first)
|
|
(*obj) = _get_next(&q->queue);
|
|
else
|
|
(*obj) = _get_prev(&q->queue);
|
|
list_del(*obj);
|
|
q->cnt--;
|
|
}
|
|
_os_spinunlock(d, &q->lock, type, &sp_flags);
|
|
|
|
return ((*obj) == NULL || (*obj) == &q->queue) ? (false) : (true);
|
|
}
|
|
|
|
u8 pq_get_front(void *d, struct phl_queue *q, _os_list **obj, enum lock_type type)
|
|
{
|
|
_os_spinlockfg sp_flags = 0;
|
|
|
|
(*obj) = NULL;
|
|
|
|
_os_spinlock(d, &q->lock, type, &sp_flags);
|
|
if(!list_empty(&q->queue) && (q->cnt > 0))
|
|
(*obj) = q->queue.next;
|
|
_os_spinunlock(d, &q->lock, type, &sp_flags);
|
|
return ((*obj) == NULL || (*obj) == &q->queue) ? (false) : (true);
|
|
}
|
|
|
|
u8 pq_get_next(void *d, struct phl_queue *queue, _os_list *cur_obj,
|
|
_os_list **obj, enum lock_type type)
|
|
{
|
|
_os_spinlockfg sp_flags;
|
|
|
|
(*obj) = NULL;
|
|
if(cur_obj == NULL)
|
|
return false;
|
|
_os_spinlock(d, &queue->lock, type, &sp_flags);
|
|
(*obj) = cur_obj->next;
|
|
_os_spinunlock(d, &queue->lock, type, &sp_flags);
|
|
return ((*obj) == NULL || (*obj) == &(queue->queue)) ? (false) : (true);
|
|
}
|
|
|
|
u8 pq_get_tail(void *d, struct phl_queue *q, _os_list **obj, enum lock_type type)
|
|
{
|
|
_os_spinlockfg sp_flags = 0;
|
|
|
|
(*obj) = NULL;
|
|
|
|
_os_spinlock(d, &q->lock, type, &sp_flags);
|
|
if(!list_empty(&q->queue) && (q->cnt > 0))
|
|
(*obj) = q->queue.prev;
|
|
_os_spinunlock(d, &q->lock, type, &sp_flags);
|
|
return ((*obj) == NULL || (*obj) == &q->queue) ? (false) : (true);
|
|
}
|
|
|
|
u8 pq_get_prev(void *d, struct phl_queue *queue, _os_list *cur_obj,
|
|
_os_list **obj, enum lock_type type)
|
|
{
|
|
_os_spinlockfg sp_flags;
|
|
|
|
(*obj) = NULL;
|
|
if(cur_obj == NULL)
|
|
return false;
|
|
_os_spinlock(d, &queue->lock, type, &sp_flags);
|
|
(*obj) = cur_obj->prev;
|
|
_os_spinunlock(d, &queue->lock, type, &sp_flags);
|
|
return ((*obj) == NULL || (*obj) == &(queue->queue)) ? (false) : (true);
|
|
}
|
|
|
|
u8 pq_search_node(void *d, struct phl_queue *q, _os_list **obj,
|
|
enum lock_type type, bool bdel, void *priv,
|
|
u8 (*search_fun)(void *d, void *obj, void *priv))
|
|
{
|
|
_os_spinlockfg sp_flags = 0;
|
|
_os_list *newobj = NULL;
|
|
bool bhit = false;
|
|
|
|
(*obj) = NULL;
|
|
_os_spinlock(d, &q->lock, type, &sp_flags);
|
|
|
|
if(!list_empty(&q->queue) && (q->cnt > 0))
|
|
newobj = _get_next(&q->queue);
|
|
|
|
while(newobj && (newobj != &(q->queue))) {
|
|
|
|
if(search_fun)
|
|
bhit = search_fun(d, newobj, priv);
|
|
|
|
if(bhit && bdel) {
|
|
list_del(newobj);
|
|
q->cnt--;
|
|
}
|
|
|
|
if(bhit) {
|
|
(*obj) = newobj;
|
|
break;
|
|
}
|
|
|
|
newobj = newobj->next;
|
|
};
|
|
_os_spinunlock(d, &q->lock, type, &sp_flags);
|
|
|
|
return ((*obj) == NULL || (*obj) == &(q->queue)) ? (false) : (true);
|
|
}
|
|
|
|
void pq_del_node(void *d, struct phl_queue *q, _os_list *obj, enum lock_type type)
|
|
{
|
|
_os_spinlockfg sp_flags;
|
|
|
|
if(obj == NULL)
|
|
return;
|
|
_os_spinlock(d, &q->lock, type, &sp_flags);
|
|
list_del(obj);
|
|
q->cnt--;
|
|
_os_spinunlock(d, &q->lock, type, &sp_flags);
|
|
}
|
|
|
|
u8 pq_insert(void *d, struct phl_queue *q, enum lock_type type, void *priv, _os_list *input,
|
|
u8 (*pq_predicate)(void *d, void *priv,_os_list *input, _os_list *obj))
|
|
{
|
|
_os_spinlockfg sp_flags;
|
|
_os_list *obj = NULL;
|
|
|
|
_os_spinlock(d, &q->lock, type, &sp_flags);
|
|
obj = q->queue.next;
|
|
while (obj != &(q->queue)) {
|
|
if (pq_predicate && (pq_predicate(d, priv, input, obj) == true))
|
|
break;
|
|
obj = obj->next;
|
|
}
|
|
list_add_tail(input, obj);
|
|
q->cnt++;
|
|
_os_spinunlock(d, &q->lock, type, &sp_flags);
|
|
return true;
|
|
}
|
|
u32 phl_get_passing_time_us(u32 start)
|
|
{
|
|
u32 now = _os_get_cur_time_us();
|
|
u32 pass = 0;
|
|
|
|
if (now == start)
|
|
pass = 0;
|
|
else if (now > start)
|
|
/* -- start -- now -- */
|
|
pass = now - start;
|
|
else
|
|
/* -- now -- start -- */
|
|
pass = 0xffffffff - start + now;
|
|
|
|
return pass;
|
|
}
|
|
|
|
u32 phl_get_passing_time_ms(u32 start)
|
|
{
|
|
u32 now = _os_get_cur_time_ms();
|
|
u32 pass = 0;
|
|
|
|
if (now == start)
|
|
pass = 0;
|
|
else if (now > start)
|
|
/* -- start -- now -- */
|
|
pass = now - start;
|
|
else
|
|
/* -- now -- start -- */
|
|
pass = 0xffffffff - start + now;
|
|
|
|
return pass;
|
|
} |