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; }
int fusion_init( int world, int abi_version, int *world_ret ) { char buf[20]; FusionEnter enter; /* Check against multiple initialization. */ if (_fusion_id) { /* Increment local reference counter. */ fusion_refs++; return _fusion_id; } direct_initialize(); /* Open Fusion Kernel Device. */ if (world < 0) { for (world=0; world<256; world++) { snprintf( buf, sizeof(buf), "/dev/fusion/%d", world ); _fusion_fd = open (buf, O_RDWR | O_NONBLOCK | O_EXCL); if (_fusion_fd < 0) { if (errno == EBUSY) continue; D_PERROR( "Fusion/Init: opening '%s' failed!\n", buf ); direct_shutdown(); return -1; } else break; } } else { snprintf( buf, sizeof(buf), "/dev/fusion/%d", world ); _fusion_fd = open (buf, O_RDWR | O_NONBLOCK); if (_fusion_fd < 0) { D_PERROR( "Fusion/Init: opening '%s' failed!\n", buf ); direct_shutdown(); return -1; } } enter.api.major = FUSION_API_MAJOR; enter.api.minor = FUSION_API_MINOR; enter.fusion_id = 0; /* Get our Fusion ID. */ if (ioctl( _fusion_fd, FUSION_ENTER, &enter )) { D_PERROR( "Fusion/Init: FUSION_ENTER failed!\n" ); goto error; } if (!enter.fusion_id) { D_ERROR( "Fusion/Init: Got no ID from FUSION_ENTER! Kernel module might be too old.\n" ); goto error; } _fusion_id = enter.fusion_id; /* Initialize local reference counter. */ fusion_refs = 1; /* Initialize shmalloc part. */ if (!__shmalloc_init( world, _fusion_id == 1 )) { D_ERROR( "Fusion/Init: Shared memory initialization failed.\n" "\n" "Please make sure that a tmpfs mount point with at least 4MB of free space\n" "is available for read/write, see the DirectFB README for more instructions.\n" ); goto error; } if (_fusion_id == 1) { _fusion_shared = __shmalloc_allocate_root( sizeof(FusionShared) ); _fusion_shared->abi_version = abi_version; fusion_skirmish_init( &_fusion_shared->arenas_lock, "Fusion Arenas" ); fusion_skirmish_init( &_fusion_shared->reactor_globals, "Fusion Reactor Globals" ); _sheap->reactor = fusion_reactor_new( sizeof(long), "Shared Memory Heap" ); if (!_sheap->reactor) { __shmalloc_exit( true, true ); goto error_reactor; } gettimeofday( &_fusion_shared->start_time, NULL ); } else { _fusion_shared = __shmalloc_get_root(); if (_fusion_shared->abi_version != abi_version) { D_ERROR( "Fusion/Init: ABI version mismatch (my: %d, their: %d)\n", abi_version, _fusion_shared->abi_version ); __shmalloc_exit( false, false ); goto error; } } __shmalloc_attach(); direct_clock_set_start( &_fusion_shared->start_time ); direct_signal_handler_add( SIGSEGV, fusion_signal_handler, NULL, &signal_handler ); read_loop = direct_thread_create( DTT_MESSAGING, fusion_read_loop, NULL, "Fusion Dispatch" ); if (world_ret) *world_ret = world; return _fusion_id; error_reactor: fusion_skirmish_destroy( &_fusion_shared->arenas_lock ); fusion_skirmish_destroy( &_fusion_shared->reactor_globals ); error: _fusion_shared = NULL; _fusion_id = 0; close( _fusion_fd ); _fusion_fd = -1; direct_shutdown(); return -1; }