git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11722 110e8d01-0319-4d1e-a829-52ad28d1bb01

This commit is contained in:
Giovanni Di Sirio 2018-03-13 09:49:55 +00:00
parent 4492ac9c2d
commit bb88c52342
15 changed files with 0 additions and 4543 deletions

View File

@ -1,311 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chbsem.h
* @brief Binary semaphores structures and macros.
*
* @addtogroup binary_semaphores
* @details Binary semaphores related APIs and services.
* <h2>Operation mode</h2>
* Binary semaphores are implemented as a set of inline functions
* that use the existing counting semaphores primitives. The
* difference between counting and binary semaphores is that the
* counter of binary semaphores is not allowed to grow above the
* value 1. Repeated signal operation are ignored. A binary
* semaphore can thus have only two defined states:
* - <b>Taken</b>, when its counter has a value of zero or lower
* than zero. A negative number represent the number of threads
* queued on the binary semaphore.
* - <b>Not taken</b>, when its counter has a value of one.
* .
* Binary semaphores are different from mutexes because there is no
* concept of ownership, a binary semaphore can be taken by a
* thread and signaled by another thread or an interrupt handler,
* mutexes can only be taken and released by the same thread. Another
* difference is that binary semaphores, unlike mutexes, do not
* implement the priority inheritance protocol.<br>
* In order to use the binary semaphores APIs the
* @p CH_CFG_USE_SEMAPHORES option must be enabled in @p chconf.h.
* @{
*/
#ifndef CHBSEM_H
#define CHBSEM_H
#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/**
* @extends semaphore_t
*
* @brief Binary semaphore type.
*/
typedef struct ch_binary_semaphore {
semaphore_t sem;
} binary_semaphore_t;
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/**
* @brief Data part of a static semaphore initializer.
* @details This macro should be used when statically initializing a semaphore
* that is part of a bigger structure.
*
* @param[in] name the name of the semaphore variable
* @param[in] taken the semaphore initial state
*/
#define _BSEMAPHORE_DATA(name, taken) \
{_SEMAPHORE_DATA(name.sem, ((taken) ? 0 : 1))}
/**
* @brief Static semaphore initializer.
* @details Statically initialized semaphores require no explicit
* initialization using @p chBSemInit().
*
* @param[in] name the name of the semaphore variable
* @param[in] taken the semaphore initial state
*/
#define BSEMAPHORE_DECL(name, taken) \
binary_semaphore_t name = _BSEMAPHORE_DATA(name, taken)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @brief Initializes a binary semaphore.
*
* @param[out] bsp pointer to a @p binary_semaphore_t structure
* @param[in] taken initial state of the binary semaphore:
* - @a false, the initial state is not taken.
* - @a true, the initial state is taken.
* .
*
* @init
*/
static inline void chBSemObjectInit(binary_semaphore_t *bsp, bool taken) {
chSemObjectInit(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1);
}
/**
* @brief Wait operation on the binary semaphore.
*
* @param[in] bsp pointer to a @p binary_semaphore_t structure
* @return A message specifying how the invoking thread has been
* released from the semaphore.
* @retval MSG_OK if the binary semaphore has been successfully taken.
* @retval MSG_RESET if the binary semaphore has been reset using
* @p bsemReset().
*
* @api
*/
static inline msg_t chBSemWait(binary_semaphore_t *bsp) {
return chSemWait(&bsp->sem);
}
/**
* @brief Wait operation on the binary semaphore.
*
* @param[in] bsp pointer to a @p binary_semaphore_t structure
* @return A message specifying how the invoking thread has been
* released from the semaphore.
* @retval MSG_OK if the binary semaphore has been successfully taken.
* @retval MSG_RESET if the binary semaphore has been reset using
* @p bsemReset().
*
* @sclass
*/
static inline msg_t chBSemWaitS(binary_semaphore_t *bsp) {
chDbgCheckClassS();
return chSemWaitS(&bsp->sem);
}
/**
* @brief Wait operation on the binary semaphore.
*
* @param[in] bsp pointer to a @p binary_semaphore_t structure
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return A message specifying how the invoking thread has been
* released from the semaphore.
* @retval MSG_OK if the binary semaphore has been successfully taken.
* @retval MSG_RESET if the binary semaphore has been reset using
* @p bsemReset().
* @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset
* within the specified timeout.
*
* @sclass
*/
static inline msg_t chBSemWaitTimeoutS(binary_semaphore_t *bsp,
sysinterval_t timeout) {
chDbgCheckClassS();
return chSemWaitTimeoutS(&bsp->sem, timeout);
}
/**
* @brief Wait operation on the binary semaphore.
*
* @param[in] bsp pointer to a @p binary_semaphore_t structure
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return A message specifying how the invoking thread has been
* released from the semaphore.
* @retval MSG_OK if the binary semaphore has been successfully taken.
* @retval MSG_RESET if the binary semaphore has been reset using
* @p bsemReset().
* @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset
* within the specified timeout.
*
* @api
*/
static inline msg_t chBSemWaitTimeout(binary_semaphore_t *bsp,
sysinterval_t timeout) {
return chSemWaitTimeout(&bsp->sem, timeout);
}
/**
* @brief Reset operation on the binary semaphore.
* @note The released threads can recognize they were waked up by a reset
* rather than a signal because the @p bsemWait() will return
* @p MSG_RESET instead of @p MSG_OK.
* @note This function does not reschedule.
*
* @param[in] bsp pointer to a @p binary_semaphore_t structure
* @param[in] taken new state of the binary semaphore
* - @a false, the new state is not taken.
* - @a true, the new state is taken.
* .
*
* @iclass
*/
static inline void chBSemResetI(binary_semaphore_t *bsp, bool taken) {
chDbgCheckClassI();
chSemResetI(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1);
}
/**
* @brief Reset operation on the binary semaphore.
* @note The released threads can recognize they were waked up by a reset
* rather than a signal because the @p bsemWait() will return
* @p MSG_RESET instead of @p MSG_OK.
*
* @param[in] bsp pointer to a @p binary_semaphore_t structure
* @param[in] taken new state of the binary semaphore
* - @a false, the new state is not taken.
* - @a true, the new state is taken.
* .
*
* @api
*/
static inline void chBSemReset(binary_semaphore_t *bsp, bool taken) {
chSemReset(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1);
}
/**
* @brief Performs a signal operation on a binary semaphore.
* @note This function does not reschedule.
*
* @param[in] bsp pointer to a @p binary_semaphore_t structure
*
* @iclass
*/
static inline void chBSemSignalI(binary_semaphore_t *bsp) {
chDbgCheckClassI();
if (bsp->sem.cnt < (cnt_t)1) {
chSemSignalI(&bsp->sem);
}
}
/**
* @brief Performs a signal operation on a binary semaphore.
*
* @param[in] bsp pointer to a @p binary_semaphore_t structure
*
* @api
*/
static inline void chBSemSignal(binary_semaphore_t *bsp) {
chSysLock();
chBSemSignalI(bsp);
chSchRescheduleS();
chSysUnlock();
}
/**
* @brief Returns the binary semaphore current state.
*
* @param[in] bsp pointer to a @p binary_semaphore_t structure
* @return The binary semaphore current state.
* @retval false if the binary semaphore is not taken.
* @retval true if the binary semaphore is taken.
*
* @iclass
*/
static inline bool chBSemGetStateI(binary_semaphore_t *bsp) {
chDbgCheckClassI();
return (bsp->sem.cnt > (cnt_t)0) ? false : true;
}
#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
#endif /* CHBSEM_H */
/** @} */

View File

@ -1,486 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chfactory.h
* @brief ChibiOS objects factory structures and macros.
*
* @addtogroup objects_factory
* @{
*/
#ifndef CHFACTORY_H
#define CHFACTORY_H
#if !defined(CH_CFG_USE_FACTORY)
#define CH_CFG_USE_FACTORY FALSE
#endif
#if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Maximum length for object names.
* @details If the specified length is zero then the name is stored by
* pointer but this could have unintended side effects.
*/
#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) || defined(__DOXYGEN__)
#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
#endif
/**
* @brief Enables the registry of generic objects.
*/
#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) || defined(__DOXYGEN__)
#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
#endif
/**
* @brief Enables factory for generic buffers.
*/
#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) || defined(__DOXYGEN__)
#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
#endif
/**
* @brief Enables factory for semaphores.
*/
#if !defined(CH_CFG_FACTORY_SEMAPHORES) || defined(__DOXYGEN__)
#define CH_CFG_FACTORY_SEMAPHORES TRUE
#endif
/**
* @brief Enables factory for mailboxes.
*/
#if !defined(CH_CFG_FACTORY_MAILBOXES) || defined(__DOXYGEN__)
#define CH_CFG_FACTORY_MAILBOXES TRUE
#endif
/**
* @brief Enables factory for objects FIFOs.
*/
#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) || defined(__DOXYGEN__)
#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) && (CH_CFG_USE_SEMAPHORES == FALSE)
/*lint -save -e767 [20.5] Valid because the #undef.*/
#undef CH_CFG_FACTORY_SEMAPHORES
#define CH_CFG_FACTORY_SEMAPHORES FALSE
/*lint restore*/
#endif
#if (CH_CFG_FACTORY_MAILBOXES == TRUE) && (CH_CFG_USE_MAILBOXES == FALSE)
/*lint -save -e767 [20.5] Valid because the #undef.*/
#undef CH_CFG_FACTORY_MAILBOXES
#define CH_CFG_FACTORY_MAILBOXES FALSE
/*lint restore*/
#endif
#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) && (CH_CFG_USE_OBJ_FIFOS == FALSE)
/*lint -save -e767 [20.5] Valid because the #undef.*/
#undef CH_CFG_FACTORY_OBJ_FIFOS
#define CH_CFG_FACTORY_OBJ_FIFOS FALSE
/*lint restore*/
#endif
#define CH_FACTORY_REQUIRES_POOLS \
((CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || \
(CH_CFG_FACTORY_SEMAPHORES == TRUE))
#define CH_FACTORY_REQUIRES_HEAP \
((CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || \
(CH_CFG_FACTORY_MAILBOXES == TRUE) || \
(CH_CFG_FACTORY_OBJ_FIFOS == TRUE))
#if (CH_CFG_FACTORY_MAX_NAMES_LENGTH < 0) || \
(CH_CFG_FACTORY_MAX_NAMES_LENGTH > 32)
#error "invalid CH_CFG_FACTORY_MAX_NAMES_LENGTH value"
#endif
#if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE)
#error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES"
#endif
#if CH_CFG_USE_MEMCORE == FALSE
#error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MEMCORE"
#endif
#if CH_FACTORY_REQUIRES_POOLS && (CH_CFG_USE_MEMPOOLS == FALSE)
#error "CH_CFG_USE_MEMPOOLS is required"
#endif
#if CH_FACTORY_REQUIRES_HEAP && (CH_CFG_USE_HEAP == FALSE)
#error "CH_CFG_USE_HEAP is required"
#endif
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/**
* @brief Type of a dynamic object list element.
*/
typedef struct ch_dyn_element {
/**
* @brief Next dynamic object in the list.
*/
struct ch_dyn_element *next;
/**
* @brief Number of references to this object.
*/
ucnt_t refs;
#if (CH_CFG_FACTORY_MAX_NAMES_LENGTH > 0) || defined(__DOXYGEN__)
char name[CH_CFG_FACTORY_MAX_NAMES_LENGTH];
#else
const char *name;
#endif
} dyn_element_t;
/**
* @brief Type of a dynamic object list.
*/
typedef struct ch_dyn_list {
dyn_element_t *next;
} dyn_list_t;
#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__)
/**
* @brief Type of a registered object.
*/
typedef struct ch_registered_static_object {
/**
* @brief List element of the registered object.
*/
dyn_element_t element;
/**
* @brief Pointer to the object.
* @note The type of the object is not stored in anyway.
*/
void *objp;
} registered_object_t;
#endif
#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__)
/**
* @brief Type of a dynamic buffer object.
*/
typedef struct ch_dyn_object {
/**
* @brief List element of the dynamic buffer object.
*/
dyn_element_t element;
/*lint -save -e9038 [18.7] Required by design.*/
/**
* @brief The buffer.
* @note This requires C99.
*/
uint8_t buffer[];
/*lint restore*/
} dyn_buffer_t;
#endif
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
* @brief Type of a dynamic semaphore.
*/
typedef struct ch_dyn_semaphore {
/**
* @brief List element of the dynamic semaphore.
*/
dyn_element_t element;
/**
* @brief The semaphore.
*/
semaphore_t sem;
} dyn_semaphore_t;
#endif
#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__)
/**
* @brief Type of a dynamic buffer object.
*/
typedef struct ch_dyn_mailbox {
/**
* @brief List element of the dynamic buffer object.
*/
dyn_element_t element;
/**
* @brief The mailbox.
*/
mailbox_t mbx;
/*lint -save -e9038 [18.7] Required by design.*/
/**
* @brief Messages buffer.
* @note This requires C99.
*/
msg_t msgbuf[];
/*lint restore*/
} dyn_mailbox_t;
#endif
#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
/**
* @brief Type of a dynamic buffer object.
*/
typedef struct ch_dyn_objects_fifo {
/**
* @brief List element of the dynamic buffer object.
*/
dyn_element_t element;
/**
* @brief The objects FIFO.
*/
objects_fifo_t fifo;
/*lint -save -e9038 [18.7] Required by design.*/
/**
* @brief Messages buffer.
* @note This open array is followed by another area containing the
* objects, this area is not represented in this structure.
* @note This requires C99.
*/
msg_t msgbuf[];
/*lint restore*/
} dyn_objects_fifo_t;
#endif
/**
* @brief Type of the factory main object.
*/
typedef struct ch_objects_factory {
/**
* @brief Factory access mutex or semaphore.
*/
#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
mutex_t mtx;
#else
semaphore_t sem;
#endif
/**
* @brief List of the registered objects.
*/
dyn_list_t obj_list;
/**
* @brief Pool of the available registered objects.
*/
memory_pool_t obj_pool;
#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__)
/**
* @brief List of the allocated buffer objects.
*/
dyn_list_t buf_list;
#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS = TRUE */
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
* @brief List of the allocated semaphores.
*/
dyn_list_t sem_list;
/**
* @brief Pool of the available semaphores.
*/
memory_pool_t sem_pool;
#endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */
#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__)
/**
* @brief List of the allocated buffer objects.
*/
dyn_list_t mbx_list;
#endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */
#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
/**
* @brief List of the allocated "objects FIFO" objects.
*/
dyn_list_t fifo_list;
#endif /* CH_CFG_FACTORY_OBJ_FIFOS = TRUE */
} objects_factory_t;
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if !defined(__DOXYGEN__)
extern objects_factory_t ch_factory;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void _factory_init(void);
#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__)
registered_object_t *chFactoryRegisterObject(const char *name,
void *objp);
registered_object_t *chFactoryFindObject(const char *name);
registered_object_t *chFactoryFindObjectByPointer(void *objp);
void chFactoryReleaseObject(registered_object_t *rop);
#endif
#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__)
dyn_buffer_t *chFactoryCreateBuffer(const char *name, size_t size);
dyn_buffer_t *chFactoryFindBuffer(const char *name);
void chFactoryReleaseBuffer(dyn_buffer_t *dbp);
#endif
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n);
dyn_semaphore_t *chFactoryFindSemaphore(const char *name);
void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp);
#endif
#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__)
dyn_mailbox_t *chFactoryCreateMailbox(const char *name, size_t n);
dyn_mailbox_t *chFactoryFindMailbox(const char *name);
void chFactoryReleaseMailbox(dyn_mailbox_t *dmp);
#endif
#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
dyn_objects_fifo_t *chFactoryCreateObjectsFIFO(const char *name,
size_t objsize,
size_t objn,
unsigned objalign);
dyn_objects_fifo_t *chFactoryFindObjectsFIFO(const char *name);
void chFactoryReleaseObjectsFIFO(dyn_objects_fifo_t *dofp);
#endif
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @brief Duplicates an object reference.
* @note This function can be used on any kind of dynamic object.
*
* @param[in] dep pointer to the element field of the object
* @return The duplicated object reference.
*
* @api
*/
static inline dyn_element_t *chFactoryDuplicateReference(dyn_element_t *dep) {
dep->refs++;
return dep;
}
#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__)
/**
* @brief Returns the pointer to the inner registered object.
*
* @param[in] rop registered object reference
* @return The pointer to the registered object.
*
* @api
*/
static inline void *chFactoryGetObject(registered_object_t *rop) {
return rop->objp;
}
#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */
#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__)
/**
* @brief Returns the size of a generic dynamic buffer object.
*
* @param[in] dbp dynamic buffer object reference
* @return The size of the buffer object in bytes.
*
* @api
*/
static inline size_t chFactoryGetBufferSize(dyn_buffer_t *dbp) {
return chHeapGetSize(dbp) - sizeof (dyn_element_t);
}
/**
* @brief Returns the pointer to the inner buffer.
*
* @param[in] dbp dynamic buffer object reference
* @return The pointer to the dynamic buffer.
*
* @api
*/
static inline uint8_t *chFactoryGetBuffer(dyn_buffer_t *dbp) {
return dbp->buffer;
}
#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE */
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
* @brief Returns the pointer to the inner semaphore.
*
* @param[in] dsp dynamic semaphore object reference
* @return The pointer to the semaphore.
*
* @api
*/
static inline semaphore_t *chFactoryGetSemaphore(dyn_semaphore_t *dsp) {
return &dsp->sem;
}
#endif /* CH_CFG_FACTORY_SEMAPHORES == TRUE */
#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__)
/**
* @brief Returns the pointer to the inner mailbox.
*
* @param[in] dmp dynamic mailbox object reference
* @return The pointer to the mailbox.
*
* @api
*/
static inline mailbox_t *chFactoryGetMailbox(dyn_mailbox_t *dmp) {
return &dmp->mbx;
}
#endif /* CH_CFG_FACTORY_MAILBOXES == TRUE */
#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
/**
* @brief Returns the pointer to the inner objects FIFO.
*
* @param[in] dofp dynamic "objects FIFO" object reference
* @return The pointer to the objects FIFO.
*
* @api
*/
static inline objects_fifo_t *chFactoryGetObjectsFIFO(dyn_objects_fifo_t *dofp) {
return &dofp->fifo;
}
#endif /* CH_CFG_FACTORY_OBJ_FIFOS == TRUE */
#endif /* CH_CFG_USE_FACTORY == TRUE */
#endif /* CHFACTORY_H */
/** @} */

View File

@ -1,342 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chfifo.h
* @brief Objects FIFO structures and macros.
* @details This module implements a generic FIFO queue of objects by
* coupling a Guarded Memory Pool (for objects storage) and
* a MailBox.<br>
* On the sender side free objects are taken from the pool, filled
* and then sent to the receiver, on the receiver side objects are
* fetched, used and then returned to the pool.
* Operations defined for object FIFOs:
* - <b>Take</b>: An object is taken from the pool of the free
* objects, can be blocking.
* - <b>Return</b>: An object is returned to the pool of the
* free objects, it is guaranteed to be non-blocking.
* - <b>Send</b>: An object is sent through the mailbox, it is
* guaranteed to be non-blocking
* - <b>Receive</b>: An object is received from the mailbox,
* can be blocking.
* .
*
* @addtogroup objects_fifo
* @{
*/
#ifndef CHFIFO_H
#define CHFIFO_H
#if !defined(CH_CFG_USE_OBJ_FIFOS)
#define CH_CFG_USE_OBJ_FIFOS TRUE
#endif
#if (CH_CFG_USE_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if CH_CFG_USE_MEMPOOLS == FALSE
#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_MEMPOOLS"
#endif
#if CH_CFG_USE_SEMAPHORES == FALSE
#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_SEMAPHORES"
#endif
#if CH_CFG_USE_MAILBOXES == FALSE
#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_MAILBOXES"
#endif
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/**
* @brief Type of an objects FIFO.
*/
typedef struct ch_objects_fifo {
/**
* @brief Pool of the free objects.
*/
guarded_memory_pool_t free;
/**
* @brief Mailbox of the sent objects.
*/
mailbox_t mbx;
} objects_fifo_t;
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @brief Initializes a FIFO object.
* @pre The messages size must be a multiple of the alignment
* requirement.
*
* @param[out] ofp pointer to a @p objects_fifo_t structure
* @param[in] objsize size of objects
* @param[in] objn number of objects available
* @param[in] objalign required objects alignment
* @param[in] objbuf pointer to the buffer of objects, it must be able
* to hold @p objn objects of @p objsize size with
* @p objealign alignment
* @param[in] msgbuf pointer to the buffer of messages, it must be able
* to hold @p objn messages
*
* @init
*/
static inline void chFifoObjectInit(objects_fifo_t *ofp, size_t objsize,
size_t objn, unsigned objalign,
void *objbuf, msg_t *msgbuf) {
chGuardedPoolObjectInitAligned(&ofp->free, objsize, objalign);
chGuardedPoolLoadArray(&ofp->free, objbuf, objn);
chMBObjectInit(&ofp->mbx, msgbuf, objn);
}
/**
* @brief Allocates a free object.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @return The pointer to the allocated object.
* @retval NULL if an object is not immediately available.
*
* @iclass
*/
static inline void *chFifoTakeObjectI(objects_fifo_t *ofp) {
return chGuardedPoolAllocI(&ofp->free);
}
/**
* @brief Allocates a free object.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The pointer to the allocated object.
* @retval NULL if an object is not available within the specified
* timeout.
*
* @sclass
*/
static inline void *chFifoTakeObjectTimeoutS(objects_fifo_t *ofp,
sysinterval_t timeout) {
return chGuardedPoolAllocTimeoutS(&ofp->free, timeout);
}
/**
* @brief Allocates a free object.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The pointer to the allocated object.
* @retval NULL if an object is not available within the specified
* timeout.
*
* @api
*/
static inline void *chFifoTakeObjectTimeout(objects_fifo_t *ofp,
sysinterval_t timeout) {
return chGuardedPoolAllocTimeout(&ofp->free, timeout);
}
/**
* @brief Releases a fetched object.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @param[in] objp pointer to the object to be released
*
* @iclass
*/
static inline void chFifoReturnObjectI(objects_fifo_t *ofp,
void *objp) {
chGuardedPoolFreeI(&ofp->free, objp);
}
/**
* @brief Releases a fetched object.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @param[in] objp pointer to the object to be released
*
* @api
*/
static inline void chFifoReturnObject(objects_fifo_t *ofp,
void *objp) {
chGuardedPoolFree(&ofp->free, objp);
}
/**
* @brief Posts an object.
* @note By design the object can be always immediately posted.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @param[in] objp pointer to the object to be posted
*
* @iclass
*/
static inline void chFifoSendObjectI(objects_fifo_t *ofp,
void *objp) {
msg_t msg;
msg = chMBPostI(&ofp->mbx, (msg_t)objp);
chDbgAssert(msg == MSG_OK, "post failed");
}
/**
* @brief Posts an object.
* @note By design the object can be always immediately posted.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @param[in] objp pointer to the object to be posted
*
* @sclass
*/
static inline void chFifoSendObjectS(objects_fifo_t *ofp,
void *objp) {
msg_t msg;
msg = chMBPostTimeoutS(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE);
chDbgAssert(msg == MSG_OK, "post failed");
}
/**
* @brief Posts an object.
* @note By design the object can be always immediately posted.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @param[in] objp pointer to the object to be released
*
* @api
*/
static inline void chFifoSendObject(objects_fifo_t *ofp, void *objp) {
msg_t msg;
msg = chMBPostTimeout(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE);
chDbgAssert(msg == MSG_OK, "post failed");
}
/**
* @brief Fetches an object.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @param[in] objpp pointer to the fetched object reference
* @return The operation status.
* @retval MSG_OK if an object has been correctly fetched.
* @retval MSG_TIMEOUT if the FIFO is empty and a message cannot be fetched.
*
* @iclass
*/
static inline msg_t chFifoReceiveObjectI(objects_fifo_t *ofp,
void **objpp) {
return chMBFetchI(&ofp->mbx, (msg_t *)objpp);
}
/**
* @brief Fetches an object.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @param[in] objpp pointer to the fetched object reference
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval MSG_OK if an object has been correctly fetched.
* @retval MSG_TIMEOUT if the operation has timed out.
*
* @sclass
*/
static inline msg_t chFifoReceiveObjectTimeoutS(objects_fifo_t *ofp,
void **objpp,
sysinterval_t timeout) {
return chMBFetchTimeoutS(&ofp->mbx, (msg_t *)objpp, timeout);
}
/**
* @brief Fetches an object.
*
* @param[in] ofp pointer to a @p objects_fifo_t structure
* @param[in] objpp pointer to the fetched object reference
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval MSG_OK if an object has been correctly fetched.
* @retval MSG_TIMEOUT if the operation has timed out.
*
* @api
*/
static inline msg_t chFifoReceiveObjectTimeout(objects_fifo_t *ofp,
void **objpp,
sysinterval_t timeout) {
return chMBFetchTimeout(&ofp->mbx, (msg_t *)objpp, timeout);
}
#endif /* CH_CFG_USE_OBJ_FIFOS == TRUE */
#endif /* CHFIFO_H */
/** @} */

View File

@ -1,182 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chheap.h
* @brief Heaps macros and structures.
*
* @addtogroup heaps
* @{
*/
#ifndef CHHEAP_H
#define CHHEAP_H
#if !defined(CH_CFG_USE_HEAP)
#define CH_CFG_USE_HEAP FALSE
#endif
#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/**
* @brief Minimum alignment used for heap.
* @note Cannot use the sizeof operator in this macro.
*/
#if (SIZEOF_PTR == 4) || defined(__DOXYGEN__)
#define CH_HEAP_ALIGNMENT 8U
#elif (SIZEOF_PTR == 2)
#define CH_HEAP_ALIGNMENT 4U
#else
#error "unsupported pointer size"
#endif
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if CH_CFG_USE_MEMCORE == FALSE
#error "CH_CFG_USE_HEAP requires CH_CFG_USE_MEMCORE"
#endif
#if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE)
#error "CH_CFG_USE_HEAP requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES"
#endif
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/**
* @brief Type of a memory heap.
*/
typedef struct memory_heap memory_heap_t;
/**
* @brief Type of a memory heap header.
*/
typedef union heap_header heap_header_t;
/**
* @brief Memory heap block header.
*/
union heap_header {
struct {
heap_header_t *next; /**< @brief Next block in free list. */
size_t pages; /**< @brief Size of the area in pages. */
} free;
struct {
memory_heap_t *heap; /**< @brief Block owner heap. */
size_t size; /**< @brief Size of the area in bytes. */
} used;
};
/**
* @brief Structure describing a memory heap.
*/
struct memory_heap {
memgetfunc2_t provider; /**< @brief Memory blocks provider for
this heap. */
heap_header_t header; /**< @brief Free blocks list header. */
#if CH_CFG_USE_MUTEXES == TRUE
mutex_t mtx; /**< @brief Heap access mutex. */
#else
semaphore_t sem; /**< @brief Heap access semaphore. */
#endif
};
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/**
* @brief Allocation of an aligned static heap buffer.
*/
#define CH_HEAP_AREA(name, size) \
ALIGNED_VAR(CH_HEAP_ALIGNMENT) \
uint8_t name[MEM_ALIGN_NEXT((size), CH_HEAP_ALIGNMENT)]
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void _heap_init(void);
void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size);
void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align);
void chHeapFree(void *p);
size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp);
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @brief Allocates a block of memory from the heap by using the first-fit
* algorithm.
* @details The allocated block is guaranteed to be properly aligned for a
* pointer data type.
*
* @param[in] heapp pointer to a heap descriptor or @p NULL in order to
* access the default heap.
* @param[in] size the size of the block to be allocated. Note that the
* allocated block may be a bit bigger than the requested
* size for alignment and fragmentation reasons.
* @return A pointer to the allocated block.
* @retval NULL if the block cannot be allocated.
*
* @api
*/
static inline void *chHeapAlloc(memory_heap_t *heapp, size_t size) {
return chHeapAllocAligned(heapp, size, CH_HEAP_ALIGNMENT);
}
/**
* @brief Returns the size of an allocated block.
* @note The returned value is the requested size, the real size is the
* same value aligned to the next @p CH_HEAP_ALIGNMENT multiple.
*
* @param[in] p pointer to the memory block
* @return Size of the block.
*
* @api
*/
static inline size_t chHeapGetSize(const void *p) {
return ((heap_header_t *)p - 1U)->used.size;
}
#endif /* CH_CFG_USE_HEAP == TRUE */
#endif /* CHHEAP_H */
/** @} */

View File

@ -1,184 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chlib.h
* @brief ChibiOS/LIB main include file.
* @details This header includes all the required library headers. This file
* is meant do be included by @p ch.h not directly by user.
*
* @addtogroup library_info
* @details OS Library related info.
* @{
*/
#ifndef CHLIB_H
#define CHLIB_H
/* Tmeporary hack.*/
#if !defined(_CHIBIOS_RT_CONF_VER_5_0_) && !defined(_CHIBIOS_NIL_CONF_VER_3_0_)
#include "chlibconf.h"
#else
#define _CHIBIOS_LIB_CONF_
#define _CHIBIOS_LIB_CONF_VER_1_0_
#endif
#include "chlicense.h"
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/**
* @brief ChibiOS/LIB identification macro.
*/
#define _CHIBIOS_LIB_
/**
* @brief Stable release flag.
*/
#define CH_OSLIB_STABLE 0
/**
* @name ChibiOS/LIB version identification
* @{
*/
/**
* @brief OS Library version string.
*/
#define CH_OSLIB_VERSION "1.0.0"
/**
* @brief Kernel version major number.
*/
#define CH_OSLIB_MAJOR 1
/**
* @brief Kernel version minor number.
*/
#define CH_OSLIB_MINOR 0
/**
* @brief Kernel version patch number.
*/
#define CH_OSLIB_PATCH 0
/** @} */
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/* Host OS checks.*/
#if !defined(_CHIBIOS_RT_) && !defined(_CHIBIOS_NIL_)
#error "OS check failed, must be included after ch.h"
#endif
/* Configuration file checks.*/
#if !defined(_CHIBIOS_LIB_CONF_)
#error "invalid configuration file"
#endif
#if !defined(_CHIBIOS_LIB_CONF_VER_1_0_)
#error "obsolete or unknown configuration file"
#endif
#if !defined(CH_CFG_USE_SEMAPHORES)
#error "CH_CFG_USE_SEMAPHORES not defined in chconf.h"
#endif
#if !defined(CH_CFG_USE_MAILBOXES)
#error "CH_CFG_USE_MAILBOXES not defined in chlibconf.h"
#endif
#if !defined(CH_CFG_USE_MEMCORE)
#error "CH_CFG_USE_MEMCORE not defined in chlibconf.h"
#endif
#if !defined(CH_CFG_USE_HEAP)
#error "CH_CFG_USE_HEAP not defined in chlibconf.h"
#endif
#if !defined(CH_CFG_USE_MEMPOOLS)
#error "CH_CFG_USE_MEMPOOLS not defined in chlibconf.h"
#endif
#if !defined(CH_CFG_USE_OBJ_FIFOS)
#error "CH_CFG_USE_OBJ_FIFOS not defined in chlibconf.h"
#endif
/* Objects factory options checks.*/
#if !defined(CH_CFG_USE_FACTORY)
#error "CH_CFG_USE_FACTORY not defined in chlibconf.h"
#endif
#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
#error "CH_CFG_FACTORY_MAX_NAMES_LENGTH not defined in chlibconf.h"
#endif
#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
#error "CH_CFG_FACTORY_OBJECTS_REGISTRY not defined in chlibconf.h"
#endif
#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
#error "CH_CFG_FACTORY_GENERIC_BUFFERS not defined in chlibconf.h"
#endif
#if !defined(CH_CFG_FACTORY_SEMAPHORES)
#error "CH_CFG_FACTORY_SEMAPHORES not defined in chlibconf.h"
#endif
#if !defined(CH_CFG_FACTORY_MAILBOXES)
#error "CH_CFG_FACTORY_MAILBOXES not defined in chlibconf.h"
#endif
#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
#error "CH_CFG_FACTORY_OBJ_FIFOS not defined in chlibconf.h"
#endif
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/*===========================================================================*/
/* Late inclusions. */
/*===========================================================================*/
/* OS Library headers.*/
#include "chbsem.h"
#include "chmboxes.h"
#include "chmemcore.h"
#include "chheap.h"
#include "chmempools.h"
#include "chfifo.h"
#include "chfactory.h"
#endif /* CHLIB_H */
/** @} */

View File

@ -1,214 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chmboxes.h
* @brief Mailboxes macros and structures.
*
* @addtogroup mailboxes
* @{
*/
#ifndef CHMBOXES_H
#define CHMBOXES_H
#if !defined(CH_CFG_USE_MAILBOXES)
#define CH_CFG_USE_MAILBOXES FALSE
#endif
#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/**
* @brief Structure representing a mailbox object.
*/
typedef struct {
msg_t *buffer; /**< @brief Pointer to the mailbox
buffer. */
msg_t *top; /**< @brief Pointer to the location
after the buffer. */
msg_t *wrptr; /**< @brief Write pointer. */
msg_t *rdptr; /**< @brief Read pointer. */
size_t cnt; /**< @brief Messages in queue. */
bool reset; /**< @brief True in reset state. */
threads_queue_t qw; /**< @brief Queued writers. */
threads_queue_t qr; /**< @brief Queued readers. */
} mailbox_t;
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/**
* @brief Data part of a static mailbox initializer.
* @details This macro should be used when statically initializing a
* mailbox that is part of a bigger structure.
*
* @param[in] name the name of the mailbox variable
* @param[in] buffer pointer to the mailbox buffer array of @p msg_t
* @param[in] size number of @p msg_t elements in the buffer array
*/
#define _MAILBOX_DATA(name, buffer, size) { \
(msg_t *)(buffer), \
(msg_t *)(buffer) + size, \
(msg_t *)(buffer), \
(msg_t *)(buffer), \
(size_t)0, \
false, \
_THREADS_QUEUE_DATA(name.qw), \
_THREADS_QUEUE_DATA(name.qr), \
}
/**
* @brief Static mailbox initializer.
* @details Statically initialized mailboxes require no explicit
* initialization using @p chMBObjectInit().
*
* @param[in] name the name of the mailbox variable
* @param[in] buffer pointer to the mailbox buffer array of @p msg_t
* @param[in] size number of @p msg_t elements in the buffer array
*/
#define MAILBOX_DECL(name, buffer, size) \
mailbox_t name = _MAILBOX_DATA(name, buffer, size)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n);
void chMBReset(mailbox_t *mbp);
void chMBResetI(mailbox_t *mbp);
msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout);
msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout);
msg_t chMBPostI(mailbox_t *mbp, msg_t msg);
msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout);
msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout);
msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg);
msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout);
msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout);
msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp);
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @brief Returns the mailbox buffer size as number of messages.
*
* @param[in] mbp the pointer to an initialized mailbox_t object
* @return The size of the mailbox.
*
* @iclass
*/
static inline size_t chMBGetSizeI(const mailbox_t *mbp) {
/*lint -save -e9033 [10.8] Perfectly safe pointers
arithmetic.*/
return (size_t)(mbp->top - mbp->buffer);
/*lint -restore*/
}
/**
* @brief Returns the number of used message slots into a mailbox.
*
* @param[in] mbp the pointer to an initialized mailbox_t object
* @return The number of queued messages.
* @retval QUEUE_RESET if the queue is in reset state.
*
* @iclass
*/
static inline size_t chMBGetUsedCountI(const mailbox_t *mbp) {
chDbgCheckClassI();
return mbp->cnt;
}
/**
* @brief Returns the number of free message slots into a mailbox.
*
* @param[in] mbp the pointer to an initialized mailbox_t object
* @return The number of empty message slots.
*
* @iclass
*/
static inline size_t chMBGetFreeCountI(const mailbox_t *mbp) {
chDbgCheckClassI();
return chMBGetSizeI(mbp) - chMBGetUsedCountI(mbp);
}
/**
* @brief Returns the next message in the queue without removing it.
* @pre A message must be waiting in the queue for this function to work
* or it would return garbage. The correct way to use this macro is
* to use @p chMBGetFullCountI() and then use this macro, all within
* a lock state.
*
* @param[in] mbp the pointer to an initialized mailbox_t object
* @return The next message in queue.
*
* @iclass
*/
static inline msg_t chMBPeekI(const mailbox_t *mbp) {
chDbgCheckClassI();
return *mbp->rdptr;
}
/**
* @brief Terminates the reset state.
*
* @param[in] mbp the pointer to an initialized mailbox_t object
*
* @xclass
*/
static inline void chMBResumeX(mailbox_t *mbp) {
mbp->reset = false;
}
#endif /* CH_CFG_USE_MAILBOXES == TRUE */
#endif /* CHMBOXES_H */
/** @} */

