module.cc revision d1e2206a9e0798e01dc18d7c7309d19f74fca9a9
172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson/****************************************************************************** 272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * 372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * Copyright (C) 2014 Google, Inc. 472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * 572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * Licensed under the Apache License, Version 2.0 (the "License"); 672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * you may not use this file except in compliance with the License. 772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * You may obtain a copy of the License at: 872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * 972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * http://www.apache.org/licenses/LICENSE-2.0 1072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * 1172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * Unless required by applicable law or agreed to in writing, software 1272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * distributed under the License is distributed on an "AS IS" BASIS, 1372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * See the License for the specific language governing permissions and 1572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * limitations under the License. 1672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson * 1772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson ******************************************************************************/ 1872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 19f8027005333c88a2f097cfd70d15c3d54c7764aeChris Manton#define LOG_TAG "bt_core_module" 2072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 2172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson#include <assert.h> 2272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson#include <dlfcn.h> 2372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson#include <pthread.h> 24d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen#include <string.h> 2572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 260f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/allocator.h" 270f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/hash_map.h" 2895b74f252f534ec757aab1fc08e086e02b2cfe8dSharvil Nanavati#include "btcore/include/module.h" 290f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/osi.h" 3005d0366413bedc16b4189b9e74395fe4b11ba41aZach Johnson#include "osi/include/hash_functions.h" 3144802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati#include "osi/include/log.h" 3272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 3372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsontypedef enum { 3472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson MODULE_STATE_NONE = 0, 3572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson MODULE_STATE_INITIALIZED = 1, 3672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson MODULE_STATE_STARTED = 2 3772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} module_state_t; 3872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 3972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic const size_t number_of_metadata_buckets = 42; 4072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic hash_map_t *metadata; 4172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson// Include this lock for now for correctness, while the startup sequence is being refactored 4272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic pthread_mutex_t metadata_lock; 4372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 4472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic bool call_lifecycle_function(module_lifecycle_fn function); 4572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic module_state_t get_module_state(const module_t *module); 4672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic void set_module_state(const module_t *module, module_state_t state); 4772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 4872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonvoid module_management_start(void) { 4972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson metadata = hash_map_new( 5072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson number_of_metadata_buckets, 5172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson hash_function_pointer, 5272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson NULL, 53aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson osi_free, 54aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson NULL 5572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson ); 5672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 5772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson pthread_mutex_init(&metadata_lock, NULL); 5872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} 5972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 6072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonvoid module_management_stop(void) { 6172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson if (!metadata) 6272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return; 6372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 6472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson hash_map_free(metadata); 6572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson metadata = NULL; 6672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 6772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson pthread_mutex_destroy(&metadata_lock); 6872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} 6972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 70d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen/* TODO: remove these externs and explicit checks once dlsym is fixed */ 71d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohenextern module_t bt_utils_module; 72d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohenextern module_t btif_config_module; 73d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohenextern module_t controller_module; 74d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohenextern module_t gki_module; 75d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohenextern module_t counter_module; 76d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohenextern module_t stack_config_module; 77d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohenextern module_t btsnoop_module; 78d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohenextern module_t hci_module; 79d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohenextern module_t bte_logmsg_module; 80d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen 8172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonconst module_t *get_module(const char *name) { 82d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen module_t* module = (module_t *)dlsym(RTLD_DEFAULT, name); 83d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen if (module) return module; 84d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen 85d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen if (!strcmp(name, "bt_utils_module")) return &bt_utils_module; 86d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen if (!strcmp(name, "btif_config_module")) return &btif_config_module; 87d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen if (!strcmp(name, "controller_module")) return &controller_module; 88d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen if (!strcmp(name, "gki_module")) return &gki_module; 89d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen if (!strcmp(name, "counter_module")) return &counter_module; 90d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen if (!strcmp(name, "stack_config_module")) return &stack_config_module; 91d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen if (!strcmp(name, "btsnoop_module")) return &btsnoop_module; 92d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen if (!strcmp(name, "hci_module")) return &hci_module; 93d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen if (!strcmp(name, "bte_logmsg_module")) return &bte_logmsg_module; 94d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen 95d1e2206a9e0798e01dc18d7c7309d19f74fca9a9Etan Cohen return NULL; 9672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} 9772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 9872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonbool module_init(const module_t *module) { 9972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(metadata != NULL); 10072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(module != NULL); 10172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(get_module_state(module) == MODULE_STATE_NONE); 10272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 10372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson if (!call_lifecycle_function(module->init)) { 10444802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati LOG_ERROR("%s failed to initialize \"%s\"", __func__, module->name); 10572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return false; 10672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson } 10772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 10872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson set_module_state(module, MODULE_STATE_INITIALIZED); 10972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return true; 11072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} 11172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 11272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonbool module_start_up(const module_t *module) { 11372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(metadata != NULL); 11472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(module != NULL); 11572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson // TODO(zachoverflow): remove module->init check once automagic order/call is in place. 11672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson // This hack is here so modules which don't require init don't have to have useless calls 11772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson // as we're converting the startup sequence. 11872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(get_module_state(module) == MODULE_STATE_INITIALIZED || module->init == NULL); 11972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 12072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson if (!call_lifecycle_function(module->start_up)) { 12144802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati LOG_ERROR("%s failed to start up \"%s\"", __func__, module->name); 12272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return false; 12372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson } 12472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 12572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson set_module_state(module, MODULE_STATE_STARTED); 12672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return true; 12772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} 12872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 12972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonvoid module_shut_down(const module_t *module) { 13072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(metadata != NULL); 13172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(module != NULL); 13272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson module_state_t state = get_module_state(module); 13372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(state <= MODULE_STATE_STARTED); 13472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 13572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson // Only something to do if the module was actually started 13672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson if (state < MODULE_STATE_STARTED) 13772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return; 13872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 13972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson if (!call_lifecycle_function(module->shut_down)) 14044802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati LOG_ERROR("%s found \"%s\" reported failure during shutdown. Continuing anyway.", __func__, module->name); 14172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 14272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson set_module_state(module, MODULE_STATE_INITIALIZED); 14372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} 14472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 14572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonvoid module_clean_up(const module_t *module) { 14672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(metadata != NULL); 14772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(module != NULL); 14872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson module_state_t state = get_module_state(module); 14972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson assert(state <= MODULE_STATE_INITIALIZED); 15072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 15172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson // Only something to do if the module was actually initialized 15272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson if (state < MODULE_STATE_INITIALIZED) 15372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return; 15472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 15572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson if (!call_lifecycle_function(module->clean_up)) 15644802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati LOG_ERROR("%s found \"%s\" reported failure during cleanup. Continuing anyway.", __func__, module->name); 15772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 15872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson set_module_state(module, MODULE_STATE_NONE); 15972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} 16072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 16172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic bool call_lifecycle_function(module_lifecycle_fn function) { 16272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson // A NULL lifecycle function means it isn't needed, so assume success 16372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson if (!function) 16472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return true; 16572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 16672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson future_t *future = function(); 16772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 16872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson // A NULL future means synchronous success 16972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson if (!future) 17072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return true; 17172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 17272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson // Otherwise fall back to the future 17372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return future_await(future); 17472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} 17572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 17672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic module_state_t get_module_state(const module_t *module) { 17772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson pthread_mutex_lock(&metadata_lock); 17872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson module_state_t *state_ptr = hash_map_get(metadata, module); 17972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson pthread_mutex_unlock(&metadata_lock); 18072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 18172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson return state_ptr ? *state_ptr : MODULE_STATE_NONE; 18272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} 18372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 18472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic void set_module_state(const module_t *module, module_state_t state) { 18572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson pthread_mutex_lock(&metadata_lock); 18672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 18772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson module_state_t *state_ptr = hash_map_get(metadata, module); 18872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson if (!state_ptr) { 18972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson state_ptr = osi_malloc(sizeof(module_state_t)); 19072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson hash_map_set(metadata, module, state_ptr); 19172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson } 19272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 19372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson pthread_mutex_unlock(&metadata_lock); 19472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson 19572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson *state_ptr = state; 19672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} 1973c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 1983c511e667e593c8ea594ca24b1d7712214245863Zach Johnson// TODO(zachoverflow): remove when everything modulized 1993c511e667e593c8ea594ca24b1d7712214245863Zach Johnson// Temporary callback-wrapper-related code 2003c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2013c511e667e593c8ea594ca24b1d7712214245863Zach Johnsontypedef struct { 2023c511e667e593c8ea594ca24b1d7712214245863Zach Johnson const module_t *module; 2033c511e667e593c8ea594ca24b1d7712214245863Zach Johnson thread_t *lifecycle_thread; 2043c511e667e593c8ea594ca24b1d7712214245863Zach Johnson thread_t *callback_thread; // we don't own this thread 2053c511e667e593c8ea594ca24b1d7712214245863Zach Johnson thread_fn callback; 2063c511e667e593c8ea594ca24b1d7712214245863Zach Johnson bool success; 2073c511e667e593c8ea594ca24b1d7712214245863Zach Johnson} callbacked_wrapper_t; 2083c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2093c511e667e593c8ea594ca24b1d7712214245863Zach Johnsonstatic void run_wrapped_start_up(void *context); 2103c511e667e593c8ea594ca24b1d7712214245863Zach Johnsonstatic void post_result_to_callback(void *context); 2113c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2123c511e667e593c8ea594ca24b1d7712214245863Zach Johnsonvoid module_start_up_callbacked_wrapper( 2133c511e667e593c8ea594ca24b1d7712214245863Zach Johnson const module_t *module, 2143c511e667e593c8ea594ca24b1d7712214245863Zach Johnson thread_t *callback_thread, 2153c511e667e593c8ea594ca24b1d7712214245863Zach Johnson thread_fn callback) { 2163c511e667e593c8ea594ca24b1d7712214245863Zach Johnson callbacked_wrapper_t *wrapper = osi_calloc(sizeof(callbacked_wrapper_t)); 2173c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2183c511e667e593c8ea594ca24b1d7712214245863Zach Johnson wrapper->module = module; 2193c511e667e593c8ea594ca24b1d7712214245863Zach Johnson wrapper->lifecycle_thread = thread_new("module_wrapper"); 2203c511e667e593c8ea594ca24b1d7712214245863Zach Johnson wrapper->callback_thread = callback_thread; 2213c511e667e593c8ea594ca24b1d7712214245863Zach Johnson wrapper->callback = callback; 2223c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2233c511e667e593c8ea594ca24b1d7712214245863Zach Johnson // Run the actual module start up 2243c511e667e593c8ea594ca24b1d7712214245863Zach Johnson thread_post(wrapper->lifecycle_thread, run_wrapped_start_up, wrapper); 2253c511e667e593c8ea594ca24b1d7712214245863Zach Johnson} 2263c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2273c511e667e593c8ea594ca24b1d7712214245863Zach Johnsonstatic void run_wrapped_start_up(void *context) { 2283c511e667e593c8ea594ca24b1d7712214245863Zach Johnson assert(context); 2293c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2303c511e667e593c8ea594ca24b1d7712214245863Zach Johnson callbacked_wrapper_t *wrapper = context; 2313c511e667e593c8ea594ca24b1d7712214245863Zach Johnson wrapper->success = module_start_up(wrapper->module); 2323c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2333c511e667e593c8ea594ca24b1d7712214245863Zach Johnson // Post the result back to the callback 2343c511e667e593c8ea594ca24b1d7712214245863Zach Johnson thread_post(wrapper->callback_thread, post_result_to_callback, wrapper); 2353c511e667e593c8ea594ca24b1d7712214245863Zach Johnson} 2363c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2373c511e667e593c8ea594ca24b1d7712214245863Zach Johnsonstatic void post_result_to_callback(void *context) { 2383c511e667e593c8ea594ca24b1d7712214245863Zach Johnson assert(context); 2393c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2403c511e667e593c8ea594ca24b1d7712214245863Zach Johnson callbacked_wrapper_t *wrapper = context; 2413c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2423c511e667e593c8ea594ca24b1d7712214245863Zach Johnson // Save the values we need for callback 2433c511e667e593c8ea594ca24b1d7712214245863Zach Johnson void *result = wrapper->success ? FUTURE_SUCCESS : FUTURE_FAIL; 2443c511e667e593c8ea594ca24b1d7712214245863Zach Johnson thread_fn callback = wrapper->callback; 2453c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2463c511e667e593c8ea594ca24b1d7712214245863Zach Johnson // Clean up the resources we used 2473c511e667e593c8ea594ca24b1d7712214245863Zach Johnson thread_stop(wrapper->lifecycle_thread); 2483c511e667e593c8ea594ca24b1d7712214245863Zach Johnson osi_free(wrapper); 2493c511e667e593c8ea594ca24b1d7712214245863Zach Johnson 2503c511e667e593c8ea594ca24b1d7712214245863Zach Johnson callback(result); 2513c511e667e593c8ea594ca24b1d7712214245863Zach Johnson} 252