DirectResult fusion_ref_zero_lock (FusionRef *ref) { DirectResult ret; D_ASSERT( ref != NULL ); ret = fusion_skirmish_prevail( &ref->multi.builtin.lock ); if (ret) return ret; if (ref->multi.builtin.call) { ret = DR_ACCESSDENIED; } else { if (ref->multi.builtin.local) _fusion_check_locals( _fusion_world(ref->multi.shared), ref ); while (ref->multi.builtin.local+ref->multi.builtin.global) { ret = fusion_skirmish_wait( &ref->multi.builtin.lock, 1000 ); /* 1 second */ if (ret && ret != DR_TIMEOUT); return ret; if (ref->multi.builtin.call) { ret = DR_ACCESSDENIED; break; } if (ref->multi.builtin.local) _fusion_check_locals( _fusion_world(ref->multi.shared), ref ); } } if (ret) fusion_skirmish_dismiss( &ref->multi.builtin.lock ); return ret; }
DFBResult dfb_core_create( CoreDFB **ret_core ) { int ret; #if FUSION_BUILD_MULTI char buf[16]; #endif CoreDFB *core = NULL; CoreDFBShared *shared = NULL; D_ASSERT( ret_core != NULL ); D_ASSERT( dfb_config != NULL ); D_DEBUG_AT( DirectFB_Core, "%s...\n", __FUNCTION__ ); pthread_mutex_lock( &core_dfb_lock ); D_ASSERT( core_dfb == NULL || core_dfb->refs > 0 ); if (core_dfb) { D_MAGIC_ASSERT( core_dfb, CoreDFB ); core_dfb->refs++; *ret_core = core_dfb; pthread_mutex_unlock( &core_dfb_lock ); return DFB_OK; } direct_initialize(); D_INFO( "DirectFB/Core: %s Application Core. ("BUILDTIME") %s%s\n", FUSION_BUILD_MULTI ? "Multi" : "Single", DIRECT_BUILD_DEBUG ? "[ DEBUG ]" : "", DIRECT_BUILD_TRACE ? "[ TRACE ]" : "" ); #if defined(DFB_DYNAMIC_LINKING) && defined(SOPATH) if (!dfb_lib_handle) #ifdef RTLD_GLOBAL dfb_lib_handle = dlopen(SOPATH, RTLD_GLOBAL|RTLD_LAZY); #else /* RTLD_GLOBAL is not defined on OpenBSD */ dfb_lib_handle = dlopen(SOPATH, RTLD_LAZY); #endif #endif ret = dfb_system_lookup(); if (ret) goto error; /* Allocate local core structure. */ core = D_CALLOC( 1, sizeof(CoreDFB) ); if (!core) { ret = D_OOM(); goto error; } core->refs = 1; core->init_handler = direct_thread_add_init_handler( dfb_core_thread_init_handler, core ); #if FUSION_BUILD_MULTI dfb_system_thread_init(); #endif direct_find_best_memcpy(); D_MAGIC_SET( core, CoreDFB ); core_dfb = core; ret = fusion_enter( dfb_config->session, DIRECTFB_CORE_ABI, FER_ANY, &core->world ); if (ret) goto error; core->fusion_id = fusion_id( core->world ); #if FUSION_BUILD_MULTI D_DEBUG_AT( DirectFB_Core, "world %d, fusion id %d\n", fusion_world_index(core->world), core->fusion_id ); snprintf( buf, sizeof(buf), "%d", fusion_world_index(core->world) ); setenv( "DIRECTFB_SESSION", buf, true ); #endif if (dfb_config->sync) { D_INFO( "DirectFB/Core: calling sync()...\n" ); direct_sync(); } if (dfb_config->core_sighandler) direct_signal_handler_add( DIRECT_SIGNAL_ANY, dfb_core_signal_handler, core, &core->signal_handler ); if (fusion_arena_enter( core->world, "DirectFB/Core", dfb_core_arena_initialize, dfb_core_arena_join, core, &core->arena, &ret ) || ret) { ret = ret ? ret : DFB_FUSION; goto error; } shared = core->shared; D_MAGIC_ASSERT( shared, CoreDFBShared ); if (dfb_config->block_all_signals) direct_signals_block_all(); if (dfb_config->deinit_check) direct_cleanup_handler_add( dfb_core_deinit_check, NULL, &core->cleanup_handler ); fusion_skirmish_prevail( &shared->lock ); if (!core->master) { while (!shared->active) fusion_skirmish_wait( &shared->lock, 0 ); } fusion_skirmish_dismiss( &shared->lock ); dfb_font_manager_create( core, &core->font_manager ); *ret_core = core; pthread_mutex_unlock( &core_dfb_lock ); D_DEBUG_AT( DirectFB_Core, "Core successfully created.\n" ); return DFB_OK; error: if (core) { if (core->world) fusion_exit( core->world, false ); if (core->init_handler) direct_thread_remove_init_handler( core->init_handler ); if (core->signal_handler) direct_signal_handler_remove( core->signal_handler ); D_MAGIC_CLEAR( core ); D_FREE( core ); core_dfb = NULL; } pthread_mutex_unlock( &core_dfb_lock ); direct_shutdown(); return ret; }