View File

@ -1,202 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chmemcore.h
* @brief Core memory manager macros and structures.
*
* @addtogroup memcore
* @{
*/
#ifndef CHMEMCORE_H
#define CHMEMCORE_H
#if !defined(CH_CFG_USE_MEMCORE)
#define CH_CFG_USE_MEMCORE FALSE
#endif
#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Managed RAM size.
* @details Size of the RAM area to be managed by the OS. If set to zero
* then the whole available RAM is used. The core memory is made
* available to the heap allocator and/or can be used directly through
* the simplified core memory allocator.
*
* @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
* @note Requires @p CH_CFG_USE_MEMCORE.
*/
#if !defined(CH_CFG_MEMCORE_SIZE) || defined(__DOXYGEN__)
#define CH_CFG_MEMCORE_SIZE 0
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if CH_CFG_MEMCORE_SIZE < 0
#error "invalid CH_CFG_MEMCORE_SIZE value specified"
#endif
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/**
* @brief Memory get function.
*/
typedef void *(*memgetfunc_t)(size_t size, unsigned align);
/**
* @brief Enhanced memory get function.
*/
typedef void *(*memgetfunc2_t)(size_t size, unsigned align, size_t offset);
/**
* @brief Type of memory core object.
*/
typedef struct {
/**
* @brief Next free address.
*/
uint8_t *nextmem;
/**
* @brief Final address.
*/
uint8_t *endmem;
} memcore_t;
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if !defined(__DOXYGEN__)
extern memcore_t ch_memcore;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void _core_init(void);
void *chCoreAllocAlignedWithOffsetI(size_t size,
unsigned align,
size_t offset);
void *chCoreAllocAlignedWithOffset(size_t size,
unsigned align,
size_t offset);
size_t chCoreGetStatusX(void);
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @brief Allocates a memory block.
* @details The allocated block is guaranteed to be properly aligned to the
* specified alignment.
*
* @param[in] size the size of the block to be allocated.
* @param[in] align desired memory alignment
* @return A pointer to the allocated memory block.
* @retval NULL allocation failed, core memory exhausted.
*
* @iclass
*/
static inline void *chCoreAllocAlignedI(size_t size, unsigned align) {
return chCoreAllocAlignedWithOffsetI(size, align, 0U);
}
/**
* @brief Allocates a memory block.
* @details The allocated block is guaranteed to be properly aligned to the
* specified alignment.
*
* @param[in] size the size of the block to be allocated
* @param[in] align desired memory alignment
* @return A pointer to the allocated memory block.
* @retval NULL allocation failed, core memory exhausted.
*
* @api
*/
static inline void *chCoreAllocAligned(size_t size, unsigned align) {
void *p;
chSysLock();
p = chCoreAllocAlignedWithOffsetI(size, align, 0U);
chSysUnlock();
return p;
}
/**
* @brief Allocates a memory block.
* @details The allocated block is guaranteed to be properly aligned for a
* pointer data type.
*
* @param[in] size the size of the block to be allocated.
* @return A pointer to the allocated memory block.
* @retval NULL allocation failed, core memory exhausted.
*
* @iclass
*/
static inline void *chCoreAllocI(size_t size) {
return chCoreAllocAlignedWithOffsetI(size, PORT_NATURAL_ALIGN, 0U);
}
/**
* @brief Allocates a memory block.
* @details The allocated block is guaranteed to be properly aligned for a
* pointer data type.
*
* @param[in] size the size of the block to be allocated.
* @return A pointer to the allocated memory block.
* @retval NULL allocation failed, core memory exhausted.
*
* @api
*/
static inline void *chCoreAlloc(size_t size) {
return chCoreAllocAlignedWithOffset(size, PORT_NATURAL_ALIGN, 0U);
}
#endif /* CH_CFG_USE_MEMCORE == TRUE */
#endif /* CHMEMCORE_H */
/** @} */

View File

@ -1,323 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chmempools.h
* @brief Memory Pools macros and structures.
*
* @addtogroup pools
* @{
*/
#ifndef CHMEMPOOLS_H
#define CHMEMPOOLS_H
#if !defined(CH_CFG_USE_MEMPOOLS)
#define CH_CFG_USE_MEMPOOLS FALSE
#endif
#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if CH_CFG_USE_MEMCORE == FALSE
#error "CH_CFG_USE_MEMPOOLS requires CH_CFG_USE_MEMCORE"
#endif
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/**
* @brief Memory pool free object header.
*/
struct pool_header {
struct pool_header *next; /**< @brief Pointer to the next pool
header in the list. */
};
/**
* @brief Memory pool descriptor.
*/
typedef struct {
struct pool_header *next; /**< @brief Pointer to the header. */
size_t object_size; /**< @brief Memory pool objects
size. */
unsigned align; /**< @brief Required alignment. */
memgetfunc_t provider; /**< @brief Memory blocks provider
for this pool. */
} memory_pool_t;
#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
* @brief Guarded memory pool descriptor.
*/
typedef struct {
semaphore_t sem; /**< @brief Counter semaphore guarding
the memory pool. */
memory_pool_t pool; /**< @brief The memory pool itself. */
} guarded_memory_pool_t;
#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/**
* @brief Data part of a static memory pool initializer.
* @details This macro should be used when statically initializing a
* memory pool that is part of a bigger structure.
*
* @param[in] name the name of the memory pool variable
* @param[in] size size of the memory pool contained objects
* @param[in] align required memory alignment
* @param[in] provider memory provider function for the memory pool
*/
#define _MEMORYPOOL_DATA(name, size, align, provider) \
{NULL, size, align, provider}
/**
* @brief Static memory pool initializer.
* @details Statically initialized memory pools require no explicit
* initialization using @p chPoolInit().
*
* @param[in] name the name of the memory pool variable
* @param[in] size size of the memory pool contained objects
* @param[in] align required memory alignment
* @param[in] provider memory provider function for the memory pool or @p NULL
* if the pool is not allowed to grow automatically
*/
#define MEMORYPOOL_DECL(name, size, align, provider) \
memory_pool_t name = _MEMORYPOOL_DATA(name, size, align, provider)
#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
* @brief Data part of a static guarded memory pool initializer.
* @details This macro should be used when statically initializing a
* memory pool that is part of a bigger structure.
*
* @param[in] name the name of the memory pool variable
* @param[in] size size of the memory pool contained objects
* @param[in] align required memory alignment
*/
#define _GUARDEDMEMORYPOOL_DATA(name, size, align) { \
_SEMAPHORE_DATA(name.sem, (cnt_t)0), \
_MEMORYPOOL_DATA(NULL, size, align, NULL) \
}
/**
* @brief Static guarded memory pool initializer.
* @details Statically initialized guarded memory pools require no explicit
* initialization using @p chGuardedPoolInit().
*
* @param[in] name the name of the guarded memory pool variable
* @param[in] size size of the memory pool contained objects
* @param[in] align required memory alignment
*/
#define GUARDEDMEMORYPOOL_DECL(name, size, align) \
guarded_memory_pool_t name = _GUARDEDMEMORYPOOL_DATA(name, size, align)
#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void chPoolObjectInitAligned(memory_pool_t *mp, size_t size,
unsigned align, memgetfunc_t provider);
void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n);
void *chPoolAllocI(memory_pool_t *mp);
void *chPoolAlloc(memory_pool_t *mp);
void chPoolFreeI(memory_pool_t *mp, void *objp);
void chPoolFree(memory_pool_t *mp, void *objp);
#if CH_CFG_USE_SEMAPHORES == TRUE
void chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp,
size_t size,
unsigned align);
void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n);
void *chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp,
sysinterval_t timeout);
void *chGuardedPoolAllocTimeout(guarded_memory_pool_t *gmp,
sysinterval_t timeout);
void chGuardedPoolFreeI(guarded_memory_pool_t *gmp, void *objp);
void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp);
#endif
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @brief Initializes an empty memory pool.
*
* @param[out] mp pointer to a @p memory_pool_t structure
* @param[in] size the size of the objects contained in this memory pool,
* the minimum accepted size is the size of a pointer to
* void.
* @param[in] provider memory provider function for the memory pool or
* @p NULL if the pool is not allowed to grow
* automatically
*
* @init
*/
static inline void chPoolObjectInit(memory_pool_t *mp,
size_t size,
memgetfunc_t provider) {
chPoolObjectInitAligned(mp, size, PORT_NATURAL_ALIGN, provider);
}
/**
* @brief Adds an object to a memory pool.
* @pre The memory pool must be already been initialized.
* @pre The added object must be of the right size for the specified
* memory pool.
* @pre The added object must be memory aligned to the size of
* @p stkalign_t type.
* @note This function is just an alias for @p chPoolFree() and has been
* added for clarity.
*
* @param[in] mp pointer to a @p memory_pool_t structure
* @param[in] objp the pointer to the object to be added
*
* @api
*/
static inline void chPoolAdd(memory_pool_t *mp, void *objp) {
chPoolFree(mp, objp);
}
/**
* @brief Adds an object to a memory pool.
* @pre The memory pool must be already been initialized.
* @pre The added object must be of the right size for the specified
* memory pool.
* @pre The added object must be memory aligned to the size of
* @p stkalign_t type.
* @note This function is just an alias for @p chPoolFreeI() and has been
* added for clarity.
*
* @param[in] mp pointer to a @p memory_pool_t structure
* @param[in] objp the pointer to the object to be added
*
* @iclass
*/
static inline void chPoolAddI(memory_pool_t *mp, void *objp) {
chPoolFreeI(mp, objp);
}
#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
* @brief Initializes an empty guarded memory pool.
*
* @param[out] gmp pointer to a @p guarded_memory_pool_t structure
* @param[in] size the size of the objects contained in this guarded
* memory pool, the minimum accepted size is the size
* of a pointer to void.
*
* @init
*/
static inline void chGuardedPoolObjectInit(guarded_memory_pool_t *gmp,
size_t size) {
chGuardedPoolObjectInitAligned(gmp, size, PORT_NATURAL_ALIGN);
}
/**
* @brief Adds an object to a guarded memory pool.
* @pre The guarded memory pool must be already been initialized.
* @pre The added object must be of the right size for the specified
* guarded memory pool.
* @pre The added object must be properly aligned.
* @note This function is just an alias for @p chGuardedPoolFree() and
* has been added for clarity.
*
* @param[in] gmp pointer to a @p guarded_memory_pool_t structure
* @param[in] objp the pointer to the object to be added
*
* @api
*/
static inline void chGuardedPoolAdd(guarded_memory_pool_t *gmp, void *objp) {
chGuardedPoolFree(gmp, objp);
}
/**
* @brief Adds an object to a guarded memory pool.
* @pre The guarded memory pool must be already been initialized.
* @pre The added object must be of the right size for the specified
* guarded memory pool.
* @pre The added object must be properly aligned.
* @note This function is just an alias for @p chGuardedPoolFreeI() and
* has been added for clarity.
*
* @param[in] gmp pointer to a @p guarded_memory_pool_t structure
* @param[in] objp the pointer to the object to be added
*
* @iclass
*/
static inline void chGuardedPoolAddI(guarded_memory_pool_t *gmp, void *objp) {
chGuardedPoolFreeI(gmp, objp);
}
/**
* @brief Allocates an object from a guarded memory pool.
* @pre The guarded memory pool must be already been initialized.
*
* @param[in] gmp pointer to a @p guarded_memory_pool_t structure
* @return The pointer to the allocated object.
* @retval NULL if the pool is empty.
*
* @iclass
*/
static inline void *chGuardedPoolAllocI(guarded_memory_pool_t *gmp) {
void *p;
p = chPoolAllocI(&gmp->pool);
if (p != NULL) {
chSemFastWaitI(&gmp->sem);
chDbgAssert(chSemGetCounterI(&gmp->sem) >= (cnt_t)0,
"semaphore out of sync");
}
return p;
}
#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
#endif /* CH_CFG_USE_MEMPOOLS == TRUE */
#endif /* CHMEMPOOLS_H */
/** @} */

