Änderungen Gruppe 30_10_2022 V2

This commit is contained in:
2022-10-30 20:01:47 +01:00
parent 269f807b31
commit 2517e52e59
239 changed files with 54983 additions and 9 deletions
@@ -0,0 +1,68 @@
cmake_minimum_required (VERSION 2.8)
get_filename_component (VIDEOCORE_ROOT "../.." ABSOLUTE)
include (${VIDEOCORE_ROOT}/makefiles/cmake/global_settings.cmake)
set (HEADERS
vcos_assert.h
vcos_atomic_flags.h
vcos_blockpool.h
vcos_cmd.h
vcos_dlfcn.h
vcos_event_flags.h
vcos_event.h
vcos.h
vcos_init.h
vcos_inttypes.h
vcos_isr.h
vcos_legacy_isr.h
vcos_logging.h
vcos_logging_control.h
vcos_lowlevel_thread.h
vcos_mem.h
vcos_mempool.h
vcos_msgqueue.h
vcos_mutex.h
vcos_named_semaphore.h
vcos_once.h
vcos_queue.h
vcos_quickslow_mutex.h
vcos_reentrant_mutex.h
vcos_semaphore.h
vcos_stdint.h
vcos_string.h
vcos_thread_attr.h
vcos_thread.h
vcos_timer.h
vcos_tls.h
vcos_types.h
)
foreach (header ${HEADERS})
configure_file ("${header}" "${VCOS_HEADERS_BUILD_DIR}/${header}" COPYONLY)
endforeach ()
if (CMAKE_COMPILER_IS_GNUCC)
add_definitions (-ggdb -Werror -Wall)
endif ()
if (CMAKE_COMPILER_2005)
add_definitions (/WX /W4 /wd4127 /D_CRT_SECURE_NO_DEPRECATE)
endif ()
include_directories (${VIDEOCORE_ROOT} ${VCOS_HEADERS_BUILD_DIR})
add_subdirectory (${RTOS})
set(VCOS_EXCLUDE_TESTS TRUE)
if (NOT DEFINED VCOS_EXCLUDE_TESTS)
add_testapp_subdirectory (test)
endif (NOT DEFINED VCOS_EXCLUDE_TESTS)
if (WIN32)
build_command (RELEASE_BUILD_CMD CONFIGURATION Release)
build_command (DEBUG_BUILD_CMD CONFIGURATION Debug)
configure_file (build_all.bat.in build_all.bat @ONLY)
endif ()
#install (FILES ${HEADERS} DESTINATION include/interface/vcos)
@@ -0,0 +1,21 @@
set (HEADERS
vcos_common.h
vcos_generic_blockpool.h
vcos_generic_event_flags.h
vcos_generic_named_sem.h
vcos_generic_quickslow_mutex.h
vcos_generic_reentrant_mtx.h
vcos_generic_tls.h
vcos_joinable_thread_from_plain.h
vcos_latch_from_sem.h
vcos_mem_from_malloc.h
vcos_mutexes_are_reentrant.h
vcos_thread_reaper.h
)
foreach (header ${HEADERS})
configure_file ("${header}" "${VCOS_HEADERS_BUILD_DIR}/generic/${header}" COPYONLY)
endforeach ()
install (FILES ${HEADERS} DESTINATION include/interface/vcos/generic)
@@ -0,0 +1,85 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "interface/vcos/vcos.h"
#ifdef __VIDEOCORE__
#include "host_support/include/vc_debug_sym.h"
#include "vcfw/vclib/vclib.h"
#endif
#include <stdlib.h>
int vcos_verify_bkpts = 0;
#ifdef __VIDEOCORE__
VC_DEBUG_VAR(vcos_verify_bkpts);
#endif
int vcos_verify_bkpts_enabled(void)
{
return vcos_verify_bkpts;
}
int vcos_verify_bkpts_enable(int enable)
{
int old = vcos_verify_bkpts;
vcos_verify_bkpts = enable;
return old;
}
/**
* Call the fatal error handler.
*/
void vcos_abort(void)
{
VCOS_ALERT("vcos_abort: Halting");
#ifdef __VIDEOCORE__
_bkpt();
#endif
#if defined(VCOS_HAVE_BACKTRACE) && !defined(NDEBUG)
vcos_backtrace_self();
#endif
#ifdef __VIDEOCORE__
/* Flush the cache to help with postmortem RAM-dump debugging */
vclib_cache_flush();
#endif
#ifdef PLATFORM_RASPBERRYPI
extern void pattern(int);
while(1)
pattern(8);
#endif
/* Insert chosen fatal error handler here */
#if defined __VIDEOCORE__ && !defined(NDEBUG)
while(1); /* allow us to attach a debugger after the fact and see where we came from. */
#else
abort(); /* on vc this ends up in _exit_halt which doesn't give us any stack backtrace */
#endif
}
@@ -0,0 +1,722 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*****************************************************************************
*
* This file provides a generic command line interface which allows
* vcos internals to be manipulated and/or displayed.
*
*****************************************************************************/
/* ---- Include Files ---------------------------------------------------- */
#include "interface/vcos/vcos.h"
#ifdef HAVE_VCOS_VERSION
#include "interface/vcos/vcos_build_info.h"
#endif
#ifdef _VIDEOCORE
#include "vcfw/logging/logging.h"
#endif
/* ---- Public Variables ------------------------------------------------- */
/* ---- Private Constants and Types -------------------------------------- */
#define VCOS_LOG_CATEGORY (&vcos_cmd_log_category)
VCOS_LOG_CAT_T vcos_cmd_log_category;
/* ---- Private Variables ------------------------------------------------ */
static struct VCOS_CMD_GLOBALS_T
{
VCOS_MUTEX_T lock;
VCOS_ONCE_T initialized;
unsigned num_cmd_entries;
unsigned num_cmd_alloc;
VCOS_CMD_T *cmd_entry;
VCOS_LOG_CAT_T *log_category;
} cmd_globals;
#ifdef HAVE_VCOS_VERSION
/* Keep the static strings in the image from being dropped by
* the linker.
*/
extern const char *vcos_get_build_strings(unsigned id);
const char *(*vcos_keep_static_strings)(unsigned);
#endif
/* ---- Private Function Prototypes -------------------------------------- */
static VCOS_STATUS_T help_cmd( VCOS_CMD_PARAM_T *param );
/* ---- Functions ------------------------------------------------------- */
/*****************************************************************************
*
* Walks through the commands looking for a particular command
*
*****************************************************************************/
static VCOS_CMD_T *find_cmd( VCOS_CMD_T *cmd_entry, const char *name )
{
VCOS_CMD_T *scan_entry = cmd_entry;
while ( scan_entry->name != NULL )
{
if ( vcos_strcmp( scan_entry->name, name ) == 0 )
{
return scan_entry;
}
scan_entry++;
}
return NULL;
}
/*****************************************************************************
*
* Saves away
* each line individually.
*
*****************************************************************************/
void vcos_cmd_always_log_output( VCOS_LOG_CAT_T *log_category )
{
cmd_globals.log_category = log_category;
}
/*****************************************************************************
*
* Walks through a buffer containing newline separated lines, and logs
* each line individually.
*
*****************************************************************************/
static void cmd_log_results( VCOS_CMD_PARAM_T *param )
{
char *start;
char *end;
start = end = param->result_buf;
while ( *start != '\0' )
{
while (( *end != '\0' ) && ( *end != '\n' ))
end++;
if ( *end == '\n' )
{
*end++ = '\0';
}
if ( cmd_globals.log_category != NULL )
{
if ( vcos_is_log_enabled( cmd_globals.log_category, VCOS_LOG_INFO ))
{
vcos_log_impl( cmd_globals.log_category, VCOS_LOG_INFO, "%s", start );
}
}
else
{
vcos_log_info( "%s", start );
}
start = end;
}
/* Since we logged the buffer, reset the pointer back to the beginning. */
param->result_ptr = param->result_buf;
param->result_buf[0] = '\0';
}
/*****************************************************************************
*
* Since we may have limited output space, we create a generic routine
* which tries to use the result space, but will switch over to using
* logging if the output is too large.
*
*****************************************************************************/
void vcos_cmd_vprintf( VCOS_CMD_PARAM_T *param, const char *fmt, va_list args )
{
int bytes_written;
int bytes_remaining;
bytes_remaining = (int)(param->result_size - ( param->result_ptr - param->result_buf ));
bytes_written = vcos_vsnprintf( param->result_ptr, bytes_remaining, fmt, args );
if ( cmd_globals.log_category != NULL )
{
/* We're going to log each line as we encounter it. If the buffer
* doesn't end in a newline, then we'll wait for one first.
*/
if ( (( bytes_written + 1 ) >= bytes_remaining )
|| ( param->result_ptr[ bytes_written - 1 ] == '\n' ))
{
cmd_log_results( param );
}
else
{
param->result_ptr += bytes_written;
}
}
else
{
if (( bytes_written + 1 ) >= bytes_remaining )
{
/* Output doesn't fit - switch over to logging */
param->use_log = 1;
*param->result_ptr = '\0'; /* Zap the partial line that didn't fit above. */
cmd_log_results( param ); /* resets result_ptr */
bytes_written = vcos_vsnprintf( param->result_ptr, bytes_remaining, fmt, args );
}
param->result_ptr += bytes_written;
}
}
/*****************************************************************************
*
* Prints the output.
*
*****************************************************************************/
void vcos_cmd_printf( VCOS_CMD_PARAM_T *param, const char *fmt, ... )
{
va_list args;
va_start( args, fmt );
vcos_cmd_vprintf( param, fmt, args );
va_end( args );
}
/*****************************************************************************
*
* Prints the arguments which were on the command line prior to ours.
*
*****************************************************************************/
static void print_argument_prefix( VCOS_CMD_PARAM_T *param )
{
int arg_idx;
for ( arg_idx = 0; &param->argv_orig[arg_idx] != param->argv; arg_idx++ )
{
vcos_cmd_printf( param, "%s ", param->argv_orig[arg_idx] );
}
}
/*****************************************************************************
*
* Prints an error message, prefixed by the command chain required to get
* to where we're at.
*
*****************************************************************************/
void vcos_cmd_error( VCOS_CMD_PARAM_T *param, const char *fmt, ... )
{
va_list args;
print_argument_prefix( param );
va_start( args, fmt );
vcos_cmd_vprintf( param, fmt, args );
va_end( args );
vcos_cmd_printf( param, "\n" );
}
/****************************************************************************
*
* usage - prints command usage for an array of commands.
*
***************************************************************************/
static void usage( VCOS_CMD_PARAM_T *param, VCOS_CMD_T *cmd_entry )
{
int cmd_idx;
int nameWidth = 0;
int argsWidth = 0;
VCOS_CMD_T *scan_entry;
vcos_cmd_printf( param, "Usage: " );
print_argument_prefix( param );
vcos_cmd_printf( param, "command [args ...]\n" );
vcos_cmd_printf( param, "\n" );
vcos_cmd_printf( param, "Where command is one of the following:\n" );
for ( cmd_idx = 0; cmd_entry[cmd_idx].name != NULL; cmd_idx++ )
{
int aw;
int nw;
scan_entry = &cmd_entry[cmd_idx];
nw = vcos_strlen( scan_entry->name );
aw = vcos_strlen( scan_entry->args );
if ( nw > nameWidth )
{
nameWidth = nw;
}
if ( aw > argsWidth )
{
argsWidth = aw;
}
}
for ( cmd_idx = 0; cmd_entry[cmd_idx].name != NULL; cmd_idx++ )
{
scan_entry = &cmd_entry[cmd_idx];
vcos_cmd_printf( param, " %-*s %-*s - %s\n",
nameWidth, scan_entry->name,
argsWidth, scan_entry->args,
scan_entry->descr );
}
}
/****************************************************************************
*
* Prints the usage for the current command.
*
***************************************************************************/
void vcos_cmd_usage( VCOS_CMD_PARAM_T *param )
{
VCOS_CMD_T *cmd_entry;
cmd_entry = param->cmd_entry;
if ( cmd_entry->sub_cmd_entry != NULL )
{
/* This command is command with sub-commands */
usage( param, param->cmd_entry->sub_cmd_entry );
}
else
{
vcos_cmd_printf( param, "Usage: " );
print_argument_prefix( param );
vcos_cmd_printf( param, "%s %s - %s\n",
param->argv[0],
param->cmd_entry->args,
param->cmd_entry->descr );
}
}
/*****************************************************************************
*
* Command to print out the help
*
* This help command is only called from the main menu.
*
*****************************************************************************/
static VCOS_STATUS_T help_cmd( VCOS_CMD_PARAM_T *param )
{
VCOS_CMD_T *found_entry;
#if 0
{
int arg_idx;
vcos_log_trace( "%s: argc = %d", __func__, param->argc );
for ( arg_idx = 0; arg_idx < param->argc; arg_idx++ )
{
vcos_log_trace( "%s: argv[%d] = '%s'", __func__, arg_idx, param->argv[arg_idx] );
}
}
#endif
/* If there is an argument after the word help, then we want to print
* help for that command.
*/
if ( param->argc == 1 )
{
if ( param->cmd_parent_entry == cmd_globals.cmd_entry )
{
/* Bare help - print the command usage for the root */
usage( param, cmd_globals.cmd_entry );
return VCOS_SUCCESS;
}
/* For all other cases help requires an argument */
vcos_cmd_error( param, "%s requires an argument", param->argv[0] );
return VCOS_EINVAL;
}
/* We were given an argument. */
if (( found_entry = find_cmd( param->cmd_parent_entry, param->argv[1] )) != NULL )
{
/* Make it look like the command that was specified is the one that's
* currently running
*/
param->cmd_entry = found_entry;
param->argv[0] = param->argv[1];
param->argv++;
param->argc--;
vcos_cmd_usage( param );
return VCOS_SUCCESS;
}
vcos_cmd_error( param, "- unrecognized command: '%s'", param->argv[1] );
return VCOS_ENOENT;
}
/*****************************************************************************
*
* Command to print out the version/build information.
*
*****************************************************************************/
#ifdef HAVE_VCOS_VERSION
static VCOS_STATUS_T version_cmd( VCOS_CMD_PARAM_T *param )
{
static const char* copyright = "Copyright (c) 2011 Broadcom";
vcos_cmd_printf( param, "%s %s\n%s\nversion %s\nhost %s",
vcos_get_build_date(),
vcos_get_build_time(),
copyright,
vcos_get_build_version(),
vcos_get_build_hostname() );
return VCOS_SUCCESS;
}
#endif
/*****************************************************************************
*
* Internal commands
*
*****************************************************************************/
static VCOS_CMD_T cmd_help = { "help", "[command]", help_cmd, NULL, "Prints command help information" };
#ifdef HAVE_VCOS_VERSION
static VCOS_CMD_T cmd_version = { "version", "", version_cmd, NULL, "Prints build/version information" };
#endif
/*****************************************************************************
*
* Walks the command table and executes the commands
*
*****************************************************************************/
static VCOS_STATUS_T execute_cmd( VCOS_CMD_PARAM_T *param, VCOS_CMD_T *cmd_entry )
{
const char *cmdStr;
VCOS_CMD_T *found_entry;
#if 0
{
int arg_idx;
vcos_cmd_printf( param, "%s: argc = %d", __func__, param->argc );
for ( arg_idx = 0; arg_idx < param->argc; arg_idx++ )
{
vcos_cmd_printf( param, " argv[%d] = '%s'", arg_idx, param->argv[arg_idx] );
}
vcos_cmd_printf( param, "\n" );
}
#endif
if ( param->argc <= 1 )
{
/* No command specified */
vcos_cmd_error( param, "%s - no command specified", param->argv[0] );
return VCOS_EINVAL;
}
/* argv[0] is the command/program that caused us to get invoked, so we strip
* it off.
*/
param->argc--;
param->argv++;
param->cmd_parent_entry = cmd_entry;
/* Not the help command, scan for the command and execute it. */
cmdStr = param->argv[0];
if (( found_entry = find_cmd( cmd_entry, cmdStr )) != NULL )
{
if ( found_entry->sub_cmd_entry != NULL )
{
return execute_cmd( param, found_entry->sub_cmd_entry );
}
param->cmd_entry = found_entry;
return found_entry->cmd_fn( param );
}
/* Unrecognized command - check to see if it was the help command */
if ( vcos_strcmp( cmdStr, cmd_help.name ) == 0 )
{
return help_cmd( param );
}
vcos_cmd_error( param, "- unrecognized command: '%s'", cmdStr );
return VCOS_ENOENT;
}
/*****************************************************************************
*
* Initializes the command line parser.
*
*****************************************************************************/
static void vcos_cmd_init( void )
{
vcos_mutex_create( &cmd_globals.lock, "vcos_cmd" );
cmd_globals.num_cmd_entries = 0;
cmd_globals.num_cmd_alloc = 0;
cmd_globals.cmd_entry = NULL;
#ifdef HAVE_VCOS_VERSION
vcos_keep_static_strings = vcos_get_build_strings;
#endif
}
/*****************************************************************************
*
* Shuts down the command line parser.
*
*****************************************************************************/
void vcos_cmd_shutdown( void )
{
vcos_mutex_delete( &cmd_globals.lock );
vcos_free( cmd_globals.cmd_entry );
cmd_globals.cmd_entry = NULL;
}
/*****************************************************************************
*
* Command line processor.
*
*****************************************************************************/
VCOS_STATUS_T vcos_cmd_execute( int argc, char **argv, size_t result_size, char *result_buf )
{
VCOS_STATUS_T rc = VCOS_EINVAL;
VCOS_CMD_PARAM_T param;
vcos_once( &cmd_globals.initialized, vcos_cmd_init );
param.argc = argc;
param.argv = param.argv_orig = argv;
param.use_log = 0;
param.result_size = result_size;
param.result_ptr = result_buf;
param.result_buf = result_buf;
result_buf[0] = '\0';
vcos_mutex_lock( &cmd_globals.lock );
rc = execute_cmd( &param, cmd_globals.cmd_entry );
if ( param.use_log )
{
cmd_log_results( &param );
vcos_snprintf( result_buf, result_size, "results logged" );
}
else
if ( cmd_globals.log_category != NULL )
{
if ( result_buf[0] != '\0' )
{
/* There is a partial line still buffered. */
vcos_cmd_printf( &param, "\n" );
}
}
vcos_mutex_unlock( &cmd_globals.lock );
return rc;
}
/*****************************************************************************
*
* Registers a command entry with the command line processor
*
*****************************************************************************/
VCOS_STATUS_T vcos_cmd_register( VCOS_CMD_T *cmd_entry )
{
VCOS_STATUS_T rc;
VCOS_UNSIGNED new_num_cmd_alloc;
VCOS_CMD_T *new_cmd_entry;
VCOS_CMD_T *old_cmd_entry;
VCOS_CMD_T *scan_entry;
vcos_once( &cmd_globals.initialized, vcos_cmd_init );
vcos_assert( cmd_entry != NULL );
vcos_assert( cmd_entry->name != NULL );
vcos_log_trace( "%s: cmd '%s'", __FUNCTION__, cmd_entry->name );
vcos_assert( cmd_entry->args != NULL );
vcos_assert(( cmd_entry->cmd_fn != NULL ) || ( cmd_entry->sub_cmd_entry != NULL ));
vcos_assert( cmd_entry->descr != NULL );
/* We expect vcos_cmd_init to be called before vcos_logging_init, so we
* need to defer registering our logging category until someplace
* like right here.
*/
if ( vcos_cmd_log_category.name == NULL )
{
/*
* If you're using the command interface, you pretty much always want
* log messages from this file to show up. So we change the default
* from ERROR to be the more reasonable INFO level.
*/
vcos_log_set_level(&vcos_cmd_log_category, VCOS_LOG_INFO);
vcos_log_register("vcos_cmd", &vcos_cmd_log_category);
/* We register a help command so that it shows up in the usage. */
vcos_cmd_register( &cmd_help );
#ifdef HAVE_VCOS_VERSION
vcos_cmd_register( &cmd_version );
#endif
}
vcos_mutex_lock( &cmd_globals.lock );
if ( cmd_globals.num_cmd_entries >= cmd_globals.num_cmd_alloc )
{
if ( cmd_globals.num_cmd_alloc == 0 )
{
/* We haven't allocated a table yet */
}
/* The number 8 is rather arbitrary. */
new_num_cmd_alloc = cmd_globals.num_cmd_alloc + 8;
/* The + 1 is to ensure that we always have a NULL entry at the end. */
new_cmd_entry = (VCOS_CMD_T *)vcos_calloc( new_num_cmd_alloc + 1, sizeof( *cmd_entry ), "vcos_cmd_entries" );
if ( new_cmd_entry == NULL )
{
rc = VCOS_ENOMEM;
goto out;
}
memcpy( new_cmd_entry, cmd_globals.cmd_entry, cmd_globals.num_cmd_entries * sizeof( *cmd_entry ));
cmd_globals.num_cmd_alloc = new_num_cmd_alloc;
old_cmd_entry = cmd_globals.cmd_entry;
cmd_globals.cmd_entry = new_cmd_entry;
vcos_free( old_cmd_entry );
}
if ( cmd_globals.num_cmd_entries == 0 )
{
/* This is the first command being registered */
cmd_globals.cmd_entry[0] = *cmd_entry;
}
else
{
/* Keep the list in alphabetical order. We start at the end and work backwards
* shuffling entries up one until we find an insertion point.
*/
for ( scan_entry = &cmd_globals.cmd_entry[cmd_globals.num_cmd_entries - 1];
scan_entry >= cmd_globals.cmd_entry; scan_entry-- )
{
if ( vcos_strcmp( cmd_entry->name, scan_entry->name ) > 0 )
{
/* We found an insertion point. */
break;
}
scan_entry[1] = scan_entry[0];
}
scan_entry[1] = *cmd_entry;
}
cmd_globals.num_cmd_entries++;
rc = VCOS_SUCCESS;
out:
vcos_mutex_unlock( &cmd_globals.lock );
return rc;
}
/*****************************************************************************
*
* Registers multiple commands.
*
*****************************************************************************/
VCOS_STATUS_T vcos_cmd_register_multiple( VCOS_CMD_T *cmd_entry )
{
VCOS_STATUS_T status;
while ( cmd_entry->name != NULL )
{
if (( status = vcos_cmd_register( cmd_entry )) != VCOS_SUCCESS )
{
return status;
}
cmd_entry++;
}
return VCOS_SUCCESS;
}
@@ -0,0 +1,96 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - common postamble code
=============================================================================*/
/** \file
*
* Postamble code included by the platform-specific header files
*/
#define VCOS_THREAD_PRI_DEFAULT VCOS_THREAD_PRI_NORMAL
#if !defined(VCOS_THREAD_PRI_INCREASE)
#error Which way to thread priorities go?
#endif
#if VCOS_THREAD_PRI_INCREASE < 0
/* smaller numbers are higher priority */
#define VCOS_THREAD_PRI_LESS(x) ((x)<VCOS_THREAD_PRI_MAX?(x)+1:VCOS_THREAD_PRI_MAX)
#define VCOS_THREAD_PRI_MORE(x) ((x)>VCOS_THREAD_PRI_MIN?(x)-1:VCOS_THREAD_PRI_MIN)
#else
/* bigger numbers are lower priority */
#define VCOS_THREAD_PRI_MORE(x) ((x)<VCOS_THREAD_PRI_MAX?(x)+1:VCOS_THREAD_PRI_MAX)
#define VCOS_THREAD_PRI_LESS(x) ((x)>VCOS_THREAD_PRI_MIN?(x)-1:VCOS_THREAD_PRI_MIN)
#endif
/* Convenience for Brits: */
#define VCOS_APPLICATION_INITIALISE VCOS_APPLICATION_INITIALIZE
/*
* Check for constant definitions
*/
#ifndef VCOS_TICKS_PER_SECOND
#error VCOS_TICKS_PER_SECOND not defined
#endif
#if !defined(VCOS_THREAD_PRI_MIN) || !defined(VCOS_THREAD_PRI_MAX)
#error Priority range not defined
#endif
#if !defined(VCOS_THREAD_PRI_HIGHEST) || !defined(VCOS_THREAD_PRI_LOWEST) || !defined(VCOS_THREAD_PRI_NORMAL)
#error Priority ordering not defined
#endif
#if !defined(VCOS_CAN_SET_STACK_ADDR)
#error Can stack addresses be set on this platform? Please set this macro to either 0 or 1.
#endif
#if (_VCOS_AFFINITY_CPU0|_VCOS_AFFINITY_CPU1) & (~_VCOS_AFFINITY_MASK)
#error _VCOS_AFFINITY_CPUxxx values are not consistent with _VCOS_AFFINITY_MASK
#endif
/** Append to the end of a singly-linked queue, O(1). Works with
* any structure where list has members 'head' and 'tail' and
* item has a 'next' pointer.
*/
#define VCOS_QUEUE_APPEND_TAIL(list, item) {\
(item)->next = NULL;\
if (!(list)->head) {\
(list)->head = (list)->tail = (item); \
} else {\
(list)->tail->next = (item); \
(list)->tail = (item); \
} \
}
#ifndef VCOS_HAVE_TIMER
VCOSPRE_ void VCOSPOST_ vcos_timer_init(void);
#endif
@@ -0,0 +1,36 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
The symbol vcos_deprecated_code may be defined at most once, by the inclusion of "vcos_deprecated.h" in vcos_init.c.
Any other inclusions of this header will cause the linker to warn about multiple definitions of vcos_deprecated_code, for example:
[ldvc] (Warning) "vcos_deprecated_code" is multiply defined in libs/vcos_threadx/vcos_init.c.o and libs/xxxxx/xxxxx.c.o
If you see a build message like this then the configuration you are building is using deprecated code.
Contact the person named in the accompanying comment for advice - do not remove the inclusion.
*/
int vcos_deprecated_code;
@@ -0,0 +1,568 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define VCOS_LOG_CATEGORY (&vcos_blockpool_log)
#include <stddef.h>
#include <string.h>
#include "interface/vcos/vcos.h"
#include "interface/vcos/generic/vcos_generic_blockpool.h"
#define VCOS_BLOCKPOOL_FOURCC(a,b,c,d) ((a) | (b << 8) | (c << 16) | (d << 24))
#define VCOS_BLOCKPOOL_MAGIC VCOS_BLOCKPOOL_FOURCC('v', 'b', 'p', 'l')
#define VCOS_BLOCKPOOL_SUBPOOL_MAGIC VCOS_BLOCKPOOL_FOURCC('v', 's', 'p', 'l')
#define VCOS_BLOCKPOOL_SUBPOOL_FLAG_NONE (0)
#define VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM (1 << 0)
#define VCOS_BLOCKPOOL_SUBPOOL_FLAG_EXTENSION (1 << 1)
/* Uncomment to enable really verbose debug messages */
/* #define VCOS_BLOCKPOOL_DEBUGGING */
/* Whether to overwrite freed blocks with 0xBD */
#ifdef VCOS_BLOCKPOOL_DEBUGGING
#define VCOS_BLOCKPOOL_OVERWRITE_ON_FREE 1
#define VCOS_BLOCKPOOL_DEBUG_MEMSET_MAX_SIZE (UINT32_MAX)
#else
#define VCOS_BLOCKPOOL_OVERWRITE_ON_FREE 0
#define VCOS_BLOCKPOOL_DEBUG_MEMSET_MAX_SIZE (2 * 1024 * 1024)
#endif
#ifdef VCOS_BLOCKPOOL_DEBUGGING
#define VCOS_BLOCKPOOL_ASSERT vcos_demand
#define VCOS_BLOCKPOOL_TRACE_LEVEL VCOS_LOG_TRACE
#define VCOS_BLOCKPOOL_DEBUG_LOG(s, ...) vcos_log_trace("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
#undef VCOS_BLOCKPOOL_OVERWRITE_ON_FREE
#define VCOS_BLOCKPOOL_OVERWRITE_ON_FREE 1
#else
#define VCOS_BLOCKPOOL_ASSERT vcos_demand
#define VCOS_BLOCKPOOL_TRACE_LEVEL VCOS_LOG_ERROR
#define VCOS_BLOCKPOOL_DEBUG_LOG(s, ...)
#endif
#define ASSERT_POOL(p) \
VCOS_BLOCKPOOL_ASSERT((p) && (p)->magic == VCOS_BLOCKPOOL_MAGIC);
#define ASSERT_SUBPOOL(p) \
VCOS_BLOCKPOOL_ASSERT((p) && (p)->magic == VCOS_BLOCKPOOL_SUBPOOL_MAGIC && \
p->start >= p->mem);
#if defined(VCOS_LOGGING_ENABLED)
static VCOS_LOG_CAT_T vcos_blockpool_log =
VCOS_LOG_INIT("vcos_blockpool", VCOS_BLOCKPOOL_TRACE_LEVEL);
#endif
static void vcos_generic_blockpool_subpool_init(
VCOS_BLOCKPOOL_T *pool, VCOS_BLOCKPOOL_SUBPOOL_T *subpool,
void *mem, size_t pool_size, VCOS_UNSIGNED num_blocks, int align,
uint32_t flags)
{
VCOS_BLOCKPOOL_HEADER_T *block;
VCOS_BLOCKPOOL_HEADER_T *end;
vcos_unused(flags);
vcos_log_trace(
"%s: pool %p subpool %p mem %p pool_size %d " \
"num_blocks %d align %d flags %x",
VCOS_FUNCTION,
pool, subpool, mem, (uint32_t) pool_size,
num_blocks, align, flags);
subpool->magic = VCOS_BLOCKPOOL_SUBPOOL_MAGIC;
subpool->mem = mem;
/* The block data pointers must be aligned according to align and the
* block header pre-preceeds the first block data.
* For large alignments there may be wasted space between subpool->mem
* and the first block header.
*/
subpool->start = (char *) subpool->mem + sizeof(VCOS_BLOCKPOOL_HEADER_T);
subpool->start = (void*)
VCOS_BLOCKPOOL_ROUND_UP((unsigned long) subpool->start, align);
subpool->start = (char *) subpool->start - sizeof(VCOS_BLOCKPOOL_HEADER_T);
vcos_assert(subpool->start >= subpool->mem);
vcos_log_trace("%s: mem %p subpool->start %p" \
" pool->block_size %d pool->block_data_size %d",
VCOS_FUNCTION, mem, subpool->start,
(int) pool->block_size, (int) pool->block_data_size);
subpool->num_blocks = num_blocks;
subpool->available_blocks = num_blocks;
subpool->free_list = NULL;
subpool->owner = pool;
/* Initialise to a predictable bit pattern unless the pool is so big
* that the delay would be noticable. */
if (pool_size < VCOS_BLOCKPOOL_DEBUG_MEMSET_MAX_SIZE)
memset(subpool->mem, 0xBC, pool_size); /* For debugging */
block = (VCOS_BLOCKPOOL_HEADER_T*) subpool->start;
end = (VCOS_BLOCKPOOL_HEADER_T*)
((char *) subpool->start + (pool->block_size * num_blocks));
subpool->end = end;
/* Initialise the free list for this subpool */
while (block < end)
{
block->owner.next = subpool->free_list;
subpool->free_list = block;
block = (VCOS_BLOCKPOOL_HEADER_T*)((char*) block + pool->block_size);
}
}
VCOS_STATUS_T vcos_generic_blockpool_init(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
void *start, VCOS_UNSIGNED pool_size, VCOS_UNSIGNED align,
VCOS_UNSIGNED flags, const char *name)
{
VCOS_STATUS_T status = VCOS_SUCCESS;
vcos_unused(name);
vcos_unused(flags);
vcos_log_trace(
"%s: pool %p num_blocks %d block_size %d start %p pool_size %d name %p",
VCOS_FUNCTION, pool, num_blocks, block_size, start, pool_size, name);
vcos_demand(pool);
vcos_demand(start);
vcos_assert((block_size > 0));
vcos_assert(num_blocks > 0);
if (! align)
align = VCOS_BLOCKPOOL_ALIGN_DEFAULT;
if (align & 0x3)
{
vcos_log_error("%s: invalid alignment %d", VCOS_FUNCTION, align);
return VCOS_EINVAL;
}
if (VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align) > pool_size)
{
vcos_log_error("%s: Pool is too small" \
" num_blocks %d block_size %d align %d"
" pool_size %d required size %d", VCOS_FUNCTION,
num_blocks, block_size, align,
pool_size, (int) VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align));
return VCOS_ENOMEM;
}
status = vcos_mutex_create(&pool->mutex, "vcos blockpool mutex");
if (status != VCOS_SUCCESS)
return status;
pool->block_data_size = block_size;
/* TODO - create flag that if set forces the header to be in its own cache
* line */
pool->block_size = VCOS_BLOCKPOOL_ROUND_UP(pool->block_data_size +
(align >= 4096 ? 32 : 0) +
sizeof(VCOS_BLOCKPOOL_HEADER_T), align);
pool->magic = VCOS_BLOCKPOOL_MAGIC;
pool->num_subpools = 1;
pool->num_extension_blocks = 0;
pool->align = align;
memset(pool->subpools, 0, sizeof(pool->subpools));
vcos_generic_blockpool_subpool_init(pool, &pool->subpools[0], start,
pool_size, num_blocks, align, VCOS_BLOCKPOOL_SUBPOOL_FLAG_NONE);
return status;
}
VCOS_STATUS_T vcos_generic_blockpool_create_on_heap(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size, VCOS_UNSIGNED align,
VCOS_UNSIGNED flags, const char *name)
{
VCOS_STATUS_T status = VCOS_SUCCESS;
size_t size = VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align);
void* mem = vcos_malloc(size, name);
vcos_log_trace("%s: num_blocks %d block_size %d name %s",
VCOS_FUNCTION, num_blocks, block_size, name);
if (! mem)
return VCOS_ENOMEM;
status = vcos_generic_blockpool_init(pool, num_blocks,
block_size, mem, size, align, flags, name);
if (status != VCOS_SUCCESS)
goto fail;
pool->subpools[0].flags |= VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM;
return status;
fail:
free(mem);
return status;
}
VCOS_STATUS_T vcos_generic_blockpool_extend(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_extensions, VCOS_UNSIGNED num_blocks)
{
VCOS_UNSIGNED i;
ASSERT_POOL(pool);
vcos_log_trace("%s: pool %p num_extensions %d num_blocks %d",
VCOS_FUNCTION, pool, num_extensions, num_blocks);
/* Extend may only be called once */
if (pool->num_subpools > 1)
return VCOS_EACCESS;
if (num_extensions < 1 ||
num_extensions > VCOS_BLOCKPOOL_MAX_SUBPOOLS - 1)
return VCOS_EINVAL;
if (num_blocks < 1)
return VCOS_EINVAL;
pool->num_subpools += num_extensions;
pool->num_extension_blocks = num_blocks;
/* Mark these subpools as valid but unallocated */
for (i = 1; i < pool->num_subpools; ++i)
{
pool->subpools[i].magic = VCOS_BLOCKPOOL_SUBPOOL_MAGIC;
pool->subpools[i].start = NULL;
pool->subpools[i].mem = NULL;
}
return VCOS_SUCCESS;
}
void *vcos_generic_blockpool_alloc(VCOS_BLOCKPOOL_T *pool)
{
VCOS_UNSIGNED i;
void* ret = NULL;
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = NULL;
ASSERT_POOL(pool);
vcos_mutex_lock(&pool->mutex);
/* Starting with the main pool try and find a free block */
for (i = 0; i < pool->num_subpools; ++i)
{
if (pool->subpools[i].start && pool->subpools[i].available_blocks > 0)
{
subpool = &pool->subpools[i];
break; /* Found a subpool with free blocks */
}
}
if (! subpool)
{
/* All current subpools are full, try to allocate a new one */
for (i = 1; i < pool->num_subpools; ++i)
{
if (! pool->subpools[i].start)
{
VCOS_BLOCKPOOL_SUBPOOL_T *s = &pool->subpools[i];
size_t size = VCOS_BLOCKPOOL_SIZE(pool->num_extension_blocks,
pool->block_data_size, pool->align);
void *mem = vcos_malloc(size, pool->name);
if (mem)
{
vcos_log_trace("%s: Allocated subpool %d", VCOS_FUNCTION, i);
vcos_generic_blockpool_subpool_init(pool, s, mem, size,
pool->num_extension_blocks,
pool->align,
VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM |
VCOS_BLOCKPOOL_SUBPOOL_FLAG_EXTENSION);
subpool = s;
break; /* Created a subpool */
}
else
{
vcos_log_warn("%s: Failed to allocate subpool", VCOS_FUNCTION);
}
}
}
}
if (subpool)
{
/* Remove from free list */
VCOS_BLOCKPOOL_HEADER_T* nb = subpool->free_list;
vcos_assert(subpool->free_list);
subpool->free_list = nb->owner.next;
/* Owner is pool so free can be called without passing pool
* as a parameter */
nb->owner.subpool = subpool;
ret = nb + 1; /* Return pointer to block data */
--(subpool->available_blocks);
}
vcos_mutex_unlock(&pool->mutex);
VCOS_BLOCKPOOL_DEBUG_LOG("pool %p subpool %p ret %p", pool, subpool, ret);
if (ret)
{
vcos_assert(ret > subpool->start);
vcos_assert(ret < subpool->end);
}
return ret;
}
void *vcos_generic_blockpool_calloc(VCOS_BLOCKPOOL_T *pool)
{
void* ret = vcos_generic_blockpool_alloc(pool);
if (ret)
memset(ret, 0, pool->block_data_size);
return ret;
}
void vcos_generic_blockpool_free(void *block)
{
VCOS_BLOCKPOOL_DEBUG_LOG("block %p", block);
if (block)
{
VCOS_BLOCKPOOL_HEADER_T* hdr = (VCOS_BLOCKPOOL_HEADER_T*) block - 1;
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = hdr->owner.subpool;
VCOS_BLOCKPOOL_T *pool = NULL;
ASSERT_SUBPOOL(subpool);
pool = subpool->owner;
ASSERT_POOL(pool);
vcos_mutex_lock(&pool->mutex);
vcos_assert((unsigned) subpool->available_blocks < subpool->num_blocks);
/* Change ownership of block to be the free list */
hdr->owner.next = subpool->free_list;
subpool->free_list = hdr;
++(subpool->available_blocks);
if (VCOS_BLOCKPOOL_OVERWRITE_ON_FREE)
memset(block, 0xBD, pool->block_data_size); /* For debugging */
if ( (subpool->flags & VCOS_BLOCKPOOL_SUBPOOL_FLAG_EXTENSION) &&
subpool->available_blocks == subpool->num_blocks)
{
VCOS_BLOCKPOOL_DEBUG_LOG("%s: freeing subpool %p mem %p", VCOS_FUNCTION,
subpool, subpool->mem);
/* Free the sub-pool if it was dynamically allocated */
vcos_free(subpool->mem);
subpool->mem = NULL;
subpool->start = NULL;
}
vcos_mutex_unlock(&pool->mutex);
}
}
VCOS_UNSIGNED vcos_generic_blockpool_available_count(VCOS_BLOCKPOOL_T *pool)
{
VCOS_UNSIGNED ret = 0;
VCOS_UNSIGNED i;
ASSERT_POOL(pool);
vcos_mutex_lock(&pool->mutex);
for (i = 0; i < pool->num_subpools; ++i)
{
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i];
ASSERT_SUBPOOL(subpool);
/* Assume the malloc of sub pool would succeed */
if (subpool->start)
ret += subpool->available_blocks;
else
ret += pool->num_extension_blocks;
}
vcos_mutex_unlock(&pool->mutex);
return ret;
}
VCOS_UNSIGNED vcos_generic_blockpool_used_count(VCOS_BLOCKPOOL_T *pool)
{
VCOS_UNSIGNED ret = 0;
VCOS_UNSIGNED i;
ASSERT_POOL(pool);
vcos_mutex_lock(&pool->mutex);
for (i = 0; i < pool->num_subpools; ++i)
{
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i];
ASSERT_SUBPOOL(subpool);
if (subpool->start)
ret += (subpool->num_blocks - subpool->available_blocks);
}
vcos_mutex_unlock(&pool->mutex);
return ret;
}
void vcos_generic_blockpool_delete(VCOS_BLOCKPOOL_T *pool)
{
vcos_log_trace("%s: pool %p", VCOS_FUNCTION, pool);
if (pool)
{
VCOS_UNSIGNED i;
ASSERT_POOL(pool);
for (i = 0; i < pool->num_subpools; ++i)
{
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i];
ASSERT_SUBPOOL(subpool);
if (subpool->mem)
{
/* For debugging */
memset(subpool->mem,
0xBE,
VCOS_BLOCKPOOL_SIZE(subpool->num_blocks,
pool->block_data_size, pool->align));
if (subpool->flags & VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM)
vcos_free(subpool->mem);
subpool->mem = NULL;
subpool->start = NULL;
}
}
vcos_mutex_delete(&pool->mutex);
memset(pool, 0xBE, sizeof(VCOS_BLOCKPOOL_T)); /* For debugging */
}
}
uint32_t vcos_generic_blockpool_elem_to_handle(void *block)
{
uint32_t ret = -1;
uint32_t index = -1;
VCOS_BLOCKPOOL_HEADER_T *hdr = NULL;
VCOS_BLOCKPOOL_T *pool = NULL;
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = NULL;
uint32_t subpool_id;
vcos_assert(block);
hdr = (VCOS_BLOCKPOOL_HEADER_T*) block - 1;
subpool = hdr->owner.subpool;
ASSERT_SUBPOOL(subpool);
pool = subpool->owner;
ASSERT_POOL(pool);
vcos_mutex_lock(&pool->mutex);
/* The handle is the index into the array of blocks combined
* with the subpool id.
*/
index = ((size_t) hdr - (size_t) subpool->start) / pool->block_size;
vcos_assert(index < subpool->num_blocks);
subpool_id = ((char*) subpool - (char*) &pool->subpools[0]) /
sizeof(VCOS_BLOCKPOOL_SUBPOOL_T);
vcos_assert(subpool_id < VCOS_BLOCKPOOL_MAX_SUBPOOLS);
vcos_assert(subpool_id < pool->num_subpools);
ret = VCOS_BLOCKPOOL_HANDLE_CREATE(index, subpool_id);
vcos_log_trace("%s: index %d subpool_id %d handle 0x%08x",
VCOS_FUNCTION, index, subpool_id, ret);
vcos_mutex_unlock(&pool->mutex);
return ret;
}
void *vcos_generic_blockpool_elem_from_handle(
VCOS_BLOCKPOOL_T *pool, uint32_t handle)
{
VCOS_BLOCKPOOL_SUBPOOL_T *subpool;
uint32_t subpool_id;
uint32_t index;
void *ret = NULL;
ASSERT_POOL(pool);
vcos_mutex_lock(&pool->mutex);
subpool_id = VCOS_BLOCKPOOL_HANDLE_GET_SUBPOOL(handle);
if (subpool_id < pool->num_subpools)
{
index = VCOS_BLOCKPOOL_HANDLE_GET_INDEX(handle);
subpool = &pool->subpools[subpool_id];
if (pool->subpools[subpool_id].magic == VCOS_BLOCKPOOL_SUBPOOL_MAGIC &&
pool->subpools[subpool_id].mem && index < subpool->num_blocks)
{
VCOS_BLOCKPOOL_HEADER_T *hdr = (VCOS_BLOCKPOOL_HEADER_T*)
((size_t) subpool->start + (index * pool->block_size));
if (hdr->owner.subpool == subpool) /* Check block is allocated */
ret = hdr + 1;
}
}
vcos_mutex_unlock(&pool->mutex);
vcos_log_trace("%s: pool %p handle 0x%08x elem %p", VCOS_FUNCTION, pool,
handle, ret);
return ret;
}
uint32_t vcos_generic_blockpool_is_valid_elem(
VCOS_BLOCKPOOL_T *pool, const void *block)
{
uint32_t ret = 0;
const char *pool_end;
VCOS_UNSIGNED i = 0;
ASSERT_POOL(pool);
if (((size_t) block) & 0x3)
return 0;
vcos_mutex_lock(&pool->mutex);
for (i = 0; i < pool->num_subpools; ++i)
{
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i];
ASSERT_SUBPOOL(subpool);
if (subpool->mem && subpool->start)
{
pool_end = (const char*)subpool->start +
(subpool->num_blocks * pool->block_size);
if ((const char*)block > (const char*)subpool->start &&
(const char*)block < pool_end)
{
const VCOS_BLOCKPOOL_HEADER_T *hdr = (
const VCOS_BLOCKPOOL_HEADER_T*) block - 1;
/* If the block has a header where the owner points to the pool then
* it's a valid block. */
ret = (hdr->owner.subpool == subpool && subpool->owner == pool);
break;
}
}
}
vcos_mutex_unlock(&pool->mutex);
return ret;
}
@@ -0,0 +1,294 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - event flags implemented via a semaphore
=============================================================================*/
#ifndef VCOS_GENERIC_BLOCKPOOL_H
#define VCOS_GENERIC_BLOCKPOOL_H
/**
* \file
*
* This provides a generic, thread safe implementation of a VCOS block pool
* fixed size memory allocator.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
/** Bits 0 to (VCOS_BLOCKPOOL_SUBPOOL_BITS - 1) are used to store the
* subpool id. */
#define VCOS_BLOCKPOOL_SUBPOOL_BITS 3
#define VCOS_BLOCKPOOL_MAX_SUBPOOLS (1 << VCOS_BLOCKPOOL_SUBPOOL_BITS)
/* Make zero an invalid handle at the cost of decreasing the maximum
* number of blocks (2^28) by 1. Alternatively, a spare bit could be
* used to indicated valid blocks but there are likely to be better
* uses for spare bits. e.g. allowing more subpools
*/
#define INDEX_OFFSET 1
#define VCOS_BLOCKPOOL_HANDLE_GET_INDEX(h) \
(((h) >> VCOS_BLOCKPOOL_SUBPOOL_BITS) - INDEX_OFFSET)
#define VCOS_BLOCKPOOL_HANDLE_GET_SUBPOOL(h) \
((h) & ((1 << VCOS_BLOCKPOOL_SUBPOOL_BITS) - 1))
#define VCOS_BLOCKPOOL_HANDLE_CREATE(i,s) \
((((i) + INDEX_OFFSET) << VCOS_BLOCKPOOL_SUBPOOL_BITS) | (s))
#define VCOS_BLOCKPOOL_INVALID_HANDLE 0
#define VCOS_BLOCKPOOL_ALIGN_DEFAULT sizeof(unsigned long)
#define VCOS_BLOCKPOOL_FLAG_NONE 0
typedef struct VCOS_BLOCKPOOL_HEADER_TAG
{
/* Blocks either refer to to the pool if they are allocated
* or the free list if they are available.
*/
union {
struct VCOS_BLOCKPOOL_HEADER_TAG *next;
struct VCOS_BLOCKPOOL_SUBPOOL_TAG* subpool;
} owner;
} VCOS_BLOCKPOOL_HEADER_T;
typedef struct VCOS_BLOCKPOOL_SUBPOOL_TAG
{
/** VCOS_BLOCKPOOL_SUBPOOL_MAGIC */
uint32_t magic;
VCOS_BLOCKPOOL_HEADER_T* free_list;
/* The start of the pool memory */
void *mem;
/* Address of the first block header */
void *start;
/* The end of the subpool */
void *end;
/** The number of blocks in this sub-pool */
VCOS_UNSIGNED num_blocks;
/** Current number of available blocks in this sub-pool */
VCOS_UNSIGNED available_blocks;
/** Pointers to the pool that owns this sub-pool */
struct VCOS_BLOCKPOOL_TAG* owner;
/** Define properties such as memory ownership */
uint32_t flags;
} VCOS_BLOCKPOOL_SUBPOOL_T;
typedef struct VCOS_BLOCKPOOL_TAG
{
/** VCOS_BLOCKPOOL_MAGIC */
uint32_t magic;
/** Thread safety for Alloc, Free, Delete, Stats */
VCOS_MUTEX_T mutex;
/** Alignment of block data pointers */
VCOS_UNSIGNED align;
/** Flags for future use e.g. cache options */
VCOS_UNSIGNED flags;
/** The size of the block data */
size_t block_data_size;
/** Block size inc overheads */
size_t block_size;
/** Name for debugging */
const char *name;
/* The number of subpools that may be used */
VCOS_UNSIGNED num_subpools;
/** Number of blocks in each dynamically allocated subpool */
VCOS_UNSIGNED num_extension_blocks;
/** Array of subpools. Subpool zero is is not deleted until the pool is
* destroed. If the index of the pool is < num_subpools and
* subpool[index.mem] is null then the subpool entry is valid but
* "not currently allocated" */
VCOS_BLOCKPOOL_SUBPOOL_T subpools[VCOS_BLOCKPOOL_MAX_SUBPOOLS];
} VCOS_BLOCKPOOL_T;
#define VCOS_BLOCKPOOL_ROUND_UP(x,s) (((x) + ((s) - 1)) & ~((s) - 1))
/**
* Calculates the size in bytes required for a block pool containing
* num_blocks of size block_size plus any overheads.
*
* The block pool header (VCOS_BLOCKPOOL_T) is allocated separately
*
* Overheads:
* block_size + header must be rounded up to meet the required alignment
* The start of the first block may need to be up to align bytes
* into the given buffer because statically allocated buffers within structures
* are not guaranteed to be aligned as required.
*/
#define VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align) \
((VCOS_BLOCKPOOL_ROUND_UP((block_size) + (align >= 4096 ? 32 : 0) + sizeof(VCOS_BLOCKPOOL_HEADER_T), \
(align)) * (num_blocks)) + (align))
/**
* Sanity check to verify whether a handle is potentially a blockpool handle
* when the pool pointer is not available.
*
* If the pool pointer is availabe use vcos_blockpool_elem_to_handle instead.
*
* @param handle the handle to verify
* @param max_blocks the expected maximum number of block in the pool
* that the handle belongs to.
*/
#define VCOS_BLOCKPOOL_IS_VALID_HANDLE_FORMAT(handle, max_blocks) \
((handle) != VCOS_BLOCKPOOL_INVALID_HANDLE \
&& VCOS_BLOCKPOOL_HANDLE_GET_INDEX((handle)) < (max_blocks))
VCOSPRE_
VCOS_STATUS_T VCOSPOST_ vcos_generic_blockpool_init(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
void *start, VCOS_UNSIGNED pool_size,
VCOS_UNSIGNED align, VCOS_UNSIGNED flags,
const char *name);
VCOSPRE_
VCOS_STATUS_T VCOSPOST_ vcos_generic_blockpool_create_on_heap(
VCOS_BLOCKPOOL_T *pool, VCOS_UNSIGNED num_blocks,
VCOS_UNSIGNED block_size,
VCOS_UNSIGNED align, VCOS_UNSIGNED flags,
const char *name);
VCOSPRE_
VCOS_STATUS_T VCOSPOST_ vcos_generic_blockpool_extend(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_extensions, VCOS_UNSIGNED num_blocks);
VCOSPRE_ void VCOSPOST_ *vcos_generic_blockpool_alloc(VCOS_BLOCKPOOL_T *pool);
VCOSPRE_ void VCOSPOST_ *vcos_generic_blockpool_calloc(VCOS_BLOCKPOOL_T *pool);
VCOSPRE_ void VCOSPOST_ vcos_generic_blockpool_free(void *block);
VCOSPRE_
VCOS_UNSIGNED VCOSPOST_ vcos_generic_blockpool_available_count(
VCOS_BLOCKPOOL_T *pool);
VCOSPRE_
VCOS_UNSIGNED VCOSPOST_ vcos_generic_blockpool_used_count(
VCOS_BLOCKPOOL_T *pool);
VCOSPRE_ void VCOSPOST_ vcos_generic_blockpool_delete(VCOS_BLOCKPOOL_T *pool);
VCOSPRE_ uint32_t VCOSPOST_ vcos_generic_blockpool_elem_to_handle(void *block);
VCOSPRE_ void VCOSPOST_
*vcos_generic_blockpool_elem_from_handle(
VCOS_BLOCKPOOL_T *pool, uint32_t handle);
VCOSPRE_ uint32_t VCOSPOST_
vcos_generic_blockpool_is_valid_elem(
VCOS_BLOCKPOOL_T *pool, const void *block);
#if defined(VCOS_INLINE_BODIES)
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_blockpool_init(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
void *start, VCOS_UNSIGNED pool_size,
VCOS_UNSIGNED align, VCOS_UNSIGNED flags, const char *name)
{
return vcos_generic_blockpool_init(pool, num_blocks, block_size,
start, pool_size, align, flags, name);
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_blockpool_create_on_heap(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
VCOS_UNSIGNED align, VCOS_UNSIGNED flags, const char *name)
{
return vcos_generic_blockpool_create_on_heap(
pool, num_blocks, block_size, align, flags, name);
}
VCOS_INLINE_IMPL
VCOS_STATUS_T VCOSPOST_ vcos_blockpool_extend(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_extensions, VCOS_UNSIGNED num_blocks)
{
return vcos_generic_blockpool_extend(pool, num_extensions, num_blocks);
}
VCOS_INLINE_IMPL
void *vcos_blockpool_alloc(VCOS_BLOCKPOOL_T *pool)
{
return vcos_generic_blockpool_alloc(pool);
}
VCOS_INLINE_IMPL
void *vcos_blockpool_calloc(VCOS_BLOCKPOOL_T *pool)
{
return vcos_generic_blockpool_calloc(pool);
}
VCOS_INLINE_IMPL
void vcos_blockpool_free(void *block)
{
vcos_generic_blockpool_free(block);
}
VCOS_INLINE_IMPL
VCOS_UNSIGNED vcos_blockpool_available_count(VCOS_BLOCKPOOL_T *pool)
{
return vcos_generic_blockpool_available_count(pool);
}
VCOS_INLINE_IMPL
VCOS_UNSIGNED vcos_blockpool_used_count(VCOS_BLOCKPOOL_T *pool)
{
return vcos_generic_blockpool_used_count(pool);
}
VCOS_INLINE_IMPL
void vcos_blockpool_delete(VCOS_BLOCKPOOL_T *pool)
{
vcos_generic_blockpool_delete(pool);
}
VCOS_INLINE_IMPL
uint32_t vcos_blockpool_elem_to_handle(void *block)
{
return vcos_generic_blockpool_elem_to_handle(block);
}
VCOS_INLINE_IMPL
void *vcos_blockpool_elem_from_handle(VCOS_BLOCKPOOL_T *pool, uint32_t handle)
{
return vcos_generic_blockpool_elem_from_handle(pool, handle);
}
VCOS_INLINE_IMPL
uint32_t vcos_blockpool_is_valid_elem(VCOS_BLOCKPOOL_T *pool, const void *block)
{
return vcos_generic_blockpool_is_valid_elem(pool, block);
}
#endif /* VCOS_INLINE_BODIES */
#ifdef __cplusplus
}
#endif
#endif /* VCOS_GENERIC_BLOCKPOOL_H */
@@ -0,0 +1,320 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - event flags implemented via mutexes
=============================================================================*/
#include "interface/vcos/vcos.h"
#include "interface/vcos/generic/vcos_generic_event_flags.h"
#include <stddef.h>
/** A structure created by a thread that waits on the event flags
* for a particular combination of flags to arrive.
*/
typedef struct VCOS_EVENT_WAITER_T
{
VCOS_UNSIGNED requested_events; /**< The events wanted */
VCOS_UNSIGNED actual_events; /**< Actual events found */
VCOS_UNSIGNED op; /**< The event operation to be used */
VCOS_STATUS_T return_status; /**< The return status the waiter should pass back */
VCOS_EVENT_FLAGS_T *flags; /**< Pointer to the original 'flags' structure */
VCOS_THREAD_T *thread; /**< Thread waiting */
struct VCOS_EVENT_WAITER_T *next;
} VCOS_EVENT_WAITER_T;
#ifndef NDEBUG
static int waiter_list_valid(VCOS_EVENT_FLAGS_T *flags);
#endif
static void event_flags_timer_expired(void *cxt);
VCOS_STATUS_T vcos_generic_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name)
{
VCOS_STATUS_T rc;
if ((rc=vcos_mutex_create(&flags->lock, name)) != VCOS_SUCCESS)
{
return rc;
}
flags->events = 0;
flags->waiters.head = flags->waiters.tail = 0;
return rc;
}
void vcos_generic_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
VCOS_UNSIGNED bitmask,
VCOS_OPTION op)
{
vcos_assert(flags);
vcos_mutex_lock(&flags->lock);
if (op == VCOS_OR)
{
flags->events |= bitmask;
}
else if (op == VCOS_AND)
{
flags->events &= bitmask;
}
else
{
vcos_assert(0);
}
/* Now wake up any threads that have now become signalled. */
if (flags->waiters.head != NULL)
{
VCOS_UNSIGNED consumed_events = 0;
VCOS_EVENT_WAITER_T **pcurrent_waiter = &flags->waiters.head;
VCOS_EVENT_WAITER_T *prev_waiter = NULL;
/* Walk the chain of tasks suspend on this event flag group to determine
* if any of their requests can be satisfied.
*/
while ((*pcurrent_waiter) != NULL)
{
VCOS_EVENT_WAITER_T *curr_waiter = *pcurrent_waiter;
/* Determine if this request has been satisfied */
/* First, find the event flags in common. */
VCOS_UNSIGNED waiter_satisfied = flags->events & curr_waiter->requested_events;
/* Second, determine if all the event flags must match */
if (curr_waiter->op & VCOS_AND)
{
/* All requested events must be present */
waiter_satisfied = (waiter_satisfied == curr_waiter->requested_events);
}
/* Wake this one up? */
if (waiter_satisfied)
{
if (curr_waiter->op & VCOS_CONSUME)
{
consumed_events |= curr_waiter->requested_events;
}
/* remove this block from the list, taking care at the end */
*pcurrent_waiter = curr_waiter->next;
if (curr_waiter->next == NULL)
flags->waiters.tail = prev_waiter;
vcos_assert(waiter_list_valid(flags));
curr_waiter->return_status = VCOS_SUCCESS;
curr_waiter->actual_events = flags->events;
_vcos_thread_sem_post(curr_waiter->thread);
}
else
{
/* move to next element in the list */
prev_waiter = *pcurrent_waiter;
pcurrent_waiter = &(curr_waiter->next);
}
}
flags->events &= ~consumed_events;
}
vcos_mutex_unlock(&flags->lock);
}
void vcos_generic_event_flags_delete(VCOS_EVENT_FLAGS_T *flags)
{
vcos_mutex_delete(&flags->lock);
}
extern VCOS_STATUS_T vcos_generic_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
VCOS_UNSIGNED bitmask,
VCOS_OPTION op,
VCOS_UNSIGNED suspend,
VCOS_UNSIGNED *retrieved_bits)
{
VCOS_EVENT_WAITER_T waitreq;
VCOS_STATUS_T rc = VCOS_EAGAIN;
int satisfied = 0;
vcos_assert(flags);
/* default retrieved bits to 0 */
*retrieved_bits = 0;
vcos_mutex_lock(&flags->lock);
switch (op & VCOS_EVENT_FLAG_OP_MASK)
{
case VCOS_AND:
if ((flags->events & bitmask) == bitmask)
{
*retrieved_bits = flags->events;
rc = VCOS_SUCCESS;
satisfied = 1;
if (op & VCOS_CONSUME)
flags->events &= ~bitmask;
}
break;
case VCOS_OR:
if (flags->events & bitmask)
{
*retrieved_bits = flags->events;
rc = VCOS_SUCCESS;
satisfied = 1;
if (op & VCOS_CONSUME)
flags->events &= ~bitmask;
}
break;
default:
vcos_assert(0);
rc = VCOS_EINVAL;
break;
}
if (!satisfied && suspend)
{
/* Have to go to sleep.
*
* Append to tail so we get FIFO ordering.
*/
waitreq.requested_events = bitmask;
waitreq.op = op;
waitreq.return_status = VCOS_EAGAIN;
waitreq.flags = flags;
waitreq.actual_events = 0;
waitreq.thread = vcos_thread_current();
waitreq.next = 0;
vcos_assert(waitreq.thread != (VCOS_THREAD_T*)-1);
VCOS_QUEUE_APPEND_TAIL(&flags->waiters, &waitreq);
if (suspend != (VCOS_UNSIGNED)-1)
_vcos_task_timer_set(event_flags_timer_expired, &waitreq, suspend);
vcos_mutex_unlock(&flags->lock);
/* go to sleep and wait to be signalled or timeout */
_vcos_thread_sem_wait();
*retrieved_bits = waitreq.actual_events;
rc = waitreq.return_status;
/* cancel the timer - do not do this while holding the mutex as it
* might be waiting for the timeout function to complete, which will
* try to take the mutex.
*/
if (suspend != (VCOS_UNSIGNED)-1)
_vcos_task_timer_cancel();
}
else
{
vcos_mutex_unlock(&flags->lock);
}
return rc;
}
/** Called when a get call times out. Remove this thread's
* entry from the waiting queue, then resume the thread.
*/
static void event_flags_timer_expired(void *cxt)
{
VCOS_EVENT_WAITER_T *waitreq = (VCOS_EVENT_WAITER_T *)cxt;
VCOS_EVENT_FLAGS_T *flags = waitreq->flags;
VCOS_EVENT_WAITER_T **plist;
VCOS_EVENT_WAITER_T *prev = NULL;
VCOS_THREAD_T *thread = 0;
vcos_assert(flags);
vcos_mutex_lock(&flags->lock);
/* walk the list of waiting threads on this event group, and remove
* the one that has expired.
*
* FIXME: could use doubly-linked list if lots of threads are found
* to be waiting on a single event flag instance.
*/
plist = &flags->waiters.head;
while (*plist != NULL)
{
if (*plist == waitreq)
{
int at_end;
/* found it */
thread = (*plist)->thread;
at_end = ((*plist)->next == NULL);
/* link past */
*plist = (*plist)->next;
if (at_end)
flags->waiters.tail = prev;
break;
}
prev = *plist;
plist = &(*plist)->next;
}
vcos_assert(waiter_list_valid(flags));
vcos_mutex_unlock(&flags->lock);
if (thread)
{
_vcos_thread_sem_post(thread);
}
}
#ifndef NDEBUG
static int waiter_list_valid(VCOS_EVENT_FLAGS_T *flags)
{
int valid;
/* Either both head and tail are NULL, or neither are NULL */
if (flags->waiters.head == NULL)
{
valid = (flags->waiters.tail == NULL);
}
else
{
valid = (flags->waiters.tail != NULL);
}
/* If head and tail point at the same non-NULL element, then there
* is only one element in the list.
*/
if (flags->waiters.head && (flags->waiters.head == flags->waiters.tail))
{
valid = (flags->waiters.head->next == NULL);
}
return valid;
}
#endif
@@ -0,0 +1,127 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - event flags implemented via a semaphore
=============================================================================*/
#ifndef VCOS_GENERIC_EVENT_FLAGS_H
#define VCOS_GENERIC_EVENT_FLAGS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
/**
* \file
*
* This provides event flags (as per Nucleus Event Groups) based on a
* mutex, a semaphore (per waiting thread) and a timer (per waiting
* thread).
*
* The data structure is a 32 bit unsigned int (the current set of
* flags) and a linked list of clients waiting to be 'satisfied'.
*
* The mutex merely locks access to the data structure. If a client
* calls vcos_event_flags_get() and the requested bits are not already
* present, it then sleeps on its per-thread semaphore after adding
* this semaphore to the queue waiting. It also sets up a timer.
*
* The per-thread semaphore and timer are actually stored in the
* thread context (joinable thread). In future it may become necessary
* to support non-VCOS threads by using thread local storage to
* create these objects and associate them with the thread.
*/
struct VCOS_EVENT_WAITER_T;
typedef struct VCOS_EVENT_FLAGS_T
{
VCOS_UNSIGNED events; /**< Events currently set */
VCOS_MUTEX_T lock; /**< Serialize access */
struct
{
struct VCOS_EVENT_WAITER_T *head; /**< List of threads waiting */
struct VCOS_EVENT_WAITER_T *tail; /**< List of threads waiting */
} waiters;
} VCOS_EVENT_FLAGS_T;
#define VCOS_OR 1
#define VCOS_AND 2
#define VCOS_CONSUME 4
#define VCOS_OR_CONSUME (VCOS_OR | VCOS_CONSUME)
#define VCOS_AND_CONSUME (VCOS_AND | VCOS_CONSUME)
#define VCOS_EVENT_FLAG_OP_MASK (VCOS_OR|VCOS_AND)
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_generic_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name);
VCOSPRE_ void VCOSPOST_ vcos_generic_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
VCOS_UNSIGNED events,
VCOS_OPTION op);
VCOSPRE_ void VCOSPOST_ vcos_generic_event_flags_delete(VCOS_EVENT_FLAGS_T *);
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_generic_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
VCOS_UNSIGNED requested_events,
VCOS_OPTION op,
VCOS_UNSIGNED suspend,
VCOS_UNSIGNED *retrieved_events);
#ifdef VCOS_INLINE_BODIES
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name) {
return vcos_generic_event_flags_create(flags, name);
}
VCOS_INLINE_IMPL
void vcos_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
VCOS_UNSIGNED events,
VCOS_OPTION op) {
vcos_generic_event_flags_set(flags, events, op);
}
VCOS_INLINE_IMPL
void vcos_event_flags_delete(VCOS_EVENT_FLAGS_T *f) {
vcos_generic_event_flags_delete(f);
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
VCOS_UNSIGNED requested_events,
VCOS_OPTION op,
VCOS_UNSIGNED suspend,
VCOS_UNSIGNED *retrieved_events) {
return vcos_generic_event_flags_get(flags, requested_events, op, suspend, retrieved_events);
}
#endif /* VCOS_INLINE_BODIES */
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,268 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define VCOS_LOG_CATEGORY (&vcos_named_sem_log_cat)
#include "interface/vcos/vcos.h"
#include "interface/vcos/generic/vcos_generic_named_sem.h"
#include "interface/vcos/vcos_blockpool.h"
#if defined(VCOS_LOGGING_ENABLED)
static VCOS_LOG_CAT_T vcos_named_sem_log_cat =
VCOS_LOG_INIT("vcos_named_sem", VCOS_LOG_ERROR);
#endif
/**
* \file
*
* Named semaphores, primarily for VCFW.
*
* Does not actually work across processes; merely emulate the API.
*
* The client initialises a VCOS_NAMED_SEMAPHORE_T, but this merely
* points at the real underlying VCOS_NAMED_SEMAPHORE_IMPL_T.
*
* semaphore_t ---\
* ----- semaphore_impl_t
* semaphore_t ---/
* /
* semaphore_t -/
*
*/
/* Maintain a block pool of semaphore implementations */
#define NUM_SEMS 16
/* Allow the pool to expand to MAX_SEMS in size */
#define MAX_SEMS 512
/** Each actual real semaphore is stored in one of these. Clients just
* get a structure with a pointer to this in it.
*
* It also contains a doubly linked list tracking the semaphores in-use.
*/
typedef struct VCOS_NAMED_SEMAPHORE_IMPL_T
{
VCOS_SEMAPHORE_T sem; /**< Actual underlying semaphore */
char name[VCOS_NAMED_SEMAPHORE_NAMELEN]; /**< Name of semaphore, copied */
unsigned refs; /**< Reference count */
struct VCOS_NAMED_SEMAPHORE_IMPL_T *next; /**< Next in the in-use list */
struct VCOS_NAMED_SEMAPHORE_IMPL_T *prev; /**< Previous in the in-use list */
} VCOS_NAMED_SEMAPHORE_IMPL_T;
static VCOS_MUTEX_T lock;
static VCOS_NAMED_SEMAPHORE_IMPL_T* sems_in_use = NULL;
static int sems_in_use_count = 0;
static int sems_total_ref_count = 0;
static VCOS_BLOCKPOOL_T sems_pool;
static char pool_mem[VCOS_BLOCKPOOL_SIZE(
NUM_SEMS, sizeof(VCOS_NAMED_SEMAPHORE_IMPL_T), VCOS_BLOCKPOOL_ALIGN_DEFAULT)];
VCOS_STATUS_T _vcos_named_semaphore_init()
{
VCOS_STATUS_T status;
status = vcos_blockpool_init(&sems_pool,
NUM_SEMS, sizeof(VCOS_NAMED_SEMAPHORE_IMPL_T),
pool_mem, sizeof(pool_mem),
VCOS_BLOCKPOOL_ALIGN_DEFAULT, 0, "vcos named semaphores");
if (status != VCOS_SUCCESS)
goto fail_blockpool;
status = vcos_blockpool_extend(&sems_pool, VCOS_BLOCKPOOL_MAX_SUBPOOLS - 1,
(MAX_SEMS - NUM_SEMS) / (VCOS_BLOCKPOOL_MAX_SUBPOOLS - 1));
if (status != VCOS_SUCCESS)
goto fail_extend;
status = vcos_mutex_create(&lock, "vcosnmsem");
if (status != VCOS_SUCCESS)
goto fail_mutex;
return status;
fail_mutex:
fail_extend:
vcos_blockpool_delete(&sems_pool);
fail_blockpool:
return status;
}
void _vcos_named_semaphore_deinit(void)
{
vcos_blockpool_delete(&sems_pool);
vcos_mutex_delete(&lock);
sems_in_use = NULL;
}
VCOS_STATUS_T
vcos_generic_named_semaphore_create(VCOS_NAMED_SEMAPHORE_T *sem,
const char *name, VCOS_UNSIGNED count)
{
VCOS_STATUS_T status = VCOS_ENOSPC;
int name_len, cmp = -1;
VCOS_NAMED_SEMAPHORE_IMPL_T *impl;
VCOS_NAMED_SEMAPHORE_IMPL_T *new_impl;
vcos_log_trace("%s: sem %p name %s count %d", __FUNCTION__,
sem, (name ? name : "null"), count);
vcos_assert(name);
vcos_mutex_lock(&lock);
name_len = vcos_strlen(name);
if (name_len >= VCOS_NAMED_SEMAPHORE_NAMELEN)
{
vcos_assert(0);
status = VCOS_EINVAL;
goto end;
}
/* do we already have this semaphore? */
impl = sems_in_use;
while (impl && (cmp = vcos_strcmp(name, impl->name)) < 0)
impl = impl->next;
if (impl && cmp == 0)
{
/* Semaphore is already in use so just increase the ref count */
impl->refs++;
sems_total_ref_count++;
sem->actual = impl;
sem->sem = &impl->sem;
status = VCOS_SUCCESS;
vcos_log_trace(
"%s: ref count %d name %s total refs %d num sems %d",
__FUNCTION__, impl->refs, impl->name,
sems_total_ref_count, sems_in_use_count);
goto end;
}
/* search for unused semaphore */
new_impl = vcos_blockpool_calloc(&sems_pool);
if (new_impl)
{
status = vcos_semaphore_create(&new_impl->sem, name, count);
if (status == VCOS_SUCCESS)
{
new_impl->refs = 1;
sems_total_ref_count++;
sems_in_use_count++;
memcpy(new_impl->name, name, name_len + 1); /* already checked length! */
sem->actual = new_impl;
sem->sem = &new_impl->sem;
/* Insert into the sorted list
* impl is either NULL or the first element where
* name > impl->name.
*/
if (impl)
{
new_impl->prev = impl->prev;
impl->prev = new_impl;
new_impl->next = impl;
if (new_impl->prev)
new_impl->prev->next = new_impl;
}
else
{
/* Appending to the tail of the list / empty list */
VCOS_NAMED_SEMAPHORE_IMPL_T *tail = sems_in_use;
while(tail && tail->next)
tail = tail->next;
if (tail)
{
tail->next = new_impl;
new_impl->prev = tail;
}
}
if (sems_in_use == impl)
{
/* Inserted at head or list was empty */
sems_in_use = new_impl;
}
vcos_log_trace(
"%s: new ref actual %p prev %p next %p count %d name %s " \
"total refs %d num sems %d",
__FUNCTION__,
new_impl, new_impl->prev, new_impl->next,
new_impl->refs, new_impl->name,
sems_total_ref_count, sems_in_use_count);
}
}
end:
vcos_mutex_unlock(&lock);
if (status != VCOS_SUCCESS)
{
vcos_log_error("%s: failed to create named semaphore name %s status %d " \
"total refs %d num sems %d",
__FUNCTION__, (name ? name : "NULL"), status,
sems_total_ref_count, sems_in_use_count);
}
return status;
}
void vcos_named_semaphore_delete(VCOS_NAMED_SEMAPHORE_T *sem)
{
VCOS_NAMED_SEMAPHORE_IMPL_T *actual = sem->actual;
vcos_mutex_lock(&lock);
/* if this fires, the semaphore has already been deleted */
vcos_assert(actual->refs);
vcos_log_trace(
"%s: actual %p ref count %d name %s prev %p next %p total refs %d num sems %d",
__FUNCTION__, actual, actual->refs, actual->name,
actual->prev, actual->next,
sems_total_ref_count, sems_in_use_count);
sems_total_ref_count--;
if (--actual->refs == 0)
{
sems_in_use_count--;
if (actual->prev)
actual->prev->next = actual->next;
if (actual->next)
actual->next->prev = actual->prev;
if (sems_in_use == actual)
sems_in_use = actual->next;
vcos_semaphore_delete(&actual->sem);
sem->actual = NULL;
sem->sem = NULL;
vcos_blockpool_free(actual);
}
vcos_mutex_unlock(&lock);
}
@@ -0,0 +1,101 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - named semaphores
=============================================================================*/
#ifndef VCOS_GENERIC_NAMED_SEM_H
#define VCOS_GENERIC_NAMED_SEM_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
/**
* \file
*
* Generic support for named semaphores, using regular ones. This is only
* suitable for emulating them on an embedded MMUless system, since there is
* no support for opening semaphores across process boundaries.
*
*/
#define VCOS_NAMED_SEMAPHORE_NAMELEN 64
/* In theory we could use the name facility provided within Nucleus. However, this
* is hard to do as semaphores are constantly being created and destroyed; we
* would need to stop everything while allocating the memory for the semaphore
* list and then walking it. So keep our own list.
*/
typedef struct VCOS_NAMED_SEMAPHORE_T
{
struct VCOS_NAMED_SEMAPHORE_IMPL_T *actual; /**< There are 'n' named semaphores per 1 actual semaphore */
VCOS_SEMAPHORE_T *sem; /**< Pointer to actual underlying semaphore */
} VCOS_NAMED_SEMAPHORE_T;
VCOSPRE_ VCOS_STATUS_T VCOSPOST_
vcos_generic_named_semaphore_create(VCOS_NAMED_SEMAPHORE_T *sem, const char *name, VCOS_UNSIGNED count);
VCOSPRE_ void VCOSPOST_ vcos_named_semaphore_delete(VCOS_NAMED_SEMAPHORE_T *sem);
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ _vcos_named_semaphore_init(void);
VCOSPRE_ void VCOSPOST_ _vcos_named_semaphore_deinit(void);
#if defined(VCOS_INLINE_BODIES)
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_named_semaphore_create(VCOS_NAMED_SEMAPHORE_T *sem, const char *name, VCOS_UNSIGNED count) {
return vcos_generic_named_semaphore_create(sem, name, count);
}
VCOS_INLINE_IMPL
void vcos_named_semaphore_wait(VCOS_NAMED_SEMAPHORE_T *sem) {
vcos_semaphore_wait(sem->sem);
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_named_semaphore_trywait(VCOS_NAMED_SEMAPHORE_T *sem) {
return vcos_semaphore_trywait(sem->sem);
}
VCOS_INLINE_IMPL
void vcos_named_semaphore_post(VCOS_NAMED_SEMAPHORE_T *sem) {
vcos_semaphore_post(sem->sem);
}
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,95 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - reentrant mutexes created from regular ones.
=============================================================================*/
#ifndef VCOS_GENERIC_QUICKSLOW_MUTEX_H
#define VCOS_GENERIC_QUICKSLOW_MUTEX_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
/**
* \file
*
* Quickslow Mutexes implemented as regular ones (i.e. quick and slow modes are the same).
*
*/
typedef VCOS_MUTEX_T VCOS_QUICKSLOW_MUTEX_T;
#if defined(VCOS_INLINE_BODIES)
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_quickslow_mutex_create(VCOS_QUICKSLOW_MUTEX_T *m, const char *name)
{
return vcos_mutex_create(m, name);
}
VCOS_INLINE_IMPL
void vcos_quickslow_mutex_delete(VCOS_QUICKSLOW_MUTEX_T *m)
{
vcos_mutex_delete(m);
}
VCOS_INLINE_IMPL
void vcos_quickslow_mutex_lock(VCOS_QUICKSLOW_MUTEX_T *m)
{
while (vcos_mutex_lock(m) == VCOS_EAGAIN);
}
VCOS_INLINE_IMPL
void vcos_quickslow_mutex_unlock(VCOS_QUICKSLOW_MUTEX_T *m)
{
vcos_mutex_unlock(m);
}
VCOS_INLINE_IMPL
void vcos_quickslow_mutex_lock_quick(VCOS_QUICKSLOW_MUTEX_T *m)
{
while (vcos_mutex_lock(m) == VCOS_EAGAIN);
}
VCOS_INLINE_IMPL
void vcos_quickslow_mutex_unlock_quick(VCOS_QUICKSLOW_MUTEX_T *m)
{
vcos_mutex_unlock(m);
}
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,76 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "interface/vcos/vcos.h"
#include "interface/vcos/vcos_reentrant_mutex.h"
VCOS_STATUS_T vcos_generic_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name)
{
m->count = 0;
m->owner = 0;
return vcos_mutex_create(&m->mutex, name);
}
void vcos_generic_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m)
{
vcos_assert(m->count == 0);
vcos_mutex_delete(&m->mutex);
}
void vcos_generic_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m)
{
VCOS_THREAD_T *thread = vcos_thread_current();
vcos_assert(m);
vcos_assert(thread != 0);
if (m->owner != thread)
{
vcos_mutex_lock(&m->mutex);
m->owner = thread;
vcos_assert(m->count == 0);
}
m->count++;
}
void vcos_generic_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m)
{
vcos_assert(m->count != 0);
vcos_assert(m->owner == vcos_thread_current());
m->count--;
if (m->count == 0)
{
m->owner = 0;
vcos_mutex_unlock(&m->mutex);
}
}
@@ -0,0 +1,95 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - reentrant mutexes created from regular ones.
=============================================================================*/
#ifndef VCOS_GENERIC_REENTRANT_MUTEX_H
#define VCOS_GENERIC_REENTRANT_MUTEX_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
/**
* \file
*
* Reentrant Mutexes from regular ones.
*
*/
typedef struct VCOS_REENTRANT_MUTEX_T
{
VCOS_MUTEX_T mutex;
VCOS_THREAD_T *owner;
unsigned count;
} VCOS_REENTRANT_MUTEX_T;
/* Extern definitions of functions that do the actual work */
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_generic_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name);
VCOSPRE_ void VCOSPOST_ vcos_generic_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m);
VCOSPRE_ void VCOSPOST_ vcos_generic_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m);
VCOSPRE_ void VCOSPOST_ vcos_generic_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m);
/* Inline forwarding functions */
#if defined(VCOS_INLINE_BODIES)
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name) {
return vcos_generic_reentrant_mutex_create(m,name);
}
VCOS_INLINE_IMPL
void vcos_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m) {
vcos_generic_reentrant_mutex_delete(m);
}
VCOS_INLINE_IMPL
void vcos_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m) {
vcos_generic_reentrant_mutex_lock(m);
}
VCOS_INLINE_IMPL
void vcos_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m) {
vcos_generic_reentrant_mutex_unlock(m);
}
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,130 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*****************************************************************************
* Copyright 2012 Broadcom Corporation. All rights reserved.
*
* This program is the proprietary software of Broadcom Corporation and/or
* its licensors, and may only be used, duplicated, modified or distributed
* pursuant to the terms and conditions of a separate, written license
* agreement executed between you and Broadcom (an "Authorized License").
* Except as set forth in an Authorized License, Broadcom grants no license
* (express or implied), right to use, or waiver of any kind with respect to
* the Software, and Broadcom expressly reserves all rights in and to the
* Software and all intellectual property rights therein. IF YOU HAVE NO
* AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY
* WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE ALL USE OF
* THE SOFTWARE.
*
* Except as expressly set forth in the Authorized License,
* 1. This program, including its structure, sequence and organization,
* constitutes the valuable trade secrets of Broadcom, and you shall use
* all reasonable efforts to protect the confidentiality thereof, and to
* use this information only in connection with your use of Broadcom
* integrated circuit products.
* 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
* RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL
* IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS
* FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS,
* QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. YOU
* ASSUME THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE.
* 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
* LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT,
* OR EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO
* YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS
* OF THE AMOUNT ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER
* IS GREATER. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF
* ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.
*****************************************************************************/
#include "interface/vcos/vcos.h"
#if defined( __KERNEL__ )
#include <linux/string.h>
#include <linux/module.h>
#else
#include <string.h>
#endif
#include <stdarg.h>
/** Like vsnprintf, except it places the output at the specified offset.
* Output is truncated to fit in buflen bytes, and is guaranteed to be NUL-terminated.
* Returns the string length before/without truncation.
*/
size_t vcos_safe_vsprintf(char *buf, size_t buflen, size_t offset, const char *fmt, va_list ap)
{
size_t space = (offset < buflen) ? (buflen - offset) : 0;
offset += vcos_vsnprintf(buf ? (buf + offset) : NULL, space, fmt, ap);
return offset;
}
/** Like snprintf, except it places the output at the specified offset.
* Output is truncated to fit in buflen bytes, and is guaranteed to be NUL-terminated.
* Returns the string length before/without truncation.
*/
size_t vcos_safe_sprintf(char *buf, size_t buflen, size_t offset, const char *fmt, ...)
{
size_t space = (offset < buflen) ? (buflen - offset) : 0;
va_list ap;
va_start(ap, fmt);
offset += vcos_vsnprintf(buf ? (buf + offset) : NULL, space, fmt, ap);
va_end(ap);
return offset;
}
/** Copies string src to dst at the specified offset.
* Output is truncated to fit in dstlen bytes, i.e. the string is at most
* (buflen - 1) characters long. Unlike strncpy, exactly one NUL is written
* to dst, which is always NUL-terminated.
* Returns the string length before/without truncation.
*/
size_t vcos_safe_strcpy(char *dst, const char *src, size_t dstlen, size_t offset)
{
if (offset < dstlen)
{
const char *p = src;
char *endp = dst + dstlen -1;
dst += offset;
for (; *p!='\0' && dst != endp; dst++, p++)
*dst = *p;
*dst = '\0';
}
offset += strlen(src);
return offset;
}
@@ -0,0 +1,164 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - generic thread local storage
=============================================================================*/
#ifndef VCOS_GENERIC_TLS_H
#define VCOS_GENERIC_TLS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "interface/vcos/vcos_types.h"
/**
* \file
*
* Do an emulation of Thread Local Storage. The platform needs to
* provide a way to set and get a per-thread pointer which is
* where the TLS data itself is stored.
*
*
* Each thread that wants to join in this scheme needs to call
* vcos_tls_thread_register().
*
* The platform needs to support the macros/functions
* _vcos_tls_thread_ptr_set() and _vcos_tls_thread_ptr_get().
*/
#ifndef VCOS_WANT_TLS_EMULATION
#error Should not be included unless TLS emulation is defined
#endif
/** Number of slots to reserve per thread. This results in an overhead
* of this many words per thread.
*/
#define VCOS_TLS_MAX_SLOTS 4
/** TLS key. Allocating one of these reserves the client one of the
* available slots.
*/
typedef VCOS_UNSIGNED VCOS_TLS_KEY_T;
/** TLS per-thread structure. Each thread gets one of these
* if TLS emulation (rather than native TLS support) is
* being used.
*/
typedef struct VCOS_TLS_THREAD_T
{
void *slots[VCOS_TLS_MAX_SLOTS];
} VCOS_TLS_THREAD_T;
/*
* Internal APIs
*/
/** Register this thread's TLS storage area. */
VCOSPRE_ void VCOSPOST_ vcos_tls_thread_register(VCOS_TLS_THREAD_T *);
/** Create a new TLS key */
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_generic_tls_create(VCOS_TLS_KEY_T *key);
/** Delete a TLS key */
VCOSPRE_ void VCOSPOST_ vcos_generic_tls_delete(VCOS_TLS_KEY_T tls);
/** Initialise the TLS library */
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_tls_init(void);
/** Deinitialise the TLS library */
VCOSPRE_ void VCOSPOST_ vcos_tls_deinit(void);
#if defined(VCOS_INLINE_BODIES)
#undef VCOS_ASSERT_LOGGING_DISABLE
#define VCOS_ASSERT_LOGGING_DISABLE 1
/*
* Implementations of public API functions
*/
/** Set the given value. Since everything is per-thread, there is no need
* for any locking.
*/
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_tls_set(VCOS_TLS_KEY_T tls, void *v) {
VCOS_TLS_THREAD_T *tlsdata = _vcos_tls_thread_ptr_get();
vcos_assert(tlsdata); /* Fires if this thread has not been registered */
if (tls<VCOS_TLS_MAX_SLOTS)
{
tlsdata->slots[tls] = v;
return VCOS_SUCCESS;
}
else
{
vcos_assert(0);
return VCOS_EINVAL;
}
}
/** Get the given value. No locking required.
*/
VCOS_INLINE_IMPL
void *vcos_tls_get(VCOS_TLS_KEY_T tls) {
VCOS_TLS_THREAD_T *tlsdata = _vcos_tls_thread_ptr_get();
vcos_assert(tlsdata); /* Fires if this thread has not been registered */
if (tls<VCOS_TLS_MAX_SLOTS)
{
return tlsdata->slots[tls];
}
else
{
vcos_assert(0);
return NULL;
}
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_tls_create(VCOS_TLS_KEY_T *key) {
return vcos_generic_tls_create(key);
}
VCOS_INLINE_IMPL
void vcos_tls_delete(VCOS_TLS_KEY_T tls) {
vcos_generic_tls_delete(tls);
}
#undef VCOS_ASSERT_LOGGING_DISABLE
#define VCOS_ASSERT_LOGGING_DISABLE 0
#endif /* VCOS_INLINE_BODIES */
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,84 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
The following header is included in order to provide one instance of the symbol vcos_deprecated_code.
Any other inclusions of this header (or "vcos_deprecated_code.inc" for assembly language) will cause the linker to warn
about multiple definitions of vcos_deprecated_code.
The idea is to include this header file for the source files which are deprecated.
Therefore the above warnning in a build indicates that the build is using deprecated code!
Contact the person named in the accompanying comment for advice - do not remove the inclusion.
*/
#include "vcos_deprecated.h"
#include "interface/vcos/vcos.h"
static int init_refcount;
VCOS_STATUS_T vcos_init(void)
{
VCOS_STATUS_T st = VCOS_SUCCESS;
vcos_global_lock();
if (init_refcount++ == 0)
st = vcos_platform_init();
vcos_global_unlock();
return st;
}
void vcos_deinit(void)
{
vcos_global_lock();
vcos_assert(init_refcount > 0);
if (init_refcount > 0 && --init_refcount == 0)
vcos_platform_deinit();
vcos_global_unlock();
}
#if defined(__GNUC__) && (__GNUC__ > 2)
void vcos_ctor(void) __attribute__((constructor, used));
void vcos_ctor(void)
{
vcos_init();
}
void vcos_dtor(void) __attribute__((destructor, used));
void vcos_dtor(void)
{
vcos_deinit();
}
#endif
@@ -0,0 +1,229 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - implementation: joinable thread from plain
=============================================================================*/
/** \file
*
* Header file for platforms creating the joinable thread from a lowlevel
* thread.
*
* In addition to the actual thread, the following are also created:
*
* - a semaphore to wait on when joining the thread
* - a semaphore to support counted suspend/resume (used by event group)
* - a per-thread timer (used by event group, but could be removed)
*/
#ifndef VCOS_JOINABLE_THREAD_FROM_PLAIN_H
#define VCOS_JOINABLE_THREAD_FROM_PLAIN_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef VCOS_SEMAPHORE_H
#include "interface/vcos/vcos_semaphore.h"
#endif
#ifndef VCOS_LOWLEVEL_THREAD_H
#include "interface/vcos/vcos_lowlevel_thread.h"
#endif
#ifndef VCOS_TIMER_H
#include "interface/vcos/vcos_timer.h"
#endif
#ifdef VCOS_WANT_TLS_EMULATION
#include "interface/vcos/generic/vcos_generic_tls.h"
#endif
#define VCOS_THREAD_MAGIC 0x56436a74
#define VCOS_THREAD_VALID(t) (t->magic == VCOS_THREAD_MAGIC)
#define VCOS_HAVE_THREAD_AT_EXIT 1
/** Thread attribute structure. Clients should not manipulate this directly, but
* should instead use the provided functions.
*/
typedef struct VCOS_THREAD_ATTR_T
{
void *ta_stackaddr;
VCOS_UNSIGNED ta_stacksz;
VCOS_UNSIGNED ta_priority;
VCOS_UNSIGNED ta_affinity;
VCOS_UNSIGNED ta_timeslice;
VCOS_UNSIGNED legacy;
VCOS_UNSIGNED ta_autostart;
} VCOS_THREAD_ATTR_T;
/** Each thread gets a timer, which is for internal VCOS use.
*/
typedef struct _VCOS_THREAD_TIMER_T
{
VCOS_TIMER_T timer;
void (*pfn)(void *);
void *cxt;
} _VCOS_THREAD_TIMER_T;
typedef void (*VCOS_THREAD_EXIT_HANDLER_T)(void *);
/** Called at thread exit.
*/
typedef struct VCOS_THREAD_EXIT_T
{
VCOS_THREAD_EXIT_HANDLER_T pfn;
void *cxt;
} VCOS_THREAD_EXIT_T;
#define VCOS_MAX_EXIT_HANDLERS 8
/* The name field isn't used for anything, so we can just copy the
* the pointer. Nucleus makes its own copy.
*/
typedef const char * VCOS_LLTHREAD_T_NAME;
#define _VCOS_LLTHREAD_NAME(dst,src) (dst)=(src)
/*
* Simulated TLS support
*/
/** Thread structure.
*
* \warning Do not access the members of this structure directly!
*/
typedef struct VCOS_THREAD_T
{
VCOS_LLTHREAD_T thread; /**< The underlying thread */
char name[16]; /**< The name */
unsigned int magic; /**< For debug */
void *exit_data; /**< Exit data passed out in vcos_joinable_thread_exit() */
void *stack; /**< Stack, if not supplied by caller */
VCOS_SEMAPHORE_T wait; /**< Semaphore to wait on at join */
VCOS_SEMAPHORE_T suspend; /**< Semaphore to wait on for counted suspend */
int16_t joined; /**< Joined yet? For debug. */
VCOS_UNSIGNED legacy; /**< Use (argc,argv) for entry point arguments */
void *(*entry)(void*); /**< Entry point */
void *arg; /**< Argument passed to entry point */
void *(*term)(void*); /**< Termination function, used by reaper */
void *term_arg; /**< Argument passed to termination function */
_VCOS_THREAD_TIMER_T _timer; /**< Internal timer, mainly for event groups */
#ifdef VCOS_WANT_TLS_EMULATION
VCOS_TLS_THREAD_T _tls; /**< TLS data when native TLS not available, or NULL */
#endif
/** Array of functions to call at thread exit */
VCOS_THREAD_EXIT_T at_exit[VCOS_MAX_EXIT_HANDLERS];
struct VCOS_THREAD_T *next; /**< For linked lists of threads */
} VCOS_THREAD_T;
#if defined(VCOS_INLINE_BODIES)
VCOS_INLINE_IMPL
void vcos_thread_attr_setstack(VCOS_THREAD_ATTR_T *attrs, void *addr, VCOS_UNSIGNED stacksz) {
attrs->ta_stackaddr = addr;
attrs->ta_stacksz = stacksz;
}
VCOS_INLINE_IMPL
void vcos_thread_attr_setstacksize(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED stacksz) {
attrs->ta_stacksz = stacksz;
}
VCOS_INLINE_IMPL
void vcos_thread_attr_setpriority(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED pri) {
attrs->ta_priority = pri;
}
VCOS_INLINE_IMPL
void vcos_thread_attr_setaffinity(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED affinity) {
attrs->ta_affinity = affinity;
}
VCOS_INLINE_IMPL
void vcos_thread_attr_settimeslice(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED ts) {
attrs->ta_timeslice = ts;
}
VCOS_INLINE_IMPL
void _vcos_thread_attr_setlegacyapi(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED legacy) {
attrs->legacy = legacy;
}
VCOS_INLINE_IMPL
void vcos_thread_attr_setautostart(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED autostart) {
attrs->ta_autostart = autostart;
}
VCOS_INLINE_IMPL
VCOS_THREAD_T *vcos_thread_current(void) {
VCOS_THREAD_T *ret = (VCOS_THREAD_T*)vcos_llthread_current();
/*If we're called from a non-vcos thread, this assert will fail.
*XXX FIXME why is this commented out?
*vcos_assert(ret->magic == VCOS_THREAD_MAGIC);
*/
return ret;
}
VCOS_INLINE_IMPL
int vcos_thread_running(VCOS_THREAD_T *thread) {
return vcos_llthread_running(&thread->thread);
}
VCOS_INLINE_IMPL
void vcos_thread_resume(VCOS_THREAD_T *thread) {
vcos_llthread_resume(&thread->thread);
}
#endif /* VCOS_INLINE_BODIES */
/**
* \brief Create a VCOS_THREAD_T for the current thread. This is so we can have
* VCOS_THREAD_Ts even for threads not originally created by VCOS (eg the
* thread that calls vcos_init)
*/
extern VCOS_STATUS_T _vcos_thread_create_attach(VCOS_THREAD_T *thread,
const char *name);
/**
* \brief Deletes the VCOS_THREAD_T, but does not wait for the underlying
* thread to exit. This will cleanup everything created by
* _vcos_thread_create_attach
*/
extern void _vcos_thread_delete(VCOS_THREAD_T *thread);
/** Register a function to be called when the current thread exits.
*/
extern VCOS_STATUS_T vcos_thread_at_exit(void (*pfn)(void*), void *cxt);
/** Deregister a previously registered at-exit function.
*/
extern void vcos_thread_deregister_at_exit(void (*pfn)(void*), void *cxt);
#ifdef __cplusplus
}
#endif
#endif /* VCOS_JOINABLE_THREAD_FROM_PLAIN_H */
@@ -0,0 +1,68 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - Construct a latch from a semaphore
=============================================================================*/
/** FIXME: rename to vcos_mutex_from_sem.c
*/
typedef struct VCOS_MUTEX_T {
VCOS_SEMAPHORE_T sem;
struct VCOS_THREAD_T *owner;
} VCOS_MUTEX_T;
extern VCOS_STATUS_T vcos_generic_mutex_create(VCOS_MUTEX_T *latch, const char *name);
extern void vcos_generic_mutex_delete(VCOS_MUTEX_T *latch);
extern VCOS_STATUS_T vcos_generic_mutex_lock(VCOS_MUTEX_T *latch);
extern void vcos_generic_mutex_unlock(VCOS_MUTEX_T *latch);
#if defined(VCOS_INLINE_BODIES)
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_mutex_create(VCOS_MUTEX_T *latch, const char *name) {
return vcos_generic_mutex_create(latch,name);
}
VCOS_INLINE_IMPL
void vcos_mutex_delete(VCOS_MUTEX_T *latch) {
vcos_generic_mutex_delete(latch);
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_mutex_lock(VCOS_MUTEX_T *latch) {
return vcos_generic_mutex_lock(latch);
}
VCOS_INLINE_IMPL
void vcos_mutex_unlock(VCOS_MUTEX_T *latch) {
vcos_generic_mutex_unlock(latch);
}
#endif /* VCOS_INLINE_BODIES */
@@ -0,0 +1,587 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
Categorized logging for VCOS - a generic implementation.
=============================================================================*/
#include "interface/vcos/vcos.h"
#include "interface/vcos/vcos_ctype.h"
#include "interface/vcos/vcos_string.h"
#include "interface/vcos/vcos_inttypes.h"
static VCOS_MUTEX_T lock;
static int warned_loglevel; /* only warn about invalid log level once */
static VCOS_VLOG_IMPL_FUNC_T vcos_vlog_impl_func = vcos_vlog_default_impl;
#define VCOS_LOG_CATEGORY (&dflt_log_category)
static VCOS_LOG_CAT_T dflt_log_category;
VCOS_LOG_CAT_T *vcos_logging_categories = NULL;
static int inited;
#if VCOS_HAVE_CMD
/*
* For kernel or videocore purposes, we generally want the log command. For
* user-space apps, they might want to provide their own log command, so we
* don't include the built in on.
*
* So pthreads/vcos_platform.h defines VCOS_WANT_LOG_CMD to be 0. It is
* undefined elsewhere.
*/
# if !defined( VCOS_WANT_LOG_CMD )
# define VCOS_WANT_LOG_CMD 1
# endif
#else
# define VCOS_WANT_LOG_CMD 0
#endif
/* For now, do not link logging categories into linked lists
* as it breaks when people unload shared libraries without
* getting the counts right.
*/
#ifdef __VIDEOCORE__
#define REGISTER_CATEGORIES 1
#else
#define REGISTER_CATEGORIES 0
#endif
#if VCOS_WANT_LOG_CMD
/*****************************************************************************
*
* Does a vcos_assert(0), which is useful to test logging.
*
*****************************************************************************/
VCOS_STATUS_T vcos_log_assert_cmd( VCOS_CMD_PARAM_T *param )
{
(void)param;
#if defined( NDEBUG ) && !defined( VCOS_RELEASE_ASSERTS )
vcos_log_error( "vcos_asserts have been compiled out" );
vcos_cmd_printf( param, "vcos_asserts have been compiled out - did a vcos_log_error instead\n" );
#else
vcos_assert(0);
vcos_cmd_printf( param, "Executed vcos_assert(0)\n" );
#endif
return VCOS_SUCCESS;
}
/*****************************************************************************
*
* Sets a vcos logging level
*
*****************************************************************************/
VCOS_STATUS_T vcos_log_set_cmd( VCOS_CMD_PARAM_T *param )
{
VCOS_LOG_CAT_T *cat;
char *name;
char *levelStr;
VCOS_LOG_LEVEL_T level;
VCOS_STATUS_T status;
if ( param->argc != 3 )
{
vcos_cmd_usage( param );
return VCOS_EINVAL;
}
name = param->argv[1];
levelStr = param->argv[2];
if ( vcos_string_to_log_level( levelStr, &level ) != VCOS_SUCCESS )
{
vcos_cmd_printf( param, "Unrecognized logging level: '%s'\n", levelStr );
return VCOS_EINVAL;
}
vcos_mutex_lock(&lock);
status = VCOS_SUCCESS;
for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
{
if ( vcos_strcmp( name, cat->name ) == 0 )
{
cat->level = level;
vcos_cmd_printf( param, "Category %s level set to %s\n", name, levelStr );
break;
}
}
if ( cat == NULL )
{
vcos_cmd_printf( param, "Unrecognized category: '%s'\n", name );
status = VCOS_ENOENT;
}
vcos_mutex_unlock(&lock);
return status;
}
/*****************************************************************************
*
* Prints out the current settings for a given category (or all cvategories)
*
*****************************************************************************/
VCOS_STATUS_T vcos_log_status_cmd( VCOS_CMD_PARAM_T *param )
{
VCOS_LOG_CAT_T *cat;
VCOS_STATUS_T status;
vcos_mutex_lock(&lock);
if ( param->argc == 1)
{
int nw;
int nameWidth = 0;
/* Print information about all of the categories. */
for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
{
nw = (int)strlen( cat->name );
if ( nw > nameWidth )
{
nameWidth = nw;
}
}
for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
{
vcos_cmd_printf( param, "%-*s - %s\n", nameWidth, cat->name, vcos_log_level_to_string( cat->level ));
}
}
else
{
/* Print information about a particular category */
for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
{
if ( vcos_strcmp( cat->name, param->argv[1] ) == 0 )
{
vcos_cmd_printf( param, "%s - %s\n", cat->name, vcos_log_level_to_string( cat->level ));
break;
}
}
if ( cat == NULL )
{
vcos_cmd_printf( param, "Unrecognized logging category: '%s'\n", param->argv[1] );
status = VCOS_ENOENT;
goto out;
}
}
status = VCOS_SUCCESS;
out:
vcos_mutex_unlock(&lock);
return status;
}
/*****************************************************************************
*
* Prints out the current settings for a given category (or all cvategories)
*
*****************************************************************************/
VCOS_STATUS_T vcos_log_test_cmd( VCOS_CMD_PARAM_T *param )
{
if ( param->argc == 1 )
{
static int seq_num = 100;
/* No additional arguments - generate a message with an incrementing number */
vcos_log_error( "Test message %d", seq_num );
seq_num++;
vcos_cmd_printf( param, "Logged 'Test message %d'\n", seq_num );
}
else
{
int arg_idx;
/* Arguments supplied - log these */
for ( arg_idx = 0; arg_idx < param->argc; arg_idx++ )
{
vcos_log_error( "argv[%d] = '%s'", arg_idx, param->argv[arg_idx] );
}
vcos_cmd_printf( param, "Logged %d line(s) of test data\n", param->argc );
}
return VCOS_SUCCESS;
}
/*****************************************************************************
*
* Internal commands
*
*****************************************************************************/
static VCOS_CMD_T log_cmd_entry[] =
{
{ "assert", "", vcos_log_assert_cmd, NULL, "Does a vcos_assert(0) to test logging" },
{ "set", "category level", vcos_log_set_cmd, NULL, "Sets the vcos logging level for a category" },
{ "status", "[category]", vcos_log_status_cmd, NULL, "Prints the vcos log status for a (or all) categories" },
{ "test", "[arbitrary text]", vcos_log_test_cmd, NULL, "Does a vcos_log to test logging" },
{ NULL, NULL, NULL, NULL, NULL }
};
static VCOS_CMD_T cmd_log =
{ "log", "command [args]", NULL, log_cmd_entry, "Commands related to vcos logging" };
#endif
void vcos_logging_init(void)
{
if (inited)
{
/* FIXME: should print a warning or something here */
return;
}
vcos_mutex_create(&lock, "vcos_log");
vcos_log_platform_init();
vcos_log_register("default", &dflt_log_category);
#if VCOS_WANT_LOG_CMD
vcos_cmd_register( &cmd_log );
#endif
vcos_assert(!inited);
inited = 1;
}
/** Read an alphanumeric token, returning True if we succeeded.
*/
static int read_tok(char *tok, size_t toklen, const char **pstr, char sep)
{
const char *str = *pstr;
size_t n = 0;
char ch;
/* skip past any whitespace */
while (str[0] && isspace((int)(str[0])))
str++;
while ((ch = *str) != '\0' &&
ch != sep &&
(isalnum((int)ch) || (ch == '_')) &&
n != toklen-1)
{
tok[n++] = ch;
str++;
}
/* did it work out? */
if (ch == '\0' || ch == sep)
{
if (ch) str++; /* move to next token if not at end */
/* yes */
tok[n] = '\0';
*pstr = str;
return 1;
}
else
{
/* no */
return 0;
}
}
const char *vcos_log_level_to_string( VCOS_LOG_LEVEL_T level )
{
switch (level)
{
case VCOS_LOG_UNINITIALIZED: return "uninit";
case VCOS_LOG_NEVER: return "never";
case VCOS_LOG_ERROR: return "error";
case VCOS_LOG_WARN: return "warn";
case VCOS_LOG_INFO: return "info";
case VCOS_LOG_TRACE: return "trace";
}
return "???";
}
VCOS_STATUS_T vcos_string_to_log_level( const char *str, VCOS_LOG_LEVEL_T *level )
{
if (strcmp(str,"error") == 0)
*level = VCOS_LOG_ERROR;
else if (strcmp(str,"never") == 0)
*level = VCOS_LOG_NEVER;
else if (strcmp(str,"warn") == 0)
*level = VCOS_LOG_WARN;
else if (strcmp(str,"warning") == 0)
*level = VCOS_LOG_WARN;
else if (strcmp(str,"info") == 0)
*level = VCOS_LOG_INFO;
else if (strcmp(str,"trace") == 0)
*level = VCOS_LOG_TRACE;
else
return VCOS_EINVAL;
return VCOS_SUCCESS;
}
static int read_level(VCOS_LOG_LEVEL_T *level, const char **pstr, char sep)
{
char buf[16];
int ret = 1;
if (read_tok(buf,sizeof(buf),pstr,sep))
{
if (vcos_string_to_log_level(buf,level) != VCOS_SUCCESS)
{
vcos_log("Invalid trace level '%s'\n", buf);
ret = 0;
}
}
else
{
ret = 0;
}
return ret;
}
void vcos_log_register(const char *name, VCOS_LOG_CAT_T *category)
{
const char *env;
VCOS_LOG_CAT_T *i;
category->name = name;
if ( category->level == VCOS_LOG_UNINITIALIZED )
{
category->level = VCOS_LOG_ERROR;
}
category->flags.want_prefix = (category != &dflt_log_category );
if (!REGISTER_CATEGORIES)
return;
vcos_mutex_lock(&lock);
/* is it already registered? */
for (i = vcos_logging_categories; i ; i = i->next )
{
if (i == category)
{
i->refcount++;
break;
}
}
if (!i)
{
/* not yet registered */
category->next = vcos_logging_categories;
vcos_logging_categories = category;
category->refcount++;
vcos_log_platform_register(category);
}
vcos_mutex_unlock(&lock);
/* Check to see if this log level has been enabled. Look for
* (<category:level>,)*
*
* VC_LOGLEVEL=ilcs:info,vchiq:warn
*/
env = _VCOS_LOG_LEVEL();
if (env)
{
do
{
char env_name[64];
VCOS_LOG_LEVEL_T level;
if (read_tok(env_name, sizeof(env_name), &env, ':') &&
read_level(&level, &env, ','))
{
if (strcmp(env_name, name) == 0)
{
category->level = level;
break;
}
}
else
{
if (!warned_loglevel)
{
vcos_log("VC_LOGLEVEL format invalid at %s\n", env);
warned_loglevel = 1;
}
return;
}
} while (env[0] != '\0');
}
vcos_log_info( "Registered log category '%s' with level %s",
category->name,
vcos_log_level_to_string( category->level ));
}
void vcos_log_unregister(VCOS_LOG_CAT_T *category)
{
VCOS_LOG_CAT_T **pcat;
if (!REGISTER_CATEGORIES)
return;
vcos_mutex_lock(&lock);
category->refcount--;
if (category->refcount == 0)
{
pcat = &vcos_logging_categories;
while (*pcat != category)
{
if (!*pcat)
break; /* possibly deregistered twice? */
if ((*pcat)->next == NULL)
{
vcos_assert(0); /* already removed! */
vcos_mutex_unlock(&lock);
return;
}
pcat = &(*pcat)->next;
}
if (*pcat)
*pcat = category->next;
vcos_log_platform_unregister(category);
}
vcos_mutex_unlock(&lock);
}
VCOSPRE_ const VCOS_LOG_CAT_T * VCOSPOST_ vcos_log_get_default_category(void)
{
return &dflt_log_category;
}
void vcos_set_log_options(const char *opt)
{
(void)opt;
}
void vcos_log_dump_mem_impl( const VCOS_LOG_CAT_T *cat,
const char *label,
uint32_t addr,
const void *voidMem,
size_t numBytes )
{
const uint8_t *mem = (const uint8_t *)voidMem;
size_t offset;
char lineBuf[ 100 ];
char *s;
while ( numBytes > 0 )
{
s = lineBuf;
for ( offset = 0; offset < 16; offset++ )
{
if ( offset < numBytes )
{
s += vcos_snprintf( s, 4, "%02x ", mem[ offset ]);
}
else
{
s += vcos_snprintf( s, 4, " " );
}
}
for ( offset = 0; offset < 16; offset++ )
{
if ( offset < numBytes )
{
uint8_t ch = mem[ offset ];
if (( ch < ' ' ) || ( ch > '~' ))
{
ch = '.';
}
*s++ = (char)ch;
}
}
*s++ = '\0';
if (( label != NULL ) && ( *label != '\0' ))
{
vcos_log_impl( cat, VCOS_LOG_INFO, "%s: %08" PRIx32 ": %s", label, addr, lineBuf );
}
else
{
vcos_log_impl( cat, VCOS_LOG_INFO, "%08" PRIx32 ": %s", addr, lineBuf );
}
addr += 16;
mem += 16;
if ( numBytes > 16 )
{
numBytes -= 16;
}
else
{
numBytes = 0;
}
}
}
void vcos_log_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, ...)
{
va_list ap;
va_start(ap,fmt);
vcos_vlog_impl( cat, _level, fmt, ap );
va_end(ap);
}
void vcos_vlog_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args)
{
vcos_vlog_impl_func( cat, _level, fmt, args );
}
void vcos_set_vlog_impl( VCOS_VLOG_IMPL_FUNC_T vlog_impl_func )
{
if ( vlog_impl_func == NULL )
{
vcos_vlog_impl_func = vcos_vlog_default_impl;
}
else
{
vcos_vlog_impl_func = vlog_impl_func;
}
}
@@ -0,0 +1,98 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - memory alloc implementation
=============================================================================*/
#include "interface/vcos/vcos.h"
#ifndef _vcos_platform_malloc
#include <stdlib.h>
#define _vcos_platform_malloc malloc
#define _vcos_platform_free free
#endif
typedef struct malloc_header_s {
uint32_t guardword;
uint32_t size;
const char *description;
void *ptr;
} MALLOC_HEADER_T;
#define MIN_ALIGN sizeof(MALLOC_HEADER_T)
#define GUARDWORDHEAP 0xa55a5aa5
void *vcos_generic_mem_alloc_aligned(VCOS_UNSIGNED size, VCOS_UNSIGNED align, const char *desc)
{
int local_align = align == 0 ? 1 : align;
int required_size = size + local_align + sizeof(MALLOC_HEADER_T);
void *ptr = _vcos_platform_malloc(required_size);
void *ret = NULL;
MALLOC_HEADER_T *h;
if (ptr)
{
ret = (void *)VCOS_ALIGN_UP(((char *)ptr)+sizeof(MALLOC_HEADER_T), local_align);
h = ((MALLOC_HEADER_T *)ret)-1;
h->size = size;
h->description = desc;
h->guardword = GUARDWORDHEAP;
h->ptr = ptr;
}
return ret;
}
void *vcos_generic_mem_alloc(VCOS_UNSIGNED size, const char *desc)
{
return vcos_generic_mem_alloc_aligned(size,MIN_ALIGN,desc);
}
void *vcos_generic_mem_calloc(VCOS_UNSIGNED count, VCOS_UNSIGNED sz, const char *desc)
{
uint32_t size = count*sz;
void *ptr = vcos_generic_mem_alloc_aligned(size,MIN_ALIGN,desc);
if (ptr)
{
memset(ptr, 0, size);
}
return ptr;
}
void vcos_generic_mem_free(void *ptr)
{
MALLOC_HEADER_T *h;
if (! ptr) return;
h = ((MALLOC_HEADER_T *)ptr)-1;
vcos_assert(h->guardword == GUARDWORDHEAP);
_vcos_platform_free(h->ptr);
}
@@ -0,0 +1,74 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
Create the vcos_malloc API from the regular system malloc/free
=============================================================================*/
/**
* \file
*
* Create the vcos malloc API from a regular system malloc/free library.
*
* The API lets callers specify an alignment.
*
* Under VideoCore this is not needed, as we can simply use the rtos_malloc routines.
* But on host platforms that won't be the case.
*
*/
VCOSPRE_ void * VCOSPOST_ vcos_generic_mem_alloc(VCOS_UNSIGNED sz, const char *desc);
VCOSPRE_ void * VCOSPOST_ vcos_generic_mem_calloc(VCOS_UNSIGNED count, VCOS_UNSIGNED sz, const char *descr);
VCOSPRE_ void VCOSPOST_ vcos_generic_mem_free(void *ptr);
VCOSPRE_ void * VCOSPOST_ vcos_generic_mem_alloc_aligned(VCOS_UNSIGNED sz, VCOS_UNSIGNED align, const char *desc);
#ifdef VCOS_INLINE_BODIES
VCOS_INLINE_IMPL
void *vcos_malloc(VCOS_UNSIGNED size, const char *description) {
return vcos_generic_mem_alloc(size, description);
}
VCOS_INLINE_IMPL
void *vcos_calloc(VCOS_UNSIGNED num, VCOS_UNSIGNED size, const char *description) {
return vcos_generic_mem_calloc(num, size, description);
}
VCOS_INLINE_IMPL
void vcos_free(void *ptr) {
vcos_generic_mem_free(ptr);
}
VCOS_INLINE_IMPL
void * vcos_malloc_aligned(VCOS_UNSIGNED size, VCOS_UNSIGNED align, const char *description) {
return vcos_generic_mem_alloc_aligned(size, align, description);
}
#endif /* VCOS_INLINE_BODIES */
@@ -0,0 +1,389 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "vcos.h"
#include "vcos_msgqueue.h"
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#define MAGIC VCOS_MSGQ_MAGIC
/* Probably a good idea for MSG_T to be multiple of 8 so that doubles
* are naturally aligned without problem.
*/
vcos_static_assert((sizeof(VCOS_MSG_T) & 7) == 0);
static void vcos_msgq_pool_on_reply(VCOS_MSG_WAITER_T *waiter,
VCOS_MSG_T *msg);
static void vcos_msgq_queue_waiter_on_reply(VCOS_MSG_WAITER_T *waiter,
VCOS_MSG_T *msg);
/** Simple reply protocol. The client creates a semaphore and waits
* for it. No queuing of multiple replies is possible but nothing needs
* to be setup in advance. Because creating semaphores is very fast on
* VideoCore there's no need to do anything elaborate to optimize create
* time - this might need revisiting on other platforms.
*/
typedef struct
{
VCOS_MSG_WAITER_T waiter;
VCOS_SEMAPHORE_T waitsem;
} VCOS_MSG_SIMPLE_WAITER_T;
static void vcos_msgq_simple_waiter_on_reply(VCOS_MSG_WAITER_T *waiter,
VCOS_MSG_T *msg)
{
VCOS_MSG_SIMPLE_WAITER_T *self;
(void)msg;
self = (VCOS_MSG_SIMPLE_WAITER_T*)waiter;
vcos_semaphore_post(&self->waitsem);
}
static VCOS_STATUS_T vcos_msgq_simple_waiter_init(VCOS_MSG_SIMPLE_WAITER_T *waiter)
{
VCOS_STATUS_T status;
status = vcos_semaphore_create(&waiter->waitsem, "waiter", 0);
waiter->waiter.on_reply = vcos_msgq_simple_waiter_on_reply;
return status;
}
static void vcos_msgq_simple_waiter_deinit(VCOS_MSG_SIMPLE_WAITER_T *waiter)
{
vcos_semaphore_delete(&waiter->waitsem);
}
/*
* Message queues
*/
static VCOS_STATUS_T vcos_msgq_create_internal(VCOS_MSGQUEUE_T *q, const char *name)
{
VCOS_STATUS_T st;
memset(q, 0, sizeof(*q));
q->waiter.on_reply = vcos_msgq_queue_waiter_on_reply;
st = vcos_semaphore_create(&q->sem, name, 0);
if (st != VCOS_SUCCESS)
goto fail_sem;
st = vcos_mutex_create(&q->lock, name);
if (st != VCOS_SUCCESS)
goto fail_mtx;
return st;
fail_mtx:
vcos_semaphore_delete(&q->sem);
fail_sem:
return st;
}
static void vcos_msgq_delete_internal(VCOS_MSGQUEUE_T *q)
{
vcos_semaphore_delete(&q->sem);
vcos_mutex_delete(&q->lock);
}
VCOS_STATUS_T vcos_msgq_create(VCOS_MSGQUEUE_T *q, const char *name)
{
VCOS_STATUS_T st;
st = vcos_msgq_create_internal(q, name);
return st;
}
void vcos_msgq_delete(VCOS_MSGQUEUE_T *q)
{
vcos_msgq_delete_internal(q);
}
/* append a message to a message queue */
static _VCOS_INLINE void msgq_append(VCOS_MSGQUEUE_T *q, VCOS_MSG_T *msg)
{
vcos_mutex_lock(&q->lock);
if (q->head == NULL)
{
q->head = q->tail = msg;
}
else
{
q->tail->next = msg;
q->tail = msg;
}
vcos_mutex_unlock(&q->lock);
}
/*
* A waiter for a message queue. Just appends the message to the
* queue, waking up the waiting thread.
*/
static void vcos_msgq_queue_waiter_on_reply(VCOS_MSG_WAITER_T *waiter,
VCOS_MSG_T *msg)
{
VCOS_MSGQUEUE_T *queue = (VCOS_MSGQUEUE_T*)waiter;
msgq_append(queue, msg);
vcos_semaphore_post(&queue->sem);
}
/* initialise this library */
VCOS_STATUS_T vcos_msgq_init(void)
{
return VCOS_SUCCESS;
}
void vcos_msgq_deinit(void)
{
}
static _VCOS_INLINE
void vcos_msg_send_helper(VCOS_MSG_WAITER_T *waiter,
VCOS_MSGQUEUE_T *dest,
uint32_t code,
VCOS_MSG_T *msg)
{
vcos_assert(msg);
vcos_assert(dest);
msg->code = code;
if (waiter)
msg->waiter = waiter;
msg->next = NULL;
msg->src_thread = vcos_thread_current();
msgq_append(dest, msg);
vcos_semaphore_post(&dest->sem);
}
/* wait on a queue for a message */
VCOS_MSG_T *vcos_msg_wait(VCOS_MSGQUEUE_T *queue)
{
VCOS_MSG_T *msg;
vcos_semaphore_wait(&queue->sem);
vcos_mutex_lock(&queue->lock);
msg = queue->head;
vcos_assert(msg); /* should always be a message here! */
queue->head = msg->next;
if (queue->head == NULL)
queue->tail = NULL;
vcos_mutex_unlock(&queue->lock);
return msg;
}
/* peek on a queue for a message */
VCOS_MSG_T *vcos_msg_peek(VCOS_MSGQUEUE_T *queue)
{
VCOS_MSG_T *msg;
vcos_mutex_lock(&queue->lock);
msg = queue->head;
/* if there's a message, remove it from the queue */
if (msg)
{
queue->head = msg->next;
if (queue->head == NULL)
queue->tail = NULL;
/* keep the semaphore count consistent */
/* coverity[lock_order]
* the semaphore must have a non-zero count so cannot block here.
*/
vcos_semaphore_wait(&queue->sem);
}
vcos_mutex_unlock(&queue->lock);
return msg;
}
void vcos_msg_send(VCOS_MSGQUEUE_T *dest, uint32_t code, VCOS_MSG_T *msg)
{
vcos_assert(msg->magic == MAGIC);
vcos_msg_send_helper(NULL, dest, code, msg);
}
/** Send on to the target queue, then wait on a simple waiter for the reply
*/
VCOS_STATUS_T vcos_msg_sendwait(VCOS_MSGQUEUE_T *dest, uint32_t code, VCOS_MSG_T *msg)
{
VCOS_STATUS_T st;
VCOS_MSG_SIMPLE_WAITER_T waiter;
vcos_assert(msg->magic == MAGIC);
/* if this fires, you've set a waiter up but are now about to obliterate it
* with the 'wait for a reply' waiter.
*/
vcos_assert(msg->waiter == NULL);
if ((st=vcos_msgq_simple_waiter_init(&waiter)) != VCOS_SUCCESS)
return st;
vcos_msg_send_helper(&waiter.waiter, dest, code, msg);
vcos_semaphore_wait(&waiter.waitsem);
vcos_msgq_simple_waiter_deinit(&waiter);
return VCOS_SUCCESS;
}
/** Send a reply to a message
*/
void vcos_msg_reply(VCOS_MSG_T *msg)
{
vcos_assert(msg->magic == MAGIC);
msg->code |= MSG_REPLY_BIT;
if (msg->waiter)
{
msg->waiter->on_reply(msg->waiter, msg);
}
else
{
VCOS_ALERT("%s: reply to non-reply message id %d",
VCOS_FUNCTION,
msg->code);
vcos_assert(0);
}
}
void vcos_msg_set_source(VCOS_MSG_T *msg, VCOS_MSGQUEUE_T *queue)
{
vcos_assert(msg);
vcos_assert(msg->magic == MAGIC);
vcos_assert(queue);
msg->waiter = &queue->waiter;
}
/*
* Message pools
*/
VCOS_STATUS_T vcos_msgq_pool_create(VCOS_MSGQ_POOL_T *pool,
size_t count,
size_t payload_size,
const char *name)
{
VCOS_STATUS_T status;
int bp_size = payload_size + sizeof(VCOS_MSG_T);
status = vcos_blockpool_create_on_heap(&pool->blockpool,
count, bp_size,
VCOS_BLOCKPOOL_ALIGN_DEFAULT,
0,
name);
if (status != VCOS_SUCCESS)
goto fail_pool;
status = vcos_semaphore_create(&pool->sem, name, count);
if (status != VCOS_SUCCESS)
goto fail_sem;
pool->waiter.on_reply = vcos_msgq_pool_on_reply;
pool->magic = MAGIC;
return status;
fail_sem:
vcos_blockpool_delete(&pool->blockpool);
fail_pool:
return status;
}
void vcos_msgq_pool_delete(VCOS_MSGQ_POOL_T *pool)
{
vcos_blockpool_delete(&pool->blockpool);
vcos_semaphore_delete(&pool->sem);
}
/** Called when a message from a pool is replied-to. Just returns
* the message back to the blockpool.
*/
static void vcos_msgq_pool_on_reply(VCOS_MSG_WAITER_T *waiter,
VCOS_MSG_T *msg)
{
vcos_unused(waiter);
vcos_assert(msg->magic == MAGIC);
vcos_msgq_pool_free(msg);
}
VCOS_MSG_T *vcos_msgq_pool_alloc(VCOS_MSGQ_POOL_T *pool)
{
VCOS_MSG_T *msg;
if (vcos_semaphore_trywait(&pool->sem) == VCOS_SUCCESS)
{
msg = vcos_blockpool_calloc(&pool->blockpool);
vcos_assert(msg);
msg->magic = MAGIC;
msg->waiter = &pool->waiter;
msg->pool = pool;
}
else
{
msg = NULL;
}
return msg;
}
void vcos_msgq_pool_free(VCOS_MSG_T *msg)
{
if (msg)
{
VCOS_MSGQ_POOL_T *pool;
vcos_assert(msg->pool);
pool = msg->pool;
vcos_assert(msg->pool->magic == MAGIC);
vcos_blockpool_free(msg);
vcos_semaphore_post(&pool->sem);
}
}
VCOS_MSG_T *vcos_msgq_pool_wait(VCOS_MSGQ_POOL_T *pool)
{
VCOS_MSG_T *msg;
vcos_semaphore_wait(&pool->sem);
msg = vcos_blockpool_calloc(&pool->blockpool);
vcos_assert(msg);
msg->magic = MAGIC;
msg->waiter = &pool->waiter;
msg->pool = pool;
return msg;
}
void vcos_msg_init(VCOS_MSG_T *msg)
{
msg->magic = MAGIC;
msg->next = NULL;
msg->waiter = NULL;
msg->pool = NULL;
}
@@ -0,0 +1,88 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - reentrant mutexes mapped directly to regular ones
=============================================================================*/
#ifndef VCOS_GENERIC_REENTRANT_MUTEX_H
#define VCOS_GENERIC_REENTRANT_MUTEX_H
#ifdef __cplusplus
extern "C" {
#endif
#include "interface/vcos/vcos_types.h"
#include "interface/vcos/vcos_mutex.h"
/**
* \file
*
* Reentrant Mutexes directly using the native re-entrant mutex.
*
*/
typedef VCOS_MUTEX_T VCOS_REENTRANT_MUTEX_T;
/* Inline forwarding functions */
#if defined(VCOS_INLINE_BODIES)
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name) {
return vcos_mutex_create(m,name);
}
VCOS_INLINE_IMPL
void vcos_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m) {
vcos_mutex_delete(m);
}
VCOS_INLINE_IMPL
void vcos_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m) {
vcos_mutex_lock(m);
}
VCOS_INLINE_IMPL
void vcos_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m) {
vcos_mutex_unlock(m);
}
VCOS_INLINE_IMPL
int vcos_reentrant_mutex_is_locked(VCOS_REENTRANT_MUTEX_T *m) {
return vcos_mutex_is_locked(m);
}
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,55 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - thread reaping
=============================================================================*/
#ifndef VCOS_THREAD_REAPER_H
#define VCOS_THREAD_REAPER_H
#define VCOS_HAVE_THREAD_REAPER
/** Initialise the thread reaper.
*/
VCOS_STATUS_T vcos_thread_reaper_init(void);
/** Reap a thread. Arranges for the thread to be automatically
* joined.
*
* @sa vcos_thread_join().
*
* @param thread the thread to terminate
* @param on_terminated called after the thread has exited
* @param cxt pass back to the callback
*
*/
void vcos_thread_reap(VCOS_THREAD_T *thread, void (*on_terminated)(void*), void *cxt);
#endif
@@ -0,0 +1,56 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <interface/vcos/vcos.h>
#ifdef HAVE_CMAKE_CONFIG
#include "cmake_config.h"
#endif
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
void vcos_backtrace_self(void)
{
#ifdef HAVE_EXECINFO_H
void *stack[64];
int depth = backtrace(stack, sizeof(stack)/sizeof(stack[0]));
char **names = backtrace_symbols(stack, depth);
int i;
if (names)
{
for (i=0; i<depth; i++)
{
printf("%s\n", names[i]);
}
free(names);
}
#endif
}
@@ -0,0 +1,46 @@
# MSVC5 does not fully support C99, enabling declaration-after-statement
# warnings allows a common MSVC5 build error to be detected in Linux builds.
if (CMAKE_COMPILER_IS_GNUCC)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wdeclaration-after-statement")
add_definitions (-D_GNU_SOURCE)
endif ()
set (HEADERS
vcos_platform.h
vcos_platform_types.h
)
foreach (header ${HEADERS})
configure_file ("${header}" "${VCOS_HEADERS_BUILD_DIR}/${header}" COPYONLY)
endforeach ()
add_subdirectory (../generic generic)
set (SOURCES
vcos_pthreads.c
vcos_dlfcn.c
../glibc/vcos_backtrace.c
../generic/vcos_generic_event_flags.c
../generic/vcos_mem_from_malloc.c
../generic/vcos_generic_named_sem.c
../generic/vcos_generic_safe_string.c
../generic/vcos_generic_reentrant_mtx.c
../generic/vcos_abort.c
../generic/vcos_cmd.c
../generic/vcos_init.c
../generic/vcos_msgqueue.c
../generic/vcos_logcat.c
../generic/vcos_generic_blockpool.c
)
if (VCOS_PTHREADS_BUILD_SHARED)
add_library (vcos SHARED ${SOURCES})
target_link_libraries (vcos pthread dl rt)
else ()
add_library (vcos ${SOURCES})
target_link_libraries (vcos pthread rt)
endif ()
#install(FILES ${HEADERS} DESTINATION include)
install(TARGETS vcos DESTINATION lib)
@@ -0,0 +1,71 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "interface/vcos/vcos.h"
#include "interface/vcos/vcos_dlfcn.h"
#include <dlfcn.h>
void *vcos_dlopen(const char *name, int mode)
{
return dlopen(name, mode);
}
void (*vcos_dlsym(void *handle, const char *name))(void)
{
return dlsym(handle, name);
}
int vcos_dlclose (void *handle)
{
return dlclose(handle);
}
int vcos_dlerror(int *err, char *buf, size_t buflen)
{
/* not really threadsafe! */
const char *errmsg = dlerror();
vcos_assert(buflen > 0);
if (errmsg)
{
*err = -1;
strncpy(buf, errmsg, buflen);
buf[buflen-1] = '\0';
}
else
{
*err = 0;
buf[0] = '\0';
}
return 0;
}
@@ -0,0 +1,102 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
FIXME: This code should be moved to 'linux', it is linux-specific and not generic
on 'pthreads'.
============================================================================*/
#ifndef VCOS_MUTEX_FROM_FUTEX_H
#define VCOS_MUTEX_FROM_FUTEX_H
#ifdef __cplusplus
extern "C" {
#endif
#include "interface/vcos/vcos_types.h"
#include "vcos_platform.h"
typedef struct VCOS_FUTEX_T
{
volatile int value;
} VCOS_FUTEX_T;
typedef VCOS_FUTEX_T VCOS_MUTEX_T;
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_futex_init(VCOS_FUTEX_T *futex);
VCOSPRE_ void VCOSPOST_ vcos_futex_delete(VCOS_FUTEX_T *futex);
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_futex_lock(VCOS_FUTEX_T *futex);
VCOSPRE_ void VCOSPOST_ vcos_futex_unlock(VCOS_FUTEX_T *futex);
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_futex_trylock(VCOS_FUTEX_T *futex);
#if defined(VCOS_INLINE_BODIES)
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_mutex_create(VCOS_MUTEX_T *latch, const char *name) {
vcos_unused(name);
return vcos_futex_init(latch);
}
VCOS_INLINE_IMPL
void vcos_mutex_delete(VCOS_MUTEX_T *latch) {
vcos_futex_delete(latch);
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_mutex_lock(VCOS_MUTEX_T *latch) {
return vcos_futex_lock(latch);
}
VCOS_INLINE_IMPL
void vcos_mutex_unlock(VCOS_MUTEX_T *latch) {
vcos_futex_unlock(latch);
}
VCOS_INLINE_IMPL
int vcos_mutex_is_locked(VCOS_MUTEX_T *latch) {
int rc = latch->value;
if (!rc) {
/* it wasn't locked */
return 0;
}
else {
return 1; /* it was locked */
}
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_mutex_trylock(VCOS_MUTEX_T *m) {
return vcos_futex_trylock(m);
}
#endif /* VCOS_INLINE_BODIES */
#ifdef __cplusplus
}
#endif
#endif /* VCOS_MUTEX_FROM_FUTEX_H */
@@ -0,0 +1,749 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - pthreads types
=============================================================================*/
/* Do not include this file directly - instead include it via vcos.h */
/** @file
*
* Pthreads implementation of VCOS.
*
*/
#ifndef VCOS_PLATFORM_H
#define VCOS_PLATFORM_H
#ifdef __cplusplus
extern "C" {
#endif
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/types.h>
#include <sched.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <signal.h>
#include <stddef.h>
#include <stdlib.h>
#include <dlfcn.h>
#define VCOS_HAVE_RTOS 1
#define VCOS_HAVE_SEMAPHORE 1
#define VCOS_HAVE_EVENT 1
#define VCOS_HAVE_QUEUE 0
#define VCOS_HAVE_LEGACY_ISR 0
#define VCOS_HAVE_TIMER 1
#define VCOS_HAVE_CANCELLATION_SAFE_TIMER 1
#define VCOS_HAVE_MEMPOOL 0
#define VCOS_HAVE_ISR 0
#define VCOS_HAVE_ATOMIC_FLAGS 1
#define VCOS_HAVE_THREAD_AT_EXIT 1
#define VCOS_HAVE_ONCE 1
#define VCOS_HAVE_BLOCK_POOL 1
#define VCOS_HAVE_FILE 0
#define VCOS_HAVE_PROC 0
#define VCOS_HAVE_CFG 0
#define VCOS_HAVE_ALIEN_THREADS 1
#define VCOS_HAVE_CMD 1
#define VCOS_HAVE_EVENT_FLAGS 1
#define VCOS_WANT_LOG_CMD 0 /* User apps should do their own thing */
#define VCOS_ALWAYS_WANT_LOGGING
#ifdef __linux__
#define VCOS_HAVE_BACKTRACE 1
#endif
#define VCOS_SO_EXT ".so"
/* Linux/pthreads seems to have different timer characteristics */
#define VCOS_TIMER_MARGIN_EARLY 0
#define VCOS_TIMER_MARGIN_LATE 15
typedef sem_t VCOS_SEMAPHORE_T;
typedef uint32_t VCOS_UNSIGNED;
typedef uint32_t VCOS_OPTION;
typedef pthread_key_t VCOS_TLS_KEY_T;
typedef pthread_once_t VCOS_ONCE_T;
typedef struct VCOS_LLTHREAD_T
{
pthread_t thread; // Must be first field.
} VCOS_LLTHREAD_T;
/* VCOS_CASSERT(offsetof(VCOS_LLTHREAD_T, thread) == 0); */
#ifndef VCOS_USE_VCOS_FUTEX
typedef pthread_mutex_t VCOS_MUTEX_T;
#else
#include "vcos_futex_mutex.h"
#endif /* VCOS_USE_VCOS_FUTEX */
typedef struct
{
VCOS_MUTEX_T mutex;
sem_t sem;
} VCOS_EVENT_T;
#define VCOS_ONCE_INIT PTHREAD_ONCE_INIT
typedef struct VCOS_TIMER_T
{
pthread_t thread; /**< id of the timer thread */
pthread_mutex_t lock; /**< lock protecting all other members of the struct */
pthread_cond_t settings_changed; /**< cond. var. for informing the timer thread about changes*/
int quit; /**< non-zero if the timer thread is requested to quit*/
struct timespec expires; /**< absolute time of next expiration, or 0 if disarmed*/
void (*orig_expiration_routine)(void*);/**< the expiration routine provided by the user of the timer*/
void *orig_context; /**< the context for exp. routine provided by the user*/
} VCOS_TIMER_T;
/** Thread attribute structure. Don't use pthread_attr directly, as
* the calls can fail, and inits must match deletes.
*/
typedef struct VCOS_THREAD_ATTR_T
{
void *ta_stackaddr;
VCOS_UNSIGNED ta_stacksz;
VCOS_UNSIGNED ta_priority;
VCOS_UNSIGNED ta_affinity;
VCOS_UNSIGNED ta_timeslice;
VCOS_UNSIGNED legacy;
} VCOS_THREAD_ATTR_T;
/** Called at thread exit.
*/
typedef struct VCOS_THREAD_EXIT_T
{
void (*pfn)(void *);
void *cxt;
} VCOS_THREAD_EXIT_T;
#define VCOS_MAX_EXIT_HANDLERS 4
typedef struct VCOS_THREAD_T
{
pthread_t thread; /**< The thread itself */
VCOS_THREAD_ENTRY_FN_T entry; /**< The thread entry point */
void *arg; /**< The argument to be passed to entry */
VCOS_SEMAPHORE_T suspend; /**< For support event groups and similar - a per thread semaphore */
VCOS_TIMER_T task_timer;
int task_timer_created; /**< non-zero if the task timer has already been created*/
void (*orig_task_timer_expiration_routine)(void*);
void *orig_task_timer_context;
VCOS_UNSIGNED legacy;
char name[16]; /**< Record the name of this thread, for diagnostics */
VCOS_UNSIGNED dummy; /**< Dummy thread created for non-vcos created threads */
/** Callback invoked at thread exit time */
VCOS_THREAD_EXIT_T at_exit[VCOS_MAX_EXIT_HANDLERS];
} VCOS_THREAD_T;
#ifdef VCOS_PTHREADS_WANT_HISR_EMULATION
typedef struct
{
VCOS_THREAD_T thread;
char stack[1024];
VCOS_SEMAPHORE_T waitsem;
} VCOS_HISR_T;
#endif
#define VCOS_SUSPEND -1
#define VCOS_NO_SUSPEND 0
#define VCOS_START 1
#define VCOS_NO_START 0
#define VCOS_THREAD_PRI_MIN (sched_get_priority_min(SCHED_OTHER))
#define VCOS_THREAD_PRI_MAX (sched_get_priority_max(SCHED_OTHER))
#define VCOS_THREAD_PRI_INCREASE (1)
#define VCOS_THREAD_PRI_HIGHEST VCOS_THREAD_PRI_MAX
#define VCOS_THREAD_PRI_LOWEST VCOS_THREAD_PRI_MIN
#define VCOS_THREAD_PRI_NORMAL ((VCOS_THREAD_PRI_MAX+VCOS_THREAD_PRI_MIN)/2)
#define VCOS_THREAD_PRI_BELOW_NORMAL (VCOS_THREAD_PRI_NORMAL-VCOS_THREAD_PRI_INCREASE)
#define VCOS_THREAD_PRI_ABOVE_NORMAL (VCOS_THREAD_PRI_NORMAL+VCOS_THREAD_PRI_INCREASE)
#define VCOS_THREAD_PRI_REALTIME VCOS_THREAD_PRI_MAX
#define _VCOS_AFFINITY_DEFAULT 0
#define _VCOS_AFFINITY_CPU0 0x100
#define _VCOS_AFFINITY_CPU1 0x200
#define _VCOS_AFFINITY_MASK 0x300
#define VCOS_CAN_SET_STACK_ADDR 0
#define VCOS_TICKS_PER_SECOND _vcos_get_ticks_per_second()
#include "generic/vcos_generic_event_flags.h"
#include "generic/vcos_generic_blockpool.h"
#include "generic/vcos_mem_from_malloc.h"
/** Convert errno values into the values recognized by vcos */
VCOSPRE_ VCOS_STATUS_T vcos_pthreads_map_error(int error);
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_pthreads_map_errno(void);
/** Register a function to be called when the current thread exits.
*/
extern VCOS_STATUS_T vcos_thread_at_exit(void (*pfn)(void*), void *cxt);
extern uint32_t _vcos_get_ticks_per_second(void);
/**
* Set to 1 by default when ANDROID is defined. Allows runtime
* switching for console apps.
*/
extern int vcos_use_android_log;
typedef struct {
VCOS_MUTEX_T mutex;
uint32_t flags;
} VCOS_ATOMIC_FLAGS_T;
#if defined(VCOS_INLINE_BODIES)
#undef VCOS_ASSERT_LOGGING_DISABLE
#define VCOS_ASSERT_LOGGING_DISABLE 1
/*
* Counted Semaphores
*/
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_semaphore_wait(VCOS_SEMAPHORE_T *sem) {
int ret;
/* gdb causes sem_wait() to EINTR when a breakpoint is hit, retry here */
while ((ret = sem_wait(sem)) == -1 && errno == EINTR)
continue;
vcos_assert(ret==0);
return VCOS_SUCCESS;
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_semaphore_trywait(VCOS_SEMAPHORE_T *sem) {
int ret;
while ((ret = sem_trywait(sem)) == -1 && errno == EINTR)
continue;
if (ret == 0)
return VCOS_SUCCESS;
else if (errno == EAGAIN)
return VCOS_EAGAIN;
else {
vcos_assert(0);
return VCOS_EINVAL;
}
}
/**
* \brief Wait on a semaphore with a timeout.
*
* Note that this function may not be implemented on all
* platforms, and may not be efficient on all platforms
* (see comment in vcos_semaphore_wait)
*
* Try to obtain the semaphore. If it is already taken, return
* VCOS_EAGAIN.
* @param sem Semaphore to wait on
* @param timeout Number of milliseconds to wait before
* returning if the semaphore can't be acquired.
* @return VCOS_SUCCESS - semaphore was taken.
* VCOS_EAGAIN - could not take semaphore (i.e. timeout
* expired)
* VCOS_EINVAL - Some other error (most likely bad
* parameters).
*/
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_semaphore_wait_timeout(VCOS_SEMAPHORE_T *sem, VCOS_UNSIGNED timeout) {
struct timespec ts;
int ret;
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
return VCOS_EINVAL;
ts.tv_sec += timeout/1000;
ts.tv_nsec += (timeout%1000)*1000*1000;
if (ts.tv_nsec > 1000000000) {
ts.tv_sec++;
ts.tv_nsec -= 1000000000;
}
while (1) {
ret = sem_timedwait( sem, &ts );
if (ret == 0) {
return VCOS_SUCCESS;
} else {
if (errno == EINTR) {
continue;
} else if (errno == ETIMEDOUT) {
return VCOS_EAGAIN;
} else {
vcos_assert(0);
return VCOS_EINVAL;
}
}
}
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_semaphore_create(VCOS_SEMAPHORE_T *sem,
const char *name,
VCOS_UNSIGNED initial_count) {
int rc = sem_init(sem, 0, initial_count);
(void)name;
if (rc != -1) return VCOS_SUCCESS;
else return vcos_pthreads_map_errno();
}
VCOS_INLINE_IMPL
void vcos_semaphore_delete(VCOS_SEMAPHORE_T *sem) {
int rc = sem_destroy(sem);
vcos_assert(rc != -1);
(void)rc;
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_semaphore_post(VCOS_SEMAPHORE_T *sem) {
int rc = sem_post(sem);
vcos_assert(rc == 0);
(void)rc;
return VCOS_SUCCESS;
}
/***********************************************************
*
* Threads
*
***********************************************************/
extern VCOS_THREAD_T *vcos_dummy_thread_create(void);
extern pthread_key_t _vcos_thread_current_key;
extern uint64_t vcos_getmicrosecs64_internal(void);
VCOS_INLINE_IMPL
uint32_t vcos_getmicrosecs(void) { return (uint32_t)vcos_getmicrosecs64_internal(); }
VCOS_INLINE_IMPL
uint64_t vcos_getmicrosecs64(void) { return vcos_getmicrosecs64_internal(); }
VCOS_INLINE_IMPL
VCOS_THREAD_T *vcos_thread_current(void) {
void *ret = pthread_getspecific(_vcos_thread_current_key);
if (ret == NULL)
{
ret = vcos_dummy_thread_create();
}
#ifdef __cplusplus
return static_cast<VCOS_THREAD_T*>(ret);
#else
return (VCOS_THREAD_T *)ret;
#endif
}
VCOS_INLINE_IMPL
void vcos_sleep(uint32_t ms) {
struct timespec ts;
ts.tv_sec = ms/1000;
ts.tv_nsec = ms % 1000 * (1000000);
nanosleep(&ts, NULL);
}
VCOS_INLINE_IMPL
void vcos_thread_attr_setstack(VCOS_THREAD_ATTR_T *attr, void *addr, VCOS_UNSIGNED sz) {
attr->ta_stackaddr = addr;
attr->ta_stacksz = sz;
}
VCOS_INLINE_IMPL
void vcos_thread_attr_setstacksize(VCOS_THREAD_ATTR_T *attr, VCOS_UNSIGNED sz) {
attr->ta_stacksz = sz;
}
VCOS_INLINE_IMPL
void vcos_thread_attr_setpriority(VCOS_THREAD_ATTR_T *attr, VCOS_UNSIGNED pri) {
(void)attr;
(void)pri;
}
VCOS_INLINE_IMPL
void vcos_thread_set_priority(VCOS_THREAD_T *thread, VCOS_UNSIGNED p) {
/* not implemented */
(void)thread;
(void)p;
}
VCOS_INLINE_IMPL
VCOS_UNSIGNED vcos_thread_get_priority(VCOS_THREAD_T *thread) {
/* not implemented */
(void)thread;
return 0;
}
VCOS_INLINE_IMPL
void vcos_thread_set_affinity(VCOS_THREAD_T *thread, VCOS_UNSIGNED affinity) {
/* not implemented */
vcos_unused(thread);
vcos_unused(affinity);
}
VCOS_INLINE_IMPL
void vcos_thread_attr_setaffinity(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED affinity) {
attrs->ta_affinity = affinity;
}
VCOS_INLINE_IMPL
void vcos_thread_attr_settimeslice(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED ts) {
attrs->ta_timeslice = ts;
}
VCOS_INLINE_IMPL
void _vcos_thread_attr_setlegacyapi(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED legacy) {
attrs->legacy = legacy;
}
VCOS_INLINE_IMPL
void vcos_thread_attr_setautostart(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED autostart) {
(void)attrs;
(void)autostart;
}
VCOS_INLINE_IMPL
VCOS_LLTHREAD_T *vcos_llthread_current(void) {
return (VCOS_LLTHREAD_T *)pthread_self();
}
/*
* Mutexes
*/
#ifndef VCOS_USE_VCOS_FUTEX
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_mutex_create(VCOS_MUTEX_T *latch, const char *name) {
int rc = pthread_mutex_init(latch, NULL);
(void)name;
if (rc == 0) return VCOS_SUCCESS;
else return vcos_pthreads_map_errno();
}
VCOS_INLINE_IMPL
void vcos_mutex_delete(VCOS_MUTEX_T *latch) {
int rc = pthread_mutex_destroy(latch);
(void)rc;
vcos_assert(rc==0);
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_mutex_lock(VCOS_MUTEX_T *latch) {
int rc = pthread_mutex_lock(latch);
vcos_assert(rc==0);
(void)rc;
return VCOS_SUCCESS;
}
VCOS_INLINE_IMPL
void vcos_mutex_unlock(VCOS_MUTEX_T *latch) {
int rc = pthread_mutex_unlock(latch);
(void)rc;
vcos_assert(rc==0);
}
VCOS_INLINE_IMPL
int vcos_mutex_is_locked(VCOS_MUTEX_T *m) {
int rc = pthread_mutex_trylock(m);
if (rc == 0) {
pthread_mutex_unlock(m);
/* it wasn't locked */
return 0;
}
else {
return 1; /* it was locked */
}
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_mutex_trylock(VCOS_MUTEX_T *m) {
int rc = pthread_mutex_trylock(m);
(void)rc;
return (rc == 0) ? VCOS_SUCCESS : VCOS_EAGAIN;
}
#endif /* VCOS_USE_VCOS_FUTEX */
/*
* Events
*/
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_event_create(VCOS_EVENT_T *event, const char *debug_name)
{
VCOS_STATUS_T status;
int rc = sem_init(&event->sem, 0, 0);
if (rc != 0) return vcos_pthreads_map_errno();
status = vcos_mutex_create(&event->mutex, debug_name);
if (status != VCOS_SUCCESS) {
sem_destroy(&event->sem);
return status;
}
return VCOS_SUCCESS;
}
VCOS_INLINE_IMPL
void vcos_event_signal(VCOS_EVENT_T *event)
{
#if VCOS_ASSERT_ENABLED
int ok = 0;
#endif
int value;
if (vcos_mutex_lock(&event->mutex) != VCOS_SUCCESS)
goto fail_mtx;
if (sem_getvalue(&event->sem, &value) != 0)
goto fail_sem;
if (value == 0)
if (sem_post(&event->sem) != 0)
goto fail_sem;
#if VCOS_ASSERT_ENABLED
ok = 1;
#endif
fail_sem:
vcos_mutex_unlock(&event->mutex);
fail_mtx:
vcos_assert(ok);
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_event_wait(VCOS_EVENT_T *event)
{
int ret;
/* gdb causes sem_wait() to EINTR when a breakpoint is hit, retry here */
while ((ret = sem_wait(&event->sem)) == -1 && errno == EINTR)
continue;
vcos_assert(ret==0);
return ret == 0 ? VCOS_SUCCESS : (VCOS_STATUS_T)errno;
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_event_try(VCOS_EVENT_T *event)
{
int ret;
while ((ret = sem_trywait(&event->sem)) == -1 && errno == EINTR)
continue;
if (ret == -1 && errno == EAGAIN)
return VCOS_EAGAIN;
else
return VCOS_SUCCESS;
}
VCOS_INLINE_IMPL
void vcos_event_delete(VCOS_EVENT_T *event)
{
int rc = sem_destroy(&event->sem);
vcos_assert(rc != -1);
(void)rc;
vcos_mutex_delete(&event->mutex);
}
VCOS_INLINE_IMPL
VCOS_UNSIGNED vcos_process_id_current(void) {
return (VCOS_UNSIGNED) getpid();
}
VCOS_INLINE_IMPL
int vcos_strcasecmp(const char *s1, const char *s2) {
return strcasecmp(s1,s2);
}
VCOS_INLINE_IMPL
int vcos_strncasecmp(const char *s1, const char *s2, size_t n) {
return strncasecmp(s1,s2,n);
}
VCOS_INLINE_IMPL
int vcos_in_interrupt(void) {
return 0;
}
/* For support event groups - per thread semaphore */
VCOS_INLINE_IMPL
void _vcos_thread_sem_wait(void) {
VCOS_THREAD_T *t = vcos_thread_current();
vcos_semaphore_wait(&t->suspend);
}
VCOS_INLINE_IMPL
void _vcos_thread_sem_post(VCOS_THREAD_T *target) {
vcos_semaphore_post(&target->suspend);
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_tls_create(VCOS_TLS_KEY_T *key) {
int st = pthread_key_create(key, NULL);
return st == 0 ? VCOS_SUCCESS: VCOS_ENOMEM;
}
VCOS_INLINE_IMPL
void vcos_tls_delete(VCOS_TLS_KEY_T tls) {
pthread_key_delete(tls);
}
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_tls_set(VCOS_TLS_KEY_T tls, void *v) {
pthread_setspecific(tls, v);
return VCOS_SUCCESS;
}
VCOS_INLINE_IMPL
void *vcos_tls_get(VCOS_TLS_KEY_T tls) {
return pthread_getspecific(tls);
}
#if VCOS_HAVE_ATOMIC_FLAGS
/*
* Atomic flags
*/
/* TODO implement properly... */
VCOS_INLINE_IMPL
VCOS_STATUS_T vcos_atomic_flags_create(VCOS_ATOMIC_FLAGS_T *atomic_flags)
{
atomic_flags->flags = 0;
return vcos_mutex_create(&atomic_flags->mutex, "VCOS_ATOMIC_FLAGS_T");
}
VCOS_INLINE_IMPL
void vcos_atomic_flags_or(VCOS_ATOMIC_FLAGS_T *atomic_flags, uint32_t flags)
{
vcos_mutex_lock(&atomic_flags->mutex);
atomic_flags->flags |= flags;
vcos_mutex_unlock(&atomic_flags->mutex);
}
VCOS_INLINE_IMPL
uint32_t vcos_atomic_flags_get_and_clear(VCOS_ATOMIC_FLAGS_T *atomic_flags)
{
uint32_t flags;
vcos_mutex_lock(&atomic_flags->mutex);
flags = atomic_flags->flags;
atomic_flags->flags = 0;
vcos_mutex_unlock(&atomic_flags->mutex);
return flags;
}
VCOS_INLINE_IMPL
void vcos_atomic_flags_delete(VCOS_ATOMIC_FLAGS_T *atomic_flags)
{
vcos_mutex_delete(&atomic_flags->mutex);
}
#endif
#if defined(linux) || defined(_HAVE_SBRK)
/* not exactly the free memory, but a measure of it */
VCOS_INLINE_IMPL
unsigned long vcos_get_free_mem(void) {
return (unsigned long)sbrk(0);
}
#endif
#ifdef VCOS_PTHREADS_WANT_HISR_EMULATION
VCOS_STATUS_T vcos_legacy_hisr_create(VCOS_HISR_T *hisr, const char *name,
void (*entry)(void),
VCOS_UNSIGNED pri,
void *stack, VCOS_UNSIGNED stack_size);
void vcos_legacy_hisr_activate(VCOS_HISR_T *hisr);
void vcos_legacy_hisr_delete(VCOS_HISR_T *hisr);
#endif
#undef VCOS_ASSERT_LOGGING_DISABLE
#define VCOS_ASSERT_LOGGING_DISABLE 0
#endif /* VCOS_INLINE_BODIES */
#define vcos_log_platform_init() _vcos_log_platform_init()
VCOSPRE_ void VCOSPOST_ _vcos_log_platform_init(void);
VCOS_INLINE_DECL void _vcos_thread_sem_wait(void);
VCOS_INLINE_DECL void _vcos_thread_sem_post(VCOS_THREAD_T *);
#define VCOS_APPLICATION_ARGC vcos_get_argc()
#define VCOS_APPLICATION_ARGV vcos_get_argv()
#include "generic/vcos_generic_reentrant_mtx.h"
#include "generic/vcos_generic_named_sem.h"
#include "generic/vcos_generic_quickslow_mutex.h"
#include "generic/vcos_common.h"
#define _VCOS_LOG_LEVEL() getenv("VC_LOGLEVEL")
VCOS_STATIC_INLINE
char *vcos_strdup(const char *str)
{
return strdup(str);
}
typedef void (*VCOS_ISR_HANDLER_T)(VCOS_UNSIGNED vecnum);
#define VCOS_DL_LAZY RTLD_LAZY
#define VCOS_DL_NOW RTLD_NOW
#define VCOS_DL_LOCAL RTLD_LOCAL
#define VCOS_DL_GLOBAL RTLD_GLOBAL
#ifdef __cplusplus
}
#endif
#endif /* VCOS_PLATFORM_H */
@@ -0,0 +1,71 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - platform-specific types and defines
=============================================================================*/
#ifndef VCOS_PLATFORM_TYPES_H
#define VCOS_PLATFORM_TYPES_H
#include "vcos_inttypes.h"
#ifdef __cplusplus
extern "C" {
#endif
#define VCOSPRE_ extern
#define VCOSPOST_
#if defined(__GNUC__) && (( __GNUC__ > 2 ) || (( __GNUC__ == 2 ) && ( __GNUC_MINOR__ >= 3 )))
#define VCOS_FORMAT_ATTR_(ARCHETYPE, STRING_INDEX, FIRST_TO_CHECK) __attribute__ ((format (ARCHETYPE, STRING_INDEX, FIRST_TO_CHECK)))
#else
#define VCOS_FORMAT_ATTR_(ARCHETYPE, STRING_INDEX, FIRST_TO_CHECK)
#endif
#if defined(__linux__) && !defined(NDEBUG) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
#define VCOS_BKPT ({ __asm volatile ("int3":::"memory"); })
#endif
/*#define VCOS_BKPT vcos_abort() */
#define VCOS_ASSERT_LOGGING 1
#define VCOS_ASSERT_LOGGING_DISABLE 0
extern void
vcos_pthreads_logging_assert(const char *file, const char *func, unsigned int line, const char *fmt, ...);
#define VCOS_ASSERT_MSG(...) ((VCOS_ASSERT_LOGGING && !VCOS_ASSERT_LOGGING_DISABLE) ? vcos_pthreads_logging_assert(__FILE__, __func__, __LINE__, __VA_ARGS__) : (void)0)
#define VCOS_INLINE_BODIES
#define VCOS_INLINE_DECL extern __inline__
#define VCOS_INLINE_IMPL static __inline__
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,902 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*#define VCOS_INLINE_BODIES */
#include "interface/vcos/vcos.h"
#include "interface/vcos/vcos_msgqueue.h"
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <linux/param.h>
/* Cygwin doesn't always have prctl.h and it doesn't have PR_SET_NAME */
#if defined( __linux__ )
# if !defined(HAVE_PRCTL)
# define HAVE_PRCTL
# endif
#include <sys/prctl.h>
#endif
#ifdef HAVE_CMAKE_CONFIG
#include "cmake_config.h"
#endif
#ifdef HAVE_MTRACE
#include <mcheck.h>
#endif
#if defined(ANDROID)
#include <android/log.h>
#endif
#ifndef VCOS_DEFAULT_STACK_SIZE
#define VCOS_DEFAULT_STACK_SIZE 4096
#endif
static int vcos_argc;
static const char **vcos_argv;
typedef void (*LEGACY_ENTRY_FN_T)(int, void *);
static VCOS_THREAD_ATTR_T default_attrs = {
.ta_stacksz = VCOS_DEFAULT_STACK_SIZE,
};
/** Singleton global lock used for vcos_global_lock/unlock(). */
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
#ifdef ANDROID
static VCOS_MUTEX_T printf_lock;
#endif
/* Create a per-thread key for faking up vcos access
* on non-vcos threads.
*/
pthread_key_t _vcos_thread_current_key;
static VCOS_UNSIGNED _vcos_thread_current_key_created = 0;
static VCOS_ONCE_T current_thread_key_once; /* init just once */
static void vcos_thread_cleanup(VCOS_THREAD_T *thread)
{
vcos_semaphore_delete(&thread->suspend);
if (thread->task_timer_created)
{
vcos_timer_delete(&thread->task_timer);
}
}
static void vcos_dummy_thread_cleanup(void *cxt)
{
VCOS_THREAD_T *thread = cxt;
if (thread->dummy)
{
int i;
/* call termination functions */
for (i=0; thread->at_exit[i].pfn != NULL; i++)
{
thread->at_exit[i].pfn(thread->at_exit[i].cxt);
}
vcos_thread_cleanup(thread);
vcos_free(thread);
}
}
static void current_thread_key_init(void)
{
vcos_assert(!_vcos_thread_current_key_created);
pthread_key_create (&_vcos_thread_current_key, vcos_dummy_thread_cleanup);
_vcos_thread_current_key_created = 1;
}
/* A VCOS wrapper for the thread which called vcos_init. */
static VCOS_THREAD_T vcos_thread_main;
static void *vcos_thread_entry(void *arg)
{
int i;
void *ret;
VCOS_THREAD_T *thread = (VCOS_THREAD_T *)arg;
vcos_assert(thread != NULL);
thread->dummy = 0;
pthread_setspecific(_vcos_thread_current_key, thread);
#if defined( HAVE_PRCTL ) && defined( PR_SET_NAME )
/* cygwin doesn't have PR_SET_NAME */
prctl( PR_SET_NAME, (unsigned long)thread->name, 0, 0, 0 );
#endif
if (thread->legacy)
{
LEGACY_ENTRY_FN_T fn = (LEGACY_ENTRY_FN_T)thread->entry;
(*fn)(0, thread->arg);
ret = 0;
}
else
{
ret = (*thread->entry)(thread->arg);
}
/* call termination functions */
for (i=0; thread->at_exit[i].pfn != NULL; i++)
{
thread->at_exit[i].pfn(thread->at_exit[i].cxt);
}
return ret;
}
static void _task_timer_expiration_routine(void *cxt)
{
VCOS_THREAD_T *thread = (VCOS_THREAD_T *)cxt;
vcos_assert(thread->orig_task_timer_expiration_routine);
thread->orig_task_timer_expiration_routine(thread->orig_task_timer_context);
thread->orig_task_timer_expiration_routine = NULL;
}
VCOS_STATUS_T vcos_thread_create(VCOS_THREAD_T *thread,
const char *name,
VCOS_THREAD_ATTR_T *attrs,
VCOS_THREAD_ENTRY_FN_T entry,
void *arg)
{
VCOS_STATUS_T st;
pthread_attr_t pt_attrs;
VCOS_THREAD_ATTR_T *local_attrs = attrs ? attrs : &default_attrs;
int rc;
vcos_assert(thread);
memset(thread, 0, sizeof(VCOS_THREAD_T));
rc = pthread_attr_init(&pt_attrs);
if (rc < 0)
return VCOS_ENOMEM;
st = vcos_semaphore_create(&thread->suspend, NULL, 0);
if (st != VCOS_SUCCESS)
{
pthread_attr_destroy(&pt_attrs);
return st;
}
pthread_attr_setstacksize(&pt_attrs, local_attrs->ta_stacksz);
#if VCOS_CAN_SET_STACK_ADDR
if (local_attrs->ta_stackaddr)
{
pthread_attr_setstackaddr(&pt_attrs, local_attrs->ta_stackaddr);
}
#else
vcos_demand(local_attrs->ta_stackaddr == 0);
#endif
/* pthread_attr_setpriority(&pt_attrs, local_attrs->ta_priority); */
vcos_assert(local_attrs->ta_stackaddr == 0); /* Not possible */
thread->entry = entry;
thread->arg = arg;
thread->legacy = local_attrs->legacy;
strncpy(thread->name, name, sizeof(thread->name));
thread->name[sizeof(thread->name)-1] = '\0';
memset(thread->at_exit, 0, sizeof(thread->at_exit));
rc = pthread_create(&thread->thread, &pt_attrs, vcos_thread_entry, thread);
pthread_attr_destroy(&pt_attrs);
if (rc < 0)
{
vcos_semaphore_delete(&thread->suspend);
return VCOS_ENOMEM;
}
else
{
return VCOS_SUCCESS;
}
}
void vcos_thread_join(VCOS_THREAD_T *thread,
void **pData)
{
pthread_join(thread->thread, pData);
vcos_thread_cleanup(thread);
}
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_thread_create_classic(VCOS_THREAD_T *thread,
const char *name,
void *(*entry)(void *arg),
void *arg,
void *stack,
VCOS_UNSIGNED stacksz,
VCOS_UNSIGNED priaff,
VCOS_UNSIGNED timeslice,
VCOS_UNSIGNED autostart)
{
VCOS_THREAD_ATTR_T attrs;
vcos_thread_attr_init(&attrs);
vcos_thread_attr_setstacksize(&attrs, stacksz);
vcos_thread_attr_setpriority(&attrs, priaff & ~_VCOS_AFFINITY_MASK);
vcos_thread_attr_setaffinity(&attrs, priaff & _VCOS_AFFINITY_MASK);
(void)timeslice;
(void)autostart;
if (VCOS_CAN_SET_STACK_ADDR)
{
vcos_thread_attr_setstack(&attrs, stack, stacksz);
}
return vcos_thread_create(thread, name, &attrs, entry, arg);
}
uint64_t vcos_getmicrosecs64_internal(void)
{
struct timeval tv;
uint64_t tm = 0;
if (!gettimeofday(&tv, NULL))
{
tm = (tv.tv_sec * 1000000LL) + tv.tv_usec;
}
return tm;
}
#ifdef ANDROID
static int log_prio[] =
{
ANDROID_LOG_INFO, /* VCOS_LOG_UNINITIALIZED */
ANDROID_LOG_INFO, /* VCOS_LOG_NEVER */
ANDROID_LOG_ERROR, /* VCOS_LOG_ERROR */
ANDROID_LOG_WARN, /* VCOS_LOG_WARN */
ANDROID_LOG_INFO, /* VCOS_LOG_INFO */
ANDROID_LOG_DEBUG /* VCOS_LOG_TRACE */
};
int vcos_use_android_log = 1;
int vcos_log_to_file = 0;
#else
int vcos_use_android_log = 0;
int vcos_log_to_file = 0;
#endif
static FILE * log_fhandle = NULL;
void vcos_vlog_default_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args)
{
(void)_level;
#ifdef ANDROID
if ( vcos_use_android_log )
{
__android_log_vprint(log_prio[_level], cat->name, fmt, args);
}
else
{
vcos_mutex_lock(&printf_lock);
#endif
if(NULL != log_fhandle)
{
if (cat->flags.want_prefix)
fprintf( log_fhandle, "%s: ", cat->name );
vfprintf(log_fhandle, fmt, args);
fputs("\n", log_fhandle);
fflush(log_fhandle);
}
#ifdef ANDROID
vcos_mutex_unlock(&printf_lock);
}
#endif
}
void _vcos_log_platform_init(void)
{
if(vcos_log_to_file)
{
char log_fname[100];
#ifdef ANDROID
snprintf(log_fname, 100, "/data/log/vcos_log%u.txt", vcos_process_id_current());
#else
snprintf(log_fname, 100, "/var/log/vcos_log%u.txt", vcos_process_id_current());
#endif
log_fhandle = fopen(log_fname, "w");
}
else
log_fhandle = stderr;
}
/* Flags for init/deinit components */
enum
{
VCOS_INIT_NAMED_SEM = (1 << 0),
VCOS_INIT_PRINTF_LOCK = (1 << 1),
VCOS_INIT_MAIN_SEM = (1 << 2),
VCOS_INIT_MSGQ = (1 << 3),
VCOS_INIT_ALL = 0xffffffff
};
static void vcos_term(uint32_t flags)
{
if (flags & VCOS_INIT_MSGQ)
vcos_msgq_deinit();
if (flags & VCOS_INIT_MAIN_SEM)
vcos_semaphore_delete(&vcos_thread_main.suspend);
#ifdef ANDROID
if (flags & VCOS_INIT_PRINTF_LOCK)
vcos_mutex_delete(&printf_lock);
#endif
if (flags & VCOS_INIT_NAMED_SEM)
_vcos_named_semaphore_deinit();
}
VCOS_STATUS_T vcos_platform_init(void)
{
VCOS_STATUS_T st;
uint32_t flags = 0;
int pst;
st = _vcos_named_semaphore_init();
if (!vcos_verify(st == VCOS_SUCCESS))
goto end;
flags |= VCOS_INIT_NAMED_SEM;
#ifdef HAVE_MTRACE
/* enable glibc memory debugging, if the environment
* variable MALLOC_TRACE names a valid file.
*/
mtrace();
#endif
#ifdef ANDROID
st = vcos_mutex_create(&printf_lock, "printf");
if (!vcos_verify(st == VCOS_SUCCESS))
goto end;
flags |= VCOS_INIT_PRINTF_LOCK;
#endif
st = vcos_once(&current_thread_key_once, current_thread_key_init);
if (!vcos_verify(st == VCOS_SUCCESS))
goto end;
/* Initialise a VCOS wrapper for the thread which called vcos_init. */
st = vcos_semaphore_create(&vcos_thread_main.suspend, NULL, 0);
if (!vcos_verify(st == VCOS_SUCCESS))
goto end;
flags |= VCOS_INIT_MAIN_SEM;
vcos_thread_main.thread = pthread_self();
pst = pthread_setspecific(_vcos_thread_current_key, &vcos_thread_main);
if (!vcos_verify(pst == 0))
{
st = VCOS_EINVAL;
goto end;
}
st = vcos_msgq_init();
if (!vcos_verify(st == VCOS_SUCCESS))
goto end;
flags |= VCOS_INIT_MSGQ;
vcos_logging_init();
end:
if (st != VCOS_SUCCESS)
vcos_term(flags);
return st;
}
void vcos_platform_deinit(void)
{
vcos_term(VCOS_INIT_ALL);
}
void vcos_global_lock(void)
{
pthread_mutex_lock(&lock);
}
void vcos_global_unlock(void)
{
pthread_mutex_unlock(&lock);
}
void vcos_thread_exit(void *arg)
{
VCOS_THREAD_T *thread = vcos_thread_current();
if ( thread && thread->dummy )
{
vcos_free ( (void*) thread );
thread = NULL;
}
pthread_exit(arg);
}
void vcos_thread_attr_init(VCOS_THREAD_ATTR_T *attrs)
{
*attrs = default_attrs;
}
VCOS_STATUS_T vcos_pthreads_map_error(int error)
{
switch (error)
{
case ENOMEM:
return VCOS_ENOMEM;
case ENXIO:
return VCOS_ENXIO;
case EAGAIN:
return VCOS_EAGAIN;
case ENOSPC:
return VCOS_ENOSPC;
default:
return VCOS_EINVAL;
}
}
VCOS_STATUS_T vcos_pthreads_map_errno(void)
{
return vcos_pthreads_map_error(errno);
}
void _vcos_task_timer_set(void (*pfn)(void*), void *cxt, VCOS_UNSIGNED ms)
{
VCOS_THREAD_T *thread = vcos_thread_current();
if (thread == NULL)
return;
vcos_assert(thread->orig_task_timer_expiration_routine == NULL);
if (!thread->task_timer_created)
{
VCOS_STATUS_T st = vcos_timer_create(&thread->task_timer, NULL,
_task_timer_expiration_routine, thread);
(void)st;
vcos_assert(st == VCOS_SUCCESS);
thread->task_timer_created = 1;
}
thread->orig_task_timer_expiration_routine = pfn;
thread->orig_task_timer_context = cxt;
vcos_timer_set(&thread->task_timer, ms);
}
void _vcos_task_timer_cancel(void)
{
VCOS_THREAD_T *thread = vcos_thread_current();
if (thread == NULL || !thread->task_timer_created)
return;
vcos_timer_cancel(&thread->task_timer);
thread->orig_task_timer_expiration_routine = NULL;
}
int vcos_vsnprintf( char *buf, size_t buflen, const char *fmt, va_list ap )
{
return vsnprintf( buf, buflen, fmt, ap );
}
int vcos_snprintf(char *buf, size_t buflen, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap,fmt);
ret = vsnprintf(buf, buflen, fmt, ap);
va_end(ap);
return ret;
}
int vcos_have_rtos(void)
{
return 1;
}
const char * vcos_thread_get_name(const VCOS_THREAD_T *thread)
{
return thread->name;
}
#ifdef VCOS_HAVE_BACKTRACK
void __attribute__((weak)) vcos_backtrace_self(void);
#endif
void vcos_pthreads_logging_assert(const char *file, const char *func, unsigned int line, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "assertion failure:%s:%d:%s():",
file, line, func);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
#ifdef VCOS_HAVE_BACKTRACK
if (vcos_backtrace_self)
vcos_backtrace_self();
#endif
abort();
}
extern VCOS_STATUS_T vcos_thread_at_exit(void (*pfn)(void*), void *cxt)
{
int i;
VCOS_THREAD_T *self = vcos_thread_current();
if (!self)
{
vcos_assert(0);
return VCOS_EINVAL;
}
for (i=0; i<VCOS_MAX_EXIT_HANDLERS; i++)
{
if (self->at_exit[i].pfn == NULL)
{
self->at_exit[i].pfn = pfn;
self->at_exit[i].cxt = cxt;
return VCOS_SUCCESS;
}
}
return VCOS_ENOSPC;
}
void vcos_set_args(int argc, const char **argv)
{
vcos_argc = argc;
vcos_argv = argv;
}
int vcos_get_argc(void)
{
return vcos_argc;
}
const char ** vcos_get_argv(void)
{
return vcos_argv;
}
/* we can't inline this, because HZ comes from sys/param.h which
* dumps all sorts of junk into the global namespace, notable MIN and
* MAX.
*/
uint32_t _vcos_get_ticks_per_second(void)
{
return HZ;
}
VCOS_STATUS_T vcos_once(VCOS_ONCE_T *once_control,
void (*init_routine)(void))
{
int rc = pthread_once(once_control, init_routine);
if (rc != 0)
{
switch (errno)
{
case EINVAL:
return VCOS_EINVAL;
default:
vcos_assert(0);
return VCOS_EACCESS;
}
}
else
{
return VCOS_SUCCESS;
}
}
VCOS_THREAD_T *vcos_dummy_thread_create(void)
{
VCOS_STATUS_T st;
VCOS_THREAD_T *thread_hndl = NULL;
int rc;
thread_hndl = (VCOS_THREAD_T *)vcos_malloc(sizeof(VCOS_THREAD_T), NULL);
vcos_assert(thread_hndl != NULL);
memset(thread_hndl, 0, sizeof(VCOS_THREAD_T));
thread_hndl->dummy = 1;
thread_hndl->thread = pthread_self();
st = vcos_semaphore_create(&thread_hndl->suspend, NULL, 0);
if (st != VCOS_SUCCESS)
{
vcos_free(thread_hndl);
return( thread_hndl );
}
vcos_once(&current_thread_key_once, current_thread_key_init);
rc = pthread_setspecific(_vcos_thread_current_key,
thread_hndl);
(void)rc;
return( thread_hndl );
}
/***********************************************************
*
* Timers
*
***********************************************************/
/* On Linux we could use POSIX timers with a bit of synchronization.
* Unfortunately POSIX timers on Bionic are NOT POSIX compliant
* what makes that option not viable.
* That's why we ended up with our own implementation of timers.
* NOTE: That condition variables on Bionic are also buggy and
* they work incorrectly with CLOCK_MONOTONIC, so we have to
* use CLOCK_REALTIME (and hope that no one will change the time
* significantly after the timer has been set up
*/
#define NSEC_IN_SEC (1000*1000*1000)
#define MSEC_IN_SEC (1000)
#define NSEC_IN_MSEC (1000*1000)
static int _timespec_is_zero(struct timespec *ts)
{
return ((ts->tv_sec == 0) && (ts->tv_nsec == 0));
}
static void _timespec_set_zero(struct timespec *ts)
{
ts->tv_sec = ts->tv_nsec = 0;
}
/* Adds left to right and stores the result in left */
static void _timespec_add(struct timespec *left, struct timespec *right)
{
left->tv_sec += right->tv_sec;
left->tv_nsec += right->tv_nsec;
if (left->tv_nsec >= (NSEC_IN_SEC))
{
left->tv_nsec -= NSEC_IN_SEC;
left->tv_sec++;
}
}
static int _timespec_is_larger(struct timespec *left, struct timespec *right)
{
if (left->tv_sec != right->tv_sec)
return left->tv_sec > right->tv_sec;
else
return left->tv_nsec > right->tv_nsec;
}
static void* _timer_thread(void *arg)
{
VCOS_TIMER_T *timer = (VCOS_TIMER_T*)arg;
pthread_mutex_lock(&timer->lock);
while (!timer->quit)
{
struct timespec now;
/* Wait until next expiry time, or until timer's settings are changed */
if (_timespec_is_zero(&timer->expires))
pthread_cond_wait(&timer->settings_changed, &timer->lock);
else
pthread_cond_timedwait(&timer->settings_changed, &timer->lock, &timer->expires);
/* See if the timer has expired - reloop if it didn't */
clock_gettime(CLOCK_REALTIME, &now);
if (_timespec_is_zero(&timer->expires) || _timespec_is_larger(&timer->expires, &now))
continue;
/* The timer has expired. Clear the expiry time and call the
* expiration routine
*/
_timespec_set_zero(&timer->expires);
timer->orig_expiration_routine(timer->orig_context);
}
pthread_mutex_unlock(&timer->lock);
return NULL;
}
VCOS_STATUS_T vcos_timer_init(void)
{
return VCOS_SUCCESS;
}
VCOS_STATUS_T vcos_timer_create(VCOS_TIMER_T *timer,
const char *name,
void (*expiration_routine)(void *context),
void *context)
{
pthread_mutexattr_t lock_attr;
VCOS_STATUS_T result = VCOS_SUCCESS;
int settings_changed_initialized = 0;
int lock_attr_initialized = 0;
int lock_initialized = 0;
(void)name;
vcos_assert(timer);
vcos_assert(expiration_routine);
memset(timer, 0, sizeof(VCOS_TIMER_T));
timer->orig_expiration_routine = expiration_routine;
timer->orig_context = context;
/* Create conditional variable for notifying the timer's thread
* when settings change.
*/
if (result == VCOS_SUCCESS)
{
int rc = pthread_cond_init(&timer->settings_changed, NULL);
if (rc == 0)
settings_changed_initialized = 1;
else
result = vcos_pthreads_map_error(rc);
}
/* Create attributes for the lock (we want it to be recursive) */
if (result == VCOS_SUCCESS)
{
int rc = pthread_mutexattr_init(&lock_attr);
if (rc == 0)
{
pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
lock_attr_initialized = 1;
}
else
{
result = vcos_pthreads_map_error(rc);
}
}
/* Create lock for the timer structure */
if (result == VCOS_SUCCESS)
{
int rc = pthread_mutex_init(&timer->lock, &lock_attr);
if (rc == 0)
lock_initialized = 1;
else
result = vcos_pthreads_map_error(rc);
}
/* Lock attributes are no longer needed */
if (lock_attr_initialized)
pthread_mutexattr_destroy(&lock_attr);
/* Create the underlying thread */
if (result == VCOS_SUCCESS)
{
int rc = pthread_create(&timer->thread, NULL, _timer_thread, timer);
if (rc != 0)
result = vcos_pthreads_map_error(rc);
}
/* Clean up if anything went wrong */
if (result != VCOS_SUCCESS)
{
if (lock_initialized)
pthread_mutex_destroy(&timer->lock);
if (settings_changed_initialized)
pthread_cond_destroy(&timer->settings_changed);
}
return result;
}
void vcos_timer_set(VCOS_TIMER_T *timer, VCOS_UNSIGNED delay_ms)
{
struct timespec now;
vcos_assert(timer);
/* Other implementations of this function do undefined things
* when delay_ms is 0. This implementation will simply assert and return
*/
vcos_assert(delay_ms != 0);
if (delay_ms == 0)
return;
pthread_mutex_lock(&timer->lock);
/* Calculate the new absolute expiry time */
clock_gettime(CLOCK_REALTIME, &now);
timer->expires.tv_sec = delay_ms / MSEC_IN_SEC;
timer->expires.tv_nsec = (delay_ms % MSEC_IN_SEC) * NSEC_IN_MSEC;
_timespec_add(&timer->expires, &now);
/* Notify the timer's thread about the change */
pthread_cond_signal(&timer->settings_changed);
pthread_mutex_unlock(&timer->lock);
}
void vcos_timer_cancel(VCOS_TIMER_T *timer)
{
vcos_assert(timer);
pthread_mutex_lock(&timer->lock);
_timespec_set_zero(&timer->expires);
pthread_cond_signal(&timer->settings_changed);
pthread_mutex_unlock(&timer->lock);
}
void vcos_timer_reset(VCOS_TIMER_T *timer, VCOS_UNSIGNED delay_ms)
{
vcos_timer_set(timer, delay_ms);
}
void vcos_timer_delete(VCOS_TIMER_T *timer)
{
vcos_assert(timer);
pthread_mutex_lock(&timer->lock);
/* Other implementation of this function (e.g. ThreadX)
* disallow it being called from the expiration routine
*/
vcos_assert(pthread_self() != timer->thread);
/* Stop the timer and set flag telling the timer thread to quit */
_timespec_set_zero(&timer->expires);
timer->quit = 1;
/* Notify the timer's thread about the change */
pthread_cond_signal(&timer->settings_changed);
/* Release the lock, so that the timer's thread can quit */
pthread_mutex_unlock(&timer->lock);
/* Wait for the timer thread to finish */
pthread_join(timer->thread, NULL);
/* Free resources used by the timer */
pthread_mutex_destroy(&timer->lock);
pthread_cond_destroy(&timer->settings_changed);
}
@@ -0,0 +1,47 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef USER_NODEFS_H
#define USER_NODEFS_H
/*
* This tells coverity not to expand the assert macro, so it still sees the
* asserts in the code, even in release builds (we currently run coverity on
* our release builds). Unfortunately MetaWare won't compile it, even though
* __COVERITY__ isn't defined, so we put this in its own header.
*
* FIXME: This belongs in the Coverity config (in a file called
* config/user_nodefs.h)
*/
#nodef assert
/*
* So we need to declare the function now that it isn't a macro any more. It's
* already built into coverity that assert is a "killpath".
*/
extern void assert(int cond);
#endif /* USER_NODEFS_H */
+221
View File
@@ -0,0 +1,221 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - public header file
=============================================================================*/
/**
* \mainpage OS Abstraction Layer
*
* \section intro Introduction
*
* This abstraction layer is here to allow the underlying OS to be easily changed (e.g. from
* Nucleus to ThreadX) and to aid in porting host applications to new targets.
*
* \subsection error Error handling
*
* Wherever possible, VCOS functions assert internally and return void. The only exceptions
* are creation functions (which might fail due to lack of resources) and functions that
* might timeout or fail due to lack of space. Errors that might be reported by the underlying
* OS API (e.g. invalid mutex) are treated as a programming error, and are merely asserted on.
*
* \section thread_synch Threads and synchronisation
*
* \subsection thread Threads
*
* The thread API is somewhat different to that found in Nucleus. In particular, threads
* cannot just be destroyed at arbitrary times and nor can they merely exit. This is so
* that the same API can be implemented across all interesting platforms without too much
* difficulty. See vcos_thread.h for details. Thread attributes are configured via
* the VCOS_THREAD_ATTR_T structure, found in vcos_thread_attr.h.
*
* \subsection sema Semaphores
*
* Counted semaphores (c.f. Nucleus NU_SEMAPHORE) are created with VCOS_SEMAPHORE_T.
* Under ThreadX on VideoCore, semaphores are implemented using VideoCore spinlocks, and
* so are quite a lot faster than ordinary ThreadX semaphores. See vcos_semaphore.h.
*
* \subsection mtx Mutexes
*
* Mutexes are used for locking. Attempts to take a mutex twice, or to unlock it
* in a different thread to the one in which it was locked should be expected to fail.
* Mutexes are not re-entrant (see vcos_reentrant_mutex.h for a slightly slower
* re-entrant mutex).
*
* \subsection evflags Event flags
*
* Event flags (the ThreadX name - also known as event groups under Nucleus) provide
* 32 flags which can be waited on by multiple clients, and signalled by multiple clients.
* A timeout can be specified. See vcos_event_flags.h. An alternative to this is the
* VCOS_EVENT_T (see vcos_event.h) which is akin to the Win32 auto-reset event, or a
* saturating counted semaphore.
*
* \subsection event Events
*
* A VCOS_EVENT_T is a bit like a saturating semaphore. No matter how many times it
* is signalled, the waiter will only wake up once. See vcos_event.h. You might think this
* is useful if you suspect that the cost of reading the semaphore count (perhaps via a
* system call) is expensive on your platform.
*
* \subsection tls Thread local storage
*
* Thread local storage is supported using vcos_tls.h. This is emulated on Nucleus
* and ThreadX.
*
* \section int Interrupts
*
* The legacy LISR/HISR scheme found in Nucleus is supported via the legacy ISR API,
* which is also supported on ThreadX. New code should avoid this, and old code should
* be migrated away from it, since it is slow. See vcos_legacy_isr.h.
*
* Registering an interrupt handler, and disabling/restoring interrupts, is handled
* using the functions in vcos_isr.h.
*
*/
/**
* \file vcos.h
*
* This is the top level header file. Clients include this. It pulls in the platform-specific
* header file (vcos_platform.h) together with header files defining the expected APIs, such
* as vcos_mutex.h, vcos_semaphore.h, etc. It is also possible to include these header files
* directly.
*
*/
#ifndef VCOS_H
#define VCOS_H
#include "vcos_assert.h"
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
#ifndef VCOS_INIT_H
#include "vcos_init.h"
#endif
#ifndef VCOS_SEMAPHORE_H
#include "vcos_semaphore.h"
#endif
#ifndef VCOS_THREAD_H
#include "vcos_thread.h"
#endif
#ifndef VCOS_MUTEX_H
#include "vcos_mutex.h"
#endif
#ifndef VCOS_MEM_H
#include "vcos_mem.h"
#endif
#ifndef VCOS_LOGGING_H
#include "vcos_logging.h"
#endif
#ifndef VCOS_STRING_H
#include "vcos_string.h"
#endif
#ifndef VCOS_EVENT_H
#include "vcos_event.h"
#endif
#ifndef VCOS_THREAD_ATTR_H
#include "vcos_thread_attr.h"
#endif
#ifndef VCOS_TLS_H
#include "vcos_tls.h"
#endif
#ifndef VCOS_REENTRANT_MUTEX_H
#include "vcos_reentrant_mutex.h"
#endif
#ifndef VCOS_NAMED_SEMAPHORE_H
#include "vcos_named_semaphore.h"
#endif
#ifndef VCOS_QUICKSLOW_MUTEX_H
#include "vcos_quickslow_mutex.h"
#endif
/* Headers with predicates */
#if VCOS_HAVE_EVENT_FLAGS
#include "vcos_event_flags.h"
#endif
#if VCOS_HAVE_QUEUE
#include "vcos_queue.h"
#endif
#if VCOS_HAVE_LEGACY_ISR
#include "vcos_legacy_isr.h"
#endif
#if VCOS_HAVE_TIMER
#include "vcos_timer.h"
#endif
#if VCOS_HAVE_MEMPOOL
#include "vcos_mempool.h"
#endif
#if VCOS_HAVE_ISR
#include "vcos_isr.h"
#endif
#if VCOS_HAVE_ATOMIC_FLAGS
#include "vcos_atomic_flags.h"
#endif
#if VCOS_HAVE_ONCE
#include "vcos_once.h"
#endif
#if VCOS_HAVE_BLOCK_POOL
#include "vcos_blockpool.h"
#endif
#if VCOS_HAVE_FILE
#include "vcos_file.h"
#endif
#if VCOS_HAVE_CFG
#include "vcos_cfg.h"
#endif
#if VCOS_HAVE_CMD
#include "vcos_cmd.h"
#endif
#endif /* VCOS_H */
@@ -0,0 +1,324 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - Assertion and error-handling macros.
=============================================================================*/
#ifndef VCOS_ASSERT_H
#define VCOS_ASSERT_H
/*
* Macro:
* vcos_assert(cond)
* vcos_assert_msg(cond, fmt, ...)
* Use:
* Detecting programming errors by ensuring that assumptions are correct.
* On failure:
* Performs a platform-dependent "breakpoint", usually with an assert-style
* message. The '_msg' variant expects a printf-style format string and
* parameters.
* If a failure is detected, the code should be fixed and rebuilt.
* In release builds:
* Generates no code, i.e. does not evaluate 'cond'.
* Returns:
* Nothing.
*
* Macro:
* vcos_demand(cond)
* vcos_demand_msg(cond, fmt, ...)
* Use:
* Detecting fatal system errors that require a reboot.
* On failure:
* Performs a platform-dependent "breakpoint", usually with an assert-style
* message, then calls vcos_abort (see below).
* In release builds:
* Calls vcos_abort() if 'cond' is false.
* Returns:
* Nothing (never, on failure).
*
* Macro:
* vcos_verify(cond)
* vcos_verify_msg(cond, fmt, ...)
* Use:
* Detecting run-time errors and interesting conditions, normally within an
* 'if' statement to catch the failures, i.e.
* if (!vcos_verify(cond)) handle_error();
* On failure:
* Generates a message and optionally stops at a platform-dependent
* "breakpoint" (usually disabled). See vcos_verify_bkpts_enable below.
* In release builds:
* Just evaluates and returns 'cond'.
* Returns:
* Non-zero if 'cond' is true, otherwise zero.
*
* Macro:
* vcos_static_assert(cond)
* Use:
* Detecting compile-time errors.
* On failure:
* Generates a compiler error.
* In release builds:
* Generates a compiler error.
*
* Function:
* void vcos_abort(void)
* Use:
* Invokes the fatal error handling mechanism, alerting the host where
* applicable.
* Returns:
* Never.
*
* Macro:
* VCOS_VERIFY_BKPTS
* Use:
* Define in a module (before including vcos.h) to specify an alternative
* flag to control breakpoints on vcos_verify() failures.
* Returns:
* Non-zero values enable breakpoints.
*
* Function:
* int vcos_verify_bkpts_enable(int enable);
* Use:
* Sets the global flag controlling breakpoints on vcos_verify failures,
* enabling the breakpoints iff 'enable' is non-zero.
* Returns:
* The previous state of the flag.
*
* Function:
* int vcos_verify_bkpts_enabled(void);
* Use:
* Queries the state of the global flag enabling breakpoints on vcos_verify
* failures.
* Returns:
* The current state of the flag.
*
* Examples:
*
* int my_breakpoint_enable_flag = 1;
*
* #define VCOS_VERIFY_BKPTS my_breakpoint_enable_flag
*
* #include "vcos.h"
*
* vcos_static_assert((sizeof(object) % 32) == 0);
*
* // ...
*
* vcos_assert_msg(postcondition_is_true, "Coding error");
*
* if (!vcos_verify_msg(buf, "Buffer allocation failed (%d bytes)", size))
* {
* // Tidy up
* // ...
* return OUT_OF_MEMORY;
* }
*
* vcos_demand(*p++==GUARDWORDHEAP);
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#ifdef __COVERITY__
#include "user_nodefs.h"
extern void __coverity_panic__(void);
#undef VCOS_ASSERT_BKPT
#define VCOS_ASSERT_BKPT __coverity_panic__()
#endif
/*
* ANDROID should NOT be defined for files built for Videocore, but currently it
* is. FIXME When that's fixed, remove the __VIDEOCORE__ band-aid.
*/
#if (defined(ANDROID) && !defined(__VIDEOCORE__))
# include "assert.h"
# define vcos_assert assert
#endif
#ifndef VCOS_VERIFY_BKPTS
#define VCOS_VERIFY_BKPTS vcos_verify_bkpts_enabled()
#endif
#ifndef VCOS_BKPT
#if defined(__VIDEOCORE__) && !defined(VCOS_ASSERT_NO_BKPTS)
#define VCOS_BKPT _bkpt()
#else
#define VCOS_BKPT (void )0
#endif
#endif
#ifndef VCOS_ASSERT_BKPT
#define VCOS_ASSERT_BKPT VCOS_BKPT
#endif
#ifndef VCOS_VERIFY_BKPT
#define VCOS_VERIFY_BKPT (VCOS_VERIFY_BKPTS ? VCOS_BKPT : (void)0)
#endif
VCOSPRE_ int VCOSPOST_ vcos_verify_bkpts_enabled(void);
VCOSPRE_ int VCOSPOST_ vcos_verify_bkpts_enable(int enable);
VCOSPRE_ void VCOSPOST_ vcos_abort(void);
#ifndef VCOS_ASSERT_MSG
#ifdef LOGGING
extern void logging_assert(const char *file, const char *func, int line, const char *format, ...);
extern void logging_assert_dump(void);
#define VCOS_ASSERT_MSG(...) ((VCOS_ASSERT_LOGGING && !VCOS_ASSERT_LOGGING_DISABLE) ? logging_assert_dump(), logging_assert(__FILE__, __func__, __LINE__, __VA_ARGS__) : (void)0)
#else
#define VCOS_ASSERT_MSG(...) ((void)0)
#endif
#endif
#ifndef VCOS_VERIFY_MSG
#define VCOS_VERIFY_MSG(...) VCOS_ASSERT_MSG(__VA_ARGS__)
#endif
#ifndef VCOS_ASSERT_LOGGING
#define VCOS_ASSERT_LOGGING 0
#endif
#ifndef VCOS_ASSERT_LOGGING_DISABLE
#define VCOS_ASSERT_LOGGING_DISABLE 0
#endif
#if !defined(NDEBUG) || defined(VCOS_RELEASE_ASSERTS)
#define VCOS_ASSERT_ENABLED 1
#define VCOS_VERIFY_ENABLED 1
#else
#define VCOS_ASSERT_ENABLED 0
#define VCOS_VERIFY_ENABLED 0
#endif
#define VCOS_DEMAND_ENABLED 1
#if VCOS_ASSERT_ENABLED
#ifndef vcos_assert
#define vcos_assert(cond) \
( (cond) ? (void)0 : (VCOS_ASSERT_MSG("%s", #cond), VCOS_ASSERT_BKPT) )
#endif
#ifndef vcos_assert_msg
#define vcos_assert_msg(cond, ...) \
( (cond) ? (void)0 : (VCOS_ASSERT_MSG(__VA_ARGS__), VCOS_ASSERT_BKPT) )
#endif
#else /* VCOS_ASSERT_ENABLED */
#ifndef vcos_assert
#define vcos_assert(cond) (void)0
#endif
#ifndef vcos_assert_msg
#define vcos_assert_msg(cond, ...) (void)0
#endif
#endif /* VCOS_ASSERT_ENABLED */
#if VCOS_DEMAND_ENABLED
#ifndef vcos_demand
#define vcos_demand(cond) \
( (cond) ? (void)0 : (VCOS_ASSERT_MSG("%s", #cond), VCOS_ASSERT_BKPT, vcos_abort()) )
#endif
#ifndef vcos_demand_msg
#define vcos_demand_msg(cond, ...) \
( (cond) ? (void)0 : (VCOS_ASSERT_MSG(__VA_ARGS__), VCOS_ASSERT_BKPT, vcos_abort()) )
#endif
#else /* VCOS_DEMAND_ENABLED */
#ifndef vcos_demand
#define vcos_demand(cond) \
( (cond) ? (void)0 : vcos_abort() )
#endif
#ifndef vcos_demand_msg
#define vcos_demand_msg(cond, ...) \
( (cond) ? (void)0 : vcos_abort() )
#endif
#endif /* VCOS_DEMAND_ENABLED */
#if VCOS_VERIFY_ENABLED
#ifndef vcos_verify
#define vcos_verify(cond) \
( (cond) ? 1 : (VCOS_VERIFY_MSG("%s", #cond), VCOS_VERIFY_BKPT, 0) )
#endif
#ifndef vcos_verify_msg
#define vcos_verify_msg(cond, ...) \
( (cond) ? 1 : (VCOS_VERIFY_MSG(__VA_ARGS__), VCOS_VERIFY_BKPT, 0) )
#endif
#else /* VCOS_VERIFY_ENABLED */
#ifndef vcos_verify
#define vcos_verify(cond) (cond)
#endif
#ifndef vcos_verify_msg
#define vcos_verify_msg(cond, ...) (cond)
#endif
#endif /* VCOS_VERIFY_ENABLED */
#ifndef vcos_static_assert
#if defined(__GNUC__)
#define vcos_static_assert(cond) __attribute__((unused)) extern int vcos_static_assert[(cond)?1:-1]
#else
#define vcos_static_assert(cond) extern int vcos_static_assert[(cond)?1:-1]
#endif
#endif
#ifndef vc_assert
#define vc_assert(cond) vcos_assert(cond)
#endif
#define vcos_unreachable() vcos_assert(0)
#define vcos_not_impl() vcos_assert(0)
/** Print out a backtrace, on supported platforms.
*/
extern void vcos_backtrace_self(void);
#ifdef __cplusplus
}
#endif
#endif /* VCOS_ASSERT_H */
@@ -0,0 +1,92 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - public header file
=============================================================================*/
#ifndef VCOS_ATOMIC_FLAGS_H
#define VCOS_ATOMIC_FLAGS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/**
* \file vcos_atomic_flags.h
*
* Defines atomic flags API.
*
* 32 flags. Atomic "or" and "get and clear" operations
*/
/**
* Create an atomic flags instance.
*
* @param atomic_flags Pointer to atomic flags instance, filled in on return
*
* @return VCOS_SUCCESS if succeeded.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_atomic_flags_create(VCOS_ATOMIC_FLAGS_T *atomic_flags);
/**
* Atomically set the specified flags.
*
* @param atomic_flags Instance to set flags on
* @param flags Mask of flags to set
*/
VCOS_INLINE_DECL
void vcos_atomic_flags_or(VCOS_ATOMIC_FLAGS_T *atomic_flags, uint32_t flags);
/**
* Retrieve the current flags and then clear them. The entire operation is
* atomic.
*
* @param atomic_flags Instance to get/clear flags from/on
*
* @return Mask of flags which were set (and we cleared)
*/
VCOS_INLINE_DECL
uint32_t vcos_atomic_flags_get_and_clear(VCOS_ATOMIC_FLAGS_T *atomic_flags);
/**
* Delete an atomic flags instance.
*
* @param atomic_flags Instance to delete
*/
VCOS_INLINE_DECL
void vcos_atomic_flags_delete(VCOS_ATOMIC_FLAGS_T *atomic_flags);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,153 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - compiler-specific attributes
=============================================================================*/
#ifndef VCOS_ATTR_H
#define VCOS_ATTR_H
/**
* Type attribute indicating the enum should be stored in as few bytes as
* possible. MetaWare does this by default, so the attribute is useful when
* structs need to be portable to GCC too.
*
* MSVC doesn't support VCOS_ENUM_PACKED, so code that needs to be portable
* across all platforms but wants the type-safety and debug-info benefits
* of enum types when possible, should do:
*
* typedef enum VCOS_ENUM_PACKED { a = 0, b = 0xffff } EXAMPLE_T;
* struct foo {
* int bar;
* #if VCOS_HAS_ENUM_PACKED
* EXAMPLE_T baz;
* #else
* uint16_t baz;
* #endif
* };
*/
#if defined(__VECTORC__)
# define VCOS_ENUM_PACKED
# define VCOS_HAS_ENUM_PACKED 0
#elif defined(__GNUC__)
# define VCOS_ENUM_PACKED __attribute__ ((packed))
# define VCOS_HAS_ENUM_PACKED 1
#elif defined(__HIGHC__)
# define VCOS_ENUM_PACKED /* packed enums are default on Metaware */
# define VCOS_HAS_ENUM_PACKED 1
#else
# define VCOS_ENUM_PACKED
# define VCOS_HAS_ENUM_PACKED 0
#endif
/** Variable attribute indicating the variable must be emitted even if it appears unused. */
#if defined(__GNUC__) || defined(__HIGHC__)
# define VCOS_ATTR_USED __attribute__ ((used))
#else
# define VCOS_ATTR_USED
#endif
/** Variable attribute indicating the compiler should not warn if the variable is unused. */
#if defined(__GNUC__) || defined(__HIGHC__)
# define VCOS_ATTR_POSSIBLY_UNUSED __attribute__ ((unused))
#else
# define VCOS_ATTR_POSSIBLY_UNUSED
#endif
/** Variable attribute requiring specific alignment.
*
* Use as:
* int VCOS_ATTR_ALIGNED(256) n;
* or:
* VCOS_ATTR_ALIGNED(256) int n;
* or if you don't want to support MSVC:
* int n VCOS_ATTR_ALIGNED(256);
*/
#if defined(__GNUC__) || defined(__HIGHC__)
# define VCOS_ATTR_ALIGNED(n) __attribute__ ((aligned(n)))
#elif defined(_MSC_VER)
# define VCOS_ATTR_ALIGNED(n) __declspec(align(n))
#else
/* Force a syntax error if this is used when the compiler doesn't support it,
* instead of silently misaligning */
# define VCOS_ATTR_ALIGNED(n) VCOS_ATTR_ALIGNED_NOT_SUPPORTED_ON_THIS_COMPILER
#endif
/** Variable attribute requiring specific ELF section.
*
* Use as:
* int n VCOS_ATTR_SECTION(".foo") = 1;
*
* A pointer like &n will have type "VCOS_ATTR_SECTION_QUALIFIER int *".
*/
#if defined(__HIGHC__) || defined(__VECTORC__)
/* hcvc requires 'far' else it'll put small objects in .sdata/.rsdata/.sbss */
# define VCOS_ATTR_SECTION(s) __attribute__ ((far, section(s)))
# define VCOS_ATTR_SECTION_QUALIFIER _Far
#elif defined(__GNUC__)
# define VCOS_ATTR_SECTION(s) __attribute__ ((section(s)))
# define VCOS_ATTR_SECTION_QUALIFIER
#else
/* Force a syntax error if this is used when the compiler doesn't support it */
# define VCOS_ATTR_SECTION(s) VCOS_ATTR_SECTION_NOT_SUPPORTED_ON_THIS_COMPILER
# define VCOS_ATTR_SECTION_QUALIFIER
#endif
/** Define a function as a weak alias to another function.
* @param ret_type Function return type.
* @param alias_name Name of the alias.
* @param param_list Function parameter list, including the parentheses.
* @param target_name Target function (bare function name, not a string).
*/
#if defined(__GNUC__) || defined(__HIGHC__)
/* N.B. gcc allows __attribute__ after parameter list, but hcvc seems to silently ignore it. */
# define VCOS_WEAK_ALIAS(ret_type, alias_name, param_list, target_name) \
__attribute__ ((weak, alias(#target_name))) ret_type alias_name param_list
#else
# define VCOS_WEAK_ALIAS(ret_type, alias, params, target) VCOS_CASSERT(0)
#endif
/** Define a function as a weak alias to another function, specified as a string.
* @param ret_type Function return type.
* @param alias_name Name of the alias.
* @param param_list Function parameter list, including the parentheses.
* @param target_name Target function name as a string.
* @note Prefer the use of VCOS_WEAK_ALIAS - it is likely to be more portable.
* Only use VCOS_WEAK_ALIAS_STR if you need to do pre-processor mangling of the target
* symbol.
*/
#if defined(__GNUC__) || defined(__HIGHC__)
/* N.B. gcc allows __attribute__ after parameter list, but hcvc seems to silently ignore it. */
# define VCOS_WEAK_ALIAS_STR(ret_type, alias_name, param_list, target_name) \
__attribute__ ((weak, alias(target_name))) ret_type alias_name param_list
#else
# define VCOS_WEAK_ALIAS_STR(ret_type, alias, params, target) VCOS_CASSERT(0)
#endif
#endif /* VCOS_ATTR_H */
@@ -0,0 +1,171 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - fixed size allocator support
=============================================================================*/
#ifndef VCOS_BLOCKPOOL_H
#define VCOS_BLOCKPOOL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/** \file
*
* Thread safe, fixed size allocator API.
*
*/
/** Initialises a block pool to use already allocated (e.g. statically)
* allocated memory.
*
* Different implementations will incur different overheads. Use
* VCOS_BLOCKPOOL_SIZE(num_blocks, block_size) to calculate the number
* of bytes required including overheads for the desired pools.
*
* @param pool Pointer to pool object
* @param num_blocks The number of blocks required.
* @param block_size The size of an individual block.
* @param start The address of the start of the pool.
* @param pool_size The size of the pool in bytes.
* @param align Alignment for block data. Use VCOS_BLOCKPOOL_ALIGN_DEFAULT
* for default word alignment.
* @param flags Reserved for future use.
* @param name Name of the pool. Used for diagnostics.
*
* @return VCOS_SUCCESS if the pool was created.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_blockpool_init(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
void *start, VCOS_UNSIGNED pool_size, VCOS_UNSIGNED align,
VCOS_UNSIGNED flags, const char *name);
/** Creates a pool of blocks of a given size within a buffer allocated on
* the heap.
*
* The heap memory is freed when the block pool is destroyed by
* calling vcos_blockpool_delete.
*
* @param pool Pointer to pool object
* @param num_blocks The number of blocks required.
* @param block_size The size of an individual block.
* @param align Alignment for block data. Use VCOS_BLOCKPOOL_ALIGN_DEFAULT
* for default word alignment.
* @param flags Reserved for future use.
* @param name Name of the pool. Used for diagnostics.
*
* @return VCOS_SUCCESS if the pool was created.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_blockpool_create_on_heap(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
VCOS_UNSIGNED align, VCOS_UNSIGNED flags,
const char *name);
/** Allocate a block from the pool
*
* @param pool Pointer to the pool to allocate from.
* @return a pointer to the newly allocated block or NULL if no blocks were
* available.
*/
VCOS_INLINE_DECL
void *vcos_blockpool_alloc(VCOS_BLOCKPOOL_T *pool);
/** Allocate a block from the pool and zero it.
*
* @param pool Pointer to the pool to allocate from.
* @return a pointer to the newly allocated block or NULL if no blocks were
* available.
*/
VCOS_INLINE_DECL
void *vcos_blockpool_calloc(VCOS_BLOCKPOOL_T *pool);
/** Returns a block to the pool.
*
* @param block The block to free.
*/
VCOS_INLINE_DECL
void vcos_blockpool_free(void *block);
/** Queries the number of available blocks in the pool.
* @param pool The pool to query.
*/
VCOS_INLINE_IMPL
VCOS_UNSIGNED vcos_blockpool_available_count(VCOS_BLOCKPOOL_T *pool);
/** Queries the number of used blocks in the pool.
* @param pool The pool to query.
*/
VCOS_INLINE_IMPL
VCOS_UNSIGNED vcos_blockpool_used_count(VCOS_BLOCKPOOL_T *pool);
/** Deinitialize a memory pool.
*
* @param pool The pool to de-initialize.
*/
VCOS_INLINE_DECL
void vcos_blockpool_delete(VCOS_BLOCKPOOL_T *pool);
/** Return an integer handle for a given allocated block. */
VCOS_INLINE_DECL
uint32_t vcos_blockpool_elem_to_handle(void *block);
/** Convert an integer handle back into a pointer.
* Returns NULL if invalid. */
VCOS_INLINE_DECL
void *vcos_blockpool_elem_from_handle(VCOS_BLOCKPOOL_T *pool, uint32_t handle);
/** Checks whether a pointer is an allocated block within the specified pool.
* Returns true if the block is valid, otherwise, false is returned. */
VCOS_INLINE_DECL
uint32_t vcos_blockpool_is_valid_elem(
VCOS_BLOCKPOOL_T *pool, const void *block);
/** May be called once to allow the block pool to be extended by dynamically
* adding subpools. The block size cannot be altered.
*
* @param num_extensions The number of extensions that may be created.
* The maximum is (VCOS_BLOCKPOOL_MAX_SUBPOOLS - 1)
* @param num_blocks The number of blocks to allocate in each in each
* dynamically allocated subpool.
* @return VCOS_SUCCESS if successful.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_blockpool_extend(VCOS_BLOCKPOOL_T *pool,
VCOS_UNSIGNED num_extensions, VCOS_UNSIGNED num_blocks);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,32 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const char *vcos_get_build_hostname( void );
const char *vcos_get_build_version( void );
const char *vcos_get_build_time( void );
const char *vcos_get_build_date( void );
@@ -0,0 +1,126 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined( VCOS_CFG_H )
#define VCOS_CFG_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
typedef struct opaque_vcos_cfg_buf_t *VCOS_CFG_BUF_T;
typedef struct opaque_vcos_cfg_entry_t *VCOS_CFG_ENTRY_T;
/** \file vcos_file.h
*
* API for accessing configuration/statistics information. This
* is loosely modelled on the linux proc entries.
*/
typedef void (*VCOS_CFG_SHOW_FPTR)( VCOS_CFG_BUF_T buf, void *data );
typedef void (*VCOS_CFG_PARSE_FPTR)( VCOS_CFG_BUF_T buf, void *data );
/** Create a configuration directory.
*
* @param entry Place to store the created config entry.
* @param parent Parent entry (for directory like config
* options).
* @param entryName Name of the directory.
*/
VCOS_STATUS_T vcos_cfg_mkdir( VCOS_CFG_ENTRY_T *entry,
VCOS_CFG_ENTRY_T *parent,
const char *dirName );
/** Create a configuration entry.
*
* @param entry Place to store the created config entry.
* @param parent Parent entry (for directory like config
* options).
* @param entryName Name of the configuration entry.
* @param showFunc Function pointer to show configuration
* data.
* @param parseFunc Function pointer to parse new data.
*/
VCOS_STATUS_T vcos_cfg_create_entry( VCOS_CFG_ENTRY_T *entry,
VCOS_CFG_ENTRY_T *parent,
const char *entryName,
VCOS_CFG_SHOW_FPTR showFunc,
VCOS_CFG_PARSE_FPTR parseFunc,
void *data );
/** Determines if a configuration entry has been created or not.
*
* @param entry Configuration entry to query.
*/
int vcos_cfg_is_entry_created( VCOS_CFG_ENTRY_T entry );
/** Returns the name of a configuration entry.
*
* @param entry Configuration entry to query.
*/
const char *vcos_cfg_get_entry_name( VCOS_CFG_ENTRY_T entry );
/** Removes a configuration entry.
*
* @param entry Configuration entry to remove.
*/
VCOS_STATUS_T vcos_cfg_remove_entry( VCOS_CFG_ENTRY_T *entry );
/** Writes data into a configuration buffer. Only valid inside
* the show function.
*
* @param buf Buffer to write data into.
* @param fmt printf style format string.
*/
void vcos_cfg_buf_printf( VCOS_CFG_BUF_T buf, const char *fmt, ... );
/** Retrieves a null terminated string of the data associated
* with the buffer. Only valid inside the parse function.
*
* @param buf Buffer to get data from.
* @param fmt printf style format string.
*/
char *vcos_cfg_buf_get_str( VCOS_CFG_BUF_T buf );
void *vcos_cfg_get_proc_entry( VCOS_CFG_ENTRY_T entry );
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,119 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined( VCOS_CMD_H )
#define VCOS_CMD_H
/* ---- Include Files ----------------------------------------------------- */
#ifndef VCOS_H
#include "vcos.h"
#endif
#include "vcos_stdint.h"
/* ---- Constants and Types ---------------------------------------------- */
struct VCOS_CMD_S;
typedef struct VCOS_CMD_S VCOS_CMD_T;
typedef struct
{
int argc; /* Number of arguments (includes the command/sub-command) */
char **argv; /* Array of arguments */
char **argv_orig; /* Original array of arguments */
VCOS_CMD_T *cmd_entry;
VCOS_CMD_T *cmd_parent_entry;
int use_log; /* Output being logged? */
size_t result_size; /* Size of result buffer. */
char *result_ptr; /* Next place to put output. */
char *result_buf; /* Start of the buffer. */
} VCOS_CMD_PARAM_T;
typedef VCOS_STATUS_T (*VCOS_CMD_FUNC_T)( VCOS_CMD_PARAM_T *param );
struct VCOS_CMD_S
{
const char *name;
const char *args;
VCOS_CMD_FUNC_T cmd_fn;
VCOS_CMD_T *sub_cmd_entry;
const char *descr;
};
/* ---- Variable Externs ------------------------------------------------- */
/* ---- Function Prototypes ---------------------------------------------- */
/*
* Common printing routine for generating command output.
*/
VCOSPRE_ void VCOSPOST_ vcos_cmd_error( VCOS_CMD_PARAM_T *param, const char *fmt, ... ) VCOS_FORMAT_ATTR_(printf, 2, 3);
VCOSPRE_ void VCOSPOST_ vcos_cmd_printf( VCOS_CMD_PARAM_T *param, const char *fmt, ... ) VCOS_FORMAT_ATTR_(printf, 2, 3);
VCOSPRE_ void VCOSPOST_ vcos_cmd_vprintf( VCOS_CMD_PARAM_T *param, const char *fmt, va_list args ) VCOS_FORMAT_ATTR_(printf, 2, 0);
/*
* Cause vcos_cmd_error, printf and vprintf to always log to the provided
* category. When this call is made, the results buffer passed into
* vcos_cmd_execute is used as a line buffer and does not need to be
* output by the caller.
*/
VCOSPRE_ void VCOSPOST_ vcos_cmd_always_log_output( VCOS_LOG_CAT_T *log_category );
/*
* Prints command usage for the current command.
*/
VCOSPRE_ void VCOSPOST_ vcos_cmd_usage( VCOS_CMD_PARAM_T *param );
/*
* Register commands to be processed
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_cmd_register( VCOS_CMD_T *cmd_entry );
/*
* Registers multiple commands to be processed. The array should
* be terminated by an entry with all zeros.
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_cmd_register_multiple( VCOS_CMD_T *cmd_entry );
/*
* Executes a command based on a command line.
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_cmd_execute( int argc, char **argv, size_t result_size, char *result_buf );
/*
* Shut down the command system and free all allocated data.
* Do not call any other command functions after this.
*/
VCOSPRE_ void VCOSPOST_ vcos_cmd_shutdown( void );
#endif /* VCOS_CMD_H */
@@ -0,0 +1,49 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - public header file
=============================================================================*/
#ifndef VCOS_CTYPE_H
#define VCOS_CTYPE_H
/**
* \file
*
* ctype functions.
*
*/
#ifdef __KERNEL__
#include <linux/ctype.h>
#else
#include <ctype.h>
#endif
#endif
@@ -0,0 +1,86 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VCOS - abstraction over dynamic library opening
=============================================================================*/
#ifndef VCOS_DLFCN_H
#define VCOS_DLFCN_H
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file
*
* Loading dynamic libraries. See also dlfcn.h.
*/
/** Open a dynamic library.
*
* @param name name of the library
* @param mode Load lazily or immediately (VCOS_DL_LAZY, VCOS_DL_NOW, VCOS_DL_LOCAL, VCOS_DL_GLOBAL).
*
* @return A handle for use in subsequent calls.
*/
VCOSPRE_ void * VCOSPOST_ vcos_dlopen(const char *name, int mode);
/** Look up a symbol.
*
* @param handle Handle to open
* @param name Name of function
*
* @return Function pointer, or NULL.
*/
VCOSPRE_ void VCOSPOST_ (*vcos_dlsym(void *handle, const char *name))(void);
/** Close a library
*
* @param handle Handle to close
*/
VCOSPRE_ int VCOSPOST_ vcos_dlclose (void *handle);
/** Return error message from library.
*
* @param err On return, set to non-zero if an error has occurred
* @param buf Buffer to write error to
* @param len Size of buffer (including terminating NUL).
*/
VCOSPRE_ int VCOSPOST_ vcos_dlerror(int *err, char *buf, size_t buflen);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,117 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - public header file for events
=============================================================================*/
#ifndef VCOS_EVENT_H
#define VCOS_EVENT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/**
* \file
*
* An event is akin to the Win32 auto-reset event.
*
*
* Signalling an event will wake up one waiting thread only. Once one
* thread has been woken the event atomically returns to the unsignalled
* state.
*
* If no threads are waiting on the event when it is signalled it remains
* signalled.
*
* This is almost, but not quite, completely unlike the "event flags"
* object based on Nucleus event groups and ThreadX event flags.
*
* In particular, it should be similar in speed to a semaphore, unlike
* the event flags.
*/
/**
* Create an event instance.
*
* @param event Filled in with constructed event.
* @param name Name of the event (for debugging)
*
* @return VCOS_SUCCESS on success, or error code.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_event_create(VCOS_EVENT_T *event, const char *name);
#ifndef vcos_event_signal
/**
* Signal the event. The event will return to being unsignalled
* after exactly one waiting thread has been woken up. If no
* threads are waiting it remains signalled.
*
* @param event The event to signal
*/
VCOS_INLINE_DECL
void vcos_event_signal(VCOS_EVENT_T *event);
/**
* Wait for the event.
*
* @param event The event to wait for
* @return VCOS_SUCCESS on success, VCOS_EAGAIN if the wait was interrupted.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_event_wait(VCOS_EVENT_T *event);
/**
* Try event, but don't block.
*
* @param event The event to try
* @return VCOS_SUCCESS on success, VCOS_EAGAIN if the event is not currently signalled
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_event_try(VCOS_EVENT_T *event);
#endif
/*
* Destroy an event.
*/
VCOS_INLINE_DECL
void vcos_event_delete(VCOS_EVENT_T *event);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,118 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - public header file
=============================================================================*/
#ifndef VCOS_EVENT_FLAGS_H
#define VCOS_EVENT_FLAGS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
#define VCOS_EVENT_FLAGS_SUSPEND VCOS_SUSPEND
#define VCOS_EVENT_FLAGS_NO_SUSPEND VCOS_NO_SUSPEND
typedef VCOS_OPTION VCOS_EVENTGROUP_OPERATION_T;
/**
* \file vcos_event_flags.h
*
* Defines event flags API.
*
* Similar to Nucleus event groups.
*
* These have the same semantics as Nucleus event groups and ThreadX event
* flags. As such, they are quite complex internally; if speed is important
* they might not be your best choice.
*
*/
/**
* Create an event flags instance.
*
* @param flags Pointer to event flags instance, filled in on return.
* @param name Name for the event flags, used for debug.
*
* @return VCOS_SUCCESS if succeeded.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name);
/**
* Set some events.
*
* @param flags Instance to set flags on
* @param events Bitmask of the flags to actually set
* @param op How the flags should be set. VCOS_OR will OR in the flags; VCOS_AND
* will AND them in, possibly clearing existing flags.
*/
VCOS_INLINE_DECL
void vcos_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
VCOS_UNSIGNED events,
VCOS_OPTION op);
/**
* Retrieve some events.
*
* Waits until the specified events have been set.
*
* @param flags Instance to wait on
* @param requested_events The bitmask to wait for
* @param op VCOS_OR - get any; VCOS_AND - get all.
* @param ms_suspend How long to wait, in milliseconds
* @param retrieved_events the events actually retrieved.
*
* @return VCOS_SUCCESS if events were retrieved. VCOS_EAGAIN if the
* timeout expired.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
VCOS_UNSIGNED requested_events,
VCOS_OPTION op,
VCOS_UNSIGNED ms_suspend,
VCOS_UNSIGNED *retrieved_events);
/**
* Delete an event flags instance.
*/
VCOS_INLINE_DECL
void vcos_event_flags_delete(VCOS_EVENT_FLAGS_T *);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,110 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - initialization routines
=============================================================================*/
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file
*
* Some OS support libraries need some initialization. To support this, call
* vcos_init() function at the start of day; vcos_deinit() at the end.
*/
/**
* vcos initialization. Call this function before using other vcos functions.
* Calls can be nested within the same process; they are reference counted so
* that only a call from uninitialized state has any effect.
* @note On platforms/toolchains that support it, gcc's constructor attribute or
* similar is used to invoke this function before main() or equivalent.
* @return Status of initialisation.
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_init(void);
/**
* vcos deinitialization. Call this function when vcos is no longer required,
* in order to free resources.
* Calls can be nested within the same process; they are reference counted so
* that only a call that decrements the reference count to 0 has any effect.
* @note On platforms/toolchains that support it, gcc's destructor attribute or
* similar is used to invoke this function after exit() or equivalent.
* @return Status of initialisation.
*/
VCOSPRE_ void VCOSPOST_ vcos_deinit(void);
/**
* Acquire global lock. This must be available independent of vcos_init()/vcos_deinit().
*/
VCOSPRE_ void VCOSPOST_ vcos_global_lock(void);
/**
* Release global lock. This must be available independent of vcos_init()/vcos_deinit().
*/
VCOSPRE_ void VCOSPOST_ vcos_global_unlock(void);
/** Pass in the argv/argc arguments passed to main() */
VCOSPRE_ void VCOSPOST_ vcos_set_args(int argc, const char **argv);
/** Return argc. */
VCOSPRE_ int VCOSPOST_ vcos_get_argc(void);
/** Return argv. */
VCOSPRE_ const char ** VCOSPOST_ vcos_get_argv(void);
/**
* Platform-specific initialisation.
* VCOS internal function, not part of public API, do not call from outside
* vcos. vcos_init()/vcos_deinit() reference count calls, so this function is
* only called from an uninitialized state, i.e. there will not be two
* consecutive calls to vcos_platform_init() without an intervening call to
* vcos_platform_deinit().
* This function is called with vcos_global_lock held.
* @return Status of initialisation.
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_platform_init(void);
/**
* Platform-specific de-initialisation.
* VCOS internal function, not part of public API, do not call from outside
* vcos.
* See vcos_platform_init() re reference counting.
* This function is called with vcos_global_lock held.
*/
VCOSPRE_ void VCOSPOST_ vcos_platform_deinit(void);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,49 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VCOS_INTTYPES_H
#define VCOS_INTTYPES_H
/** \file
* Attempt to provide the support for fixed width integer types as per
* inttypes.h. This simply includes inttypes.h, which should find the
* system/toolchain version if present, otherwise falling back to the version
* in <platform>. The vcos versions initially only provide the
* most common printf() macros.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
#ifdef __cplusplus
}
#endif
#endif /* VCOS_INTTYPES_H */
@@ -0,0 +1,90 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - IRQ support
=============================================================================*/
#ifndef VCOS_ISR_H
#define VCOS_ISR_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/**
* \file vcos_isr.h
*
* \section isr ISR support
*
* API for dispatching interrupts.
*/
/**
*
* Register an interrupt handler. The old handler (if any) is returned in
* old_handler. The old handler should be called if the interrupt was not
* for you.
*
* The handler function will be called in a context with interrupts disabled,
* so should be written to be as short as possible. If significant processing
* is needed, the handler should delegate to a thread.
*
* The handler function can call any OS primitive that does not block (e.g.
* post a semaphore or set an event flag). Blocking operations (including memory
* allocation from the system heap) are not permitted.
*
* To deregister an ISR, pass in NULL.
*
* @param vec Vector to register for
* @param handler Handler to be called
* @param old_handler Updated with the old handler, or NULL.
*/
VCOS_INLINE_DECL
void vcos_register_isr(VCOS_UNSIGNED vec,
VCOS_ISR_HANDLER_T handler,
VCOS_ISR_HANDLER_T *old_handler);
/** Disable interrupts, returning the old value (enabled/disabled) to the caller.
*/
VCOS_INLINE_DECL
VCOS_UNSIGNED vcos_int_disable(void);
/** Restore the previous interrupt enable/disable state.
*/
VCOS_INLINE_DECL
void vcos_int_restore(VCOS_UNSIGNED previous);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,102 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - legacy (Nucleus) IRQ support
=============================================================================*/
#ifndef VCOS_LEGACY_ISR_H
#define VCOS_LEGACY_ISR_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/** \file vcos_legacy_isr.h
*
* API for dispatching interrupts the Nucleus way, via a LISR and HISR.
* New code should use the single-dispatch scheme - the LISR/HISR
* distinction is not necessary.
*
* Under ThreadX, a HISR is implemented as a high-priority thread which
* waits on a counting semaphore to call the HISR function. Although this
* provides a good approximation to the Nucleus semantics, it is potentially
* slow if all you are trying to do is to wake a thread from LISR context.
*/
/** Register a LISR. This is identical to the NU_Register_LISR API.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_register_legacy_lisr(VCOS_UNSIGNED vecnum,
void (*lisr)(VCOS_INT),
void (**old_lisr)(VCOS_INT));
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_legacy_hisr_create(VCOS_HISR_T *hisr, const char *name,
void (*entry)(void),
VCOS_UNSIGNED pri,
void *stack, VCOS_UNSIGNED stack_size);
/** Activate a HISR. On an OS which has no distinction between a HISR and LISR,
* this may use some kind of emulation, which could well be less efficient than
* a normal ISR.`
*
* @param hisr HISR to activate.
*/
VCOS_INLINE_DECL
void vcos_legacy_hisr_activate(VCOS_HISR_T *hisr);
/** Delete a HISR.
*
* @param hisr HISR to delete.
*/
VCOS_INLINE_DECL
void vcos_legacy_hisr_delete(VCOS_HISR_T *hisr);
/** Are we in a legacy LISR?
*
* @return On Nucleus, non-zero if in a LISR. On other platforms, non-zero if
* in an interrupt.
*/
VCOS_INLINE_DECL
int vcos_in_legacy_lisr(void);
/** Is the current thread actually a fake HISR thread? Only implemented
* on platforms that fake up HISRs.
*/
#ifndef VCOS_LISRS_NEED_HISRS
VCOSPRE_ int VCOSPOST_ vcos_current_thread_is_fake_hisr_thread(VCOS_HISR_T *);
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,315 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - logging support
=============================================================================*/
#ifndef VCOS_LOGGING_H
#define VCOS_LOGGING_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
#include "vcos_logging_control.h"
/**
* \file
*
* Logging support
*
* This provides categorised logging. Clients register
* a category, and then get a number of logging levels for
* that category.
*
* The logging level flag is tested using a flag *before* the
* function call, which makes logging very fast when disabled - there
* is no function call overhead just to find out that this log
* message is disabled.
*
* \section VCOS_LOG_CATEGORY
*
* As a convenience, clients define VCOS_LOG_CATEGORY to point to
* their category; the various vcos_log_xxx() macros then expand to
* use this.
*
* e.g.
*
* #define VCOS_LOG_CATEGORY (&my_category)
*
* #include <vcos.h>
*
* VCOS_LOG_CAT_T my_category;
*
* ....
*
* vcos_log_trace("Stuff happened: %d", n_stuff);
*
*/
/** Logging levels */
typedef enum VCOS_LOG_LEVEL_T
{
VCOS_LOG_UNINITIALIZED = 0,
VCOS_LOG_NEVER,
VCOS_LOG_ERROR,
VCOS_LOG_WARN,
VCOS_LOG_INFO,
VCOS_LOG_TRACE,
} VCOS_LOG_LEVEL_T;
/** Initialize a logging category without going through vcos_log_register().
*
* This is useful for the case where there is no obvious point to do the
* registration (no initialization function for the module). However, it
* means that your logging category is not registered, so cannot be easily
* changed at run-time.
*/
#define VCOS_LOG_INIT(n,l) { l, n, 0, {0}, 0, 0 }
/** A registered logging category.
*/
typedef struct VCOS_LOG_CAT_T
{
VCOS_LOG_LEVEL_T level; /**< Which levels are enabled for this category */
const char *name; /**< Name for this category. */
struct VCOS_LOG_CAT_T *next;
struct {
unsigned int want_prefix:1;
} flags;
unsigned int refcount;
void *platform_data; /**< platform specific data */
} VCOS_LOG_CAT_T;
typedef void (*VCOS_VLOG_IMPL_FUNC_T)(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args);
/** Convert a VCOS_LOG_LEVEL_T into a printable string.
* The platform needs to implement this function.
*/
VCOSPRE_ const char * VCOSPOST_ vcos_log_level_to_string( VCOS_LOG_LEVEL_T level );
/** Convert a string into a VCOS_LOG_LEVEL_T
* The platform needs to implement this function.
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_string_to_log_level( const char *str, VCOS_LOG_LEVEL_T *level );
/** Log a message. Basic API. Normal code should not use this.
* The platform needs to implement this function.
*/
VCOSPRE_ void VCOSPOST_ vcos_log_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, ...) VCOS_FORMAT_ATTR_(printf, 3, 4);
/** Log a message using a varargs parameter list. Normal code should
* not use this.
*/
VCOSPRE_ void VCOSPOST_ vcos_vlog_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args) VCOS_FORMAT_ATTR_(printf, 3, 0);
/** Set the function which does the actual logging output.
* Passing in NULL causes the default logging function to be
* used.
*/
VCOSPRE_ void VCOSPOST_ vcos_set_vlog_impl( VCOS_VLOG_IMPL_FUNC_T vlog_impl_func );
/** The default logging function, which is provided by each
* platform.
*/
VCOSPRE_ void VCOSPOST_ vcos_vlog_default_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args) VCOS_FORMAT_ATTR_(printf, 3, 0);
/*
* Initialise the logging subsystem. This is called from
* vcos_init() so you don't normally need to call it.
*/
VCOSPRE_ void VCOSPOST_ vcos_logging_init(void);
/** Register a logging category.
*
* @param name the name of this category.
* @param category the category to register.
*/
VCOSPRE_ void VCOSPOST_ vcos_log_register(const char *name, VCOS_LOG_CAT_T *category);
/** Unregister a logging category.
*/
VCOSPRE_ void VCOSPOST_ vcos_log_unregister(VCOS_LOG_CAT_T *category);
/** Return a default logging category, for people too lazy to create their own.
*
* Using the default category will be slow (there's an extra function
* call overhead). Don't do this in normal code.
*/
VCOSPRE_ const VCOS_LOG_CAT_T * VCOSPOST_ vcos_log_get_default_category(void);
VCOSPRE_ void VCOSPOST_ vcos_set_log_options(const char *opt);
/** Set the logging level for a category at run time. Without this, the level
* will be that set by vcos_log_register from a platform-specific source.
*
* @param category the category to modify.
* @param level the new logging level for this category.
*/
VCOS_STATIC_INLINE void vcos_log_set_level(VCOS_LOG_CAT_T *category, VCOS_LOG_LEVEL_T level)
{
category->level = level;
}
#define vcos_log_dump_mem(cat,label,addr,voidMem,numBytes) do { if (vcos_is_log_enabled(cat,VCOS_LOG_TRACE)) vcos_log_dump_mem_impl(cat,label,addr,voidMem,numBytes); } while (0)
void vcos_log_dump_mem_impl( const VCOS_LOG_CAT_T *cat,
const char *label,
uint32_t addr,
const void *voidMem,
size_t numBytes );
/*
* Platform specific hooks (optional).
*/
#ifndef vcos_log_platform_init
#define vcos_log_platform_init() (void)0
#endif
#ifndef vcos_log_platform_register
#define vcos_log_platform_register(category) (void)0
#endif
#ifndef vcos_log_platform_unregister
#define vcos_log_platform_unregister(category) (void)0
#endif
/* VCOS_TRACE() - deprecated macro which just outputs in a debug build and
* is a no-op in a release build.
*
* _VCOS_LOG_X() - internal macro which outputs if the current level for the
* particular category is higher than the supplied message level.
*/
#define VCOS_LOG_DFLT_CATEGORY vcos_log_get_default_category()
#define _VCOS_LEVEL(x) (x)
#define vcos_is_log_enabled(cat,_level) (_VCOS_LEVEL((cat)->level) >= _VCOS_LEVEL(_level))
#if defined(_VCOS_METAWARE) || defined(__GNUC__)
# if !defined(AMPUTATE_ALL_VCOS_LOGGING) && (!defined(NDEBUG) || defined(VCOS_ALWAYS_WANT_LOGGING))
# define VCOS_LOGGING_ENABLED
# define _VCOS_LOG_X(cat, _level, fmt...) do { if (vcos_is_log_enabled(cat,_level)) vcos_log_impl(cat,_level,fmt); } while (0)
# define _VCOS_VLOG_X(cat, _level, fmt, ap) do { if (vcos_is_log_enabled(cat,_level)) vcos_vlog_impl(cat,_level,fmt,ap); } while (0)
# else
# define _VCOS_LOG_X(cat, _level, fmt...) (void)0
# define _VCOS_VLOG_X(cat, _level, fmt, ap) (void)0
# endif
# define vcos_log_error(...) _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_ERROR, __VA_ARGS__)
# define vcos_log_warn(...) _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_WARN, __VA_ARGS__)
# define vcos_log_info(...) _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_INFO, __VA_ARGS__)
# define vcos_log_trace(...) _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE, __VA_ARGS__)
# define vcos_vlog_error(fmt,ap) _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_ERROR, fmt, ap)
# define vcos_vlog_warn(fmt,ap) _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_WARN, fmt, ap)
# define vcos_vlog_info(fmt,ap) _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_INFO, fmt, ap)
# define vcos_vlog_trace(fmt,ap) _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE, fmt, ap)
# define vcos_logc_error(cat,...) _VCOS_LOG_X(cat, VCOS_LOG_ERROR, __VA_ARGS__)
# define vcos_logc_warn(cat,...) _VCOS_LOG_X(cat, VCOS_LOG_WARN, __VA_ARGS__)
# define vcos_logc_info(cat,...) _VCOS_LOG_X(cat, VCOS_LOG_INFO, __VA_ARGS__)
# define vcos_logc_trace(cat,...) _VCOS_LOG_X(cat, VCOS_LOG_TRACE, __VA_ARGS__)
# define vcos_vlogc_error(cat,fmt,ap) _VCOS_VLOG_X(cat, VCOS_LOG_ERROR, fmt, ap)
# define vcos_vlogc_warn(cat,fmt,ap) _VCOS_VLOG_X(cat, VCOS_LOG_WARN, fmt, ap)
# define vcos_vlogc_info(cat,fmt,ap) _VCOS_VLOG_X(cat, VCOS_LOG_INFO, fmt, ap)
# define vcos_vlogc_trace(cat,fmt,ap) _VCOS_VLOG_X(cat, VCOS_LOG_TRACE, fmt, ap)
# define vcos_log(...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, __VA_ARGS__)
# define vcos_vlog(fmt,ap) _VCOS_VLOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, fmt, ap)
# define VCOS_ALERT(...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_ERROR, __VA_ARGS__)
# define VCOS_TRACE(...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, __VA_ARGS__)
/*
* MS Visual Studio - pre 2005 does not grok variadic macros
*/
#elif defined(_MSC_VER)
# if _MSC_VER >= 1400
# if !defined(AMPUTATE_ALL_VCOS_LOGGING) && (!defined(NDEBUG) || defined(VCOS_ALWAYS_WANT_LOGGING))
# define VCOS_LOGGING_ENABLED
# define _VCOS_LOG_X(cat, _level, fmt,...) do { if (vcos_is_log_enabled(cat,_level)) vcos_log_impl(cat, _level, fmt, __VA_ARGS__); } while (0)
# else
# define _VCOS_LOG_X(cat, _level, fmt,...) (void)0
# endif
# define vcos_log_error(fmt,...) _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_ERROR, fmt, __VA_ARGS__)
# define vcos_log_warn(fmt,...) _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_WARN, fmt, __VA_ARGS__)
# define vcos_log_info(fmt,...) _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_INFO, fmt, __VA_ARGS__)
# define vcos_log_trace(fmt,...) _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE, fmt, __VA_ARGS__)
# define vcos_logc_error(cat,fmt,...) _VCOS_LOG_X(cat, VCOS_LOG_ERROR, fmt, __VA_ARGS__)
# define vcos_logc_warn(cat,fmt,...) _VCOS_LOG_X(cat, VCOS_LOG_WARN, fmt, __VA_ARGS__)
# define vcos_logc_info(cat,fmt,...) _VCOS_LOG_X(cat, VCOS_LOG_INFO, fmt, __VA_ARGS__)
# define vcos_logc_trace(cat,fmt,...) _VCOS_LOG_X(cat, VCOS_LOG_TRACE, fmt, __VA_ARGS__)
# define vcos_log(fmt,...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, fmt, __VA_ARGS__)
# define VCOS_ALERT(fmt,...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_ERROR, fmt, __VA_ARGS__)
# define VCOS_TRACE(fmt,...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, fmt, __VA_ARGS__)
# else /* _MSC_VER >= 1400 */
/* do not define these */
# endif /* _MSC_VER >= 1400 */
#endif
#if VCOS_HAVE_CMD
#include "vcos_cmd.h"
/*
* These are the log sub-commands. They're exported here for user-mode apps which
* may want to call these, since the "log" command isn't registered for user-mode
* apps (vcdbg for example, has its own log command).
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_assert_cmd( VCOS_CMD_PARAM_T *param );
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_set_cmd( VCOS_CMD_PARAM_T *param );
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_status_cmd( VCOS_CMD_PARAM_T *param );
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_test_cmd( VCOS_CMD_PARAM_T *param );
#endif
#ifdef __cplusplus
}
#endif
#endif /* VCOS_LOGGING_H */
@@ -0,0 +1,28 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -0,0 +1,129 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - low level thread support
=============================================================================*/
#ifndef VCOS_LOWLEVEL_THREAD_H
#define VCOS_LOWLEVEL_THREAD_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#ifndef VCOS_PLATFORM_H
#include "pthreads/vcos_platform.h"
#endif
/**
* \file
*
* This defines a low level thread API that is supported by *some* operating systems
* and can be used to construct the regular "joinable thread" API on those operating
* systems.
*
* Most clients will not need to use this code.
*
* \sa vcos_joinable_thread.h
*/
/**
* \brief Create a thread.
*
* This creates a thread which can be stopped either by returning from the
* entry point function or by calling vcos_llthread_exit from within the entry
* point function. The thread must be cleaned up by calling
* vcos_llthread_delete. vcos_llthread_delete may or may not terminate the
* thread.
*
* The preemptible parameter familiar from Nucleus is removed, as it is unused in
* VideoCore code. Affinity is added, since we do use this.
*
* @param thread Filled in with thread instance
* @param name An optional name for the thread. "" may be used (but
* a name will aid in debugging).
* @param entry Entry point
* @param arg A single argument passed to the entry point function
* @param stack Pointer to stack address
* @param stacksz Size of stack in bytes
* @param priority Priority of task, between VCOS_PRI_LOW and VCOS_PRI_HIGH
* @param affinity CPU affinity
*
* @sa vcos_llthread_terminate vcos_llthread_delete
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_llthread_create(VCOS_LLTHREAD_T *thread,
const char *name,
VCOS_LLTHREAD_ENTRY_FN_T entry,
void *arg,
void *stack,
VCOS_UNSIGNED stacksz,
VCOS_UNSIGNED priority,
VCOS_UNSIGNED affinity,
VCOS_UNSIGNED timeslice,
VCOS_UNSIGNED autostart);
/**
* \brief Exits the current thread.
*/
VCOSPRE_ void VCOSPOST_ vcos_llthread_exit(void);
/**
* \brief Delete a thread. This must be called to cleanup after
* vcos_llthread_create. This may or may not terminate the thread.
* It does not clean up any resources that may have been
* allocated by the thread.
*/
VCOSPRE_ void VCOSPOST_ vcos_llthread_delete(VCOS_LLTHREAD_T *thread);
/**
* \brief Return current lowlevel thread pointer.
*/
VCOS_INLINE_DECL
VCOS_LLTHREAD_T *vcos_llthread_current(void);
/**
* Resume a thread.
*/
VCOS_INLINE_DECL
void vcos_llthread_resume(VCOS_LLTHREAD_T *thread);
VCOSPRE_ int VCOSPOST_ vcos_llthread_running(VCOS_LLTHREAD_T *thread);
/**
* \brief Create a VCOS_LLTHREAD_T for the current thread. This is so we can
* have VCOS_LLTHREAD_Ts even for threads not originally created by VCOS (eg
* the thread that calls vcos_init).
*/
extern VCOS_STATUS_T _vcos_llthread_create_attach(VCOS_LLTHREAD_T *thread);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,101 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - memory support
=============================================================================*/
#ifndef VCOS_MEM_H
#define VCOS_MEM_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/** \file
*
* Memory allocation api (malloc/free equivalents) is for benefit of host
* applications. VideoCore code should use rtos_XXX functions.
*
*/
/** Allocate memory
*
* @param size Size of memory to allocate
* @param description Description, to aid in debugging. May be ignored internally on some platforms.
*/
VCOS_INLINE_DECL
void *vcos_malloc(VCOS_UNSIGNED size, const char *description);
void *vcos_kmalloc(VCOS_UNSIGNED size, const char *description);
void *vcos_kcalloc(VCOS_UNSIGNED num, VCOS_UNSIGNED size, const char *description);
/** Allocate cleared memory
*
* @param num Number of items to allocate.
* @param size Size of each item in bytes.
* @param description Description, to aid in debugging. May be ignored internally on some platforms.
*/
VCOS_INLINE_DECL
void *vcos_calloc(VCOS_UNSIGNED num, VCOS_UNSIGNED size, const char *description);
/** Free memory
*
* Free memory that has been allocated.
*/
VCOS_INLINE_DECL
void vcos_free(void *ptr);
void vcos_kfree(void *ptr);
/** Allocate aligned memory
*
* Allocate memory aligned on the specified boundary.
*
* @param size Size of memory to allocate
* @param description Description, to aid in debugging. May be ignored internally on some platforms.
*/
VCOS_INLINE_DECL
void *vcos_malloc_aligned(VCOS_UNSIGNED size, VCOS_UNSIGNED align, const char *description);
/** Return the amount of free heap memory
*
*/
VCOS_INLINE_DECL
unsigned long vcos_get_free_mem(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,109 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - memory pool support
=============================================================================*/
#ifndef VCOS_MEMPOOL_H
#define VCOS_MEMPOOL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/** \file
*
* Memory pools - variable sized allocator.
*
* A very basic memory pool API.
*
* This interface is deliberately not thread safe - clients should add
* their own locking, if required.
*
*
* \fixme: Add fixed-size allocator.
*
*/
/** Initialize a memory pool. The control data is taken from the memory
* supplied itself.
*
* Note: the dmalloc pool uses the memory supplied for its control
* area. This is probably a bit broken, as it stops you creating
* a pool in some "special" area of memory, while leaving the control
* information in normal memory.
*
* @param pool Pointer to pool object.
*
* @param name Name for the pool. Used for diagnostics.
*
* @param start Starting address. Must be at least 8byte aligned.
*
* @param size Size of pool in bytes.
*
* @return VCOS_SUCCESS if pool was created.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_mempool_create(VCOS_MEMPOOL_T *pool, const char *name, void *start, VCOS_UNSIGNED size);
/** Allocate some memory from a pool. If no memory is available, it
* returns NULL.
*
* @param pool Pool to allocate from
* @param len Length of memory to allocate
*
*/
VCOS_INLINE_DECL
void *vcos_mempool_alloc(VCOS_MEMPOOL_T *pool, VCOS_UNSIGNED len);
/** Free some memory back to a pool.
*
* @param pool Pool to return to
* @param mem Memory to return
*/
VCOS_INLINE_DECL
void vcos_mempool_free(VCOS_MEMPOOL_T *pool, void *mem);
/** Deinitialize a memory pool.
*
* @param pool Pool to return to
*/
VCOS_INLINE_DECL
void vcos_mempool_delete(VCOS_MEMPOOL_T *pool);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,280 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VCOS - packet-like messages, based loosely on those found in TRIPOS.
In the simple case, only the server thread creates a message queue, and
clients wait for replies on a semaphore. In more complex cases, clients can
also create message queues (not yet implemented).
Although it's possible for a thread to create multiple queues and listen
on them in turn, if you find yourself doing this it's probably a bug.
=============================================================================*/
#ifndef VCOS_MSGQUEUE_H
#define VCOS_MSGQUEUE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
#include "vcos_blockpool.h"
/**
* \file
*
* Packet-like messages, based loosely on those found in TRIPOS and
* derivatives thereof.
*
* A task can send a message *pointer* to another task, where it is
* queued on a linked list and the task woken up. The receiving task
* consumes all of the messages on its input queue, and optionally
* sends back replies using the original message memory.
*
* A caller can wait for the reply to a specific message - any other
* messages that arrive in the meantime are queued separately.
*
*
* All messages have a standard common layout, but the payload area can
* be used freely to extend this.
*/
#define VCOS_MSGQ_MAGIC 0x5147534d
/** Map the payload portion of a message to a structure pointer.
*/
#define VCOS_MSG_DATA(_msg) (void*)((_msg)->data)
/** Standard message ids - FIXME - these need to be done properly! */
#define VCOS_MSG_N_QUIT 1
#define VCOS_MSG_N_OPEN 2
#define VCOS_MSG_N_CLOSE 3
#define VCOS_MSG_N_PRIVATE (1<<20)
#define VCOS_MSG_REPLY_BIT (1<<31)
/** Make gnuc compiler be happy about pointer punning */
#ifdef __GNUC__
#define __VCOS_MAY_ALIAS __attribute__((__may_alias__))
#else
#define __VCOS_MAY_ALIAS
#endif
struct VCOS_MSG_T;
/* Replies go to one of these objects.
*/
typedef struct VCOS_MSG_WAITER_T
{
/* When the reply is sent, this function gets called with the
* address of the waiter.
*/
void (*on_reply)(struct VCOS_MSG_WAITER_T *waiter,
struct VCOS_MSG_T *msg);
} VCOS_MSG_WAITER_T;
/** A single message queue.
*/
typedef struct VCOS_MSGQUEUE_T
{
VCOS_MSG_WAITER_T waiter; /**< So we can wait on a queue */
struct VCOS_MSG_T *head; /**< head of linked list of messages waiting on this queue */
struct VCOS_MSG_T *tail; /**< tail of message queue */
VCOS_SEMAPHORE_T sem; /**< thread waits on this for new messages */
VCOS_MUTEX_T lock; /**< locks the messages list */
int attached; /**< Is this attached to a thread? */
} VCOS_MSGQUEUE_T;
/** A single message
*/
typedef struct VCOS_MSG_T
{
uint32_t magic; /**< Sanity checking */
uint32_t code; /**< message code */
struct VCOS_MSG_T *next; /**< next in queue */
VCOS_THREAD_T *src_thread; /**< for debug */
struct VCOS_MSG_WAITER_T *waiter; /**< client waiter structure */
struct VCOS_MSGQ_POOL_T *pool; /**< Pool allocated from, or NULL */
} VCOS_MSG_T;
#define MSG_REPLY_BIT (1<<31)
/** Initialize a VCOS_MSG_T. Can also use vcos_msg_init().
*/
#define VCOS_MSG_INITIALIZER {VCOS_MSGQ_MAGIC, 0, NULL, NULL, NULL, 0}
/** A pool of messages. This contains its own waiter and
* semaphore, as well as a blockpool for the actual memory
* management.
*
* When messages are returned to the waiter, it posts the
* semaphore.
*
* When waiting for a message, we just wait on the semaphore.
* When allocating without waiting, we just try-wait on the
* semaphore.
*
* If we managed to claim the semaphore, then by definition
* there must be at least that many free messages in the
* blockpool.
*/
typedef struct VCOS_MSGQ_POOL_T
{
VCOS_MSG_WAITER_T waiter;
VCOS_BLOCKPOOL_T blockpool;
VCOS_SEMAPHORE_T sem;
uint32_t magic;
} VCOS_MSGQ_POOL_T;
/** Initalise the library. Normally called from vcos_init().
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_msgq_init(void);
/** De-initialise the library. Normally called from vcos_deinit().
*/
VCOSPRE_ void VCOSPOST_ vcos_msgq_deinit(void);
/** Send a message.
*
* @param dest Destination message queue
* @param code Message code.
* @param msg Pointer to message to send. Must not go out of scope before
* message is received (do not declare on the stack).
*/
VCOSPRE_ void VCOSPOST_ vcos_msg_send(VCOS_MSGQUEUE_T *dest, uint32_t code, VCOS_MSG_T *msg);
/** Send a message and wait for a reply.
*
* @param dest Destination message queue
* @param code Message code.
* @param msg Pointer to message to send. May be declared on the stack.
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_msg_sendwait(VCOS_MSGQUEUE_T *queue, uint32_t code, VCOS_MSG_T *msg);
/** Wait for a message on a queue.
*/
VCOSPRE_ VCOS_MSG_T * VCOSPOST_ vcos_msg_wait(VCOS_MSGQUEUE_T *queue);
/** Peek for a message on this thread's endpoint. If a message is not
* available, NULL is returned. If a message is available it will be
* removed from the endpoint and returned.
*/
VCOSPRE_ VCOS_MSG_T * VCOSPOST_ vcos_msg_peek(VCOS_MSGQUEUE_T *queue);
/** Send a reply to a message
*/
VCOSPRE_ void VCOSPOST_ vcos_msg_reply(VCOS_MSG_T *msg);
/** Set the reply queue for a message. When the message is replied-to, it
* will return to the given queue.
*
* @param msg Message
* @param queue Message queue the message should return to
*/
VCOSPRE_ void VCOSPOST_ vcos_msg_set_source(VCOS_MSG_T *msg, VCOS_MSGQUEUE_T *queue);
/** Initialise a newly allocated message. This only needs to be called
* for messages allocated on the stack, heap or statically. It is not
* needed for messages allocated from a pool.
*/
VCOSPRE_ void VCOSPOST_ vcos_msg_init(VCOS_MSG_T *msg);
/** Create a message queue to wait on.
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_msgq_create(VCOS_MSGQUEUE_T *queue, const char *name);
/** Destroy a queue
*/
VCOSPRE_ void VCOSPOST_ vcos_msgq_delete(VCOS_MSGQUEUE_T *queue);
/*
* Message pools
*/
/** Create a pool of messages. Messages can be allocated from the pool and
* sent to a message queue. Replying to the message will automatically
* free it back to the pool.
*
* The pool is threadsafe.
*
* @param count number of messages in the pool
* @param payload_size maximum message payload size, not including MSG_T.
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_msgq_pool_create(
VCOS_MSGQ_POOL_T *pool,
size_t count,
size_t payload_size,
const char *name);
/** Destroy a message pool.
*/
VCOSPRE_ void VCOSPOST_ vcos_msgq_pool_delete(VCOS_MSGQ_POOL_T *pool);
/** Allocate a message from a message pool.
*
* Note:
*
* If the alloc fails (returns NULL) then your worker thread has stopped
* servicing requests or your pool is too small for the latency in
* the system. Your best bet to handle this is to fail the call that
* needs to send the message.
*
* The returned message payload area is initialised to zero.
*
* @param pool Pool to allocate from.
* @return Message or NULL if pool exhausted.
*/
VCOSPRE_ VCOS_MSG_T *VCOSPOST_ vcos_msgq_pool_alloc(VCOS_MSGQ_POOL_T *pool);
/** Wait for a message from a message pool. Waits until a
* message is available in the pool and then allocates it. If
* one is already available, returns immediately.
*
* This call can never fail.
*
* The returned message payload area is initialised to zero.
*
* @param pool Pool to allocate from.
* @return Message
*/
VCOSPRE_ VCOS_MSG_T *VCOSPOST_ vcos_msgq_pool_wait(VCOS_MSGQ_POOL_T *pool);
/** Explicitly free a message and return it to its pool.
*
* @param msg Message to free. No-op if NULL.
*/
VCOSPRE_ void VCOSPOST_ vcos_msgq_pool_free(VCOS_MSG_T *msg);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,112 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - mutex public header file
=============================================================================*/
#ifndef VCOS_MUTEX_H
#define VCOS_MUTEX_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/**
* \file vcos_mutex.h
*
* Mutex API. Mutexes are not re-entrant, as supporting this adds extra code
* that slows down clients which have been written sensibly.
*
* \sa vcos_reentrant_mutex.h
*
*/
/** Create a mutex.
*
* @param m Filled in with mutex on return
* @param name A non-null name for the mutex, used for diagnostics.
*
* @return VCOS_SUCCESS if mutex was created, or error code.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_mutex_create(VCOS_MUTEX_T *m, const char *name);
/** Delete the mutex.
*/
VCOS_INLINE_DECL
void vcos_mutex_delete(VCOS_MUTEX_T *m);
/**
* \brief Wait to claim the mutex.
*
* On most platforms this always returns VCOS_SUCCESS, and so would ideally be
* a void function, however some platforms allow a wait to be interrupted so
* it remains non-void.
*
* Try to obtain the mutex.
* @param m Mutex to wait on
* @return VCOS_SUCCESS - mutex was taken.
* VCOS_EAGAIN - could not take mutex.
*/
#ifndef vcos_mutex_lock
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_mutex_lock(VCOS_MUTEX_T *m);
/** Release the mutex.
*/
VCOS_INLINE_DECL
void vcos_mutex_unlock(VCOS_MUTEX_T *m);
#endif
/** Test if the mutex is already locked.
*
* @return 1 if mutex is locked, 0 if it is unlocked.
*/
VCOS_INLINE_DECL
int vcos_mutex_is_locked(VCOS_MUTEX_T *m);
/** Obtain the mutex if possible.
*
* @param m the mutex to try to obtain
*
* @return VCOS_SUCCESS if mutex is succesfully obtained, or VCOS_EAGAIN
* if it is already in use by another thread.
*/
#ifndef vcos_mutex_trylock
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_mutex_trylock(VCOS_MUTEX_T *m);
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,113 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - named semaphores
=============================================================================*/
#ifndef VCOS_NAMED_SEMAPHORE_H
#define VCOS_NAMED_SEMAPHORE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/**
* \file
*
* Create a named semaphore, or open an existing one by name.
*
*/
/**
* \brief Create a named semaphore.
*
* Semaphores are not re-entrant.
*
* @param sem Pointer to memory to be initialized
* @param name A name for this semaphore.
* @param count The initial count for the semaphore.
*
* @return VCOS_SUCCESS if the semaphore was created.
*
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_named_semaphore_create(VCOS_NAMED_SEMAPHORE_T *sem, const char *name, VCOS_UNSIGNED count);
/**
* \brief Wait on a named semaphore.
*
* There is no timeout option on a semaphore, as adding this will slow down
* implementations on some platforms. If you need that kind of behaviour, use
* an event group.
*
* This always returns VCOS_SUCCESS and so should really be a void function. However
* too many lines of code would need to be changed in non-trivial ways, so for now
* it is non-void.
*
* @param sem Semaphore to wait on
* @return VCOS_SUCCESS - semaphore was taken.
*
*/
VCOS_INLINE_DECL
void vcos_named_semaphore_wait(VCOS_NAMED_SEMAPHORE_T *sem);
/**
* \brief Try to wait for a semaphore.
*
* Try to obtain the semaphore. If it is already taken, return VCOS_TIMEOUT.
* @param sem Semaphore to wait on
* @return VCOS_SUCCESS - semaphore was taken.
* VCOS_EAGAIN - could not take semaphore
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_named_semaphore_trywait(VCOS_NAMED_SEMAPHORE_T *sem);
/**
* \brief Post a semaphore.
*
* @param sem Semaphore to wait on
*/
VCOS_INLINE_DECL
void vcos_named_semaphore_post(VCOS_NAMED_SEMAPHORE_T *sem);
/**
* \brief Delete a semaphore, releasing any resources consumed by it.
*
* @param sem Semaphore to wait on
*/
void vcos_named_semaphore_delete(VCOS_NAMED_SEMAPHORE_T *sem);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,62 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - 'once'
=============================================================================*/
#ifndef VCOS_ONCE_H
#define VCOS_ONCE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/**
* \file vcos_once.h
*
* Ensure something is called only once.
*
* Initialize once_control to VCOS_ONCE_INIT. The first
* time this is called, the init_routine will be called. Thereafter
* it won't.
*
* \sa pthread_once()
*
*/
VCOS_STATUS_T vcos_once(VCOS_ONCE_T *once_control,
void (*init_routine)(void));
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,105 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - Queue public header file
=============================================================================*/
#ifndef VCOS_QUEUE_H
#define VCOS_QUEUE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/** \file vcos_queue.h
*
* API for accessing a fixed length queue.
*
* Nucleus offers variable length items, but this feature is not used
* in the current code base, so is withdrawn to simplify the API.
*/
/** Create a fixed length queue.
*
* @param queue Pointer to queue control block
* @param name Name of queue
* @param message_size Size of each queue message item in words (words are sizeof VCOS_UNSIGNED).
* @param queue_start Start address of queue area
* @param queue_size Size in words (words are sizeof VCOS_UNSIGNED) of queue
*
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_queue_create(VCOS_QUEUE_T *queue,
const char *name,
VCOS_UNSIGNED message_size,
void *queue_start,
VCOS_UNSIGNED queue_size);
/** Delete a queue.
* @param queue The queue to delete
*/
VCOS_INLINE_DECL
void vcos_queue_delete(VCOS_QUEUE_T *queue);
/** Send an item to a queue. If there is no space, the call with
* either block waiting for space, or return an error, depending
* on the value of the wait parameter.
*
* @param queue The queue to send to
* @param src The data to send (length set when queue was created)
* @param wait Whether to wait for space (VCOS_SUSPEND) or fail if
* no space (VCOS_NO_SUSPEND).
*
* @return If space available, returns VCOS_SUCCESS. Otherwise returns
* VCOS_EAGAIN if no space available before timeout expires.
*
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_queue_send(VCOS_QUEUE_T *queue, const void *src, VCOS_UNSIGNED wait);
/** Receive an item from a queue.
* @param queue The queue to receive from
* @param dst Where to write the data to
* @param wait Whether to wait (VCOS_SUSPEND) or fail if
* empty (VCOS_NO_SUSPEND).
*
* @return If an item is available, returns VCOS_SUCCESS. Otherwise returns
* VCOS_EAGAIN if no item available before timeout expires.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_queue_receive(VCOS_QUEUE_T *queue, void *dst, VCOS_UNSIGNED wait);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,101 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - mutex public header file
=============================================================================*/
#ifndef VCOS_QUICKSLOW_MUTEX_H
#define VCOS_QUICKSLOW_MUTEX_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/**
* \file vcos_quickslow_mutex.h
*
* "Quick/Slow" Mutex API. This is a mutex which supports an additional "quick"
* (spinlock-based) locking mechanism. While in this quick locked state, other
* operating system commands will be unavailable and the caller should complete
* whatever it has to do in a short, bounded length of time (as the spinlock
* completely locks out other system activity).
*
* \sa vcos_mutex.h
*
*/
/** Create a mutex.
*
* @param m Filled in with mutex on return
* @param name A non-null name for the mutex, used for diagnostics.
*
* @return VCOS_SUCCESS if mutex was created, or error code.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_quickslow_mutex_create(VCOS_QUICKSLOW_MUTEX_T *m, const char *name);
/** Delete the mutex.
*/
VCOS_INLINE_DECL
void vcos_quickslow_mutex_delete(VCOS_QUICKSLOW_MUTEX_T *m);
/**
* \brief Wait to claim the mutex ("slow" mode).
*
* Obtain the mutex.
*/
VCOS_INLINE_DECL
void vcos_quickslow_mutex_lock(VCOS_QUICKSLOW_MUTEX_T *m);
/** Release the mutex ("slow" mode).
*/
VCOS_INLINE_DECL
void vcos_quickslow_mutex_unlock(VCOS_QUICKSLOW_MUTEX_T *m);
/**
* \brief Wait to claim the mutex ("quick" mode).
*
* Obtain the mutex. The caller must not call any OS functions or do anything
* "slow" before the corresponding call to vcos_mutex_quickslow_unlock_quick.
*/
VCOS_INLINE_DECL
void vcos_quickslow_mutex_lock_quick(VCOS_QUICKSLOW_MUTEX_T *m);
/** Release the mutex ("quick" mode).
*/
VCOS_INLINE_DECL
void vcos_quickslow_mutex_unlock_quick(VCOS_QUICKSLOW_MUTEX_T *m);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,86 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - reentrant mutex public header file
=============================================================================*/
#ifndef VCOS_REENTRANT_MUTEX_H
#define VCOS_REENTRANT_MUTEX_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/**
* \file
*
* Reentrant Mutex API. You can take one of these mutexes even if you've already
* taken it. Just to make sure.
*
* A re-entrant mutex may be slower on some platforms than a regular one.
*
* \sa vcos_mutex.h
*
*/
/** Create a mutex.
*
* @param m Filled in with mutex on return
* @param name A non-null name for the mutex, used for diagnostics.
*
* @return VCOS_SUCCESS if mutex was created, or error code.
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name);
/** Delete the mutex.
*/
VCOS_INLINE_DECL
void vcos_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m);
/** Wait to claim the mutex. Must not have already been claimed by the current thread.
*/
#ifndef vcos_reentrant_mutexlock
VCOS_INLINE_DECL
void vcos_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m);
/** Release the mutex.
*/
VCOS_INLINE_DECL
void vcos_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m);
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,158 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - public header file
=============================================================================*/
#ifndef VCOS_SEMAPHORE_H
#define VCOS_SEMAPHORE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#ifndef VCOS_PLATFORM_H
#include "pthreads/vcos_platform.h"
#endif
/**
* \file vcos_semaphore.h
*
* \section sem Semaphores
*
* This provides counting semaphores. Semaphores are not re-entrant. On sensible
* operating systems a semaphore can always be posted but can only be taken in
* thread (not interrupt) context. Under Nucleus, a LISR cannot post a semaphore,
* although it would not be hard to lift this restriction.
*
* \subsection timeout Timeout
*
* On both Nucleus and ThreadX a semaphore can be taken with a timeout. This is
* not supported by VCOS because it makes the non-timeout code considerably more
* complicated (and hence slower). In the unlikely event that you need a timeout
* with a semaphore, and you cannot simply redesign your code to avoid it, use
* an event flag (vcos_event_flags.h).
*
* \subsection sem_nucleus Changes from Nucleus:
*
* Semaphores are always "FIFO" - i.e. sleeping threads are woken in FIFO order. That's
* because:
* \arg there's no support for NU_PRIORITY in threadx (though it can be emulated, slowly)
* \arg we don't appear to actually consciously use it - for example, Dispmanx uses
* it, but all threads waiting are the same priority.
*
*/
/**
* \brief Create a semaphore.
*
* Create a semaphore.
*
* @param sem Pointer to memory to be initialized
* @param name A name for this semaphore. The name may be truncated internally.
* @param count The initial count for the semaphore.
*
* @return VCOS_SUCCESS if the semaphore was created.
*
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_semaphore_create(VCOS_SEMAPHORE_T *sem, const char *name, VCOS_UNSIGNED count);
/**
* \brief Wait on a semaphore.
*
* There is no timeout option on a semaphore, as adding this will slow down
* implementations on some platforms. If you need that kind of behaviour, use
* an event group.
*
* On most platforms this always returns VCOS_SUCCESS, and so would ideally be
* a void function, however some platforms allow a wait to be interrupted so
* it remains non-void.
*
* @param sem Semaphore to wait on
* @return VCOS_SUCCESS - semaphore was taken.
* VCOS_EAGAIN - could not take semaphore
*
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_semaphore_wait(VCOS_SEMAPHORE_T *sem);
/**
* \brief Wait on a semaphore with a timeout.
*
* Note that this function may not be implemented on all
* platforms, and may not be efficient on all platforms
* (see comment in vcos_semaphore_wait)
*
* Try to obtain the semaphore. If it is already taken, return
* VCOS_EAGAIN.
* @param sem Semaphore to wait on
* @param timeout Number of milliseconds to wait before
* returning if the semaphore can't be acquired.
* @return VCOS_SUCCESS - semaphore was taken.
* VCOS_EAGAIN - could not take semaphore (i.e. timeout
* expired)
* VCOS_EINVAL - Some other error (most likely bad
* parameters).
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_semaphore_wait_timeout(VCOS_SEMAPHORE_T *sem, VCOS_UNSIGNED timeout);
/**
* \brief Try to wait for a semaphore.
*
* Try to obtain the semaphore. If it is already taken, return VCOS_TIMEOUT.
* @param sem Semaphore to wait on
* @return VCOS_SUCCESS - semaphore was taken.
* VCOS_EAGAIN - could not take semaphore
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_semaphore_trywait(VCOS_SEMAPHORE_T *sem);
/**
* \brief Post a semaphore.
*
* @param sem Semaphore to wait on
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_semaphore_post(VCOS_SEMAPHORE_T *sem);
/**
* \brief Delete a semaphore, releasing any resources consumed by it.
*
* @param sem Semaphore to wait on
*/
VCOS_INLINE_DECL
void vcos_semaphore_delete(VCOS_SEMAPHORE_T *sem);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,47 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VCOS_STDBOOL_H
#define VCOS_STDBOOL_H
#ifndef __cplusplus
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
#include <stdbool.h>
#else
/* sizeof(bool) == 1. hopefully this matches up with c++ (so structures and
* such containing bool are binary compatible), but the c++ standard doesn't
* require sizeof(bool) == 1, so there's no guarantee */
typedef unsigned char bool;
enum {
false,
true
};
#endif
#endif /* __cplusplus */
#endif
@@ -0,0 +1,107 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VCOS_STDINT_H
#define VCOS_STDINT_H
/** \file
* Attempt to provide the types defined in stdint.h.
*
* Except for use with lcc, this simply includes stdint.h, which should find
* the system/toolchain version if present, otherwise falling back to the
* version in <platform>.
*/
#ifdef __cplusplus
extern "C" {
#endif
#if defined (VCMODS_LCC)
#include <limits.h>
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed long int32_t;
typedef unsigned long uint32_t;
typedef int32_t intptr_t;
typedef uint32_t uintptr_t;
typedef int32_t intmax_t;
typedef uint32_t uintmax_t;
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
#define INT8_MIN SCHAR_MIN
#define INT8_MAX SCHAR_MAX
#define UINT8_MAX UCHAR_MAX
#define INT16_MIN SHRT_MIN
#define INT16_MAX SHRT_MAX
#define UINT16_MAX USHRT_MAX
#define INT32_MIN LONG_MIN
#define INT32_MAX LONG_MAX
#define UINT32_MAX ULONG_MAX
#define INTPTR_MIN INT32_MIN
#define INTPTR_MAX INT32_MAX
#define UINTPTR_MAX UINT32_MAX
#define INTMAX_MIN INT32_MIN
#define INTMAX_MAX INT32_MAX
#define UINTMAX_MAX UINT32_MAX
/* N.B. 64-bit integer types are not currently supported by lcc.
* However, these symbols are referenced in header files included by files
* compiled by lcc for VCE, so removing them would break the build.
* The solution here then is to define them, as the correct size, but in a
* way that should make them unusable in normal arithmetic operations.
*/
typedef struct { uint32_t a; uint32_t b; } int64_t;
typedef struct { uint32_t a; uint32_t b; } uint64_t;
#else
#include <stdint.h>
#endif
#ifdef __cplusplus
}
#endif
#endif /* VCOS_STDINT_H */
@@ -0,0 +1,129 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - public header file
=============================================================================*/
#ifndef VCOS_STRING_H
#define VCOS_STRING_H
/**
* \file
*
* String functions.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
#ifdef __KERNEL__
#include <linux/string.h>
#else
#include <string.h>
#endif
/** Case insensitive string comparison.
*
*/
VCOS_INLINE_DECL
int vcos_strcasecmp(const char *s1, const char *s2);
VCOS_INLINE_DECL
int vcos_strncasecmp(const char *s1, const char *s2, size_t n);
VCOSPRE_ int VCOSPOST_ vcos_vsnprintf(char *buf, size_t buflen, const char *fmt, va_list ap);
VCOSPRE_ int VCOSPOST_ vcos_snprintf(char *buf, size_t buflen, const char *fmt, ...);
/** Like vsnprintf, except it places the output at the specified offset.
* Output is truncated to fit in buflen bytes, and is guaranteed to be NUL-terminated.
* Returns the string length before/without truncation.
*/
VCOSPRE_ size_t VCOSPOST_ vcos_safe_vsprintf(char *buf, size_t buflen, size_t offset, const char *fmt, va_list ap);
#define VCOS_SAFE_VSPRINTF(buf, offset, fmt, ap) \
vcos_safe_vsprintf(buf, sizeof(buf) + ((char (*)[sizeof(buf)])buf - &(buf)), offset, fmt, ap)
/** Like snprintf, except it places the output at the specified offset.
* Output is truncated to fit in buflen bytes, and is guaranteed to be NUL-terminated.
* Returns the string length before/without truncation.
*/
VCOSPRE_ size_t VCOSPOST_ vcos_safe_sprintf(char *buf, size_t buflen, size_t offset, const char *fmt, ...);
/* The Metaware compiler currently has a bug in its variadic macro handling which
causes it to append a spurious command to the end of its __VA_ARGS__ data.
Do not use until this has been fixed (and this comment has been deleted). */
#define VCOS_SAFE_SPRINTF(buf, offset, ...) \
vcos_safe_sprintf(buf, sizeof(buf) + ((char (*)[sizeof(buf)])buf - &(buf)), offset, __VA_ARGS__)
/** Copies string src to dst at the specified offset.
* Output is truncated to fit in dstlen bytes, i.e. the string is at most
* (buflen - 1) characters long. Unlike strncpy, exactly one NUL is written
* to dst, which is always NUL-terminated.
* Returns the string length before/without truncation.
*/
VCOSPRE_ size_t VCOSPOST_ vcos_safe_strcpy(char *dst, const char *src, size_t dstlen, size_t offset);
#define VCOS_SAFE_STRCPY(dst, src, offset) \
vcos_safe_strcpy(dst, src, sizeof(dst) + ((char (*)[sizeof(dst)])dst - &(dst)), offset)
VCOS_STATIC_INLINE
int vcos_strlen(const char *s) { return (int)strlen(s); }
VCOS_STATIC_INLINE
int vcos_strcmp(const char *s1, const char *s2) { return strcmp(s1,s2); }
VCOS_STATIC_INLINE
int vcos_strncmp(const char *cs, const char *ct, size_t count) { return strncmp(cs, ct, count); }
VCOS_STATIC_INLINE
char *vcos_strcpy(char *dst, const char *src) { return strcpy(dst, src); }
VCOS_STATIC_INLINE
char *vcos_strncpy(char *dst, const char *src, size_t count) { return strncpy(dst, src, count); }
VCOS_STATIC_INLINE
void *vcos_memcpy(void *dst, const void *src, size_t n) { memcpy(dst, src, n); return dst; }
VCOS_STATIC_INLINE
void *vcos_memset(void *p, int c, size_t n) { return memset(p, c, n); }
VCOS_STATIC_INLINE
int vcos_memcmp(const void *ptr1, const void *ptr2, size_t count) { return memcmp(ptr1, ptr2, count); }
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,282 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - public header file
=============================================================================*/
#ifndef VCOS_THREAD_H
#define VCOS_THREAD_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/**
* \file vcos_thread.h
*
* \section thread Threads
*
* Under Nucleus, a thread is created by NU_Create_Task, passing in the stack
* and various other parameters. To stop the thread, NU_Terminate_Thread() and
* NU_Delete_Thread() are called.
*
* Unfortunately it's not possible to emulate this API under some fairly common
* operating systems. Under Windows you can't pass in the stack, and you can't
* safely terminate a thread.
*
* Therefore, an API which is similar to the pthreads API is used instead. This
* API can (mostly) be emulated under all interesting operating systems.
*
* Obviously this makes the code somewhat more complicated on VideoCore than it
* would otherwise be - we end up with an extra mutex per thread, and some code
* that waits for it. The benefit is that we have a single way of creating
* threads that works consistently on all platforms (apart from stack supplying).
*
* \subsection stack Stack
*
* It's still not possible to pass in the stack address, but this can be made
* much more obvious in the API: the relevant function is missing and the
* CPP symbol VCOS_CAN_SET_STACK_ADDR is zero rather than one.
*
* \subsection thr_create Creating a thread
*
* The simplest way to create a thread is with vcos_thread_create() passing in a
* NULL thread parameter argument. To wait for the thread to exit, call
* vcos_thread_join().
*
* \subsection back Backward compatibility
*
* To ease migration, a "classic" thread creation API is provided for code
* that used to make use of Nucleus, vcos_thread_create_classic(). The
* arguments are not exactly the same, as the PREEMPT parameter is dropped.
*
*/
#define VCOS_AFFINITY_CPU0 _VCOS_AFFINITY_CPU0
#define VCOS_AFFINITY_CPU1 _VCOS_AFFINITY_CPU1
#define VCOS_AFFINITY_MASK _VCOS_AFFINITY_MASK
#define VCOS_AFFINITY_DEFAULT _VCOS_AFFINITY_DEFAULT
#define VCOS_AFFINITY_THISCPU _VCOS_AFFINITY_THISCPU
/** Report whether or not we have an RTOS at all, and hence the ability to
* create threads.
*/
VCOSPRE_ int VCOSPOST_ vcos_have_rtos(void);
/** Create a thread. It must be cleaned up by calling vcos_thread_join().
*
* @param thread Filled in on return with thread
* @param name A name for the thread. May be the empty string.
* @param attrs Attributes; default attributes will be used if this is NULL.
* @param entry Entry point.
* @param arg Argument passed to the entry point.
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_thread_create(VCOS_THREAD_T *thread,
const char *name,
VCOS_THREAD_ATTR_T *attrs,
VCOS_THREAD_ENTRY_FN_T entry,
void *arg);
/** Exit the thread from within the thread function itself.
* Resources must still be cleaned up via a call to thread_join().
*
* The thread can also be terminated by simply exiting the thread function.
*
* @param data Data passed to thread_join. May be NULL.
*/
VCOSPRE_ void VCOSPOST_ vcos_thread_exit(void *data);
/** Wait for a thread to terminate and then clean up its resources.
*
* @param thread Thread to wait for
* @param pData Updated to point at data provided in vcos_thread_exit or exit
* code of thread function.
*/
VCOSPRE_ void VCOSPOST_ vcos_thread_join(VCOS_THREAD_T *thread,
void **pData);
/**
* \brief Create a thread using an API similar to the one "traditionally"
* used under Nucleus.
*
* This creates a thread which must be cleaned up by calling vcos_thread_join().
* The thread cannot be simply terminated (as in Nucleus and ThreadX) as thread
* termination is not universally supported.
*
* @param thread Filled in with thread instance
* @param name An optional name for the thread. NULL or "" may be used (but
* a name will aid in debugging).
* @param entry Entry point
* @param arg A single argument passed to the entry point function
* @param stack Pointer to stack address
* @param stacksz Size of stack in bytes
* @param priaff Priority of task, between VCOS_PRI_LOW and VCOS_PRI_HIGH, ORed with the CPU affinity
* @param autostart If non-zero the thread will start immediately.
* @param timeslice Timeslice (system ticks) for this thread.
*
* @sa vcos_thread_terminate vcos_thread_delete
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_thread_create_classic(VCOS_THREAD_T *thread,
const char *name,
void *(*entry)(void *arg),
void *arg,
void *stack,
VCOS_UNSIGNED stacksz,
VCOS_UNSIGNED priaff,
VCOS_UNSIGNED timeslice,
VCOS_UNSIGNED autostart);
/**
* \brief Set a thread's priority
*
* Set the priority for a thread.
*
* @param thread The thread
* @param pri Thread priority in VCOS_PRI_MASK bits; affinity in VCOS_AFFINITY_MASK bits.
*/
VCOS_INLINE_DECL
void vcos_thread_set_priority(VCOS_THREAD_T *thread, VCOS_UNSIGNED pri);
/**
* \brief Return the currently executing thread.
*
*/
VCOS_INLINE_DECL
VCOS_THREAD_T *vcos_thread_current(void);
/**
* \brief Return the thread's priority.
*/
VCOS_INLINE_DECL
VCOS_UNSIGNED vcos_thread_get_priority(VCOS_THREAD_T *thread);
/**
* \brief Return the thread's cpu affinity.
*/
VCOS_INLINE_DECL
VCOS_UNSIGNED vcos_thread_get_affinity(VCOS_THREAD_T *thread);
/**
* \brief Set the thread's cpu affinity.
*/
VCOS_INLINE_DECL
void vcos_thread_set_affinity(VCOS_THREAD_T *thread, VCOS_UNSIGNED affinity);
/**
* \brief Query whether we are in an interrupt.
*
* @return 1 if in interrupt context.
*/
VCOS_INLINE_DECL
int vcos_in_interrupt(void);
/**
* \brief Sleep a while.
*
* @param ms Number of milliseconds to sleep for
*
* This may actually sleep a whole number of ticks.
*/
VCOS_INLINE_DECL
void vcos_sleep(uint32_t ms);
/**
* \brief Return the value of the hardware microsecond counter.
*
*/
VCOS_INLINE_DECL
uint32_t vcos_getmicrosecs(void);
VCOS_INLINE_DECL
uint64_t vcos_getmicrosecs64(void);
#define vcos_get_ms() (vcos_getmicrosecs()/1000)
/**
* \brief Return a unique identifier for the current process
*
*/
VCOS_INLINE_DECL
VCOS_UNSIGNED vcos_process_id_current(void);
/** Relinquish this time slice. */
VCOS_INLINE_DECL
void vcos_thread_relinquish(void);
/** Return the name of the given thread.
*/
VCOSPRE_ const char * VCOSPOST_ vcos_thread_get_name(const VCOS_THREAD_T *thread);
/** Change preemption. This is almost certainly not what you want, as it won't
* work reliably in a multicore system: although you can affect the preemption
* on *this* core, you won't affect what's happening on the other core(s).
*
* It's mainly here to ease migration. If you're using it in new code, you
* probably need to think again.
*
* @param pe New preemption, VCOS_PREEMPT or VCOS_NO_PREEMPT
* @return Old value of preemption.
*/
VCOS_INLINE_DECL
VCOS_UNSIGNED vcos_change_preemption(VCOS_UNSIGNED pe);
/** Is a thread still running, or has it exited?
*
* Note: this exists for some fairly scary code in the video codec tests. Don't
* try to use it for anything else, as it may well not do what you expect.
*
* @param thread thread to query
* @return non-zero if thread is running, or zero if it has exited.
*/
VCOS_INLINE_DECL
int vcos_thread_running(VCOS_THREAD_T *thread);
/** Resume a thread.
*
* @param thread thread to resume
*/
VCOS_INLINE_DECL
void vcos_thread_resume(VCOS_THREAD_T *thread);
/*
* Internal APIs - may not always be present and should not be used in
* client code.
*/
extern void _vcos_task_timer_set(void (*pfn)(void*), void *, VCOS_UNSIGNED ms);
extern void _vcos_task_timer_cancel(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,96 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - thread attributes
=============================================================================*/
#ifndef VCOS_THREAD_ATTR_H
#define VCOS_THREAD_ATTR_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file
*
* Attributes for thread creation.
*
*/
/** Initialize thread attribute struct. This call does not allocate memory,
* and so cannot fail.
*
*/
VCOSPRE_ void VCOSPOST_ vcos_thread_attr_init(VCOS_THREAD_ATTR_T *attrs);
/** Set the stack address and size. If not set, a stack will be allocated automatically.
*
* This can only be set on some platforms. It will always be possible to set the stack
* address on VideoCore, but on host platforms, support may well not be available.
*/
#if VCOS_CAN_SET_STACK_ADDR
VCOS_INLINE_DECL
void vcos_thread_attr_setstack(VCOS_THREAD_ATTR_T *attrs, void *addr, VCOS_UNSIGNED sz);
#endif
/** Set the stack size. If not set, a default size will be used. Attempting to call this after having
* set the stack location with vcos_thread_attr_setstack() will result in undefined behaviour.
*/
VCOS_INLINE_DECL
void vcos_thread_attr_setstacksize(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED sz);
/** Set the task priority. If not set, a default value will be used.
*/
VCOS_INLINE_DECL
void vcos_thread_attr_setpriority(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED pri);
/** Set the task cpu affinity. If not set, the default will be used.
*/
VCOS_INLINE_DECL
void vcos_thread_attr_setaffinity(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED aff);
/** Set the timeslice. If not set the default will be used.
*/
VCOS_INLINE_DECL
void vcos_thread_attr_settimeslice(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED ts);
/** The thread entry function takes (argc,argv), as per Nucleus, with
* argc being 0. This may be withdrawn in a future release and should not
* be used in new code.
*/
VCOS_INLINE_DECL
void _vcos_thread_attr_setlegacyapi(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED legacy);
VCOS_INLINE_DECL
void vcos_thread_attr_setautostart(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED autostart);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,117 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - timer support
=============================================================================*/
#ifndef VCOS_TIMER_H
#define VCOS_TIMER_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#ifndef VCOS_PLATFORM_H
#include "pthreads/vcos_platform.h"
#endif
/** \file vcos_timer.h
*
* Timers are single shot.
*
* Timer times are in milliseconds.
*
* \note that timer callback functions are called from an arbitrary thread
* context. The expiration function should do its work as quickly as possible;
* blocking should be avoided.
*
* \note On Windows, the separate function vcos_timer_init() must be called
* as timer initialization from DllMain is not possible.
*/
/** Perform timer subsystem initialization. This function is not needed
* on non-Windows platforms but is still present so that it can be
* called. On Windows it is needed because vcos_init() gets called
* from DLL initialization where it is not possible to create a
* time queue (deadlock occurs if you try).
*
* @return VCOS_SUCCESS on success. VCOS_EEXIST if this has already been called
* once. VCOS_ENOMEM if resource allocation failed.
*/
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_timer_init(void);
/** Create a timer in a disabled state.
*
* The timer is initially disabled.
*
* @param timer timer handle
* @param name name for timer
* @param expiration_routine function to call when timer expires
* @param context context passed to expiration routine
*
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_timer_create(VCOS_TIMER_T *timer,
const char *name,
void (*expiration_routine)(void *context),
void *context);
/** Start a timer running.
*
* Timer must be stopped.
*
* @param timer timer handle
* @param delay Delay to wait for, in ms
*/
VCOS_INLINE_DECL
void vcos_timer_set(VCOS_TIMER_T *timer, VCOS_UNSIGNED delay);
/** Stop an already running timer.
*
* @param timer timer handle
*/
VCOS_INLINE_DECL
void vcos_timer_cancel(VCOS_TIMER_T *timer);
/** Stop a timer and restart it.
* @param timer timer handle
* @param delay delay in ms
*/
VCOS_INLINE_DECL
void vcos_timer_reset(VCOS_TIMER_T *timer, VCOS_UNSIGNED delay);
VCOS_INLINE_DECL
void vcos_timer_delete(VCOS_TIMER_T *timer);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,84 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - thread local storage
=============================================================================*/
#ifndef VCOS_TLS_H
#define VCOS_TLS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "vcos_types.h"
#include "pthreads/vcos_platform.h"
/** Create a new thread local storage data key visible to all threads in
* the current process.
*
* @param key The key to create
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_tls_create(VCOS_TLS_KEY_T *key);
/** Delete an existing TLS data key.
*/
VCOS_INLINE_DECL
void vcos_tls_delete(VCOS_TLS_KEY_T tls);
/** Set the value seen by the current thread.
*
* @param key The key to update
* @param v The value to set for the current thread.
*
* @return VCOS_SUCCESS, or VCOS_ENOMEM if memory for this slot
* could not be allocated.
*
* If TLS is being emulated via VCOS then the memory required
* can be preallocated at thread creation time
*/
VCOS_INLINE_DECL
VCOS_STATUS_T vcos_tls_set(VCOS_TLS_KEY_T tls, void *v);
/** Get the value for the current thread.
*
* @param key The key to update
*
* @return The current value for this thread.
*/
VCOS_INLINE_DECL
void *vcos_tls_get(VCOS_TLS_KEY_T tls);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,283 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
VideoCore OS Abstraction Layer - basic types
=============================================================================*/
#ifndef VCOS_TYPES_H
#define VCOS_TYPES_H
#define VCOS_VERSION 1
#include <stddef.h>
#include "pthreads/vcos_platform_types.h"
#include "vcos_attr.h"
#if !defined(VCOSPRE_) || !defined(VCOSPOST_)
#error VCOSPRE_ and VCOSPOST_ not defined!
#endif
/* Redefine these here; this means that existing header files can carry on
* using the VCHPOST/VCHPRE macros rather than having huge changes, which
* could cause nasty merge problems.
*/
#ifndef VCHPOST_
#define VCHPOST_ VCOSPOST_
#endif
#ifndef VCHPRE_
#define VCHPRE_ VCOSPRE_
#endif
/** Entry function for a lowlevel thread.
*
* Returns void for consistency with Nucleus/ThreadX.
*/
typedef void (*VCOS_LLTHREAD_ENTRY_FN_T)(void *);
/** Thread entry point. Returns a void* for consistency
* with pthreads.
*/
typedef void *(*VCOS_THREAD_ENTRY_FN_T)(void*);
/* Error return codes - chosen to be similar to errno values */
typedef enum
{
VCOS_SUCCESS,
VCOS_EAGAIN,
VCOS_ENOENT,
VCOS_ENOSPC,
VCOS_EINVAL,
VCOS_EACCESS,
VCOS_ENOMEM,
VCOS_ENOSYS,
VCOS_EEXIST,
VCOS_ENXIO,
VCOS_EINTR
} VCOS_STATUS_T;
/* Some compilers (MetaWare) won't inline with -g turned on, which then results
* in a lot of code bloat. To overcome this, inline functions are forward declared
* with the prefix VCOS_INLINE_DECL, and implemented with the prefix VCOS_INLINE_IMPL.
*
* That then means that in a release build, "static inline" can be used in the obvious
* way, but in a debug build the implementations can be skipped in all but one file,
* by using VCOS_INLINE_BODIES.
*
* VCOS_INLINE_DECL - put this at the start of an inline forward declaration of a VCOS
* function.
*
* VCOS_INLINE_IMPL - put this at the start of an inlined implementation of a VCOS
* function.
*
*/
/* VCOS_EXPORT - it turns out that in some circumstances we need the implementation of
* a function even if it is usually inlined.
*
* In particular, if we have a codec that is usually provided in object form, if it
* was built for a debug build it will be full of calls to vcos_XXX(). If this is used
* in a *release* build, then there won't be any of these calls around in the main image
* as they will all have been inlined. The problem also exists for vcos functions called
* from assembler.
*
* VCOS_EXPORT ensures that the named function will be emitted as a regular (not static-inline)
* function inside vcos_<platform>.c so that it can be linked against. Doing this for every
* VCOS function would be a bit code-bloat-tastic, so it is only done for those that need it.
*
*/
#ifdef __cplusplus
#define _VCOS_INLINE inline
#else
#define _VCOS_INLINE __inline
#endif
#if defined(NDEBUG)
#ifdef __GNUC__
# define VCOS_INLINE_DECL extern __inline__
# define VCOS_INLINE_IMPL static __inline__
#else
# define VCOS_INLINE_DECL static _VCOS_INLINE /* declare a func */
# define VCOS_INLINE_IMPL static _VCOS_INLINE /* implement a func inline */
#endif
# if defined(VCOS_WANT_IMPL)
# define VCOS_EXPORT
# else
# define VCOS_EXPORT VCOS_INLINE_IMPL
# endif /* VCOS_WANT_IMPL */
#define VCOS_INLINE_BODIES
#else /* NDEBUG */
#if !defined(VCOS_INLINE_DECL)
#define VCOS_INLINE_DECL extern
#endif
#if !defined(VCOS_INLINE_IMPL)
#define VCOS_INLINE_IMPL
#endif
#define VCOS_EXPORT VCOS_INLINE_IMPL
#endif
#define VCOS_STATIC_INLINE static _VCOS_INLINE
#if defined(__HIGHC__) || defined(__HIGHC_ANSI__)
#define _VCOS_METAWARE
#endif
/** It seems that __FUNCTION__ isn't standard!
*/
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2 || defined(__VIDEOCORE__)
# define VCOS_FUNCTION __FUNCTION__
# else
# define VCOS_FUNCTION "<unknown>"
# endif
#else
# define VCOS_FUNCTION __func__
#endif
#define _VCOS_MS_PER_TICK (1000/VCOS_TICKS_PER_SECOND)
/* Convert a number of milliseconds to a tick count. Internal use only - fails to
* convert VCOS_SUSPEND correctly.
*/
#define _VCOS_MS_TO_TICKS(ms) (((ms)+_VCOS_MS_PER_TICK-1)/_VCOS_MS_PER_TICK)
#define VCOS_TICKS_TO_MS(ticks) ((ticks) * _VCOS_MS_PER_TICK)
/** VCOS version of DATESTR, from pcdisk.h. Used by the hostreq service.
*/
typedef struct vcos_datestr
{
uint8_t cmsec; /**< Centesimal mili second */
uint16_t date; /**< Date */
uint16_t time; /**< Time */
} VCOS_DATESTR;
/* Compile-time assert - declares invalid array length if condition
* not met, or array of length one if OK.
*/
#define VCOS_CASSERT(e) extern char vcos_compile_time_check[1/(e)]
#define vcos_min(x,y) ((x) < (y) ? (x) : (y))
#define vcos_max(x,y) ((x) > (y) ? (x) : (y))
/** Return the count of an array. FIXME: under gcc we could make
* this report an error for pointers using __builtin_types_compatible().
*/
#define vcos_countof(x) (sizeof((x)) / sizeof((x)[0]))
/* for backward compatibility */
#define countof(x) (sizeof((x)) / sizeof((x)[0]))
#define VCOS_ALIGN_DOWN(p,n) (((ptrdiff_t)(p)) & ~((n)-1))
#define VCOS_ALIGN_UP(p,n) VCOS_ALIGN_DOWN((ptrdiff_t)(p)+(n)-1,(n))
#ifdef _MSC_VER
#define vcos_alignof(T) __alignof(T)
#elif defined(__GNUC__)
#define vcos_alignof(T) __alignof__(T)
#else
#define vcos_alignof(T) (sizeof(struct { T t; char ch; }) - sizeof(T))
#endif
/** bool_t is not a POSIX type so cannot rely on it. Define it here.
* It's not even defined in stdbool.h.
*/
typedef int32_t vcos_bool_t;
typedef int32_t vcos_fourcc_t;
#define VCOS_FALSE 0
#define VCOS_TRUE (!VCOS_FALSE)
/** Mark unused arguments to keep compilers quiet */
#define vcos_unused(x) (void)(x)
/** For backward compatibility */
typedef vcos_fourcc_t fourcc_t;
typedef vcos_fourcc_t FOURCC_T;
#ifdef __cplusplus
#define VCOS_EXTERN_C_BEGIN extern "C" {
#define VCOS_EXTERN_C_END }
#else
#define VCOS_EXTERN_C_BEGIN
#define VCOS_EXTERN_C_END
#endif
/** Variable attribute indicating the variable must be emitted even if it appears unused. */
#if defined(__GNUC__) || defined(_VCOS_METAWARE)
# define VCOS_ATTR_USED __attribute__ ((used))
#else
# define VCOS_ATTR_USED
#endif
/** Variable attribute requiring specific alignment. */
#if defined(__GNUC__) || defined(_VCOS_METAWARE)
# define VCOS_ATTR_ALIGNED(n) __attribute__ ((aligned(n)))
#else
# define VCOS_ATTR_ALIGNED(n)
#endif
/** Define a function as a weak alias to another function.
* @param ret_type Function return type.
* @param alias_name Name of the alias.
* @param param_list Function parameter list, including the parentheses.
* @param target_name Target function (bare function name, not a string).
*/
#if defined(__GNUC__) || defined(_VCOS_METAWARE)
/* N.B. gcc allows __attribute__ after parameter list, but hcvc seems to silently ignore it. */
# define VCOS_WEAK_ALIAS(ret_type, alias_name, param_list, target_name) \
__attribute__ ((weak, alias(#target_name))) ret_type alias_name param_list
#else
# define VCOS_WEAK_ALIAS(ret_type, alias, params, target) VCOS_CASSERT(0)
#endif
/** Define a function as a weak alias to another function, specified as a string.
* @param ret_type Function return type.
* @param alias_name Name of the alias.
* @param param_list Function parameter list, including the parentheses.
* @param target_name Target function name as a string.
* @note Prefer the use of VCOS_WEAK_ALIAS - it is likely to be more portable.
* Only use VCOS_WEAK_ALIAS_STR if you need to do pre-processor mangling of the target
* symbol.
*/
#if defined(__GNUC__) || defined(_VCOS_METAWARE)
/* N.B. gcc allows __attribute__ after parameter list, but hcvc seems to silently ignore it. */
# define VCOS_WEAK_ALIAS_STR(ret_type, alias_name, param_list, target_name) \
__attribute__ ((weak, alias(target_name))) ret_type alias_name param_list
#else
# define VCOS_WEAK_ALIAS_STR(ret_type, alias, params, target) VCOS_CASSERT(0)
#endif
#endif