Android蓝牙源码分析——关于GKI

来源:互联网 发布:知足知不足的阅读答案 编辑:程序博客网 时间:2024/05/23 14:00

GKI模块是Bluedroid中用于线程间通信的,我们知道蓝牙所有的操作最终都会交给Bluedroid处理,而调用方可能来自多个线程,Bluedroid中有大量的全局变量,为避免多线程导致的数据不一致问题,干脆统一切换到一个固定的工作线程中执行。类似于Java中的post Runnable,这里是给线程发送消息或事件。

接下来我们开始分析GKI源码,文件并不多,我们首先以gki模块的初始化为入口,在gki_ulinux.c中,如下:

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();    alarm_service_init();    gki_cb.com.OSTicks = (UINT32) times(0);    pthread_mutexattr_init(&attr);    p_os = &gki_cb.os;    pthread_mutex_init(&p_os->GKI_mutex, &attr);    struct sigevent sigevent;    memset(&sigevent, 0, sizeof(sigevent));    sigevent.sigev_notify = SIGEV_THREAD;    sigevent.sigev_notify_function = (void (*)(union sigval))bt_alarm_cb;    sigevent.sigev_value.sival_ptr = NULL;    if (timer_create(CLOCK_REALTIME, &sigevent, &posix_timer) == -1) {        timer_created = false;    } else {        timer_created = true;    }}

首先将gki_cb清零,这个变量非常重要,如下:

tGKI_CB   gki_cb;typedef struct{    tGKI_OS     os;    tGKI_COM_CB com;} tGKI_CB;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];} tGKI_OS;typedef struct {    UINT8  *OSStack[GKI_MAX_TASKS];         /* pointer to beginning of stack */    UINT16  OSStackSize[GKI_MAX_TASKS];     /* stack size available to each task */    INT8   *OSTName[GKI_MAX_TASKS];         /* name of the task */    UINT8   OSRdyTbl[GKI_MAX_TASKS];        /* current state of the task */    UINT16  OSWaitEvt[GKI_MAX_TASKS];       /* events that have to be processed by the task */    UINT16  OSWaitForEvt[GKI_MAX_TASKS];    /* events the task is waiting for*/    UINT32  OSTicks;                        /* system ticks from start */    UINT32  OSIdleCnt;                      /* idle counter */    INT16   OSDisableNesting;               /* counter to keep track of interrupt disable nesting */    INT16   OSLockNesting;                  /* counter to keep track of sched lock nesting */    INT16   OSIntNesting;                   /* counter to keep track of interrupt nesting */    /* Timer related variables    */    INT32   OSTicksTilExp;      /* Number of ticks till next timer expires */    INT32   OSNumOrigTicks;     /* Number of ticks between last timer expiration to the next one */    INT32   OSWaitTmr   [GKI_MAX_TASKS];  /* ticks the task has to wait, for specific events */    /* Buffer related variables    */    BUFFER_HDR_T    *OSTaskQFirst[GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the first event in the task mailbox */    BUFFER_HDR_T    *OSTaskQLast [GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the last event in the task mailbox */    /* Define the buffer pool management variables    */    FREE_QUEUE_T    freeq[GKI_NUM_TOTAL_BUF_POOLS];    UINT16   pool_buf_size[GKI_NUM_TOTAL_BUF_POOLS];    UINT16   pool_max_count[GKI_NUM_TOTAL_BUF_POOLS];    UINT16   pool_additions[GKI_NUM_TOTAL_BUF_POOLS];    /* Define the buffer pool start addresses    */    UINT8   *pool_start[GKI_NUM_TOTAL_BUF_POOLS];   /* array of pointers to the start of each buffer pool */    UINT8   *pool_end[GKI_NUM_TOTAL_BUF_POOLS];     /* array of pointers to the end of each buffer pool */    UINT16   pool_size[GKI_NUM_TOTAL_BUF_POOLS];    /* actual size of the buffers in a pool */    /* Define the buffer pool access control variables */    void        *p_user_mempool;                    /* User O/S memory pool */    UINT16      pool_access_mask;                   /* Bits are set if the corresponding buffer pool is a restricted pool */    UINT8       pool_list[GKI_NUM_TOTAL_BUF_POOLS]; /* buffer pools arranged in the order of size */    UINT8       curr_total_no_of_pools;             /* number of fixed buf pools + current number of dynamic pools */    BOOLEAN     timer_nesting;                      /* flag to prevent timer interrupt nesting */} tGKI_COM_CB;

tGKI_OS里有个GKI全局锁,一个线程池,还有关于evt和timeout的锁和条件变量。tGKI_COM_CB作为整个GKI的控制中心,里面的数据结构很复杂。

我们继续回到gki_init,在将gki_cb清零后,接下里先后初始化buffer, timer和alarm_service。然后初始化tGKI_OS中的GKI全局锁,最后创建一个定时器,当定时器到期时内核会启动一个线程执行bt_alarm_cb回调函数。

再来看gki_buffer_init是如何初始化缓冲区的,如下:

void gki_buffer_init(void){    UINT8   i, tt, mb;    tGKI_COM_CB *p_cb = &gki_cb.com;    /* Initialize mailboxes */    for (tt = 0; tt < GKI_MAX_TASKS; tt++)    {        for (mb = 0; mb < NUM_TASK_MBOX; mb++)        {            p_cb->OSTaskQFirst[tt][mb] = NULL;            p_cb->OSTaskQLast [tt][mb] = NULL;        }    }    for (tt = 0; tt < GKI_NUM_TOTAL_BUF_POOLS; tt++)    {        p_cb->pool_start[tt] = NULL;        p_cb->pool_end[tt]   = NULL;        p_cb->pool_size[tt]  = 0;        p_cb->freeq[tt].p_first = 0;        p_cb->freeq[tt].p_last  = 0;        p_cb->freeq[tt].size    = 0;        p_cb->freeq[tt].total   = 0;        p_cb->freeq[tt].cur_cnt = 0;        p_cb->freeq[tt].max_cnt = 0;    }    /* Use default from target.h */    p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;    /* add pools to the pool_list which is arranged in the order of size */    for(i=0; i < GKI_NUM_FIXED_BUF_POOLS ; i++)    {        p_cb->pool_list[i] = i;    }    p_cb->curr_total_no_of_pools = GKI_NUM_FIXED_BUF_POOLS;    return;}

GKI缓冲区相关的控制数据结构都在tGKI_COM_CB中,如下:

/* Buffer related variables */BUFFER_HDR_T    *OSTaskQFirst[GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the first event in the task mailbox */BUFFER_HDR_T    *OSTaskQLast [GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the last event in the task mailbox */typedef struct _buffer_hdr{    struct _buffer_hdr *p_next;   /* next buffer in the queue */    UINT8   q_id;                 /* id of the queue */    UINT8   task_id;              /* task which allocated the buffer*/    UINT8   status;               /* FREE, UNLINKED or QUEUED */    UINT8   Type;} BUFFER_HDR_T;

这里OSTaskQFirst和OSTaskQLast是个BUFFER_HDR_T的二维数组,看上去每个TASK有一个TASK_MBOX数组:

#define GKI_MAX_TASKS 3/************************************************************************** Mailbox definitions. Each task has 4 mailboxes that are used to** send buffers to the task.*/#define TASK_MBOX_0    0#define TASK_MBOX_1    1#define TASK_MBOX_2    2#define TASK_MBOX_3    3#define NUM_TASK_MBOX  4#define GKI_NUM_TOTAL_BUF_POOLS     10

从注释上看每个task有4个mailbox,这个mailbox是用于向task发送buffer的,buffer中可能带了各种参数。

我们回到gki_buffer_init中看是如何初始化buffer的,首先将所有的mailbox都初始化为null,然后gki中一共有GKI_NUM_TOTAL_BUF_POOLS个缓冲池都需要初始化。

再来看gki_timers_init是如何初始化timers的:

void gki_timers_init(void){    UINT8   tt;    gki_cb.com.OSTicksTilExp = 0;       /* Remaining time (of OSTimeCurTimeout) before next timer expires */    gki_cb.com.OSNumOrigTicks = 0;    for (tt = 0; tt < GKI_MAX_TASKS; tt++)    {        gki_cb.com.OSWaitTmr   [tt] = 0;    }    return;}

timers相比buffer就简单多了,只有三个变量相关,如下:

/* Timer related variables */INT32   OSTicksTilExp;      /* Number of ticks till next timer expires */INT32   OSNumOrigTicks;     /* Number of ticks between last timer expiration to the next one */INT32   OSWaitTmr   [GKI_MAX_TASKS];  /* ticks the task has to wait, for specific events */

这里的初始化就是给他们都设为0而已。

再来看看alarm_service_init,如下:

static void alarm_service_init() {    alarm_service.ticks_scheduled = 0;    alarm_service.timer_started_us = 0;    alarm_service.timer_last_expired_us = 0;    alarm_service.wakelock = FALSE;    raise_priority_a2dp(TASK_JAVA_ALARM);}// Alarm service structure used to pass up via JNI to the bluetooth// app in order to create a wakeable Alarm.typedef struct{    UINT32 ticks_scheduled;    UINT64 timer_started_us;    UINT64 timer_last_expired_us;    bool wakelock;} alarm_service_t;

到这里gki初始化完成了,GKI_init是被谁调用的呢?是被bte_main.c中的bte_main_boot_entry调用的,如下:

/********************************************************************************** Function         bte_main_boot_entry**** Description      BTE MAIN API - Entry point for BTE chip/stack initialization**** Returns          None********************************************************************************/void bte_main_boot_entry(void){    /* initialize OS */    GKI_init();    bte_main_in_hw_init();    bte_load_conf(BTE_STACK_CONF_FILE);    bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE);    pthread_mutex_init(&cleanup_lock, NULL);}

bte_main_boot_entry又是被谁调用的呢?在btif_core.c的btif_init_bluetooth中,如下:

bt_status_t btif_init_bluetooth() {    UINT8 status;    btif_config_init();    bte_main_boot_entry();    /* As part of the init, fetch the local BD ADDR */    memset(&btif_local_bd_addr, 0, sizeof(bt_bdaddr_t));    btif_fetch_local_bdaddr(&btif_local_bd_addr);    /* start btif task */    status = GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR,                (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE),                sizeof(btif_task_stack));    if (status != GKI_SUCCESS)        return BT_STATUS_FAIL;    return BT_STATUS_SUCCESS;}

而btif_init_bluetooth又是被bluetooth.c中init函数调用的,而这个Init又是被谁调用的呢?在Bluetooth.c中如下:

static const bt_interface_t bluetoothInterface = {    sizeof(bluetoothInterface),    init,    enable,    disable,    cleanup,    get_adapter_properties,    get_adapter_property,    set_adapter_property,    get_remote_device_properties,    get_remote_device_property,    set_remote_device_property,    get_remote_service_record,    get_remote_services,    start_discovery,    cancel_discovery,    create_bond,    remove_bond,    cancel_bond,    get_connection_state,    pin_reply,    ssp_reply,    get_profile_interface,    dut_mode_configure,    dut_mode_send,#if BLE_INCLUDED == TRUE    le_test_mode,#else    NULL,#endif    config_hci_snoop_log,    set_os_callouts,    read_energy_info,};const bt_interface_t* bluetooth__get_bluetooth_interface (){    /* fixme -- add property to disable bt interface ? */    return &bluetoothInterface;}static int open_bluetooth_stack (const struct hw_module_t* module, char const* name,                                 struct hw_device_t** abstraction){    UNUSED(name);    bluetooth_device_t *stack = malloc(sizeof(bluetooth_device_t) );    memset(stack, 0, sizeof(bluetooth_device_t) );    stack->common.tag = HARDWARE_DEVICE_TAG;    stack->common.version = 0;    stack->common.module = (struct hw_module_t*)module;    stack->common.close = close_bluetooth_stack;    stack->get_bluetooth_interface = bluetooth__get_bluetooth_interface;    *abstraction = (struct hw_device_t*)stack;    return 0;}static struct hw_module_methods_t bt_stack_module_methods = {    .open = open_bluetooth_stack,};struct hw_module_t HAL_MODULE_INFO_SYM = {    .tag = HARDWARE_MODULE_TAG,    .version_major = 1,    .version_minor = 0,    .id = BT_HARDWARE_MODULE_ID,    .name = "Bluetooth Stack",    .author = "The Android Open Source Project",    .methods = &bt_stack_module_methods};

在com_android_bluetooth_btservice_AdapterService.cpp中初始化时有如下代码:

const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);err = hw_get_module(id, (hw_module_t const**) &module);if (err == 0) {    hw_device_t* abstraction;    err = module->methods->open(module, id, &abstraction);    if (err == 0) {        bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;        sBluetoothInterface = btStack->get_bluetooth_interface();    } else {       ALOGE("Error while opening Bluetooth library");    }}

这个sBluetoothInterface就是Bluetooth.c中的&bluetoothInterface,这里面有很多函数指针,当调用init时最终就会走到GKI_init。什么时候调用的呢?在initNative中,如下:

static bool initNative(JNIEnv* env, jobject obj) {    sJniAdapterServiceObj = env->NewGlobalRef(obj);    sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));    if (sBluetoothInterface) {        int ret = sBluetoothInterface->init(&sBluetoothCallbacks);        if (ret != BT_STATUS_SUCCESS) {            ALOGE("Error while setting the callbacks: %d\n", ret);            sBluetoothInterface = NULL;            return JNI_FALSE;        }        ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts);        if (ret != BT_STATUS_SUCCESS) {            ALOGE("Error while setting Bluetooth callouts: %d\n", ret);            sBluetoothInterface->cleanup();            sBluetoothInterface = NULL;            return JNI_FALSE;        }        if ( (sBluetoothSocketInterface = (btsock_interface_t *)                  sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {                ALOGE("Error getting socket interface");        }        return JNI_TRUE;    }    return JNI_FALSE;}

而这个InitNative是AdapterService.java中的native函数,如下:

private native boolean initNative();

该函数调用是在AdapterService的onCreate时,如下:

@Overridepublic void onCreate() {    super.onCreate();    debugLog("onCreate()");    mBinder = new AdapterServiceBinder(this);    mAdapterProperties = new AdapterProperties(this);    mAdapterStateMachine =  AdapterState.make(this, mAdapterProperties);    mJniCallbacks =  new JniCallbacks(mAdapterStateMachine, mAdapterProperties);    initNative();    mNativeAvailable=true;    mCallbacks = new RemoteCallbackList<IBluetoothCallback>();    //Load the name and address    getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR);    getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME);    mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);    mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);    mSdpManager = SdpManager.init(this);    registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP));    mProfileObserver = new ProfileObserver(getApplicationContext(), this, new Handler());    mProfileObserver.start();}

好了,GKI初始化的整个调用路径都搞清楚了,接下来看GKI_create_task是如何创建任务的,如下:

UINT8 GKI_create_task (TASKPTR task_entry, UINT8 task_id, INT8 *taskname, UINT16 *stack, UINT16 stacksize){    struct sched_param param;    int policy, ret = 0;    pthread_attr_t attr1;    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_condattr_t cond_attr;    pthread_condattr_init(&cond_attr);    pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);    pthread_mutex_init(&gki_cb.os.thread_evt_mutex[task_id], NULL);    pthread_cond_init (&gki_cb.os.thread_evt_cond[task_id], &cond_attr);    pthread_mutex_init(&gki_cb.os.thread_timeout_mutex[task_id], NULL);    pthread_cond_init (&gki_cb.os.thread_timeout_cond[task_id], NULL);    /* 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]);    return (GKI_SUCCESS);}

这里会创建一个线程执行gki_task_entry,我们看看这个线程入口函数,如下:

static 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);    /* Call the actual thread entry point */    (p_pthread_info->task_entry)(p_pthread_info->params);    pthread_exit(0);    /* GKI tasks have no return value */}

这里prctl用于给线程重命名,然后关键是执行线程的task_entry函数,这个task_entry是GKI_create_task时传入的回调。

我们再来看看哪里调用过了GKI_create_task,主要是两个地方,一个是btif_core.c中的btif_init_bluetooth,另一处是bte_main.c中的bte_main_enable。我们先看btif_init_bluetooth,因为这是初始化后创建的第一个task。

/* start btif task */status = GKI_create_task(btif_task, BTIF_TASK, BTIF_TASK_STR,            (UINT16 *) ((UINT8 *)btif_task_stack + BTIF_TASK_STACK_SIZE),            sizeof(btif_task_stack));

第一个参数是任务的入口函数,第二个是taskid,第三个是task名称,如下:

#define BTIF_TASK_STR        ((INT8 *) "BTIF")#define BTU_TASK                0#define BTIF_TASK               1#define A2DP_MEDIA_TASK         2

看来这个btif task是个蓝牙核心线程,如下:

static void btif_task(UINT32 params){    UINT16   event;    BT_HDR   *p_msg;    btif_associate_evt();    for(;;)    {        /* wait for specified events */        event = GKI_wait(0xFFFF, 0);        /*         * Wait for the trigger to init chip and stack. This trigger will         * be received by btu_task once the UART is opened and ready         */        if (event == BT_EVT_TRIGGER_STACK_INIT)        {            #if (BLE_INCLUDED == TRUE)            btif_dm_load_ble_local_keys();            #endif            BTA_EnableBluetooth(bte_dm_evt);        }        /*         * Failed to initialize controller hardware, reset state and bring         * down all threads         */        if (event == BT_EVT_HARDWARE_INIT_FAIL)        {            bte_main_disable();            btif_queue_release();            GKI_task_self_cleanup(BTIF_TASK);            bte_main_shutdown();            btif_dut_mode = 0;            btif_core_state = BTIF_CORE_STATE_DISABLED;            HAL_CBACK(bt_hal_cbacks,adapter_state_changed_cb,BT_STATE_OFF);            break;        }        if (event & EVENT_MASK(GKI_SHUTDOWN_EVT))            break;        if(event & TASK_MBOX_1_EVT_MASK)        {            while((p_msg = GKI_read_mbox(BTU_BTIF_MBOX)) != NULL)            {                switch (p_msg->event)                {                    case BT_EVT_CONTEXT_SWITCH_EVT:                        btif_context_switched(p_msg);                        break;                    default:                        BTIF_TRACE_ERROR("unhandled btif event (%d)", p_msg->event & BT_EVT_MASK);                        break;                }                GKI_freebuf(p_msg);            }        }    }    btif_disassociate_evt();}

这里在一个无限for循环中用GKI_wait等待事件,当遇到某些事件时break。接下来看看bte_main.c中的bte_main_enable,如下:

void bte_main_enable(){    /* Initialize BTE control block */    BTE_Init();    lpm_enabled = FALSE;    GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR,                    (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE),                    sizeof(bte_btu_stack));    bte_hci_enable();    GKI_run();}

原来BTU_TASK是在这里初始化的,看下入口函数btu_task,如下:

/*********************************************************************************** Function         btu_task**** Description      This is the main task of the Bluetooth Upper Layers unit.**                  It sits in a loop waiting for messages, and dispatches them**                  to the appropiate handlers.**** Returns          should never return*********************************************************************************/BTU_API UINT32 btu_task (UINT32 param){    UINT16           event;    BT_HDR          *p_msg;    UINT8            i;    UINT16           mask;    BOOLEAN          handled;    /* Initialize the mandatory core stack control blocks       (BTU, BTM, L2CAP, and SDP)     */    btu_init_core();    /* Initialize any optional stack components */    BTE_InitStack();    bta_sys_init();    /* Send a startup evt message to BTIF_TASK to kickstart the init procedure */    GKI_send_event(BTIF_TASK, BT_EVT_TRIGGER_STACK_INIT);    prctl(PR_SET_NAME, (unsigned long)"BTU TASK", 0, 0, 0);    raise_priority_a2dp(TASK_HIGH_BTU);    /* Wait for, and process, events */    for (;;)    {        event = GKI_wait (0xFFFF, 0);        if (event & TASK_MBOX_0_EVT_MASK)        {            /* Process all messages in the queue */            while ((p_msg = (BT_HDR *) GKI_read_mbox (BTU_HCI_RCV_MBOX)) != NULL)            {                /* Determine the input message type. */                switch (p_msg->event & BT_EVT_MASK)                {                }            }        }    }    return(0);}

这里省略了不少代码,可以看到BTU_TASK远比BTIF_TASK复杂,不过结构都一样,也是在一个loop里不停地GKI_wait获取event,然后处理event。从注释上看BTU是Bluetooth Upper Layers unit的意思。这里我们暂时不去看各种event的处理,只是了解整个底层GKI的架构。

我们注意到这里在进入loop之前做了一些初始化,先看btu_init_core,如下:

void btu_init_core(void){    /* Initialize the mandatory core stack components */    btm_init();    l2c_init();    sdp_init();#if BLE_INCLUDED == TRUE    gatt_init();#if (defined(SMP_INCLUDED) && SMP_INCLUDED == TRUE)    SMP_Init();#endif    btm_ble_init();#endif}

再往下看会调GKI_send_event(BTIF_TASK, BT_EVT_TRIGGER_STACK_INIT);向BTIF_TASK发送BT_EVT_TRIGGER_STACK_INIT这个event。我们来看GKI是如何发送消息的,如下:

/*********************************************************************************** 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){    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]);        return ( GKI_SUCCESS );    }    return (GKI_FAILURE);}

这里先给目标task的event锁锁上,然后或上该task等待的event,通知该task线程有新的event了,然后解锁返回。我们再看看GKI_wait是如何等待event的:

/*********************************************************************************** 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_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(&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", (int)rtask, (int)flag, (int)timeout, (int)evt);    return (evt);}

首先设置OSWaitForEvt,如果设置成0xFFFF就表示所有的事件都要关注,然后锁上thread_evt_mutex,看来这个锁是用来锁OSWaitEvt的,这个是收到的待处理的事件。如果没有事件待处理则清空OSWaitForEvt然后返回。如果有事件,如果需要超时等待,则调用pthread_cond_timedwait,否则调用pthread_cond_wait,则task会阻塞等信号。BTIF TASK和BTU TASK都是不用超时等待的。当有别的线程发event过来时会唤醒当前task,然后从OSWaitEvt中取出要处理的event。

接下来看GKI_send_msg,这和发送event有所区别,如下:

void GKI_send_msg (UINT8 task_id, UINT8 mbox, void *msg){    BUFFER_HDR_T    *p_hdr;    tGKI_COM_CB *p_cb = &gki_cb.com;    p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE);    GKI_disable();    if (p_cb->OSTaskQFirst[task_id][mbox])        p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;    else        p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;    p_cb->OSTaskQLast[task_id][mbox] = p_hdr;    p_hdr->p_next = NULL;    p_hdr->status = BUF_STATUS_QUEUED;    p_hdr->task_id = task_id;    GKI_enable();    GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox));    return;}

这里每个task都有若干个mailbox,每个mailbox下都有一个buffer队列,这里其实就是发送一个buffer挂载到对应task的对应box下的buffer队列上。然后发送一个事件通知该task有新的message了。

再来看task是如何读取这些message的,在GKI_read_mbox中,如下:

void *GKI_read_mbox (UINT8 mbox){    UINT8           task_id = GKI_get_taskid();    void            *p_buf = NULL;    BUFFER_HDR_T    *p_hdr;    GKI_disable();    if (gki_cb.com.OSTaskQFirst[task_id][mbox])    {        p_hdr = gki_cb.com.OSTaskQFirst[task_id][mbox];        gki_cb.com.OSTaskQFirst[task_id][mbox] = p_hdr->p_next;        p_hdr->p_next = NULL;        p_hdr->status = BUF_STATUS_UNLINKED;        p_buf = (UINT8 *)p_hdr + BUFFER_HDR_SIZE;    }    GKI_enable();    return (p_buf);}

值得注意的是每次发送或者读message都要对GKI全局mutex上锁,完毕后还要释放锁。这里读mbox其实就是从mbox的buffer队列里取下队列头返回。

0 0