View File

@ -1,3 +0,0 @@
All the code contained under ./os/common/oslib are optional RTOS modules
compatible with both RT and NIL. The code is placed under ./os/common in
order to prevent code duplication and disalignments.

View File

@ -1,725 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chfactory.c
* @brief ChibiOS objects factory and registry code.
*
* @addtogroup objects_factory
* @details The object factory is a subsystem that allows to:
* - Register static objects by name.
* - Dynamically create objects and assign them a name.
* - Retrieve existing objects by name.
* - Free objects by reference.
* .
* Allocated OS objects are handled using a reference counter, only
* when all references have been released then the object memory is
* freed in a pool.<br>
* @pre This subsystem requires the @p CH_CFG_USE_MEMCORE and
* @p CH_CFG_USE_MEMPOOLS options to be set to @p TRUE. The
* option @p CH_CFG_USE_HEAP is also required if the support
* for variable length objects is enabled.
* @note Compatible with RT and NIL.
* @{
*/
#include <string.h>
#include "ch.h"
#if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module local definitions. */
/*===========================================================================*/
/*
* Defaults on the best synchronization mechanism available.
*/
#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
#define F_LOCK() chMtxLock(&ch_factory.mtx)
#define F_UNLOCK() chMtxUnlock(&ch_factory.mtx)
#else
#define F_LOCK() (void) chSemWait(&ch_factory.sem)
#define F_UNLOCK() chSemSignal(&ch_factory.sem)
#endif
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/**
* @brief Factory object static instance.
* @note It is a global object because it could be accessed through
* a specific debugger plugin.
*/
objects_factory_t ch_factory;
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
static inline void dyn_list_init(dyn_list_t *dlp) {
dlp->next = (dyn_element_t *)dlp;
}
static dyn_element_t *dyn_list_find(const char *name, dyn_list_t *dlp) {
dyn_element_t *p = dlp->next;
while (p != (dyn_element_t *)dlp) {
if (strncmp(p->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH) == 0) {
return p;
}
p = p->next;
}
return NULL;
}
static dyn_element_t *dyn_list_unlink(dyn_element_t *element,
dyn_list_t *dlp) {
dyn_element_t *prev = (dyn_element_t *)dlp;
/* Scanning the list.*/
while (prev->next != (dyn_element_t *)dlp) {
if (prev->next == element) {
/* Found.*/
prev->next = element->next;
return element;
}
/* Next element in the list.*/
prev = prev->next;
}
return NULL;
}
#if CH_FACTORY_REQUIRES_HEAP || defined(__DOXYGEN__)
static dyn_element_t *dyn_create_object_heap(const char *name,
dyn_list_t *dlp,
size_t size) {
dyn_element_t *dep;
chDbgCheck(name != NULL);
/* Checking if an object with this name has already been created.*/
dep = dyn_list_find(name, dlp);
if (dep != NULL) {
return NULL;
}
/* Allocating space for the new buffer object.*/
/*lint -save -e668 [] Lint is confused by the above chDbgCheck() and
incorrectly assumes that strncpy() could receive a NULL pointer.*/
dep = (dyn_element_t *)chHeapAlloc(NULL, size);
if (dep == NULL) {
return NULL;
}
/* Initializing object list element.*/
strncpy(dep->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH);
/*lint -restore*/
dep->refs = (ucnt_t)1;
dep->next = dlp->next;
/* Updating factory list.*/
dlp->next = dep;
return dep;
}
static void dyn_release_object_heap(dyn_element_t *dep,
dyn_list_t *dlp) {
chDbgCheck(dep != NULL);
chDbgAssert(dep->refs > (ucnt_t)0, "invalid references number");
dep->refs--;
if (dep->refs == (ucnt_t)0) {
dep = dyn_list_unlink(dep, dlp);
chHeapFree((void *)dep);
}
}
#endif /* CH_FACTORY_REQUIRES_HEAP */
#if CH_FACTORY_REQUIRES_POOLS || defined(__DOXYGEN__)
static dyn_element_t *dyn_create_object_pool(const char *name,
dyn_list_t *dlp,
memory_pool_t *mp) {
dyn_element_t *dep;
chDbgCheck(name != NULL);
/* Checking if an object object with this name has already been created.*/
dep = dyn_list_find(name, dlp);
if (dep != NULL) {
return NULL;
}
/* Allocating space for the new object.*/
dep = (dyn_element_t *)chPoolAlloc(mp);
if (dep == NULL) {
return NULL;
}
/* Initializing object list element.*/
/*lint -save -e668 [] Lint is confused by the above chDbgCheck() and
incorrectly assumes that strncpy() could receive a NULL pointer.*/
strncpy(dep->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH);
/*lint -restore*/
dep->refs = (ucnt_t)1;
dep->next = dlp->next;
/* Updating factory list.*/
dlp->next = (dyn_element_t *)dep;
return dep;
}
static void dyn_release_object_pool(dyn_element_t *dep,
dyn_list_t *dlp,
memory_pool_t *mp) {
chDbgCheck(dep != NULL);
chDbgAssert(dep->refs > (ucnt_t)0, "invalid references number");
dep->refs--;
if (dep->refs == (ucnt_t)0) {
dep = dyn_list_unlink(dep, dlp);
chPoolFree(mp, (void *)dep);
}
}
#endif /* CH_FACTORY_REQUIRES_POOLS */
static dyn_element_t *dyn_find_object(const char *name, dyn_list_t *dlp) {
dyn_element_t *dep;
chDbgCheck(name != NULL);
/* Checking if an object with this name has already been created.*/
dep = dyn_list_find(name, dlp);
if (dep != NULL) {
/* Increasing references counter.*/
dep->refs++;
}
return dep;
}
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief Initializes the objects factory.
*
* @init
*/
void _factory_init(void) {
#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
chMtxObjectInit(&ch_factory.mtx);
#else
chSemObjectInit(&ch_factory.sem, (cnt_t)1);
#endif
#if CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE
dyn_list_init(&ch_factory.obj_list);
chPoolObjectInit(&ch_factory.obj_pool,
sizeof (registered_object_t),
chCoreAllocAlignedI);
#endif
#if CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE
dyn_list_init(&ch_factory.buf_list);
#endif
#if CH_CFG_FACTORY_SEMAPHORES == TRUE
dyn_list_init(&ch_factory.sem_list);
chPoolObjectInit(&ch_factory.sem_pool,
sizeof (dyn_semaphore_t),
chCoreAllocAlignedI);
#endif
#if CH_CFG_FACTORY_MAILBOXES == TRUE
dyn_list_init(&ch_factory.mbx_list);
#endif
#if CH_CFG_FACTORY_OBJ_FIFOS == TRUE
dyn_list_init(&ch_factory.fifo_list);
#endif
}
#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXIGEN__)
/**
* @brief Registers a generic object.
* @post A reference to the registered object is returned and the
* reference counter is initialized to one.
*
* @param[in] name name to be assigned to the registered object
* @param[in] objp pointer to the object to be registered
*
* @return The reference to the registered object.
* @retval NULL if the object to be registered cannot be allocated or
* a registered object with the same name exists.
*
* @api
*/
registered_object_t *chFactoryRegisterObject(const char *name,
void *objp) {
registered_object_t *rop;
F_LOCK();
rop = (registered_object_t *)dyn_create_object_pool(name,
&ch_factory.obj_list,
&ch_factory.obj_pool);
if (rop != NULL) {
/* Initializing registered object data.*/
rop->objp = objp;
}
F_UNLOCK();
return rop;
}
/**
* @brief Retrieves a registered object.
* @post A reference to the registered object is returned with the
* reference counter increased by one.
*
* @param[in] name name of the registered object
*
* @return The reference to the found registered object.
* @retval NULL if a registered object with the specified name
* does not exist.
*
* @api
*/
registered_object_t *chFactoryFindObject(const char *name) {
registered_object_t *rop;
F_LOCK();
rop = (registered_object_t *)dyn_find_object(name, &ch_factory.obj_list);
F_UNLOCK();
return rop;
}
/**
* @brief Retrieves a registered object by pointer.
* @post A reference to the registered object is returned with the
* reference counter increased by one.
*
* @param[in] objp pointer to the object to be retrieved
*
* @return The reference to the found registered object.
* @retval NULL if a registered object with the specified pointer
* does not exist.
*
* @api
*/
registered_object_t *chFactoryFindObjectByPointer(void *objp) {
registered_object_t *rop = (registered_object_t *)ch_factory.obj_list.next;
F_LOCK();
while ((void *)rop != (void *)&ch_factory.obj_list) {
if (rop->objp == objp) {
rop->element.refs++;
F_UNLOCK();
return rop;
}
rop = (registered_object_t *)rop->element.next;
}
F_UNLOCK();
return NULL;
}
/**
* @brief Releases a registered object.
* @details The reference counter of the registered object is decreased
* by one, if reaches zero then the registered object memory
* is freed.
* @note The object itself is not freed, it could be static, only the
* allocated list element is freed.
*
* @param[in] rop registered object reference
*
* @api
*/
void chFactoryReleaseObject(registered_object_t *rop){
F_LOCK();
dyn_release_object_pool(&rop->element,
&ch_factory.obj_list,
&ch_factory.obj_pool);
F_UNLOCK();
}
#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */
#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXIGEN__)
/**
* @brief Creates a generic dynamic buffer object.
* @post A reference to the dynamic buffer object is returned and the
* reference counter is initialized to one.
* @post The dynamic buffer object is filled with zeros.
*
* @param[in] name name to be assigned to the new dynamic buffer object
* @param[in] size payload size of the dynamic buffer object to be created
*
* @return The reference to the created dynamic buffer object.
* @retval NULL if the dynamic buffer object cannot be allocated or
* a dynamic buffer object with the same name exists.
*
* @api
*/
dyn_buffer_t *chFactoryCreateBuffer(const char *name, size_t size) {
dyn_buffer_t *dbp;
F_LOCK();
dbp = (dyn_buffer_t *)dyn_create_object_heap(name,
&ch_factory.buf_list,
size);
if (dbp != NULL) {
/* Initializing buffer object data.*/
memset((void *)dbp->buffer, 0, size);
}
F_UNLOCK();
return dbp;
}
/**
* @brief Retrieves a dynamic buffer object.
* @post A reference to the dynamic buffer object is returned with the
* reference counter increased by one.
*
* @param[in] name name of the dynamic buffer object
*
* @return The reference to the found dynamic buffer object.
* @retval NULL if a dynamic buffer object with the specified name
* does not exist.
*
* @api
*/
dyn_buffer_t *chFactoryFindBuffer(const char *name) {
dyn_buffer_t *dbp;
F_LOCK();
dbp = (dyn_buffer_t *)dyn_find_object(name, &ch_factory.buf_list);
F_UNLOCK();
return dbp;
}
/**
* @brief Releases a dynamic buffer object.
* @details The reference counter of the dynamic buffer object is decreased
* by one, if reaches zero then the dynamic buffer object memory
* is freed.
*
* @param[in] dbp dynamic buffer object reference
*
* @api
*/
void chFactoryReleaseBuffer(dyn_buffer_t *dbp) {
F_LOCK();
dyn_release_object_heap(&dbp->element, &ch_factory.buf_list);
F_UNLOCK();
}
#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS = TRUE */
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXIGEN__)
/**
* @brief Creates a dynamic semaphore object.
* @post A reference to the dynamic semaphore object is returned and the
* reference counter is initialized to one.
* @post The dynamic semaphore object is initialized and ready to use.
*
* @param[in] name name to be assigned to the new dynamic semaphore object
* @param[in] n dynamic semaphore object counter initialization value
*
* @return The reference to the created dynamic semaphore object.
* @retval NULL if the dynamic semaphore object cannot be allocated or
* a dynamic semaphore with the same name exists.
*
* @api
*/
dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n) {
dyn_semaphore_t *dsp;
F_LOCK();
dsp = (dyn_semaphore_t *)dyn_create_object_pool(name,
&ch_factory.sem_list,
&ch_factory.sem_pool);
if (dsp != NULL) {
/* Initializing semaphore object dataa.*/
chSemObjectInit(&dsp->sem, n);
}
F_UNLOCK();
return dsp;
}
/**
* @brief Retrieves a dynamic semaphore object.
* @post A reference to the dynamic semaphore object is returned with the
* reference counter increased by one.
*
* @param[in] name name of the dynamic semaphore object
*
* @return The reference to the found dynamic semaphore object.
* @retval NULL if a dynamic semaphore object with the specified name
* does not exist.
*
* @api
*/
dyn_semaphore_t *chFactoryFindSemaphore(const char *name) {
dyn_semaphore_t *dsp;
F_LOCK();
dsp = (dyn_semaphore_t *)dyn_find_object(name, &ch_factory.sem_list);
F_UNLOCK();
return dsp;
}
/**
* @brief Releases a dynamic semaphore object.
* @details The reference counter of the dynamic semaphore object is decreased
* by one, if reaches zero then the dynamic semaphore object memory
* is freed.
*
* @param[in] dsp dynamic semaphore object reference
*
* @api
*/
void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp) {
F_LOCK();
dyn_release_object_pool(&dsp->element,
&ch_factory.sem_list,
&ch_factory.sem_pool);
F_UNLOCK();
}
#endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */
#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXIGEN__)
/**
* @brief Creates a dynamic mailbox object.
* @post A reference to the dynamic mailbox object is returned and the
* reference counter is initialized to one.
* @post The dynamic mailbox object is initialized and ready to use.
*
* @param[in] name name to be assigned to the new dynamic mailbox object
* @param[in] n mailbox buffer size as number of messages
*
* @return The reference to the created dynamic mailbox object.
* @retval NULL if the dynamic mailbox object cannot be allocated or
* a dynamic mailbox object with the same name exists.
*
* @api
*/
dyn_mailbox_t *chFactoryCreateMailbox(const char *name, size_t n) {
dyn_mailbox_t *dmp;
F_LOCK();
dmp = (dyn_mailbox_t *)dyn_create_object_heap(name,
&ch_factory.mbx_list,
sizeof (dyn_mailbox_t) +
(n * sizeof (msg_t)));
if (dmp != NULL) {
/* Initializing mailbox object data.*/
chMBObjectInit(&dmp->mbx, dmp->msgbuf, n);
}
F_UNLOCK();
return dmp;
}
/**
* @brief Retrieves a dynamic mailbox object.
* @post A reference to the dynamic mailbox object is returned with the
* reference counter increased by one.
*
* @param[in] name name of the dynamic mailbox object
*
* @return The reference to the found dynamic mailbox object.
* @retval NULL if a dynamic mailbox object with the specified name
* does not exist.
*
* @api
*/
dyn_mailbox_t *chFactoryFindMailbox(const char *name) {
dyn_mailbox_t *dmp;
F_LOCK();
dmp = (dyn_mailbox_t *)dyn_find_object(name, &ch_factory.mbx_list);
F_UNLOCK();
return dmp;
}
/**
* @brief Releases a dynamic mailbox object.
* @details The reference counter of the dynamic mailbox object is decreased
* by one, if reaches zero then the dynamic mailbox object memory
* is freed.
*
* @param[in] dmp dynamic mailbox object reference
*
* @api
*/
void chFactoryReleaseMailbox(dyn_mailbox_t *dmp) {
F_LOCK();
dyn_release_object_heap(&dmp->element, &ch_factory.mbx_list);
F_UNLOCK();
}
#endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */
#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXIGEN__)
/**
* @brief Creates a dynamic "objects FIFO" object.
* @post A reference to the dynamic "objects FIFO" object is returned and
* the reference counter is initialized to one.
* @post The dynamic "objects FIFO" object is initialized and ready to use.
*
* @param[in] name name to be assigned to the new dynamic "objects FIFO"
* object
* @param[in] objsize size of objects
* @param[in] objn number of objects available
* @param[in] objalign required objects alignment
* @return The reference to the created dynamic "objects FIFO"
* object.
* @retval NULL if the dynamic "objects FIFO" object cannot be
* allocated or a dynamic "objects FIFO" object with
* the same name exists.
*
* @api
*/
dyn_objects_fifo_t *chFactoryCreateObjectsFIFO(const char *name,
size_t objsize,
size_t objn,
unsigned objalign) {
dyn_objects_fifo_t *dofp;
F_LOCK();
dofp = (dyn_objects_fifo_t *)dyn_create_object_heap(name,
&ch_factory.fifo_list,
sizeof (dyn_objects_fifo_t) +
(objn * sizeof (msg_t)) +
(objn * objsize));
if (dofp != NULL) {
/* Initializing mailbox object data.*/
chFifoObjectInit(&dofp->fifo, objsize, objn, objalign,
(void *)&dofp->msgbuf[objn], dofp->msgbuf);
}
F_UNLOCK();
return dofp;
}
/**
* @brief Retrieves a dynamic "objects FIFO" object.
* @post A reference to the dynamic "objects FIFO" object is returned with
* the reference counter increased by one.
*
* @param[in] name name of the dynamic "objects FIFO" object
*
* @return The reference to the found dynamic "objects FIFO"
* object.
* @retval NULL if a dynamic "objects FIFO" object with the specified
* name does not exist.
*
* @api
*/
dyn_objects_fifo_t *chFactoryFindObjectsFIFO(const char *name) {
dyn_objects_fifo_t *dofp;
F_LOCK();
dofp = (dyn_objects_fifo_t *)dyn_find_object(name, &ch_factory.fifo_list);
F_UNLOCK();
return dofp;
}
/**
* @brief Releases a dynamic "objects FIFO" object.
* @details The reference counter of the dynamic "objects FIFO" object is
* decreased by one, if reaches zero then the dynamic "objects FIFO"
* object memory is freed.
*
* @param[in] dofp dynamic "objects FIFO" object reference
*
* @api
*/
void chFactoryReleaseObjectsFIFO(dyn_objects_fifo_t *dofp) {
F_LOCK();
dyn_release_object_heap(&dofp->element, &ch_factory.fifo_list);
F_UNLOCK();
}
#endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */
#endif /* CH_CFG_USE_FACTORY == TRUE */
/** @} */

