IOSharedDataQueue.cpp [plain text]
#include <IOKit/IOSharedDataQueue.h>
#include <IOKit/IODataQueueShared.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOMemoryDescriptor.h>
#ifdef dequeue
#undef dequeue
#endif
#define super IODataQueue
OSDefineMetaClassAndStructors(IOSharedDataQueue, IODataQueue)
IOSharedDataQueue *IOSharedDataQueue::withCapacity(UInt32 size)
{
IOSharedDataQueue *dataQueue = new IOSharedDataQueue;
if (dataQueue) {
if (!dataQueue->initWithCapacity(size)) {
dataQueue->release();
dataQueue = 0;
}
}
return dataQueue;
}
IOSharedDataQueue *IOSharedDataQueue::withEntries(UInt32 numEntries, UInt32 entrySize)
{
IOSharedDataQueue *dataQueue = new IOSharedDataQueue;
if (dataQueue) {
if (!dataQueue->initWithEntries(numEntries, entrySize)) {
dataQueue->release();
dataQueue = 0;
}
}
return dataQueue;
}
Boolean IOSharedDataQueue::initWithCapacity(UInt32 size)
{
IODataQueueAppendix * appendix;
if (!super::init()) {
return false;
}
dataQueue = (IODataQueueMemory *)IOMallocAligned(round_page(size + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE), PAGE_SIZE);
if (dataQueue == 0) {
return false;
}
dataQueue->queueSize = size;
dataQueue->head = 0;
dataQueue->tail = 0;
appendix = (IODataQueueAppendix *)((UInt8 *)dataQueue + size + DATA_QUEUE_MEMORY_HEADER_SIZE);
appendix->version = 0;
notifyMsg = &(appendix->msgh);
setNotificationPort(MACH_PORT_NULL);
return true;
}
void IOSharedDataQueue::free()
{
if (dataQueue) {
IOFreeAligned(dataQueue, round_page(dataQueue->queueSize + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE));
dataQueue = NULL;
}
super::free();
}
IOMemoryDescriptor *IOSharedDataQueue::getMemoryDescriptor()
{
IOMemoryDescriptor *descriptor = 0;
if (dataQueue != 0) {
descriptor = IOMemoryDescriptor::withAddress(dataQueue, dataQueue->queueSize + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE, kIODirectionOutIn);
}
return descriptor;
}
IODataQueueEntry * IOSharedDataQueue::peek()
{
IODataQueueEntry *entry = 0;
if (dataQueue && (dataQueue->head != dataQueue->tail)) {
IODataQueueEntry * head = 0;
UInt32 headSize = 0;
UInt32 headOffset = dataQueue->head;
UInt32 queueSize = dataQueue->queueSize;
head = (IODataQueueEntry *)((char *)dataQueue->queue + headOffset);
headSize = head->size;
if ((headOffset + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize) ||
((headOffset + headSize + DATA_QUEUE_ENTRY_HEADER_SIZE) > queueSize))
{
entry = dataQueue->queue;
} else {
entry = head;
}
}
return entry;
}
Boolean IOSharedDataQueue::dequeue(void *data, UInt32 *dataSize)
{
Boolean retVal = TRUE;
IODataQueueEntry * entry = 0;
UInt32 entrySize = 0;
UInt32 newHeadOffset = 0;
if (dataQueue) {
if (dataQueue->head != dataQueue->tail) {
IODataQueueEntry * head = 0;
UInt32 headSize = 0;
UInt32 headOffset = dataQueue->head;
UInt32 queueSize = dataQueue->queueSize;
head = (IODataQueueEntry *)((char *)dataQueue->queue + headOffset);
headSize = head->size;
if ((headOffset + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize) ||
((headOffset + headSize + DATA_QUEUE_ENTRY_HEADER_SIZE) > queueSize)) {
entry = dataQueue->queue;
entrySize = entry->size;
newHeadOffset = entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE;
} else {
entry = head;
entrySize = entry->size;
newHeadOffset = headOffset + entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE;
}
}
if (entry) {
if (data) {
if (dataSize) {
if (entrySize <= *dataSize) {
memcpy(data, &(entry->data), entrySize);
dataQueue->head = newHeadOffset;
} else {
retVal = FALSE;
}
} else {
retVal = FALSE;
}
} else {
dataQueue->head = newHeadOffset;
}
if (dataSize) {
*dataSize = entrySize;
}
} else {
retVal = FALSE;
}
} else {
retVal = FALSE;
}
return retVal;
}
OSMetaClassDefineReservedUnused(IOSharedDataQueue, 0);
OSMetaClassDefineReservedUnused(IOSharedDataQueue, 1);
OSMetaClassDefineReservedUnused(IOSharedDataQueue, 2);
OSMetaClassDefineReservedUnused(IOSharedDataQueue, 3);
OSMetaClassDefineReservedUnused(IOSharedDataQueue, 4);
OSMetaClassDefineReservedUnused(IOSharedDataQueue, 5);
OSMetaClassDefineReservedUnused(IOSharedDataQueue, 6);
OSMetaClassDefineReservedUnused(IOSharedDataQueue, 7);