From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/lib/voodoo/dispatcher.cpp | 231 ++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100755 Source/DirectFB/lib/voodoo/dispatcher.cpp (limited to 'Source/DirectFB/lib/voodoo/dispatcher.cpp') diff --git a/Source/DirectFB/lib/voodoo/dispatcher.cpp b/Source/DirectFB/lib/voodoo/dispatcher.cpp new file mode 100755 index 0000000..af98c0a --- /dev/null +++ b/Source/DirectFB/lib/voodoo/dispatcher.cpp @@ -0,0 +1,231 @@ +/* + (c) Copyright 2001-2011 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//#define DIRECT_ENABLE_DEBUG + +#include + +extern "C" { +#include +#include +#include +#include +#include +#include + +#include +#include +} + +#include +#include +#include + + +D_DEBUG_DOMAIN( Voodoo_Dispatcher, "Voodoo/Dispatcher", "Voodoo Dispatcher" ); + +/**********************************************************************************************************************/ + +VoodooDispatcher::VoodooDispatcher( VoodooManager *manager ) + : + magic(0), + manager(manager), + packets(NULL) +{ + D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p )\n", __func__, this ); + + /* Initialize lock. */ + direct_mutex_init( &lock ); + + /* Initialize wait queue. */ + direct_waitqueue_init( &queue ); + + D_MAGIC_SET( this, VoodooDispatcher ); + + + dispatch_loop = direct_thread_create( DTT_MESSAGING, DispatchLoopMain, this, "Voodoo Dispatch" ); +} + +VoodooDispatcher::~VoodooDispatcher() +{ + D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p )\n", __func__, this ); + + D_MAGIC_ASSERT( this, VoodooDispatcher ); + + /* Acquire lock and wake up waiters. */ + direct_mutex_lock( &lock ); + direct_waitqueue_broadcast( &queue ); + direct_mutex_unlock( &lock ); + + /* Wait for dispatcher loop exiting. */ + direct_thread_join( dispatch_loop ); + direct_thread_destroy( dispatch_loop ); + + /* Destroy queue. */ + direct_waitqueue_deinit( &queue ); + + /* Destroy lock. */ + direct_mutex_deinit( &lock ); + + D_MAGIC_CLEAR( this ); +} + +bool +VoodooDispatcher::Ready() +{ + D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p )\n", __func__, this ); + + D_MAGIC_ASSERT( this, VoodooDispatcher ); + + direct_mutex_lock( &lock ); + + bool ready = direct_list_count_elements_EXPENSIVE( packets ) < 3; + + direct_mutex_unlock( &lock ); + + return ready; +} + +void +VoodooDispatcher::PutPacket( VoodooPacket *packet ) +{ + D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p, packet %p )\n", __func__, this, packet ); + + D_MAGIC_ASSERT( this, VoodooDispatcher ); + + direct_mutex_lock( &lock ); + + direct_list_append( &packets, &packet->link ); + + direct_waitqueue_broadcast( &queue ); + + direct_mutex_unlock( &lock ); +} + +void +VoodooDispatcher::ProcessMessages( VoodooMessageHeader *first, + size_t total_length ) +{ + D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p, first %p, total_length "_ZU" )\n", + __func__, this, first, total_length ); + + D_MAGIC_ASSERT( this, VoodooDispatcher ); + + VoodooMessageHeader *header = first; + size_t offset = 0; + size_t aligned; + + while (offset < total_length) { + /* Get the message header. */ + header = (VoodooMessageHeader *)((char*) first + offset); + aligned = VOODOO_MSG_ALIGN( header->size ); + + D_DEBUG_AT( Voodoo_Dispatcher, " -> Next message has %d ("_ZU") bytes and is of type %d... (offset "_ZU"/"_ZU")\n", + header->size, aligned, header->type, offset, total_length ); + + D_ASSERT( header->size >= (int) sizeof(VoodooMessageHeader) ); + D_ASSERT( header->size <= MAX_MSG_SIZE ); + + D_ASSERT( offset + aligned <= total_length ); + + switch (header->type) { + case VMSG_SUPER: + manager->handle_super( (VoodooSuperMessage*) header ); + break; + + case VMSG_REQUEST: + manager->handle_request( (VoodooRequestMessage*) header ); + break; + + case VMSG_RESPONSE: + manager->handle_response( (VoodooResponseMessage*) header ); + break; + + default: + D_BUG( "invalid message type %d", header->type ); + break; + } + + offset += aligned; + } + + D_ASSERT( offset == total_length ); +} + +/**********************************************************************************************************************/ + +void * +VoodooDispatcher::DispatchLoop() +{ + D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p )\n", __func__, this ); + + direct_mutex_lock( &lock ); + + while (!manager->is_quit) { + VoodooPacket *packet; + + D_MAGIC_ASSERT( this, VoodooDispatcher ); + + if (packets) { + packet = (VoodooPacket*) packets; + + direct_list_remove( &packets, &packet->link ); + + manager->link->WakeUp( manager->link ); + } + else { + direct_waitqueue_wait( &queue, &lock ); + + continue; + } + + + direct_mutex_unlock( &lock ); + + ProcessMessages( (VoodooMessageHeader*) packet->data_start(), packet->size() ); + + D_FREE( packet ); + + direct_mutex_lock( &lock ); + } + + direct_mutex_unlock( &lock ); + + return NULL; +} + +void * +VoodooDispatcher::DispatchLoopMain( DirectThread *thread, void *arg ) +{ + D_DEBUG_AT( Voodoo_Dispatcher, "VoodooDispatcher::%s( %p, thread %p )\n", __func__, arg, thread ); + + VoodooDispatcher *dispatcher = (VoodooDispatcher*) arg; + + return dispatcher->DispatchLoop(); +} + -- cgit