module.cc revision f8027005333c88a2f097cfd70d15c3d54c7764ae
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>
2472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
250f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/allocator.h"
260f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/hash_map.h"
2795b74f252f534ec757aab1fc08e086e02b2cfe8dSharvil Nanavati#include "btcore/include/module.h"
280f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/osi.h"
2905d0366413bedc16b4189b9e74395fe4b11ba41aZach Johnson#include "osi/include/hash_functions.h"
3044802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati#include "osi/include/log.h"
3172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
3272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsontypedef enum {
3372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  MODULE_STATE_NONE = 0,
3472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  MODULE_STATE_INITIALIZED = 1,
3572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  MODULE_STATE_STARTED = 2
3672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson} module_state_t;
3772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
3872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic const size_t number_of_metadata_buckets = 42;
3972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic hash_map_t *metadata;
4072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson// Include this lock for now for correctness, while the startup sequence is being refactored
4172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic pthread_mutex_t metadata_lock;
4272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
4372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic bool call_lifecycle_function(module_lifecycle_fn function);
4472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic module_state_t get_module_state(const module_t *module);
4572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic void set_module_state(const module_t *module, module_state_t state);
4672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
4772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonvoid module_management_start(void) {
4872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  metadata = hash_map_new(
4972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    number_of_metadata_buckets,
5072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    hash_function_pointer,
5172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    NULL,
52aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson    osi_free,
53aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson    NULL
5472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  );
5572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
5672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  pthread_mutex_init(&metadata_lock, NULL);
5772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson}
5872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
5972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonvoid module_management_stop(void) {
6072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  if (!metadata)
6172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    return;
6272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
6372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  hash_map_free(metadata);
6472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  metadata = NULL;
6572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
6672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  pthread_mutex_destroy(&metadata_lock);
6772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson}
6872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
6972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonconst module_t *get_module(const char *name) {
7072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  return (module_t *)dlsym(RTLD_DEFAULT, name);
7172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson}
7272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
7372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonbool module_init(const module_t *module) {
7472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(metadata != NULL);
7572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(module != NULL);
7672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(get_module_state(module) == MODULE_STATE_NONE);
7772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
7872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  if (!call_lifecycle_function(module->init)) {
7944802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati    LOG_ERROR("%s failed to initialize \"%s\"", __func__, module->name);
8072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    return false;
8172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  }
8272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
8372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  set_module_state(module, MODULE_STATE_INITIALIZED);
8472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  return true;
8572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson}
8672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
8772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonbool module_start_up(const module_t *module) {
8872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(metadata != NULL);
8972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(module != NULL);
9072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  // TODO(zachoverflow): remove module->init check once automagic order/call is in place.
9172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  // This hack is here so modules which don't require init don't have to have useless calls
9272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  // as we're converting the startup sequence.
9372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(get_module_state(module) == MODULE_STATE_INITIALIZED || module->init == NULL);
9472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
9572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  if (!call_lifecycle_function(module->start_up)) {
9644802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati    LOG_ERROR("%s failed to start up \"%s\"", __func__, module->name);
9772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    return false;
9872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  }
9972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
10072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  set_module_state(module, MODULE_STATE_STARTED);
10172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  return true;
10272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson}
10372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
10472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonvoid module_shut_down(const module_t *module) {
10572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(metadata != NULL);
10672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(module != NULL);
10772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  module_state_t state = get_module_state(module);
10872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(state <= MODULE_STATE_STARTED);
10972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
11072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  // Only something to do if the module was actually started
11172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  if (state < MODULE_STATE_STARTED)
11272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    return;
11372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
11472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  if (!call_lifecycle_function(module->shut_down))
11544802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati    LOG_ERROR("%s found \"%s\" reported failure during shutdown. Continuing anyway.", __func__, module->name);
11672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
11772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  set_module_state(module, MODULE_STATE_INITIALIZED);
11872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson}
11972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
12072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonvoid module_clean_up(const module_t *module) {
12172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(metadata != NULL);
12272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(module != NULL);
12372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  module_state_t state = get_module_state(module);
12472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  assert(state <= MODULE_STATE_INITIALIZED);
12572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
12672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  // Only something to do if the module was actually initialized
12772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  if (state < MODULE_STATE_INITIALIZED)
12872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    return;
12972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
13072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  if (!call_lifecycle_function(module->clean_up))
13144802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati    LOG_ERROR("%s found \"%s\" reported failure during cleanup. Continuing anyway.", __func__, module->name);
13272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
13372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  set_module_state(module, MODULE_STATE_NONE);
13472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson}
13572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
13672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic bool call_lifecycle_function(module_lifecycle_fn function) {
13772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  // A NULL lifecycle function means it isn't needed, so assume success
13872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  if (!function)
13972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    return true;
14072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
14172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  future_t *future = function();
14272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
14372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  // A NULL future means synchronous success
14472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  if (!future)
14572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    return true;
14672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
14772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  // Otherwise fall back to the future
14872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  return future_await(future);
14972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson}
15072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
15172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic module_state_t get_module_state(const module_t *module) {
15272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  pthread_mutex_lock(&metadata_lock);
15372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  module_state_t *state_ptr = hash_map_get(metadata, module);
15472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  pthread_mutex_unlock(&metadata_lock);
15572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
15672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  return state_ptr ? *state_ptr : MODULE_STATE_NONE;
15772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson}
15872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
15972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnsonstatic void set_module_state(const module_t *module, module_state_t state) {
16072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  pthread_mutex_lock(&metadata_lock);
16172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
16272f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  module_state_t *state_ptr = hash_map_get(metadata, module);
16372f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  if (!state_ptr) {
16472f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    state_ptr = osi_malloc(sizeof(module_state_t));
16572f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson    hash_map_set(metadata, module, state_ptr);
16672f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  }
16772f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
16872f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  pthread_mutex_unlock(&metadata_lock);
16972f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson
17072f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson  *state_ptr = state;
17172f308ee6d3983ae2c0d67be3de2451f2dd72dcbZach Johnson}
1723c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
1733c511e667e593c8ea594ca24b1d7712214245863Zach Johnson// TODO(zachoverflow): remove when everything modulized
1743c511e667e593c8ea594ca24b1d7712214245863Zach Johnson// Temporary callback-wrapper-related code
1753c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
1763c511e667e593c8ea594ca24b1d7712214245863Zach Johnsontypedef struct {
1773c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  const module_t *module;
1783c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  thread_t *lifecycle_thread;
1793c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  thread_t *callback_thread; // we don't own this thread
1803c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  thread_fn callback;
1813c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  bool success;
1823c511e667e593c8ea594ca24b1d7712214245863Zach Johnson} callbacked_wrapper_t;
1833c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
1843c511e667e593c8ea594ca24b1d7712214245863Zach Johnsonstatic void run_wrapped_start_up(void *context);
1853c511e667e593c8ea594ca24b1d7712214245863Zach Johnsonstatic void post_result_to_callback(void *context);
1863c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
1873c511e667e593c8ea594ca24b1d7712214245863Zach Johnsonvoid module_start_up_callbacked_wrapper(
1883c511e667e593c8ea594ca24b1d7712214245863Zach Johnson    const module_t *module,
1893c511e667e593c8ea594ca24b1d7712214245863Zach Johnson    thread_t *callback_thread,
1903c511e667e593c8ea594ca24b1d7712214245863Zach Johnson    thread_fn callback) {
1913c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  callbacked_wrapper_t *wrapper = osi_calloc(sizeof(callbacked_wrapper_t));
1923c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
1933c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  wrapper->module = module;
1943c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  wrapper->lifecycle_thread = thread_new("module_wrapper");
1953c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  wrapper->callback_thread = callback_thread;
1963c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  wrapper->callback = callback;
1973c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
1983c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  // Run the actual module start up
1993c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  thread_post(wrapper->lifecycle_thread, run_wrapped_start_up, wrapper);
2003c511e667e593c8ea594ca24b1d7712214245863Zach Johnson}
2013c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
2023c511e667e593c8ea594ca24b1d7712214245863Zach Johnsonstatic void run_wrapped_start_up(void *context) {
2033c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  assert(context);
2043c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
2053c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  callbacked_wrapper_t *wrapper = context;
2063c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  wrapper->success = module_start_up(wrapper->module);
2073c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
2083c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  // Post the result back to the callback
2093c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  thread_post(wrapper->callback_thread, post_result_to_callback, wrapper);
2103c511e667e593c8ea594ca24b1d7712214245863Zach Johnson}
2113c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
2123c511e667e593c8ea594ca24b1d7712214245863Zach Johnsonstatic void post_result_to_callback(void *context) {
2133c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  assert(context);
2143c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
2153c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  callbacked_wrapper_t *wrapper = context;
2163c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
2173c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  // Save the values we need for callback
2183c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  void *result = wrapper->success ? FUTURE_SUCCESS : FUTURE_FAIL;
2193c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  thread_fn callback = wrapper->callback;
2203c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
2213c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  // Clean up the resources we used
2223c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  thread_stop(wrapper->lifecycle_thread);
2233c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  osi_free(wrapper);
2243c511e667e593c8ea594ca24b1d7712214245863Zach Johnson
2253c511e667e593c8ea594ca24b1d7712214245863Zach Johnson  callback(result);
2263c511e667e593c8ea594ca24b1d7712214245863Zach Johnson}
227