View File

@ -1,399 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chheap.c
* @brief Heaps code.
*
* @addtogroup heaps
* @details Heap Allocator related APIs.
* <h2>Operation mode</h2>
* The heap allocator implements a first-fit strategy and its APIs
* are functionally equivalent to the usual @p malloc() and @p free()
* library functions. The main difference is that the OS heap APIs
* are guaranteed to be thread safe and there is the ability to
* return memory blocks aligned to arbitrary powers of two.<br>
* @pre In order to use the heap APIs the @p CH_CFG_USE_HEAP option must
* be enabled in @p chconf.h.
* @note Compatible with RT and NIL.
* @{
*/
#include "ch.h"
#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module local definitions. */
/*===========================================================================*/
/*
* Defaults on the best synchronization mechanism available.
*/
#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
#define H_LOCK(h) chMtxLock(&(h)->mtx)
#define H_UNLOCK(h) chMtxUnlock(&(h)->mtx)
#else
#define H_LOCK(h) (void) chSemWait(&(h)->sem)
#define H_UNLOCK(h) chSemSignal(&(h)->sem)
#endif
#define H_BLOCK(hp) ((hp) + 1U)
#define H_LIMIT(hp) (H_BLOCK(hp) + H_PAGES(hp))
#define H_NEXT(hp) ((hp)->free.next)
#define H_PAGES(hp) ((hp)->free.pages)
#define H_HEAP(hp) ((hp)->used.heap)
#define H_SIZE(hp) ((hp)->used.size)
/*
* Number of pages between two pointers in a MISRA-compatible way.
*/
#define NPAGES(p1, p2) \
/*lint -save -e9033 [10.8] The cast is safe.*/ \
((size_t)((p1) - (p2))) \
/*lint -restore*/
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
/**
* @brief Default heap descriptor.
*/
static memory_heap_t default_heap;
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief Initializes the default heap.
*
* @notapi
*/
void _heap_init(void) {
default_heap.provider = chCoreAllocAlignedWithOffset;
H_NEXT(&default_heap.header) = NULL;
H_PAGES(&default_heap.header) = 0;
#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
chMtxObjectInit(&default_heap.mtx);
#else
chSemObjectInit(&default_heap.sem, (cnt_t)1);
#endif
}
/**
* @brief Initializes a memory heap from a static memory area.
* @note The heap buffer base and size are adjusted if the passed buffer
* is not aligned to @p CH_HEAP_ALIGNMENT. This mean that the
* effective heap size can be less than @p size.
*
* @param[out] heapp pointer to the memory heap descriptor to be initialized
* @param[in] buf heap buffer base
* @param[in] size heap size
*
* @init
*/
void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size) {
heap_header_t *hp = (heap_header_t *)MEM_ALIGN_NEXT(buf, CH_HEAP_ALIGNMENT);
chDbgCheck((heapp != NULL) && (size > 0U));
/* Adjusting the size in case the initial block was not correctly
aligned.*/
/*lint -save -e9033 [10.8] Required cast operations.*/
size -= (size_t)((uint8_t *)hp - (uint8_t *)buf);
/*lint restore*/
/* Initializing the heap header.*/
heapp->provider = NULL;
H_NEXT(&heapp->header) = hp;
H_PAGES(&heapp->header) = 0;
H_NEXT(hp) = NULL;
H_PAGES(hp) = (size - sizeof (heap_header_t)) / CH_HEAP_ALIGNMENT;
#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
chMtxObjectInit(&heapp->mtx);
#else
chSemObjectInit(&heapp->sem, (cnt_t)1);
#endif
}
/**
* @brief Allocates a block of memory from the heap by using the first-fit
* algorithm.
* @details The allocated block is guaranteed to be properly aligned to the
* specified alignment.
*
* @param[in] heapp pointer to a heap descriptor or @p NULL in order to
* access the default heap.
* @param[in] size the size of the block to be allocated. Note that the
* allocated block may be a bit bigger than the requested
* size for alignment and fragmentation reasons.
* @param[in] align desired memory alignment
* @return A pointer to the aligned allocated block.
* @retval NULL if the block cannot be allocated.
*
* @api
*/
void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align) {
heap_header_t *qp, *hp, *ahp;
size_t pages;
chDbgCheck((size > 0U) && MEM_IS_VALID_ALIGNMENT(align));
/* If an heap is not specified then the default system header is used.*/
if (heapp == NULL) {
heapp = &default_heap;
}
/* Minimum alignment is constrained by the heap header structure size.*/
if (align < CH_HEAP_ALIGNMENT) {
align = CH_HEAP_ALIGNMENT;
}
/* Size is converted in number of elementary allocation units.*/
pages = MEM_ALIGN_NEXT(size, CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT;
/* Taking heap mutex/semaphore.*/
H_LOCK(heapp);
/* Start of the free blocks list.*/
qp = &heapp->header;
while (H_NEXT(qp) != NULL) {
/* Next free block.*/
hp = H_NEXT(qp);
/* Pointer aligned to the requested alignment.*/
ahp = (heap_header_t *)MEM_ALIGN_NEXT(H_BLOCK(hp), align) - 1U;
if ((ahp < H_LIMIT(hp)) && (pages <= NPAGES(H_LIMIT(hp), ahp + 1U))) {
/* The block is large enough to contain a correctly aligned area
of sufficient size.*/
if (ahp > hp) {
/* The block is not properly aligned, must split it.*/
size_t bpages;
bpages = NPAGES(H_LIMIT(hp), H_BLOCK(ahp));
H_PAGES(hp) = NPAGES(ahp, H_BLOCK(hp));
if (bpages > pages) {
/* The block is bigger than required, must split the excess.*/
heap_header_t *fp;
/* Creating the excess block.*/
fp = H_BLOCK(ahp) + pages;
H_PAGES(fp) = (bpages - pages) - 1U;
/* Linking the excess block.*/
H_NEXT(fp) = H_NEXT(hp);
H_NEXT(hp) = fp;
}
hp = ahp;
}
else {
/* The block is already properly aligned.*/
if (H_PAGES(hp) == pages) {
/* Exact size, getting the whole block.*/
H_NEXT(qp) = H_NEXT(hp);
}
else {
/* The block is bigger than required, must split the excess.*/
heap_header_t *fp;
fp = H_BLOCK(hp) + pages;
H_NEXT(fp) = H_NEXT(hp);
H_PAGES(fp) = NPAGES(H_LIMIT(hp), H_BLOCK(fp));
H_NEXT(qp) = fp;
}
}
/* Setting in the block owner heap and size.*/
H_SIZE(hp) = size;
H_HEAP(hp) = heapp;
/* Releasing heap mutex/semaphore.*/
H_UNLOCK(heapp);
/*lint -save -e9087 [11.3] Safe cast.*/
return (void *)H_BLOCK(hp);
/*lint -restore*/
}
/* Next in the free blocks list.*/
qp = hp;
}
/* Releasing heap mutex/semaphore.*/
H_UNLOCK(heapp);
/* More memory is required, tries to get it from the associated provider
else fails.*/
if (heapp->provider != NULL) {
ahp = heapp->provider((pages + 1U) * CH_HEAP_ALIGNMENT,
align,
sizeof (heap_header_t));
if (ahp != NULL) {
hp = ahp - 1U;
H_HEAP(hp) = heapp;
H_SIZE(hp) = size;
/*lint -save -e9087 [11.3] Safe cast.*/
return (void *)ahp;
/*lint -restore*/
}
}
return NULL;
}
/**
* @brief Frees a previously allocated memory block.
*
* @param[in] p pointer to the memory block to be freed
*
* @api
*/
void chHeapFree(void *p) {
heap_header_t *qp, *hp;
memory_heap_t *heapp;
chDbgCheck((p != NULL) && MEM_IS_ALIGNED(p, CH_HEAP_ALIGNMENT));
/*lint -save -e9087 [11.3] Safe cast.*/
hp = (heap_header_t *)p - 1U;
/*lint -restore*/
heapp = H_HEAP(hp);
qp = &heapp->header;
/* Size is converted in number of elementary allocation units.*/
H_PAGES(hp) = MEM_ALIGN_NEXT(H_SIZE(hp),
CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT;
/* Taking heap mutex/semaphore.*/
H_LOCK(heapp);
while (true) {
chDbgAssert((hp < qp) || (hp >= H_LIMIT(qp)), "within free block");
if (((qp == &heapp->header) || (hp > qp)) &&
((H_NEXT(qp) == NULL) || (hp < H_NEXT(qp)))) {
/* Insertion after qp.*/
H_NEXT(hp) = H_NEXT(qp);
H_NEXT(qp) = hp;
/* Verifies if the newly inserted block should be merged.*/
if (H_LIMIT(hp) == H_NEXT(hp)) {
/* Merge with the next block.*/
H_PAGES(hp) += H_PAGES(H_NEXT(hp)) + 1U;
H_NEXT(hp) = H_NEXT(H_NEXT(hp));
}
if ((H_LIMIT(qp) == hp)) {
/* Merge with the previous block.*/
H_PAGES(qp) += H_PAGES(hp) + 1U;
H_NEXT(qp) = H_NEXT(hp);
}
break;
}
qp = H_NEXT(qp);
}
/* Releasing heap mutex/semaphore.*/
H_UNLOCK(heapp);
return;
}
/**
* @brief Reports the heap status.
* @note This function is meant to be used in the test suite, it should
* not be really useful for the application code.
*
* @param[in] heapp pointer to a heap descriptor or @p NULL in order to
* access the default heap.
* @param[in] totalp pointer to a variable that will receive the total
* fragmented free space or @ NULL
* @param[in] largestp pointer to a variable that will receive the largest
* free free block found space or @ NULL
* @return The number of fragments in the heap.
*
* @api
*/
size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp) {
heap_header_t *qp;
size_t n, tpages, lpages;
if (heapp == NULL) {
heapp = &default_heap;
}
H_LOCK(heapp);
tpages = 0U;
lpages = 0U;
n = 0U;
qp = &heapp->header;
while (H_NEXT(qp) != NULL) {
size_t pages = H_PAGES(H_NEXT(qp));
/* Updating counters.*/
n++;
tpages += pages;
if (pages > lpages) {
lpages = pages;
}
qp = H_NEXT(qp);
}
/* Writing out fragmented free memory.*/
if (totalp != NULL) {
*totalp = tpages * CH_HEAP_ALIGNMENT;
}
/* Writing out unfragmented free memory.*/
if (largestp != NULL) {
*largestp = lpages * CH_HEAP_ALIGNMENT;
}
H_UNLOCK(heapp);
return n;
}
#endif /* CH_CFG_USE_HEAP == TRUE */
/** @} */

View File

@ -1,522 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chmboxes.c
* @brief Mailboxes code.
*
* @addtogroup mailboxes
* @details Asynchronous messages.
* <h2>Operation mode</h2>
* A mailbox is an asynchronous communication mechanism.<br>
* Operations defined for mailboxes:
* - <b>Post</b>: Posts a message on the mailbox in FIFO order.
* - <b>Post Ahead</b>: Posts a message on the mailbox with urgent
* priority.
* - <b>Fetch</b>: A message is fetched from the mailbox and removed
* from the queue.
* - <b>Reset</b>: The mailbox is emptied and all the stored messages
* are lost.
* .
* A message is a variable of type msg_t that is guaranteed to have
* the same size of and be compatible with (data) pointers (anyway an
* explicit cast is needed).
* If larger messages need to be exchanged then a pointer to a
* structure can be posted in the mailbox but the posting side has
* no predefined way to know when the message has been processed. A
* possible approach is to allocate memory (from a memory pool for
* example) from the posting side and free it on the fetching side.
* Another approach is to set a "done" flag into the structure pointed
* by the message.
* @pre In order to use the mailboxes APIs the @p CH_CFG_USE_MAILBOXES
* option must be enabled in @p chconf.h.
* @note Compatible with RT and NIL.
* @{
*/
#include "ch.h"
#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief Initializes a @p mailbox_t object.
*
* @param[out] mbp the pointer to the @p mailbox_t structure to be
* initialized
* @param[in] buf pointer to the messages buffer as an array of @p msg_t
* @param[in] n number of elements in the buffer array
*
* @init
*/
void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n) {
chDbgCheck((mbp != NULL) && (buf != NULL) && (n > (size_t)0));
mbp->buffer = buf;
mbp->rdptr = buf;
mbp->wrptr = buf;
mbp->top = &buf[n];
mbp->cnt = (size_t)0;
mbp->reset = false;
chThdQueueObjectInit(&mbp->qw);
chThdQueueObjectInit(&mbp->qr);
}
/**
* @brief Resets a @p mailbox_t object.
* @details All the waiting threads are resumed with status @p MSG_RESET and
* the queued messages are lost.
* @post The mailbox is in reset state, all operations will fail and
* return @p MSG_RESET until the mailbox is enabled again using
* @p chMBResumeX().
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
*
* @api
*/
void chMBReset(mailbox_t *mbp) {
chSysLock();
chMBResetI(mbp);
chSchRescheduleS();
chSysUnlock();
}
/**
* @brief Resets a @p mailbox_t object.
* @details All the waiting threads are resumed with status @p MSG_RESET and
* the queued messages are lost.
* @post The mailbox is in reset state, all operations will fail and
* return @p MSG_RESET until the mailbox is enabled again using
* @p chMBResumeX().
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
*
* @api
*/
void chMBResetI(mailbox_t *mbp) {
chDbgCheckClassI();
chDbgCheck(mbp != NULL);
mbp->wrptr = mbp->buffer;
mbp->rdptr = mbp->buffer;
mbp->cnt = (size_t)0;
mbp->reset = true;
chThdDequeueAllI(&mbp->qw, MSG_RESET);
chThdDequeueAllI(&mbp->qr, MSG_RESET);
}
/**
* @brief Posts a message into a mailbox.
* @details The invoking thread waits until a empty slot in the mailbox becomes
* available or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
* @param[in] msg the message to be posted on the mailbox
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval MSG_OK if a message has been correctly posted.
* @retval MSG_RESET if the mailbox has been reset.
* @retval MSG_TIMEOUT if the operation has timed out.
*
* @api
*/
msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) {
msg_t rdymsg;
chSysLock();
rdymsg = chMBPostTimeoutS(mbp, msg, timeout);
chSysUnlock();
return rdymsg;
}
/**
* @brief Posts a message into a mailbox.
* @details The invoking thread waits until a empty slot in the mailbox becomes
* available or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
* @param[in] msg the message to be posted on the mailbox
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval MSG_OK if a message has been correctly posted.
* @retval MSG_RESET if the mailbox has been reset.
* @retval MSG_TIMEOUT if the operation has timed out.
*
* @sclass
*/
msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) {
msg_t rdymsg;
chDbgCheckClassS();
chDbgCheck(mbp != NULL);
do {
/* If the mailbox is in reset state then returns immediately.*/
if (mbp->reset) {
return MSG_RESET;
}
/* Is there a free message slot in queue? if so then post.*/
if (chMBGetFreeCountI(mbp) > (size_t)0) {
*mbp->wrptr++ = msg;
if (mbp->wrptr >= mbp->top) {
mbp->wrptr = mbp->buffer;
}
mbp->cnt++;
/* If there is a reader waiting then makes it ready.*/
chThdDequeueNextI(&mbp->qr, MSG_OK);
chSchRescheduleS();
return MSG_OK;
}
/* No space in the queue, waiting for a slot to become available.*/
rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout);
} while (rdymsg == MSG_OK);
return rdymsg;
}
/**
* @brief Posts a message into a mailbox.
* @details This variant is non-blocking, the function returns a timeout
* condition if the queue is full.
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
* @param[in] msg the message to be posted on the mailbox
* @return The operation status.
* @retval MSG_OK if a message has been correctly posted.
* @retval MSG_RESET if the mailbox has been reset.
* @retval MSG_TIMEOUT if the mailbox is full and the message cannot be
* posted.
*
* @iclass
*/
msg_t chMBPostI(mailbox_t *mbp, msg_t msg) {
chDbgCheckClassI();
chDbgCheck(mbp != NULL);
/* If the mailbox is in reset state then returns immediately.*/
if (mbp->reset) {
return MSG_RESET;
}
/* Is there a free message slot in queue? if so then post.*/
if (chMBGetFreeCountI(mbp) > (size_t)0) {
*mbp->wrptr++ = msg;
if (mbp->wrptr >= mbp->top) {
mbp->wrptr = mbp->buffer;
}
mbp->cnt++;
/* If there is a reader waiting then makes it ready.*/
chThdDequeueNextI(&mbp->qr, MSG_OK);
return MSG_OK;
}
/* No space, immediate timeout.*/
return MSG_TIMEOUT;
}
/**
* @brief Posts an high priority message into a mailbox.
* @details The invoking thread waits until a empty slot in the mailbox becomes
* available or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
* @param[in] msg the message to be posted on the mailbox
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval MSG_OK if a message has been correctly posted.
* @retval MSG_RESET if the mailbox has been reset.
* @retval MSG_TIMEOUT if the operation has timed out.
*
* @api
*/
msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) {
msg_t rdymsg;
chSysLock();
rdymsg = chMBPostAheadTimeoutS(mbp, msg, timeout);
chSysUnlock();
return rdymsg;
}
/**
* @brief Posts an high priority message into a mailbox.
* @details The invoking thread waits until a empty slot in the mailbox becomes
* available or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
* @param[in] msg the message to be posted on the mailbox
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval MSG_OK if a message has been correctly posted.
* @retval MSG_RESET if the mailbox has been reset.
* @retval MSG_TIMEOUT if the operation has timed out.
*
* @sclass
*/
msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) {
msg_t rdymsg;
chDbgCheckClassS();
chDbgCheck(mbp != NULL);
do {
/* If the mailbox is in reset state then returns immediately.*/
if (mbp->reset) {
return MSG_RESET;
}
/* Is there a free message slot in queue? if so then post.*/
if (chMBGetFreeCountI(mbp) > (size_t)0) {
if (--mbp->rdptr < mbp->buffer) {
mbp->rdptr = mbp->top - 1;
}
*mbp->rdptr = msg;
mbp->cnt++;
/* If there is a reader waiting then makes it ready.*/
chThdDequeueNextI(&mbp->qr, MSG_OK);
chSchRescheduleS();
return MSG_OK;
}
/* No space in the queue, waiting for a slot to become available.*/
rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout);
} while (rdymsg == MSG_OK);
return rdymsg;
}
/**
* @brief Posts an high priority message into a mailbox.
* @details This variant is non-blocking, the function returns a timeout
* condition if the queue is full.
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
* @param[in] msg the message to be posted on the mailbox
* @return The operation status.
* @retval MSG_OK if a message has been correctly posted.
* @retval MSG_RESET if the mailbox has been reset.
* @retval MSG_TIMEOUT if the mailbox is full and the message cannot be
* posted.
*
* @iclass
*/
msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg) {
chDbgCheckClassI();
chDbgCheck(mbp != NULL);
/* If the mailbox is in reset state then returns immediately.*/
if (mbp->reset) {
return MSG_RESET;
}
/* Is there a free message slot in queue? if so then post.*/
if (chMBGetFreeCountI(mbp) > (size_t)0) {
if (--mbp->rdptr < mbp->buffer) {
mbp->rdptr = mbp->top - 1;
}
*mbp->rdptr = msg;
mbp->cnt++;
/* If there is a reader waiting then makes it ready.*/
chThdDequeueNextI(&mbp->qr, MSG_OK);
return MSG_OK;
}
/* No space, immediate timeout.*/
return MSG_TIMEOUT;
}
/**
* @brief Retrieves a message from a mailbox.
* @details The invoking thread waits until a message is posted in the mailbox
* or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
* @param[out] msgp pointer to a message variable for the received message
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval MSG_OK if a message has been correctly fetched.
* @retval MSG_RESET if the mailbox has been reset.
* @retval MSG_TIMEOUT if the operation has timed out.
*
* @api
*/
msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) {
msg_t rdymsg;
chSysLock();
rdymsg = chMBFetchTimeoutS(mbp, msgp, timeout);
chSysUnlock();
return rdymsg;
}
/**
* @brief Retrieves a message from a mailbox.
* @details The invoking thread waits until a message is posted in the mailbox
* or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
* @param[out] msgp pointer to a message variable for the received message
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval MSG_OK if a message has been correctly fetched.
* @retval MSG_RESET if the mailbox has been reset.
* @retval MSG_TIMEOUT if the operation has timed out.
*
* @sclass
*/
msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) {
msg_t rdymsg;
chDbgCheckClassS();
chDbgCheck((mbp != NULL) && (msgp != NULL));
do {
/* If the mailbox is in reset state then returns immediately.*/
if (mbp->reset) {
return MSG_RESET;
}
/* Is there a message in queue? if so then fetch.*/
if (chMBGetUsedCountI(mbp) > (size_t)0) {
*msgp = *mbp->rdptr++;
if (mbp->rdptr >= mbp->top) {
mbp->rdptr = mbp->buffer;
}
mbp->cnt--;
/* If there is a writer waiting then makes it ready.*/
chThdDequeueNextI(&mbp->qw, MSG_OK);
chSchRescheduleS();
return MSG_OK;
}
/* No message in the queue, waiting for a message to become available.*/
rdymsg = chThdEnqueueTimeoutS(&mbp->qr, timeout);
} while (rdymsg == MSG_OK);
return rdymsg;
}
/**
* @brief Retrieves a message from a mailbox.
* @details This variant is non-blocking, the function returns a timeout
* condition if the queue is empty.
*
* @param[in] mbp the pointer to an initialized @p mailbox_t object
* @param[out] msgp pointer to a message variable for the received message
* @return The operation status.
* @retval MSG_OK if a message has been correctly fetched.
* @retval MSG_RESET if the mailbox has been reset.
* @retval MSG_TIMEOUT if the mailbox is empty and a message cannot be
* fetched.
*
* @iclass
*/
msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp) {
chDbgCheckClassI();
chDbgCheck((mbp != NULL) && (msgp != NULL));
/* If the mailbox is in reset state then returns immediately.*/
if (mbp->reset) {
return MSG_RESET;
}
/* Is there a message in queue? if so then fetch.*/
if (chMBGetUsedCountI(mbp) > (size_t)0) {
*msgp = *mbp->rdptr++;
if (mbp->rdptr >= mbp->top) {
mbp->rdptr = mbp->buffer;
}
mbp->cnt--;
/* If there is a writer waiting then makes it ready.*/
chThdDequeueNextI(&mbp->qw, MSG_OK);
return MSG_OK;
}
/* No message, immediate timeout.*/
return MSG_TIMEOUT;
}
#endif /* CH_CFG_USE_MAILBOXES == TRUE */
/** @} */

