diff options
author | Andre Eisenbach <andre@broadcom.com> | 2012-02-22 13:18:21 -0800 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:11 -0700 |
commit | e448862a47c08eb23185aaed574b39264f5005fc (patch) | |
tree | 2bc6246e3091315e77224fd798ea2fe8074ef972 /gki/ulinux | |
parent | a2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff) | |
download | external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2 |
Initial Bluedroid stack commit
Diffstat (limited to 'gki/ulinux')
-rw-r--r-- | gki/ulinux/data_types.h | 71 | ||||
-rw-r--r-- | gki/ulinux/gki_int.h | 111 | ||||
-rw-r--r-- | gki/ulinux/gki_ulinux.c | 1355 |
3 files changed, 1537 insertions, 0 deletions
diff --git a/gki/ulinux/data_types.h b/gki/ulinux/data_types.h new file mode 100644 index 0000000..5263bba --- /dev/null +++ b/gki/ulinux/data_types.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Name data_types.h +** $Header: /Bluetooth/gki/data_types.h 7 9/13/00 11:01a Jjose $ +** +** Function this file contains common data type definitions used +** throughout the Widcomm Bluetooth code +** +** Date Modification +** ----------------------- +** 3/12/99 Create +** 07/27/00 Added nettohs macro for Little Endian +** +** Copyright (c) 1999- 2002, Widcomm Inc., All Rights Reserved. +** Proprietary and confidential. +** +*****************************************************************************/ + +#ifndef DATA_TYPES_H +#define DATA_TYPES_H + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned long UINT32; +typedef signed long INT32; +typedef signed char INT8; +typedef signed short INT16; +typedef unsigned char BOOLEAN; + + +typedef UINT32 TIME_STAMP; + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +typedef unsigned char UBYTE; + +#ifdef __arm +#define PACKED __packed +#define INLINE __inline +#else +#define PACKED +#define INLINE +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN FALSE +#endif + +#define UINT16_LOW_BYTE(x) ((x) & 0xff) +#define UINT16_HI_BYTE(x) ((x) >> 8) + + +#define BCM_STRCAT_S(x1,x2,x3) strcat((x1),(x3)) +#define BCM_STRNCAT_S(x1,x2,x3,x4) strncat((x1),(x3),(x4)) +#define BCM_STRCPY_S(x1,x2,x3) strcpy((x1),(x3)) +#define BCM_STRNCPY_S(x1,x2,x3,x4) strncpy((x1),(x3),(x4)) + + + +#endif + diff --git a/gki/ulinux/gki_int.h b/gki/ulinux/gki_int.h new file mode 100644 index 0000000..4aaf500 --- /dev/null +++ b/gki/ulinux/gki_int.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Name gki_int.h +** +** Function This file contains GKI private definitions +** +** +** Copyright (c) 1999-2010, Widcomm Inc., All Rights Reserved. +** Proprietary and confidential. +** +*****************************************************************************/ +#ifndef GKI_INT_H +#define GKI_INT_H + +#include "gki_common.h" +#include <pthread.h> +#include <sys/prctl.h> + +/********************************************************************** +** OS specific definitions +*/ +/* The base priority used for pthread based GKI task. below value is to keep it retro compatible. + * It is recommended to use (GKI_MAX_TASKS+3), this will assign real time priorities GKI_MAX_TASKS- + * task_id -2 to the thread */ +#ifndef GKI_LINUX_BASE_PRIORITY +#define GKI_LINUX_BASE_PRIORITY 30 +#endif + +/* The base policy used for pthread based GKI task. the sched defines are defined here to avoid undefined values due + * to missing header file, see pthread functions! Overall it is recommend however to use SCHED_NOMRAL */ +#define GKI_SCHED_NORMAL 0 +#define GKI_SCHED_FIFO 1 +#define GKI_SCHED_RR 2 +#ifndef GKI_LINUX_BASE_POLICY +#define GKI_LINUX_BASE_POLICY GKI_SCHED_NORMAL +#endif + +/* GKI timer bases should use GKI_SCHED_FIFO to ensure the least jitter possible */ +#ifndef GKI_LINUX_TIMER_POLICY +#define GKI_LINUX_TIMER_POLICY GKI_SCHED_FIFO +#endif + +/* the GKI_timer_update() thread should have the highest real time priority to ensue correct + * timer expiry. + */ +#ifndef GKI_LINUX_TIMER_TICK_PRIORITY +#define GKI_LINUX_TIMER_TICK_PRIORITY GKI_LINUX_BASE_PRIORITY+2 +#endif + +/* the AV timer should preferably run above the gki timer tick to ensure precise AV timing + * If you observe AV jitter under have load you may increase this one */ +#ifndef GKI_LINUX_AV_TIMER_PRIORITY +#define GKI_LINUX_AV_TIMER_PRIORITY GKI_LINUX_BASE_PRIORITY+3 +#endif + +/* defines by how much the nice value of the PROCESS should be changed. Values allowed: + * -19 to +19. a negative value give higher priority to btld compared to the default nice value + * of 20. in case of SCHED_NORMAL, a level of -5 should give a good btld/bt performance. + * In case of real time scheduling, leave default value. + */ +#ifndef GKI_LINUX_DEFAULT_NICE_INC +#define GKI_LINUX_DEFAULT_NICE_INC -7 +#endif + +typedef struct +{ + pthread_mutex_t GKI_mutex; + pthread_t thread_id[GKI_MAX_TASKS]; + pthread_mutex_t thread_evt_mutex[GKI_MAX_TASKS]; + pthread_cond_t thread_evt_cond[GKI_MAX_TASKS]; + pthread_mutex_t thread_timeout_mutex[GKI_MAX_TASKS]; + pthread_cond_t thread_timeout_cond[GKI_MAX_TASKS]; + int no_timer_suspend; /* 1: no suspend, 0 stop calling GKI_timer_update() */ + pthread_mutex_t gki_timer_mutex; + pthread_cond_t gki_timer_cond; +#if (GKI_DEBUG == TRUE) + pthread_mutex_t GKI_trace_mutex; +#endif +} tGKI_OS; + +/* condition to exit or continue GKI_run() timer loop */ +#define GKI_TIMER_TICK_RUN_COND 1 +#define GKI_TIMER_TICK_STOP_COND 0 + +extern void gki_system_tick_start_stop_cback(BOOLEAN start); + +/* Contains common control block as well as OS specific variables */ +typedef struct +{ + tGKI_OS os; + tGKI_COM_CB com; +} tGKI_CB; + + +#ifdef __cplusplus +extern "C" { +#endif + +#if GKI_DYNAMIC_MEMORY == FALSE +GKI_API extern tGKI_CB gki_cb; +#else +GKI_API extern tGKI_CB *gki_cb_ptr; +#define gki_cb (*gki_cb_ptr) +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/gki/ulinux/gki_ulinux.c b/gki/ulinux/gki_ulinux.c new file mode 100644 index 0000000..73e93dc --- /dev/null +++ b/gki/ulinux/gki_ulinux.c @@ -0,0 +1,1355 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * 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. + * + *****************************************************************************/ + +/**************************************************************************** +** +** Name gki_linux_pthreads.c +** +** Function pthreads version of Linux GKI. This version is used for +** settop projects that already use pthreads and not pth. +** +*****************************************************************************/ + +#include <stdio.h> +#include <stdarg.h> +#include <errno.h> +#include <sys/times.h> + +#include <pthread.h> /* must be 1st header defined */ +#include <time.h> +#include "gki_int.h" + +#define LOG_TAG "GKI_LINUX" + +#include <utils/Log.h> + +/***************************************************************************** +** Constants & Macros +******************************************************************************/ + +#ifndef GKI_TICK_TIMER_DEBUG +#define GKI_TICK_TIMER_DEBUG FALSE +#endif + + +/* always log errors */ +#define GKI_ERROR_LOG(fmt, ...) LOGE ("##### ERROR : %s: " fmt "#####", __FUNCTION__, ## __VA_ARGS__) + +#if defined (GKI_TICK_TIMER_DEBUG) && (GKI_TICK_TIMER_DEBUG == TRUE) +#define GKI_TIMER_TRACE(fmt, ...) LOGI ("%s: " fmt, __FUNCTION__, ## __VA_ARGS__) +#else +#define GKI_TIMER_TRACE(fmt, ...) +#endif + + +#define SCHED_NORMAL 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 +#define SCHED_BATCH 3 + +#define NANOSEC_PER_MILLISEC (1000000) +#define NSEC_PER_SEC (1000*NANOSEC_PER_MILLISEC) + +/* works only for 1ms to 1000ms heart beat ranges */ +#define LINUX_SEC (1000/TICKS_PER_SEC) + +#define LOCK(m) pthread_mutex_lock(&m) +#define UNLOCK(m) pthread_mutex_unlock(&m) +#define INIT(m) pthread_mutex_init(&m, NULL) + +#define WAKE_LOCK_ID "brcm_btld" +#define PARTIAL_WAKE_LOCK 1 + +#if GKI_DYNAMIC_MEMORY == FALSE +tGKI_CB gki_cb; +#endif + +#ifdef NO_GKI_RUN_RETURN +static pthread_t timer_thread_id = 0; +static int shutdown_timer = 0; +#endif + +#ifndef GKI_SHUTDOWN_EVT +#define GKI_SHUTDOWN_EVT APPL_EVT_7 +#endif + +/***************************************************************************** +** Local type definitions +******************************************************************************/ + +#define pthread_cond_timedwait_monotonic pthread_cond_timedwait + +typedef struct +{ + UINT8 task_id; /* GKI task id */ + TASKPTR task_entry; /* Task entry function*/ + UINT32 params; /* Extra params to pass to task entry function */ +} gki_pthread_info_t; + + +/***************************************************************************** +** Static variables +******************************************************************************/ + +int g_GkiTimerWakeLockOn = 0; +gki_pthread_info_t gki_pthread_info[GKI_MAX_TASKS]; + +/***************************************************************************** +** Static functions +******************************************************************************/ + +/***************************************************************************** +** Externs +******************************************************************************/ + +extern int acquire_wake_lock(int lock, const char* id); +extern int release_wake_lock(const char* id); + +/***************************************************************************** +** Functions +******************************************************************************/ + + +/***************************************************************************** +** +** Function gki_task_entry +** +** Description GKI pthread callback +** +** Returns void +** +*******************************************************************************/ + +void gki_task_entry(UINT32 params) +{ + gki_pthread_info_t *p_pthread_info = (gki_pthread_info_t *)params; + gki_cb.os.thread_id[p_pthread_info->task_id] = pthread_self(); + + prctl(PR_SET_NAME, (unsigned long)gki_cb.com.OSTName[p_pthread_info->task_id], 0, 0, 0); + + GKI_TRACE("gki_task_entry task_id=%i\n", p_pthread_info->task_id); + + /* Call the actual thread entry point */ + (p_pthread_info->task_entry)(p_pthread_info->params); + + GKI_TRACE("gki_task task_id=%i terminating\n", p_pthread_info->task_id); + + pthread_exit(0); /* GKI tasks have no return value */ +} +/* end android */ + +/******************************************************************************* +** +** Function GKI_init +** +** Description This function is called once at startup to initialize +** all the timer structures. +** +** Returns void +** +*******************************************************************************/ + +void GKI_init(void) +{ + pthread_mutexattr_t attr; + tGKI_OS *p_os; + + memset (&gki_cb, 0, sizeof (gki_cb)); + + gki_buffer_init(); + gki_timers_init(); + gki_cb.com.OSTicks = (UINT32) times(0); + + pthread_mutexattr_init(&attr); + +#ifndef __CYGWIN__ + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); +#endif + p_os = &gki_cb.os; + pthread_mutex_init(&p_os->GKI_mutex, &attr); + /* pthread_mutex_init(&GKI_sched_mutex, NULL); */ +#if (GKI_DEBUG == TRUE) + pthread_mutex_init(&p_os->GKI_trace_mutex, NULL); +#endif + /* pthread_mutex_init(&thread_delay_mutex, NULL); */ /* used in GKI_delay */ + /* pthread_cond_init (&thread_delay_cond, NULL); */ + + /* Initialiase GKI_timer_update suspend variables & mutexes to be in running state. + * this works too even if GKI_NO_TICK_STOP is defined in btld.txt */ + p_os->no_timer_suspend = GKI_TIMER_TICK_RUN_COND; + pthread_mutex_init(&p_os->gki_timer_mutex, NULL); + pthread_cond_init(&p_os->gki_timer_cond, NULL); +} + + +/******************************************************************************* +** +** Function GKI_get_os_tick_count +** +** Description This function is called to retrieve the native OS system tick. +** +** Returns Tick count of native OS. +** +*******************************************************************************/ +UINT32 GKI_get_os_tick_count(void) +{ + /* TODO - add any OS specific code here */ + return (gki_cb.com.OSTicks); +} + +/******************************************************************************* +** +** Function GKI_create_task +** +** Description This function is called to create a new OSS task. +** +** Parameters: task_entry - (input) pointer to the entry function of the task +** task_id - (input) Task id is mapped to priority +** taskname - (input) name given to the task +** stack - (input) pointer to the top of the stack (highest memory location) +** stacksize - (input) size of the stack allocated for the task +** +** Returns GKI_SUCCESS if all OK, GKI_FAILURE if any problem +** +** NOTE This function take some parameters that may not be needed +** by your particular OS. They are here for compatability +** of the function prototype. +** +*******************************************************************************/ +UINT8 GKI_create_task (TASKPTR task_entry, UINT8 task_id, INT8 *taskname, UINT16 *stack, UINT16 stacksize) +{ + UINT16 i; + UINT8 *p; + struct sched_param param; + int policy, ret = 0; + pthread_attr_t attr1; + + GKI_TRACE( "GKI_create_task %x %d %s %x %d\n", task_entry, task_id, taskname, stack, + stacksize); + + if (task_id >= GKI_MAX_TASKS) + { + GKI_TRACE("Error! task ID > max task allowed"); + return (GKI_FAILURE); + } + + + gki_cb.com.OSRdyTbl[task_id] = TASK_READY; + gki_cb.com.OSTName[task_id] = taskname; + gki_cb.com.OSWaitTmr[task_id] = 0; + gki_cb.com.OSWaitEvt[task_id] = 0; + + /* Initialize mutex and condition variable objects for events and timeouts */ + pthread_mutex_init(&gki_cb.os.thread_evt_mutex[task_id], NULL); + pthread_cond_init (&gki_cb.os.thread_evt_cond[task_id], NULL); + pthread_mutex_init(&gki_cb.os.thread_timeout_mutex[task_id], NULL); + pthread_cond_init (&gki_cb.os.thread_timeout_cond[task_id], NULL); + + pthread_attr_init(&attr1); + /* by default, pthread creates a joinable thread */ +#if ( FALSE == GKI_PTHREAD_JOINABLE ) + pthread_attr_setdetachstate(&attr1, PTHREAD_CREATE_DETACHED); + + GKI_TRACE("GKI creating task %i\n", task_id); +#else + GKI_TRACE("GKI creating JOINABLE task %i\n", task_id); +#endif + + /* On Android, the new tasks starts running before 'gki_cb.os.thread_id[task_id]' is initialized */ + /* Pass task_id to new task so it can initialize gki_cb.os.thread_id[task_id] for it calls GKI_wait */ + gki_pthread_info[task_id].task_id = task_id; + gki_pthread_info[task_id].task_entry = task_entry; + gki_pthread_info[task_id].params = 0; + + ret = pthread_create( &gki_cb.os.thread_id[task_id], + &attr1, + (void *)gki_task_entry, + &gki_pthread_info[task_id]); + + if (ret != 0) + { + printf("pthread_create failed(%d), %s!\n\r", ret, taskname); + return GKI_FAILURE; + } + + if(pthread_getschedparam(gki_cb.os.thread_id[task_id], &policy, ¶m)==0) + { +#if (GKI_LINUX_BASE_POLICY!=GKI_SCHED_NORMAL) +#if defined(PBS_SQL_TASK) + if (task_id == PBS_SQL_TASK) + { + GKI_TRACE("PBS SQL lowest priority task"); + policy = SCHED_NORMAL; + } + else +#endif +#endif + { + /* check if define in gki_int.h is correct for this compile environment! */ + policy = GKI_LINUX_BASE_POLICY; +#if (GKI_LINUX_BASE_POLICY!=GKI_SCHED_NORMAL) + param.sched_priority = GKI_LINUX_BASE_PRIORITY - task_id - 2; +#endif + } + pthread_setschedparam(gki_cb.os.thread_id[task_id], policy, ¶m); + } + + GKI_TRACE( "Leaving GKI_create_task %x %d %x %s %x %d\n", + task_entry, + task_id, + gki_cb.os.thread_id[task_id], + taskname, + stack, + stacksize); + + return (GKI_SUCCESS); +} + +void GKI_destroy_task(UINT8 task_id) +{ +#if ( FALSE == GKI_PTHREAD_JOINABLE ) + int i = 0; +#else + int result; +#endif + if (gki_cb.com.OSRdyTbl[task_id] != TASK_DEAD) + { + gki_cb.com.OSRdyTbl[task_id] = TASK_DEAD; + + /* paranoi settings, make sure that we do not execute any mailbox events */ + gki_cb.com.OSWaitEvt[task_id] &= ~(TASK_MBOX_0_EVT_MASK|TASK_MBOX_1_EVT_MASK| + TASK_MBOX_2_EVT_MASK|TASK_MBOX_3_EVT_MASK); + GKI_send_event(task_id, EVENT_MASK(GKI_SHUTDOWN_EVT)); + +#if ( FALSE == GKI_PTHREAD_JOINABLE ) + i = 0; + + while ((gki_cb.com.OSWaitEvt[task_id] != 0) && (++i < 10)) + usleep(100 * 1000); +#else + result = pthread_join( gki_cb.os.thread_id[task_id], NULL ); + if ( result < 0 ) + { + GKI_TRACE( "pthread_join() FAILED: result: %d", result ); + } +#endif + GKI_ERROR_LOG( "GKI_shutdown(): task %s dead\n", gki_cb.com.OSTName[task_id]); + GKI_exit_task(task_id); + } + +} + + +/******************************************************************************* +** +** Function GKI_shutdown +** +** Description shutdowns the GKI tasks/threads in from max task id to 0 and frees +** pthread resources! +** IMPORTANT: in case of join method, GKI_shutdown must be called outside +** a GKI thread context! +** +** Returns void +** +*******************************************************************************/ + +void GKI_shutdown(void) +{ + UINT8 task_id; +#if ( FALSE == GKI_PTHREAD_JOINABLE ) + int i = 0; +#else + int result; +#endif + +#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS + gki_dealloc_free_queue(); +#endif + + /* release threads and set as TASK_DEAD. going from low to high priority fixes + * GKI_exception problem due to btu->hci sleep request events */ + for (task_id = GKI_MAX_TASKS; task_id > 0; task_id--) + { + if (gki_cb.com.OSRdyTbl[task_id - 1] != TASK_DEAD) + { + gki_cb.com.OSRdyTbl[task_id - 1] = TASK_DEAD; + + /* paranoi settings, make sure that we do not execute any mailbox events */ + gki_cb.com.OSWaitEvt[task_id-1] &= ~(TASK_MBOX_0_EVT_MASK|TASK_MBOX_1_EVT_MASK| + TASK_MBOX_2_EVT_MASK|TASK_MBOX_3_EVT_MASK); + GKI_send_event(task_id - 1, EVENT_MASK(GKI_SHUTDOWN_EVT)); + +#if ( FALSE == GKI_PTHREAD_JOINABLE ) + i = 0; + + while ((gki_cb.com.OSWaitEvt[task_id - 1] != 0) && (++i < 10)) + usleep(100 * 1000); +#else + result = pthread_join( gki_cb.os.thread_id[task_id-1], NULL ); + + if ( result < 0 ) + { + LOGE( "pthread_join() FAILED: result: %d", result ); + } +#endif + // GKI_ERROR_LOG( "GKI_shutdown(): task %s dead\n", gki_cb.com.OSTName[task_id]); + GKI_exit_task(task_id - 1); + } + } + + /* Destroy mutex and condition variable objects */ + pthread_mutex_destroy(&gki_cb.os.GKI_mutex); + + /* pthread_mutex_destroy(&GKI_sched_mutex); */ +#if (GKI_DEBUG == TRUE) + pthread_mutex_destroy(&gki_cb.os.GKI_trace_mutex); +#endif + /* pthread_mutex_destroy(&thread_delay_mutex); + pthread_cond_destroy (&thread_delay_cond); */ +#if ( FALSE == GKI_PTHREAD_JOINABLE ) + i = 0; +#endif + +#ifdef NO_GKI_RUN_RETURN + shutdown_timer = 1; +#endif + if (g_GkiTimerWakeLockOn) + { + GKI_TRACE("GKI_shutdown : release_wake_lock(brcm_btld)"); + release_wake_lock(WAKE_LOCK_ID); + g_GkiTimerWakeLockOn = 0; + } +} + +/******************************************************************************* + ** + ** Function gki_system_tick_start_stop_cback + ** + ** Description This function runs a task + ** + ** Parameters: start: TRUE start system tick (again), FALSE stop + ** + ** Returns void + ** + *********************************************************************************/ + +void gki_system_tick_start_stop_cback(BOOLEAN start) +{ + tGKI_OS *p_os = &gki_cb.os; + volatile int *p_run_cond = &p_os->no_timer_suspend; + static int wake_lock_count; + if ( FALSE == start ) + { + /* this can lead to a race condition. however as we only read this variable in the timer loop + * we should be fine with this approach. otherwise uncomment below mutexes. + */ + /* GKI_disable(); */ + *p_run_cond = GKI_TIMER_TICK_STOP_COND; + /* GKI_enable(); */ + + GKI_TIMER_TRACE(">>> STOP GKI_timer_update(), wake_lock_count:%d", --wake_lock_count); + + release_wake_lock(WAKE_LOCK_ID); + g_GkiTimerWakeLockOn = 0; + } + else + { + /* restart GKI_timer_update() loop */ + acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); + + g_GkiTimerWakeLockOn = 1; + *p_run_cond = GKI_TIMER_TICK_RUN_COND; + + pthread_mutex_lock( &p_os->gki_timer_mutex ); + pthread_cond_signal( &p_os->gki_timer_cond ); + pthread_mutex_unlock( &p_os->gki_timer_mutex ); + + GKI_TIMER_TRACE(">>> START GKI_timer_update(), wake_lock_count:%d", ++wake_lock_count ); + } +} + + +/******************************************************************************* +** +** Function GKI_run +** +** Description This function runs a task +**** +** Returns void +** +** NOTE This function is only needed for operating systems where +** starting a task is a 2-step process. Most OS's do it in +** one step, If your OS does it in one step, this function +** should be empty. +*********************************************************************************/ + +#ifdef NO_GKI_RUN_RETURN +void* timer_thread(void *arg) +{ + struct timespec delay; + int err; + + while(!shutdown_timer) + { + delay.tv_sec = LINUX_SEC / 1000; + delay.tv_nsec = 1000 * 1000 * (LINUX_SEC%1000); + + /* [u]sleep can't be used because it uses SIGALRM */ + + do { + err = nanosleep(&delay, &delay); + } while (err < 0 && errno ==EINTR); + + GKI_timer_update(1); + } + GKI_TRACE("gki_ulinux: Exiting timer_thread"); + pthread_exit(NULL); + return NULL; +} +#endif + + +/***************************************************************************** +** +** Function gki_set_timer_scheduling +** +** Description helper function to set scheduling policy and priority of btdl +** +** Returns void +** +*******************************************************************************/ + +static void gki_set_timer_scheduling( void ) +{ + pid_t main_pid = getpid(); + struct sched_param param; + int policy; + + policy = sched_getscheduler(main_pid); + + if ( policy != -1 ) + { + GKI_TRACE("gki_set_timer_scheduling(()::scheduler current policy: %d", policy); + + /* ensure highest priority in the system + 2 to allow space for read threads */ + param.sched_priority = GKI_LINUX_TIMER_TICK_PRIORITY; + + if ( 0!=sched_setscheduler(main_pid, GKI_LINUX_TIMER_POLICY, ¶m ) ) + { + GKI_TRACE("sched_setscheduler() failed with error: %d", errno); + } + } + else + { + GKI_TRACE( "getscheduler failed: %d", errno); + } +} + + +/***************************************************************************** +** +** Function GKI_freeze +** +** Description Freeze GKI. Relevant only when NO_GKI_RUN_RETURN is defined +** +** Returns +** +*******************************************************************************/ + +void GKI_freeze() +{ +#ifdef NO_GKI_RUN_RETURN + shutdown_timer = 1; + /* Ensure that the timer thread exits */ + pthread_join(timer_thread_id, NULL); +#endif +} + +/***************************************************************************** +** +** Function GKI_run +** +** Description Main GKI loop +** +** Returns +** +*******************************************************************************/ + +void GKI_run (void *p_task_id) +{ + struct timespec delay; + int err; + volatile int * p_run_cond = &gki_cb.os.no_timer_suspend; + +#ifndef GKI_NO_TICK_STOP + /* adjust btld scheduling scheme now */ + gki_set_timer_scheduling(); + + /* register start stop function which disable timer loop in GKI_run() when no timers are + * in any GKI/BTA/BTU this should save power when BTLD is idle! */ + GKI_timer_queue_register_callback( gki_system_tick_start_stop_cback ); + GKI_TRACE( "GKI_run(): Start/Stop GKI_timer_update_registered!" ); +#endif + +#ifdef NO_GKI_RUN_RETURN + pthread_attr_t timer_attr; + + shutdown_timer = 0; + + pthread_attr_init(&timer_attr); + if (pthread_create( &timer_thread_id, + &timer_attr, + timer_thread, + NULL) != 0 ) + { + printf("GKI_run: pthread_create failed to create timer_thread!\n\r"); + return; + } + + prctl(PR_SET_NAME, (unsigned long)"gki timer", 0, 0, 0); + +#else + GKI_TRACE("GKI_run "); + for (;;) + { + do + { + /* adjust hear bit tick in btld by changning TICKS_PER_SEC!!!!! this formula works only for + * 1-1000ms heart beat units! */ + delay.tv_sec = LINUX_SEC / 1000; + delay.tv_nsec = 1000 * 1000 * (LINUX_SEC % 1000); + + /* [u]sleep can't be used because it uses SIGALRM */ + do + { + err = nanosleep(&delay, &delay); + } while (err < 0 && errno == EINTR); + + /* the unit should be alsways 1 (1 tick). only if you vary for some reason heart beat tick + * e.g. power saving you may want to provide more ticks + */ + GKI_timer_update( 1 ); + /* BT_TRACE_2( TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, "update: tv_sec: %d, tv_nsec: %d", delay.tv_sec, delay.tv_nsec ); */ + } while ( GKI_TIMER_TICK_RUN_COND == *p_run_cond ); + + /* currently on reason to exit above loop is no_timer_suspend == GKI_TIMER_TICK_STOP_COND + * block timer main thread till re-armed by */ + + GKI_TIMER_TRACE(">>> SUSPENDED GKI_timer_update()" ); + + pthread_mutex_lock( &gki_cb.os.gki_timer_mutex ); + pthread_cond_wait( &gki_cb.os.gki_timer_cond, &gki_cb.os.gki_timer_mutex ); + pthread_mutex_unlock( &gki_cb.os.gki_timer_mutex ); + + /* potentially we need to adjust os gki_cb.com.OSTicks */ + GKI_TIMER_TRACE(">>> RESTARTED GKI_timer_update(): run_cond: %d", + *p_run_cond ); + + } +#endif + return; +} + + +/******************************************************************************* +** +** Function GKI_stop +** +** Description This function is called to stop +** the tasks and timers when the system is being stopped +** +** Returns void +** +** NOTE This function is NOT called by the Widcomm stack and +** profiles. If you want to use it in your own implementation, +** put specific code here. +** +*******************************************************************************/ + +void GKI_stop (void) +{ + UINT8 task_id; + + /* gki_queue_timer_cback(FALSE); */ + /* TODO - add code here if needed*/ + + for(task_id = 0; task_id<GKI_MAX_TASKS; task_id++) + { + if(gki_cb.com.OSRdyTbl[task_id] != TASK_DEAD) + { + GKI_exit_task(task_id); + } + } +} + + +/******************************************************************************* +** +** Function GKI_wait +** +** Description This function is called by tasks to wait for a specific +** event or set of events. The task may specify the duration +** that it wants to wait for, or 0 if infinite. +** +** Parameters: flag - (input) the event or set of events to wait for +** timeout - (input) the duration that the task wants to wait +** for the specific events (in system ticks) +** +** +** Returns the event mask of received events or zero if timeout +** +*******************************************************************************/ +UINT16 GKI_wait (UINT16 flag, UINT32 timeout) +{ + UINT16 evt; + UINT8 rtask; + struct timespec abstime = { 0, 0 }; + + int sec; + int nano_sec; + + rtask = GKI_get_taskid(); + + GKI_TRACE("GKI_wait %d %x %d", rtask, flag, timeout); + + gki_cb.com.OSWaitForEvt[rtask] = flag; + + /* protect OSWaitEvt[rtask] from modification from an other thread */ + pthread_mutex_lock(&gki_cb.os.thread_evt_mutex[rtask]); + + if (!(gki_cb.com.OSWaitEvt[rtask] & flag)) + { + if (timeout) + { + clock_gettime(CLOCK_MONOTONIC, &abstime); + + /* add timeout */ + sec = timeout / 1000; + nano_sec = (timeout % 1000) * NANOSEC_PER_MILLISEC; + abstime.tv_nsec += nano_sec; + if (abstime.tv_nsec > NSEC_PER_SEC) + { + abstime.tv_sec += (abstime.tv_nsec / NSEC_PER_SEC); + abstime.tv_nsec = abstime.tv_nsec % NSEC_PER_SEC; + } + abstime.tv_sec += sec; + + pthread_cond_timedwait_monotonic(&gki_cb.os.thread_evt_cond[rtask], + &gki_cb.os.thread_evt_mutex[rtask], &abstime); + + } + else + { + pthread_cond_wait(&gki_cb.os.thread_evt_cond[rtask], &gki_cb.os.thread_evt_mutex[rtask]); + } + + /* TODO: check, this is probably neither not needed depending on phtread_cond_wait() implmentation, + e.g. it looks like it is implemented as a counter in which case multiple cond_signal + should NOT be lost! */ + + /* we are waking up after waiting for some events, so refresh variables + no need to call GKI_disable() here as we know that we will have some events as we've been waking + up after condition pending or timeout */ + + if (gki_cb.com.OSTaskQFirst[rtask][0]) + gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_0_EVT_MASK; + if (gki_cb.com.OSTaskQFirst[rtask][1]) + gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_1_EVT_MASK; + if (gki_cb.com.OSTaskQFirst[rtask][2]) + gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_2_EVT_MASK; + if (gki_cb.com.OSTaskQFirst[rtask][3]) + gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_3_EVT_MASK; + + if (gki_cb.com.OSRdyTbl[rtask] == TASK_DEAD) + { + gki_cb.com.OSWaitEvt[rtask] = 0; + /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock when cond is met */ + pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]); + return (EVENT_MASK(GKI_SHUTDOWN_EVT)); + } + } + + /* Clear the wait for event mask */ + gki_cb.com.OSWaitForEvt[rtask] = 0; + + /* Return only those bits which user wants... */ + evt = gki_cb.com.OSWaitEvt[rtask] & flag; + + /* Clear only those bits which user wants... */ + gki_cb.com.OSWaitEvt[rtask] &= ~flag; + + /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock mutex when cond is met */ + pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]); + + GKI_TRACE("GKI_wait %d %x %d %x done", rtask, flag, timeout, evt); + return (evt); +} + + +/******************************************************************************* +** +** Function GKI_delay +** +** Description This function is called by tasks to sleep unconditionally +** for a specified amount of time. The duration is in milliseconds +** +** Parameters: timeout - (input) the duration in milliseconds +** +** Returns void +** +*******************************************************************************/ + +void GKI_delay (UINT32 timeout) +{ + UINT8 rtask = GKI_get_taskid(); + struct timespec delay; + int err; + + GKI_TRACE("GKI_delay %d %d", rtask, timeout); + + delay.tv_sec = timeout / 1000; + delay.tv_nsec = 1000 * 1000 * (timeout%1000); + + /* [u]sleep can't be used because it uses SIGALRM */ + + do { + err = nanosleep(&delay, &delay); + } while (err < 0 && errno ==EINTR); + + /* Check if task was killed while sleeping */ + + /* NOTE : if you do not implement task killing, you do not need this check */ + + if (rtask && gki_cb.com.OSRdyTbl[rtask] == TASK_DEAD) + { + } + + GKI_TRACE("GKI_delay %d %d done", rtask, timeout); + + return; +} + + +/******************************************************************************* +** +** Function GKI_send_event +** +** Description This function is called by tasks to send events to other +** tasks. Tasks can also send events to themselves. +** +** Parameters: task_id - (input) The id of the task to which the event has to +** be sent +** event - (input) The event that has to be sent +** +** +** Returns GKI_SUCCESS if all OK, else GKI_FAILURE +** +*******************************************************************************/ + +UINT8 GKI_send_event (UINT8 task_id, UINT16 event) +{ + GKI_TRACE("GKI_send_event %d %x", task_id, event); + + /* use efficient coding to avoid pipeline stalls */ + if (task_id < GKI_MAX_TASKS) + { + /* protect OSWaitEvt[task_id] from manipulation in GKI_wait() */ + pthread_mutex_lock(&gki_cb.os.thread_evt_mutex[task_id]); + + /* Set the event bit */ + gki_cb.com.OSWaitEvt[task_id] |= event; + + pthread_cond_signal(&gki_cb.os.thread_evt_cond[task_id]); + + pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[task_id]); + + GKI_TRACE("GKI_send_event %d %x done", task_id, event); + return ( GKI_SUCCESS ); + } + return (GKI_FAILURE); +} + + +/******************************************************************************* +** +** Function GKI_isend_event +** +** Description This function is called from ISRs to send events to other +** tasks. The only difference between this function and GKI_send_event +** is that this function assumes interrupts are already disabled. +** +** Parameters: task_id - (input) The destination task Id for the event. +** event - (input) The event flag +** +** Returns GKI_SUCCESS if all OK, else GKI_FAILURE +** +** NOTE This function is NOT called by the Widcomm stack and +** profiles. If you want to use it in your own implementation, +** put your code here, otherwise you can delete the entire +** body of the function. +** +*******************************************************************************/ +UINT8 GKI_isend_event (UINT8 task_id, UINT16 event) +{ + GKI_TRACE("GKI_isend_event %d %x", task_id, event); + GKI_TRACE("GKI_isend_event %d %x done", task_id, event); + return GKI_send_event(task_id, event); +} + + +/******************************************************************************* +** +** Function GKI_get_taskid +** +** Description This function gets the currently running task ID. +** +** Returns task ID +** +** NOTE The Widcomm upper stack and profiles may run as a single task. +** If you only have one GKI task, then you can hard-code this +** function to return a '1'. Otherwise, you should have some +** OS-specific method to determine the current task. +** +*******************************************************************************/ +UINT8 GKI_get_taskid (void) +{ + int i; + + pthread_t thread_id = pthread_self( ); + + GKI_TRACE("GKI_get_taskid %x", thread_id); + + for (i = 0; i < GKI_MAX_TASKS; i++) { + if (gki_cb.os.thread_id[i] == thread_id) { + //GKI_TRACE("GKI_get_taskid %x %d done", thread_id, i); + return(i); + } + } + + GKI_TRACE("GKI_get_taskid: task id = -1"); + + return(-1); +} + + +/******************************************************************************* +** +** Function GKI_map_taskname +** +** Description This function gets the task name of the taskid passed as arg. +** If GKI_MAX_TASKS is passed as arg the currently running task +** name is returned +** +** Parameters: task_id - (input) The id of the task whose name is being +** sought. GKI_MAX_TASKS is passed to get the name of the +** currently running task. +** +** Returns pointer to task name +** +** NOTE this function needs no customization +** +*******************************************************************************/ + +INT8 *GKI_map_taskname (UINT8 task_id) +{ + GKI_TRACE("GKI_map_taskname %d", task_id); + + if (task_id < GKI_MAX_TASKS) + { + GKI_TRACE("GKI_map_taskname %d %s done", task_id, gki_cb.com.OSTName[task_id]); + return (gki_cb.com.OSTName[task_id]); + } + else if (task_id == GKI_MAX_TASKS ) + { + return (gki_cb.com.OSTName[GKI_get_taskid()]); + } + else + { + return (INT8*)"BAD"; + } +} + + +/******************************************************************************* +** +** Function GKI_enable +** +** Description This function enables interrupts. +** +** Returns void +** +*******************************************************************************/ +void GKI_enable (void) +{ + GKI_TRACE("GKI_enable"); + pthread_mutex_unlock(&gki_cb.os.GKI_mutex); + GKI_TRACE("Leaving GKI_enable"); + return; +} + + +/******************************************************************************* +** +** Function GKI_disable +** +** Description This function disables interrupts. +** +** Returns void +** +*******************************************************************************/ + +void GKI_disable (void) +{ + GKI_TRACE("GKI_disable"); + + pthread_mutex_lock(&gki_cb.os.GKI_mutex); + + GKI_TRACE("Leaving GKI_disable"); + return; +} + + +/******************************************************************************* +** +** Function GKI_exception +** +** Description This function throws an exception. +** This is normally only called for a nonrecoverable error. +** +** Parameters: code - (input) The code for the error +** msg - (input) The message that has to be logged +** +** Returns void +** +*******************************************************************************/ + +void GKI_exception (UINT16 code, char *msg) +{ + UINT8 task_id; + int i = 0; + + GKI_ERROR_LOG( "GKI_exception(): Task State Table\n"); + + for(task_id = 0; task_id < GKI_MAX_TASKS; task_id++) + { + GKI_ERROR_LOG( "TASK ID [%d] task name [%s] state [%d]\n", + task_id, + gki_cb.com.OSTName[task_id], + gki_cb.com.OSRdyTbl[task_id]); + } + + GKI_TRACE("GKI_exception %d %s", code, msg); + GKI_ERROR_LOG( "\n********************************************************************\n"); + GKI_ERROR_LOG( "* GKI_exception(): %d %s\n", code, msg); + GKI_ERROR_LOG( "********************************************************************\n"); + +#if 0//(GKI_DEBUG == TRUE) + GKI_disable(); + + if (gki_cb.com.ExceptionCnt < GKI_MAX_EXCEPTION) + { + EXCEPTION_T *pExp; + + pExp = &gki_cb.com.Exception[gki_cb.com.ExceptionCnt++]; + pExp->type = code; + pExp->taskid = GKI_get_taskid(); + strncpy((char *)pExp->msg, msg, GKI_MAX_EXCEPTION_MSGLEN - 1); + } + + GKI_enable(); +#endif + + GKI_TRACE("GKI_exception %d %s done", code, msg); + + + return; +} + + +/******************************************************************************* +** +** Function GKI_get_time_stamp +** +** Description This function formats the time into a user area +** +** Parameters: tbuf - (output) the address to the memory containing the +** formatted time +** +** Returns the address of the user area containing the formatted time +** The format of the time is ???? +** +** NOTE This function is only called by OBEX. +** +*******************************************************************************/ +INT8 *GKI_get_time_stamp (INT8 *tbuf) +{ + UINT32 ms_time; + UINT32 s_time; + UINT32 m_time; + UINT32 h_time; + INT8 *p_out = tbuf; + + gki_cb.com.OSTicks = times(0); + ms_time = GKI_TICKS_TO_MS(gki_cb.com.OSTicks); + s_time = ms_time/100; /* 100 Ticks per second */ + m_time = s_time/60; + h_time = m_time/60; + + ms_time -= s_time*100; + s_time -= m_time*60; + m_time -= h_time*60; + + *p_out++ = (INT8)((h_time / 10) + '0'); + *p_out++ = (INT8)((h_time % 10) + '0'); + *p_out++ = ':'; + *p_out++ = (INT8)((m_time / 10) + '0'); + *p_out++ = (INT8)((m_time % 10) + '0'); + *p_out++ = ':'; + *p_out++ = (INT8)((s_time / 10) + '0'); + *p_out++ = (INT8)((s_time % 10) + '0'); + *p_out++ = ':'; + *p_out++ = (INT8)((ms_time / 10) + '0'); + *p_out++ = (INT8)((ms_time % 10) + '0'); + *p_out++ = ':'; + *p_out = 0; + + return (tbuf); +} + + +/******************************************************************************* +** +** Function GKI_register_mempool +** +** Description This function registers a specific memory pool. +** +** Parameters: p_mem - (input) pointer to the memory pool +** +** Returns void +** +** NOTE This function is NOT called by the Widcomm stack and +** profiles. If your OS has different memory pools, you +** can tell GKI the pool to use by calling this function. +** +*******************************************************************************/ +void GKI_register_mempool (void *p_mem) +{ + gki_cb.com.p_user_mempool = p_mem; + + return; +} + +/******************************************************************************* +** +** Function GKI_os_malloc +** +** Description This function allocates memory +** +** Parameters: size - (input) The size of the memory that has to be +** allocated +** +** Returns the address of the memory allocated, or NULL if failed +** +** NOTE This function is called by the Widcomm stack when +** dynamic memory allocation is used. (see dyn_mem.h) +** +*******************************************************************************/ +void *GKI_os_malloc (UINT32 size) +{ + return (malloc(size)); +} + +/******************************************************************************* +** +** Function GKI_os_free +** +** Description This function frees memory +** +** Parameters: size - (input) The address of the memory that has to be +** freed +** +** Returns void +** +** NOTE This function is NOT called by the Widcomm stack and +** profiles. It is only called from within GKI if dynamic +** +*******************************************************************************/ +void GKI_os_free (void *p_mem) +{ + if(p_mem != NULL) + free(p_mem); + return; +} + + +/******************************************************************************* +** +** Function GKI_suspend_task() +** +** Description This function suspends the task specified in the argument. +** +** Parameters: task_id - (input) the id of the task that has to suspended +** +** Returns GKI_SUCCESS if all OK, else GKI_FAILURE +** +** NOTE This function is NOT called by the Widcomm stack and +** profiles. If you want to implement task suspension capability, +** put specific code here. +** +*******************************************************************************/ +UINT8 GKI_suspend_task (UINT8 task_id) +{ + GKI_TRACE("GKI_suspend_task %d - NOT implemented", task_id); + + + GKI_TRACE("GKI_suspend_task %d done", task_id); + + return (GKI_SUCCESS); +} + + +/******************************************************************************* +** +** Function GKI_resume_task() +** +** Description This function resumes the task specified in the argument. +** +** Parameters: task_id - (input) the id of the task that has to resumed +** +** Returns GKI_SUCCESS if all OK +** +** NOTE This function is NOT called by the Widcomm stack and +** profiles. If you want to implement task suspension capability, +** put specific code here. +** +*******************************************************************************/ +UINT8 GKI_resume_task (UINT8 task_id) +{ + GKI_TRACE("GKI_resume_task %d - NOT implemented", task_id); + + + GKI_TRACE("GKI_resume_task %d done", task_id); + + return (GKI_SUCCESS); +} + + +/******************************************************************************* +** +** Function GKI_exit_task +** +** Description This function is called to stop a GKI task. +** +** Parameters: task_id - (input) the id of the task that has to be stopped +** +** Returns void +** +** NOTE This function is NOT called by the Widcomm stack and +** profiles. If you want to use it in your own implementation, +** put specific code here to kill a task. +** +*******************************************************************************/ +void GKI_exit_task (UINT8 task_id) +{ + GKI_disable(); + gki_cb.com.OSRdyTbl[task_id] = TASK_DEAD; + + /* Destroy mutex and condition variable objects */ + pthread_mutex_destroy(&gki_cb.os.thread_evt_mutex[task_id]); + pthread_cond_destroy (&gki_cb.os.thread_evt_cond[task_id]); + pthread_mutex_destroy(&gki_cb.os.thread_timeout_mutex[task_id]); + pthread_cond_destroy (&gki_cb.os.thread_timeout_cond[task_id]); + + GKI_enable(); + + //GKI_send_event(task_id, EVENT_MASK(GKI_SHUTDOWN_EVT)); + + GKI_TRACE("GKI_exit_task %d done", task_id); + return; +} + + +/******************************************************************************* +** +** Function GKI_sched_lock +** +** Description This function is called by tasks to disable scheduler +** task context switching. +** +** Returns void +** +** NOTE This function is NOT called by the Widcomm stack and +** profiles. If you want to use it in your own implementation, +** put code here to tell the OS to disable context switching. +** +*******************************************************************************/ +void GKI_sched_lock(void) +{ + GKI_TRACE("GKI_sched_lock"); + return; +} + + +/******************************************************************************* +** +** Function GKI_sched_unlock +** +** Description This function is called by tasks to enable scheduler switching. +** +** Returns void +** +** NOTE This function is NOT called by the Widcomm stack and +** profiles. If you want to use it in your own implementation, +** put code here to tell the OS to re-enable context switching. +** +*******************************************************************************/ +void GKI_sched_unlock(void) +{ + GKI_TRACE("GKI_sched_unlock"); +} + + |