Browse Source
GQUEUE as a seperate module GOS changes including basic Win32 O/S supportremotes/origin_old/ugfx_release_2.6
18 changed files with 1107 additions and 315 deletions
@ -0,0 +1,229 @@ |
|||
/*
|
|||
ChibiOS/GFX - Copyright (C) 2012, 2013 |
|||
Joel Bodenmann aka Tectu <joel@unormal.org> |
|||
|
|||
This file is part of ChibiOS/GFX. |
|||
|
|||
ChibiOS/GFX is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ChibiOS/GFX 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. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/**
|
|||
* @file include/gqueue/gqueue.h |
|||
* @brief GQUEUE header file. |
|||
* |
|||
* @addtogroup GQUEUE |
|||
* @brief GQUEUE provides queue management. There are 3 types of queues: |
|||
* <ul><li><b>Asynchronous Queues (ASync) </b> - Queue operations never block</li> |
|||
* <li><b>Get Synchronous Queues (GSync) </b> - Queue Get operations block until something is placed in the Queue</li> |
|||
* <li><b>Put Synchronous Queues (PSync)</b> - Queue Put operations block until the element is removed from the Queue</li> |
|||
* <li><b>Fully Synchronous Queues (FSync)</b> - Queue GET and Put operations block</li> |
|||
* </ul> |
|||
* We need 4 types of queues even though fully synchronous queues support all operations including asynchronous |
|||
* operations because fully synchronous queues have the highest storage requirements. The other queue types are |
|||
* optimizations. Efficiency IS important to use (particularly RAM efficiency). |
|||
* In practice we only implement ASync, GSync and FSync queues as PSync queues are of dubious value. |
|||
* @{ |
|||
*/ |
|||
|
|||
#ifndef _GQUEUE_H |
|||
#define _GQUEUE_H |
|||
|
|||
#if GFX_USE_GQUEUE || defined(__DOXYGEN__) |
|||
|
|||
/**
|
|||
* @brief A queue |
|||
* @{ |
|||
*/ |
|||
typedef struct gfxQueueASync { |
|||
struct gfxQueueASyncItem *head; |
|||
struct gfxQueueASyncItem *tail; |
|||
} gfxQueueAsync; |
|||
typedef struct gfxQueueGSync { |
|||
struct gfxQueueGSyncItem *head; |
|||
struct gfxQueueGSyncItem *tail; |
|||
gfxSem sem; |
|||
} gfxQueueGSync; |
|||
typedef struct gfxQueueFSync { |
|||
struct gfxQueueFSyncItem *head; |
|||
struct gfxQueueFSyncItem *tail; |
|||
gfxSem sem; |
|||
} gfxQueueGSync; |
|||
/* @} */ |
|||
|
|||
/**
|
|||
* @brief A queue item |
|||
* @{ |
|||
*/ |
|||
typedef struct gfxQueueASyncItem { |
|||
struct gfxQueueASyncItem *next; |
|||
} gfxQueueASyncItem; |
|||
typedef struct gfxQueueGSyncItem { |
|||
struct gfxQueueGSyncItem *next; |
|||
} gfxQueueGSyncItem; |
|||
typedef struct gfxQueueFSyncItem { |
|||
struct gfxQueueFSyncItem *next; |
|||
gfxSem sem; |
|||
} gfxQueueFSyncItem; |
|||
/* @} */ |
|||
|
|||
|
|||
/*===========================================================================*/ |
|||
/* Function declarations. */ |
|||
/*===========================================================================*/ |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
/**
|
|||
* @brief Initialise a queue. |
|||
* |
|||
* @param[in] pqueue A pointer to the queue |
|||
* |
|||
* @note Whilst queues are normally FIFO, a GFX queue also supports push and pop operations. |
|||
* A pop operation is the same as normal get from the queue but a push places the item |
|||
* at the head of the queue instead of the tail (as a put would). |
|||
* |
|||
* @api |
|||
* @{ |
|||
*/ |
|||
void gfxQueueASyncInit(gfxQueueASync *pqueue); |
|||
void gfxQueueGSyncInit(gfxQueueGSync *pqueue); |
|||
void gfxQueueFSyncInit(gfxQueueFSync *pqueue); |
|||
/* @} */ |
|||
|
|||
/**
|
|||
* @brief Get an item from the head of the queue. |
|||
* @return NULL if the timeout expires before an item is available |
|||
* |
|||
* @param[in] pqueue A pointer to the queue |
|||
* @param[in] ms The maxmimum time to wait for an item. For ASync queues this parameter is |
|||
* not specified as TIME_IMMEDIATE is assumed. |
|||
* |
|||
* @api |
|||
* @{ |
|||
*/ |
|||
gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue); |
|||
gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms); |
|||
gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms); |
|||
/* @} */ |
|||
|
|||
/**
|
|||
* @brief Put an item on the end of the queue. |
|||
* @return none for ASync and GSync queues; For FSync queues - FALSE on timeout, otherwise TRUE |
|||
* |
|||
* @param[in] pqueue A pointer to the queue |
|||
* @param[in] pitem A pointer to the queue item |
|||
* @param[in] ms The maxmimum time to wait for an item to be removed from the queue (only for FSync queues) |
|||
* |
|||
* @note FSync: Use a delay time of TIME_IMMEDIATE if you don't want to wait until the |
|||
* item is removed from the queue. Note that even if the timeout occurs - the item |
|||
* remains in the queue. |
|||
* |
|||
* @api |
|||
* @{ |
|||
*/ |
|||
void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); |
|||
void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); |
|||
bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms); |
|||
/* @} */ |
|||
|
|||
/**
|
|||
* @brief Pop an item from the head of the queue. |
|||
* @detail This is exactly the same as the Get operation above. |
|||
* |
|||
* @api |
|||
* @{ |
|||
*/ |
|||
#define gfxQueueASyncPop(pqueue) gfxQueueASyncGet(pqueue) |
|||
#define gfxQueueGSyncPop(pqueue, ms) gfxQueueGSyncGet(pqueue, ms) |
|||
#define gfxQueueFSyncPop(pqueue, ms) gfxQueueFSyncGet(pqueue, ms) |
|||
/* @} */ |
|||
|
|||
/**
|
|||
* @brief Push an item into the start of the queue. |
|||
* @return none for ASync and GSync queues; For FSync queues - FALSE on timeout, otherwise TRUE |
|||
* |
|||
* @param[in] pqueue A pointer to the queue |
|||
* @param[in] pitem A pointer to the queue item |
|||
* @param[in] ms The maxmimum time to wait for an item to be popped (only for FSync queues) |
|||
* |
|||
* @note FSync: Use a delay time of TIME_IMMEDIATE if you don't want to wait until the |
|||
* item is removed from the queue. Note that even if the timeout occurs - the item |
|||
* remains in the queue. |
|||
* |
|||
* @api |
|||
* @{ |
|||
*/ |
|||
void gfxQueueASyncPush(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); |
|||
void gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); |
|||
bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms); |
|||
/* @} */ |
|||
|
|||
/**
|
|||
* @brief Remove an item from the queue. |
|||
* @note Removes the specified item from the queue where-ever it is in the queue |
|||
* |
|||
* @param[in] pqueue A pointer to the queue |
|||
* @param[in] pitem A pointer to the queue item |
|||
* |
|||
* @note If the item isn't in the queue the routine just returns. |
|||
* @note If a process is waiting on the Put/Push operation for the item, that process |
|||
* will be signaled. |
|||
* |
|||
* @api |
|||
* @{ |
|||
*/ |
|||
void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); |
|||
void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); |
|||
void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem); |
|||
/* @} */ |
|||
|
|||
/**
|
|||
* @brief Is the queue empty? |
|||
* @return TRUE if the queue is empty |
|||
* |
|||
* @param[in] pqueue A pointer to the queue |
|||
* |
|||
* @api |
|||
* @{ |
|||
*/ |
|||
bool_t gfxQueueASyncIsEmpty(gfxQueueASync *pqueue); |
|||
bool_t gfxQueueGSyncIsEmpty(gfxQueueGSync *pqueue); |
|||
bool_t gfxQueueFSyncIsEmpty(gfxQueueFSync *pqueue); |
|||
/* @} */ |
|||
|
|||
/**
|
|||
* @brief Is an item in the queue? |
|||
* @return TRUE if the item is in the queue? |
|||
* |
|||
* @param[in] pqueue A pointer to the queue |
|||
* @param[in] pitem A pointer to the queue item |
|||
* |
|||
* @note This operation may be expensive. |
|||
* |
|||
* @api |
|||
* @{ |
|||
*/ |
|||
bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); |
|||
bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); |
|||
bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem); |
|||
/* @} */ |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif /* GFX_USE_GQUEUE */ |
|||
#endif /* _GQUEUE_H */ |
|||
/** @} */ |
@ -0,0 +1,66 @@ |
|||
/*
|
|||
ChibiOS/GFX - Copyright (C) 2012, 2013 |
|||
Joel Bodenmann aka Tectu <joel@unormal.org> |
|||
|
|||
This file is part of ChibiOS/GFX. |
|||
|
|||
ChibiOS/GFX is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ChibiOS/GFX 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. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
/**
|
|||
* @file include/gqueue/options.h |
|||
* @brief GQUEUE - Queue options header file. |
|||
* |
|||
* @addtogroup GQUEUE |
|||
* @{ |
|||
*/ |
|||
|
|||
#ifndef _GQUEUE_OPTIONS_H |
|||
#define _GQUEUE_OPTIONS_H |
|||
|
|||
/**
|
|||
* @name GQUEUE Functions to include. |
|||
* @{ |
|||
*/ |
|||
/**
|
|||
* @brief Enable Asynchronous Queues |
|||
* @details Defaults to FALSE |
|||
*/ |
|||
#ifndef GQUEUE_NEED_ASYNC |
|||
#define GQUEUE_NEED_ASYNC FALSE |
|||
#endif |
|||
/**
|
|||
* @brief Enable Get-Synchronous Queues |
|||
* @details Defaults to FALSE |
|||
*/ |
|||
#ifndef GQUEUE_NEED_GSYNC |
|||
#define GQUEUE_NEED_GSYNC FALSE |
|||
#endif |
|||
/**
|
|||
* @brief Enable Fully Synchronous Queues |
|||
* @details Defaults to FALSE |
|||
*/ |
|||
#ifndef GQUEUE_NEED_FSYNC |
|||
#define GQUEUE_NEED_FSYNC FALSE |
|||
#endif |
|||
/**
|
|||
* @} |
|||
* |
|||
* @name GQUEUE Optional Sizing Parameters |
|||
* @{ |
|||
*/ |
|||
/** @} */ |
|||
|
|||
#endif /* _GQUEUE_OPTIONS_H */ |
|||
/** @} */ |
@ -0,0 +1,255 @@ |
|||
/*
|
|||
ChibiOS/GFX - Copyright (C) 2012, 2013 |
|||
Joel Bodenmann aka Tectu <joel@unormal.org> |
|||
|
|||
This file is part of ChibiOS/GFX. |
|||
|
|||
ChibiOS/GFX is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ChibiOS/GFX 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. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/**
|
|||
* @file src/gqueue/gqueue.c |
|||
* @brief GQUEUE source file. |
|||
*/ |
|||
#if GFX_USE_GQUEUE |
|||
|
|||
#if GQUEUE_NEED_ASYNC |
|||
void gfxQueueASyncInit(gfxQueueASync *pqueue) { |
|||
pqueue->head = pqueue->tail = 0; |
|||
} |
|||
gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue) { |
|||
gfxQueueASyncItem *pi; |
|||
|
|||
if (!pqueue->head) return 0; |
|||
gfxSystemLock(); |
|||
if ((pi = pqueue->head)) |
|||
pqueue->head = pi->next; |
|||
gfxSytemUnlock(); |
|||
return pi; |
|||
} |
|||
void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { |
|||
pitem->next = 0; |
|||
|
|||
gfxSystemLock(); |
|||
if (!pqueue->head) { |
|||
pqueue->head = pqueue->tail = pitem; |
|||
} else { |
|||
pqueue->tail->next = pitem; |
|||
pqueue->tail = pitem; |
|||
} |
|||
gfxSystemUnlock(); |
|||
} |
|||
void gfxQueueASyncPush(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { |
|||
gfxSystemLock(); |
|||
pitem->next = pqueue->head; |
|||
pqueue->head = pitem; |
|||
if (!pitem->next) |
|||
pqueue->tail = pitem; |
|||
gfxSystemUnlock(); |
|||
} |
|||
void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { |
|||
if (!pitem) return; |
|||
gfxSystemLock(); |
|||
if (pqueue->head) { |
|||
if (pqueue->head == pitem) { |
|||
pqueue->head = pitem->next; |
|||
} else { |
|||
for(gfxQueueASyncItem *pi = pqueue->head; pi->next; pi = pi->next) { |
|||
if (pi->next == pitem) { |
|||
pi->next = pitem->next; |
|||
if (pqueue->tail == pitem) |
|||
pqueue->tail = pi; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
gfxSystemUnlock(); |
|||
} |
|||
bool_t gfxQueueASyncIsEmpty(gfxQueueASync *pqueue) { |
|||
return pqueue->head == NULL; |
|||
} |
|||
bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { |
|||
gfxSystemLock(); |
|||
for(gfxQueueASyncItem *pi = pqueue->head; pi; pi = pi->next) { |
|||
if (pi == pitem) { |
|||
gfxSystemUnlock(); |
|||
return TRUE; |
|||
} |
|||
} |
|||
gfxSystemUnlock(); |
|||
return FALSE; |
|||
} |
|||
#endif |
|||
|
|||
#if GQUEUE_NEED_GSYNC |
|||
void gfxQueueGSyncInit(gfxQueueGSync *pqueue) { |
|||
pqueue->head = pqueue->tail = 0; |
|||
gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT); |
|||
} |
|||
gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms) { |
|||
gfxQueueGSyncItem *pi; |
|||
|
|||
if (!gfxSemWait(&pqueue->sem, ms)) return 0; |
|||
gfxSystemLock(); |
|||
pi = pqueue->head; |
|||
pqueue->head = pi->next; |
|||
gfxSytemUnlock(); |
|||
return pi; |
|||
} |
|||
void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { |
|||
pitem->next = 0; |
|||
|
|||
gfxSystemLock(); |
|||
if (!pqueue->head) { |
|||
pqueue->head = pqueue->tail = pitem; |
|||
} else { |
|||
pqueue->tail->next = pitem; |
|||
pqueue->tail = pitem; |
|||
} |
|||
gfxSystemUnlock(); |
|||
|
|||
gfxSemSignal(&pqueue->sem); |
|||
} |
|||
void gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { |
|||
gfxSystemLock(); |
|||
pitem->next = pqueue->head; |
|||
pqueue->head = pitem; |
|||
if (!pitem->next) |
|||
pqueue->tail = pitem; |
|||
gfxSystemUnlock(); |
|||
|
|||
gfxSemSignal(&pqueue->sem); |
|||
} |
|||
void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { |
|||
if (!pitem) return; |
|||
gfxSystemLock(); |
|||
if (pqueue->head) { |
|||
if (pqueue->head == pitem) { |
|||
pqueue->head = pitem->next; |
|||
} else { |
|||
for(gfxQueueGSyncItem *pi = pqueue->head; pi->next; pi = pi->next) { |
|||
if (pi->next == pitem) { |
|||
pi->next = pitem->next; |
|||
if (pqueue->tail == pitem) |
|||
pqueue->tail = pi; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
gfxSystemUnlock(); |
|||
} |
|||
bool_t gfxQueueGSyncIsEmpty(gfxQueueGSync *pqueue) { |
|||
return pqueue->head == NULL; |
|||
} |
|||
bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { |
|||
gfxSystemLock(); |
|||
for(gfxQueueGSyncItem *pi = pqueue->head; pi; pi = pi->next) { |
|||
if (pi == pitem) { |
|||
gfxSystemUnlock(); |
|||
return TRUE; |
|||
} |
|||
} |
|||
gfxSystemUnlock(); |
|||
return FALSE; |
|||
} |
|||
#endif |
|||
|
|||
#if GQUEUE_NEED_FSYNC |
|||
void gfxQueueFSyncInit(gfxQueueFSync *pqueue) { |
|||
pqueue->head = pqueue->tail = 0; |
|||
gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT); |
|||
} |
|||
gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms) { |
|||
gfxQueueFSyncItem *pi; |
|||
|
|||
if (!gfxSemWait(&pqueue->sem, ms)) return 0; |
|||
gfxSystemLock(); |
|||
pi = pqueue->head; |
|||
pqueue->head = pi->next; |
|||
gfxSytemUnlock(); |
|||
|
|||
gfxSemSignalI(&pi->sem); |
|||
gfxSemDestroy(&pi->sem); |
|||
return pi; |
|||
} |
|||
bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) { |
|||
gfxSemInit(&pitem->sem, 0, 1); |
|||
pitem->next = 0; |
|||
|
|||
gfxSystemLock(); |
|||
if (!pqueue->head) { |
|||
pqueue->head = pqueue->tail = pitem; |
|||
} else { |
|||
pqueue->tail->next = pitem; |
|||
pqueue->tail = pitem; |
|||
} |
|||
gfxSystemUnlock(); |
|||
|
|||
gfxSemSignal(&pqueue->sem); |
|||
return gfxSemWait(&pitem->sem, ms); |
|||
} |
|||
bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) { |
|||
gfxSemInit(&pitem->sem, 0, 1); |
|||
|
|||
gfxSystemLock(); |
|||
pitem->next = pqueue->head; |
|||
pqueue->head = pitem; |
|||
if (!pitem->next) |
|||