View File

@ -1,175 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chmemcore.c
* @brief Core memory manager code.
*
* @addtogroup memcore
* @details Core Memory Manager related APIs and services.
* <h2>Operation mode</h2>
* The core memory manager is a simplified allocator that only
* allows to allocate memory blocks without the possibility to
* free them.<br>
* This allocator is meant as a memory blocks provider for the
* other allocators such as:
* - C-Runtime allocator (through a compiler specific adapter module).
* - Heap allocator (see @ref heaps).
* - Memory pools allocator (see @ref pools).
* .
* By having a centralized memory provider the various allocators
* can coexist and share the main memory.<br>
* This allocator, alone, is also useful for very simple
* applications that just require a simple way to get memory
* blocks.
* @pre In order to use the core memory manager APIs the @p CH_CFG_USE_MEMCORE
* option must be enabled in @p chconf.h.
* @note Compatible with RT and NIL.
* @{
*/
#include "ch.h"
#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/**
* @brief Memory core descriptor.
*/
memcore_t ch_memcore;
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief Low level memory manager initialization.
*
* @notapi
*/
void _core_init(void) {
#if CH_CFG_MEMCORE_SIZE == 0
extern uint8_t __heap_base__[];
extern uint8_t __heap_end__[];
/*lint -save -e9033 [10.8] Required cast operations.*/
ch_memcore.nextmem = __heap_base__;
ch_memcore.endmem = __heap_end__;
/*lint restore*/
#else
static uint8_t static_heap[CH_CFG_MEMCORE_SIZE];
ch_memcore.nextmem = &static_heap[0];
ch_memcore.endmem = &static_heap[CH_CFG_MEMCORE_SIZE];
#endif
}
/**
* @brief Allocates a memory block.
* @details This function allocates a block of @p offset + @p size bytes. The
* returned pointer has @p offset bytes before its address and
* @p size bytes after.
*
* @param[in] size the size of the block to be allocated.
* @param[in] align desired memory alignment
* @param[in] offset aligned pointer offset
* @return A pointer to the allocated memory block.
* @retval NULL allocation failed, core memory exhausted.
*
* @iclass
*/
void *chCoreAllocAlignedWithOffsetI(size_t size,
unsigned align,
size_t offset) {
uint8_t *p, *next;
chDbgCheckClassI();
chDbgCheck(MEM_IS_VALID_ALIGNMENT(align));
size = MEM_ALIGN_NEXT(size, align);
p = (uint8_t *)MEM_ALIGN_NEXT(ch_memcore.nextmem + offset, align);
next = p + size;
/* Considering also the case where there is numeric overflow.*/
if ((next > ch_memcore.endmem) || (next < ch_memcore.nextmem)) {
return NULL;
}
ch_memcore.nextmem = next;
return p;
}
/**
* @brief Allocates a memory block.
* @details This function allocates a block of @p offset + @p size bytes. The
* returned pointer has @p offset bytes before its address and
* @p size bytes after.
*
* @param[in] size the size of the block to be allocated.
* @param[in] align desired memory alignment
* @param[in] offset aligned pointer offset
* @return A pointer to the allocated memory block.
* @retval NULL allocation failed, core memory exhausted.
*
* @api
*/
void *chCoreAllocAlignedWithOffset(size_t size,
unsigned align,
size_t offset) {
void *p;
chSysLock();
p = chCoreAllocAlignedWithOffsetI(size, align, offset);
chSysUnlock();
return p;
}
/**
* @brief Core memory status.
*
* @return The size, in bytes, of the free core memory.
*
* @xclass
*/
size_t chCoreGetStatusX(void) {
/*lint -save -e9033 [10.8] The cast is safe.*/
return (size_t)(ch_memcore.endmem - ch_memcore.nextmem);
/*lint -restore*/
}
#endif /* CH_CFG_USE_MEMCORE == TRUE */
/** @} */

View File

@ -1,349 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 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 chmempools.c
* @brief Memory Pools code.
*
* @addtogroup pools
* @details Memory Pools related APIs and services.
* <h2>Operation mode</h2>
* The Memory Pools APIs allow to allocate/free fixed size objects in
* <b>constant time</b> and reliably without memory fragmentation
* problems.<br>
* Memory Pools do not enforce any alignment constraint on the
* contained object however the objects must be properly aligned
* to contain a pointer to void.
* @pre In order to use the memory pools APIs the @p CH_CFG_USE_MEMPOOLS option
* must be enabled in @p chconf.h.
* @note Compatible with RT and NIL.
* @{
*/
#include "ch.h"
#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief Initializes an empty memory pool.
*
* @param[out] mp pointer to a @p memory_pool_t structure
* @param[in] size the size of the objects contained in this memory pool,
* the minimum accepted size is the size of a pointer to
* void.
* @param[in] align required memory alignment
* @param[in] provider memory provider function for the memory pool or
* @p NULL if the pool is not allowed to grow
* automatically
*
* @init
*/
void chPoolObjectInitAligned(memory_pool_t *mp, size_t size,
unsigned align, memgetfunc_t provider) {
chDbgCheck((mp != NULL) && (size >= sizeof(void *)));
mp->next = NULL;
mp->object_size = size;
mp->align = align;
mp->provider = provider;
}
/**
* @brief Loads a memory pool with an array of static objects.
* @pre The memory pool must already be initialized.
* @pre The array elements must be of the right size for the specified
* memory pool.
* @pre The array elements size must be a multiple of the alignment
* requirement for the pool.
* @post The memory pool contains the elements of the input array.
*
* @param[in] mp pointer to a @p memory_pool_t structure
* @param[in] p pointer to the array first element
* @param[in] n number of elements in the array
*
* @api
*/
void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n) {
chDbgCheck((mp != NULL) && (n != 0U));
while (n != 0U) {
chPoolAdd(mp, p);
/*lint -save -e9087 [11.3] Safe cast.*/
p = (void *)(((uint8_t *)p) + mp->object_size);
/*lint -restore*/
n--;
}
}
/**
* @brief Allocates an object from a memory pool.
* @pre The memory pool must already be initialized.
*
* @param[in] mp pointer to a @p memory_pool_t structure
* @return The pointer to the allocated object.
* @retval NULL if pool is empty.
*
* @iclass
*/
void *chPoolAllocI(memory_pool_t *mp) {
void *objp;
chDbgCheckClassI();
chDbgCheck(mp != NULL);
objp = mp->next;
/*lint -save -e9013 [15.7] There is no else because it is not needed.*/
if (objp != NULL) {
mp->next = mp->next->next;
}
else if (mp->provider != NULL) {
objp = mp->provider(mp->object_size, mp->align);
}
/*lint -restore*/
return objp;
}
/**
* @brief Allocates an object from a memory pool.
* @pre The memory pool must already be initialized.
*
* @param[in] mp pointer to a @p memory_pool_t structure
* @return The pointer to the allocated object.
* @retval NULL if pool is empty.
*
* @api
*/
void *chPoolAlloc(memory_pool_t *mp) {
void *objp;
chSysLock();
objp = chPoolAllocI(mp);
chSysUnlock();
return objp;
}
/**
* @brief Releases an object into a memory pool.
* @pre The memory pool must already be initialized.
* @pre The freed object must be of the right size for the specified
* memory pool.
* @pre The added object must be properly aligned.
*
* @param[in] mp pointer to a @p memory_pool_t structure
* @param[in] objp the pointer to the object to be released
*
* @iclass
*/
void chPoolFreeI(memory_pool_t *mp, void *objp) {
struct pool_header *php = objp;
chDbgCheckClassI();
chDbgCheck((mp != NULL) && (objp != NULL));
chDbgAssert(((size_t)objp & MEM_ALIGN_MASK(mp->align)) == 0U,
"unaligned object");
php->next = mp->next;
mp->next = php;
}
/**
* @brief Releases an object into a memory pool.
* @pre The memory pool must already be initialized.
* @pre The freed object must be of the right size for the specified
* memory pool.
* @pre The added object must be properly aligned.
*
* @param[in] mp pointer to a @p memory_pool_t structure
* @param[in] objp the pointer to the object to be released
*
* @api
*/
void chPoolFree(memory_pool_t *mp, void *objp) {
chSysLock();
chPoolFreeI(mp, objp);
chSysUnlock();
}
#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
* @brief Initializes an empty guarded memory pool.
*
* @param[out] gmp pointer to a @p guarded_memory_pool_t structure
* @param[in] size the size of the objects contained in this guarded
* memory pool, the minimum accepted size is the size
* of a pointer to void.
* @param[in] align required memory alignment
*
* @init
*/
void chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp,
size_t size,
unsigned align) {
chPoolObjectInitAligned(&gmp->pool, size, align, NULL);
chSemObjectInit(&gmp->sem, (cnt_t)0);
}
/**
* @brief Loads a guarded memory pool with an array of static objects.
* @pre The guarded memory pool must already be initialized.
* @pre The array elements must be of the right size for the specified
* guarded memory pool.
* @post The guarded memory pool contains the elements of the input array.
*
* @param[in] gmp pointer to a @p guarded_memory_pool_t structure
* @param[in] p pointer to the array first element
* @param[in] n number of elements in the array
*
* @api
*/
void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n) {
chDbgCheck((gmp != NULL) && (n != 0U));
while (n != 0U) {
chGuardedPoolAdd(gmp, p);
/*lint -save -e9087 [11.3] Safe cast.*/
p = (void *)(((uint8_t *)p) + gmp->pool.object_size);
/*lint -restore*/
n--;
}
}
/**
* @brief Allocates an object from a guarded memory pool.
* @pre The guarded memory pool must already be initialized.
*
* @param[in] gmp pointer to a @p guarded_memory_pool_t structure
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The pointer to the allocated object.
* @retval NULL if the operation timed out.
*
* @sclass
*/
void *chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp,
sysinterval_t timeout) {
msg_t msg;
msg = chSemWaitTimeoutS(&gmp->sem, timeout);
if (msg != MSG_OK) {
return NULL;
}
return chPoolAllocI(&gmp->pool);
}
/**
* @brief Allocates an object from a guarded memory pool.
* @pre The guarded memory pool must already be initialized.
*
* @param[in] gmp pointer to a @p guarded_memory_pool_t structure
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The pointer to the allocated object.
* @retval NULL if the operation timed out.
*
* @api
*/
void *chGuardedPoolAllocTimeout(guarded_memory_pool_t *gmp,
sysinterval_t timeout) {
void *p;
chSysLock();
p = chGuardedPoolAllocTimeoutS(gmp, timeout);
chSysUnlock();
return p;
}
/**
* @brief Releases an object into a guarded memory pool.
* @pre The guarded memory pool must already be initialized.
* @pre The freed object must be of the right size for the specified
* guarded memory pool.
* @pre The added object must be properly aligned.
*
* @param[in] gmp pointer to a @p guarded_memory_pool_t structure
* @param[in] objp the pointer to the object to be released
*
* @iclass
*/
void chGuardedPoolFreeI(guarded_memory_pool_t *gmp, void *objp) {
chPoolFreeI(&gmp->pool, objp);
chSemSignalI(&gmp->sem);
}
/**
* @brief Releases an object into a guarded memory pool.
* @pre The guarded memory pool must already be initialized.
* @pre The freed object must be of the right size for the specified
* guarded memory pool.
* @pre The added object must be properly aligned.
*
* @param[in] gmp pointer to a @p guarded_memory_pool_t structure
* @param[in] objp the pointer to the object to be released
*
* @api
*/
void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp) {
chSysLock();
chGuardedPoolFreeI(gmp, objp);
chSchRescheduleS();
chSysUnlock();
}
#endif
#endif /* CH_CFG_USE_MEMPOOLS == TRUE */
/** @} */

View File

@ -1,126 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file templates/chlibconf.h
* @brief Configuration file template.
* @details A copy of this file must be placed in each project directory, it
* contains the application specific kernel settings.
*
* @addtogroup oslib_config
* @details OS Library related settings.
* @{
*/
#ifndef CHLIBCONF_H
#define CHLIBCONF_H
#define _CHIBIOS_LIB_CONF_
#define _CHIBIOS_LIB_CONF_VER_1_0_
/**
* @brief Mailboxes APIs.
* @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_SEMAPHORES in chconf.h.
*/
#define CH_CFG_USE_MAILBOXES TRUE
/**
* @brief Core Memory Manager APIs.
* @details If enabled then the core memory manager APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MEMCORE TRUE
/**
* @brief Heap Allocator APIs.
* @details If enabled then the memory heap allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
* @p CH_CFG_USE_SEMAPHORES in chconf.h.
* @note Mutexes are recommended.
*/
#define CH_CFG_USE_HEAP TRUE
/**
* @brief Memory Pools Allocator APIs.
* @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MEMPOOLS TRUE
/**
* @brief Objects FIFOs APIs.
* @details If enabled then the objects FIFOs APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_OBJ_FIFOS TRUE
/**
* @brief Objects Factory APIs.
* @details If enabled then the objects factory APIs are included in the
* kernel.
*
* @note The default is @p FALSE.
*/
#define CH_CFG_USE_FACTORY TRUE
/**
* @brief Maximum length for object names.
* @details If the specified length is zero then the name is stored by
* pointer but this could have unintended side effects.
*/
#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
/**
* @brief Enables the registry of generic objects.
*/
#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
/**
* @brief Enables factory for generic buffers.
*/
#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
/**
* @brief Enables factory for semaphores.
*/
#define CH_CFG_FACTORY_SEMAPHORES TRUE
/**
* @brief Enables factory for mailboxes.
*/
#define CH_CFG_FACTORY_MAILBOXES TRUE
/**
* @brief Enables factory for objects FIFOs.
*/
#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
#endif /* CHLIBCONF_H */
/** @} */