Beispiel #1
0
DirectResult
fusion_call_init (FusionCall        *call,
                  FusionCallHandler  handler,
                  void              *ctx,
                  const FusionWorld *world)
{
     D_ASSERT( call != NULL );
     D_ASSERT( handler != NULL );
     D_MAGIC_ASSERT( world, FusionWorld );
     D_MAGIC_ASSERT( world->shared, FusionWorldShared );

     memset( call, 0, sizeof(FusionCall) );

     call->call_id = ++world->shared->call_ids;

     /* Store handler, called directly when called by ourself. */
     call->handler = handler;
     call->ctx     = ctx;

     /* Store own fusion id. */
     call->fusion_id = fusion_id( world );

     /* Keep back pointer to shared world data. */
     call->shared = world->shared;

     return DR_OK;
}
Beispiel #2
0
DirectResult
fusion_ref_init (FusionRef         *ref,
                 const char        *name,
                 const FusionWorld *world)
{
     D_ASSERT( ref != NULL );
     D_ASSERT( name != NULL );
     D_MAGIC_ASSERT( world, FusionWorld );

     D_DEBUG_AT( Fusion_Ref, "fusion_ref_init( %p, '%s' )\n", ref, name ? : "" );
     
     ref->multi.id = ++world->shared->ref_ids;
     
     ref->multi.builtin.local  = 0;
     ref->multi.builtin.global = 0;
     
     fusion_skirmish_init( &ref->multi.builtin.lock, name, world );
     
     ref->multi.builtin.call = NULL;

     /* Keep back pointer to shared world data. */
     ref->multi.shared  = world->shared;
     ref->multi.creator = fusion_id( world );

     return DR_OK;
}
Beispiel #3
0
static ReactionResult
reaction_callback( const void *msg_data,
                   void       *ctx )
{
     MSG( "Received message (FusionID %lu, pid %d)!\n", fusion_id( m_world ), getpid() );

     return RS_REMOVE;
}
Beispiel #4
0
static FusionCallHandlerResult
dispatch_callback (int           caller,
                   int           call_arg,
                   void         *call_ptr,
                   void         *ctx,
                   unsigned int  serial,
                   int          *ret_val )
{
     MSG( "Got dispatch callback (FusionID %lu, pid %d)!\n", fusion_id( m_world ), getpid() );

     return FCHR_RETURN;
}
Beispiel #5
0
DirectResult
fusion_call_init3 (FusionCall         *call,
                   FusionCallHandler3  handler3,
                   void               *ctx,
                   const FusionWorld  *world)
{
     FusionCallNew call_new;

     if (direct_log_domain_check( &Fusion_Call )) // avoid call to direct_trace_lookup_symbol_at
          D_DEBUG_AT( Fusion_Call, "%s( %p, %p <%s>, %p, %p )\n", __FUNCTION__, call, handler3,
                      direct_trace_lookup_symbol_at( handler3 ), ctx, world );

     D_ASSERT( call != NULL );
     D_ASSERT( handler3 != NULL );
     D_MAGIC_ASSERT( world, FusionWorld );
     D_MAGIC_ASSERT( world->shared, FusionWorldShared );

     /* Called from others. */
     call_new.handler = handler3;
     call_new.ctx     = ctx;

     while (ioctl( world->fusion_fd, FUSION_CALL_NEW, &call_new )) {
          switch (errno) {
               case EINTR:
                    continue;
               default:
                    break;
          }

          D_PERROR ("FUSION_CALL_NEW");

          return DR_FAILURE;
     }

     memset( call, 0, sizeof(FusionCall) );

     /* Store handler, called directly when called by ourself. */
     call->handler3 = handler3;
     call->ctx      = ctx;

     /* Store call and own fusion id. */
     call->call_id   = call_new.call_id;
     call->fusion_id = fusion_id( world );

     /* Keep back pointer to shared world data. */
     call->shared = world->shared;

     D_DEBUG_AT( Fusion_Call, "  -> call id %d\n", call->call_id );

     return DR_OK;
}
Beispiel #6
0
DirectResult
coma_thread_init( ComaThread *thread,
                  Coma       *coma )
{
     FusionWorld *world;

     D_ASSERT( thread != NULL );
     D_ASSERT( coma != NULL );

     D_DEBUG_AT( Coma_Thread, "%s( %p, %p )\n", __FUNCTION__, thread, coma );

     world = coma_world( coma );

     thread->shmpool = coma_shmpool( coma );

     /* Remember creator. */
     thread->fusion_id = fusion_id( world );

     D_MAGIC_SET( thread, ComaThread );

     return DR_OK;
}
Beispiel #7
0
int
dfb_state_init( CardState *state, CoreDFB *core )
{
     D_ASSERT( state != NULL );

     memset( state, 0, sizeof(CardState) );

     state->core           = core;
     state->fusion_id      = fusion_id( dfb_core_world(core) );
     state->modified       = SMF_ALL;
     state->src_blend      = DSBF_SRCALPHA;
     state->dst_blend      = DSBF_INVSRCALPHA;
     state->render_options = dfb_config->render_options;

     state->matrix[0] = 0x10000; 
     state->matrix[1] = 0x00000; 
     state->matrix[2] = 0x00000;
     state->matrix[3] = 0x00000; 
     state->matrix[4] = 0x10000; 
     state->matrix[5] = 0x00000;
     state->matrix[6] = 0x00000; 
     state->matrix[7] = 0x00000; 
     state->matrix[8] = 0x10000;
     state->affine_matrix = DFB_TRUE;

     state->from      = CSBR_FRONT;
     state->to        = CSBR_BACK;

     direct_util_recursive_pthread_mutex_init( &state->lock );

     direct_serial_init( &state->dst_serial );
     direct_serial_init( &state->src_serial );
     direct_serial_init( &state->src_mask_serial );
     direct_serial_init( &state->src2_serial );

     D_MAGIC_SET( state, CardState );

     return 0;
}
Beispiel #8
0
DirectResult
fusion_ref_init (FusionRef         *ref,
                 const char        *name,
                 const FusionWorld *world)
{
     FusionEntryInfo info;

     D_ASSERT( ref != NULL );
     D_ASSERT( name != NULL );
     D_MAGIC_ASSERT( world, FusionWorld );

     D_DEBUG_AT( Fusion_Ref, "fusion_ref_init( %p, '%s' )\n", ref, name ? : "" );

     while (ioctl( world->fusion_fd, FUSION_REF_NEW, &ref->multi.id )) {
          if (errno == EINTR)
               continue;

          D_PERROR( "FUSION_REF_NEW" );
          return DR_FUSION;
     }

     D_DEBUG_AT( Fusion_Ref, "  -> new ref %p [%d]\n", ref, ref->multi.id );

     info.type = FT_REF;
     info.id   = ref->multi.id;

     direct_snputs( info.name, name, sizeof(info.name) );

     ioctl( world->fusion_fd, FUSION_ENTRY_SET_INFO, &info );

     /* Keep back pointer to shared world data. */
     ref->multi.shared  = world->shared;
     ref->multi.creator = fusion_id( world );

     return DR_OK;
}
Beispiel #9
0
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;
}
Beispiel #10
0
DirectResult
fusion_call_execute3(FusionCall          *call,
                     FusionCallExecFlags  flags,
                     int                  call_arg,
                     void                *ptr,
                     unsigned int         length,
                     void                *ret_ptr,
                     unsigned int         ret_size,
                     unsigned int        *ret_length)
{
     FusionWorld *world;
     CallTLS     *call_tls;

     D_DEBUG_AT( Fusion_Call, "%s( %p, flags 0x%x, arg %d, ptr %p, length %u, ret_ptr %p, ret_size %u )\n",
                 __FUNCTION__, call, flags, call_arg, ptr, length, ret_ptr, ret_size );

     if (ret_size > FUSION_CALL_RETURN_DATA_MAX)
          return DR_LIMITEXCEEDED;

     D_ASSERT( call != NULL );

//     if (!call->handler)
//          return DR_DESTROYED;

#if D_DEBUG_ENABLED
     if (direct_log_domain_check( &Fusion_Call )) // avoid call to direct_trace_lookup_symbol_at
          D_DEBUG_AT( Fusion_Call, "  -> %s\n", direct_trace_lookup_symbol_at( call->handler3 ) );
#endif

     world = _fusion_world( call->shared );

     call_tls = Call_GetTLS( world );

     if (call->fusion_id == fusion_id( world ) &&
         (!(flags & FCEF_NODIRECT) || (call_tls->dispatcher)))
     {
          FusionCallHandlerResult result;
          unsigned int            execute_length;

          D_ASSERT( call->handler3 != NULL );

          result = call->handler3( call->fusion_id, call_arg, ptr, length, call->ctx, 0, ret_ptr, ret_size, &execute_length );

          if (result != FCHR_RETURN)
               D_WARN( "local call handler returned FCHR_RETAIN, need FCEF_NODIRECT" );

          if (ret_length)
               *ret_length = execute_length;
     }
     else {
          FusionCallExecute3  execute;
          DirectResult        ret   = DR_OK;

          // check whether we can cache this call
          if (flags & FCEF_QUEUE && fusion_config->call_bin_max_num > 0) {
               D_ASSERT( flags & FCEF_ONEWAY );

               if (call_tls->bins_data_len + length > fusion_config->call_bin_max_data) {
                    ret = fusion_world_flush_calls( world, 0 );
                    if (ret)
                         return ret;
               }

               call_tls->bins[call_tls->bins_num].call_id    = call->call_id;
               call_tls->bins[call_tls->bins_num].call_arg   = call_arg;
               call_tls->bins[call_tls->bins_num].ptr        = NULL;
               call_tls->bins[call_tls->bins_num].length     = length;
               call_tls->bins[call_tls->bins_num].ret_ptr    = ret_ptr;
               call_tls->bins[call_tls->bins_num].ret_length = ret_size;
               call_tls->bins[call_tls->bins_num].flags      = flags | FCEF_FOLLOW;

               if (length > 0) {
                    call_tls->bins[call_tls->bins_num].ptr = &call_tls->bins_data[call_tls->bins_data_len];
                    direct_memcpy( &call_tls->bins_data[call_tls->bins_data_len], ptr, length );
                    call_tls->bins_data_len += length;
               }

               call_tls->bins_num++;

               if (call_tls->bins_num == 1)
                    call_tls->bins_create_ts = direct_clock_get_millis();
               else if (call_tls->bins_num >= fusion_config->call_bin_max_num || direct_clock_get_millis() - call_tls->bins_create_ts >= EXECUTE3_BIN_FLUSH_MILLIS)
                    ret = fusion_world_flush_calls( world, 0 );    

               return ret;
          }

          ret = fusion_world_flush_calls( world, 1 );

          execute.call_id    = call->call_id;
          execute.call_arg   = call_arg;
          execute.ptr        = ptr;
          execute.length     = length;
          execute.ret_ptr    = ret_ptr;
          execute.ret_length = ret_size;
          execute.flags      = flags | FCEF_RESUMABLE;
          execute.serial     = 0;

          D_DEBUG_AT( Fusion_Call, "  -> ptr %p, length %u\n", ptr, length );

          while (ioctl( world->fusion_fd, FUSION_CALL_EXECUTE3, &execute )) {
               switch (errno) {
                    case EINTR:
                         continue;
                    case EINVAL:
                         D_ERROR ("Fusion/Call: invalid call (id 0x%08x)\n", call->call_id);
                         return DR_INVARG;
                    case EIDRM:
                         return DR_DESTROYED;
                    default:
                         break;
               }

               D_PERROR ("FUSION_CALL_EXECUTE3 (call id 0x%08x, creator %lu)", call->call_id, call->fusion_id );

               return DR_FAILURE;
          }

          if (ret_length)
               *ret_length = execute.ret_length;
     }

     return DR_OK;
}
Beispiel #11
0
int
main( int argc, char *argv[] )
{
     DirectResult   ret;
     pid_t          child_pid;
     TestMessage    message = {0};
     FusionReactor *reactor;
     Reaction       reaction;
     FusionCall     call;

     DirectFBInit( &argc, &argv );

     ret = fusion_enter( -1, 0, FER_MASTER, &m_world );
     if (ret) {
          D_DERROR( ret, "fusion_enter() failed" );
          return ret;
     }

     MSG( "Entered world %d as master (FusionID %lu, pid %d)\n",
          fusion_world_index( m_world ), fusion_id( m_world ), getpid() );


     reactor = fusion_reactor_new( sizeof(TestMessage), "Test", m_world );
     if (!reactor) {
          D_ERROR( "fusion_reactor_new() failed\n" );
          return -1;
     }


     MSG( "Attaching to reactor...\n" );

     ret = fusion_reactor_attach( reactor, reaction_callback, NULL, &reaction );
     if (ret) {
          D_DERROR( ret, "fusion_reactor_attach() failed" );
          return ret;
     }


     MSG( ".........FORKING NOW.........\n" );

     fusion_world_set_fork_action( m_world, FFA_FORK );
     child_pid = fork();
     fusion_world_set_fork_action( m_world, FFA_CLOSE );

     switch (child_pid) {
          case -1:
               D_PERROR( "fork() failed" );
               break;

          case 0:
               setsid();
               MSG( "...arrived after fork() in child (pid %d)..\n", getpid() );
               MSG( "..child (FusionID %lu).\n", fusion_id( m_world ) );
               usleep( 400000 );
               break;

          default:
               usleep( 100000 );
               MSG( "...returned from fork() in parent, child pid %d.\n", child_pid );

               MSG( "Initializing dispatch callback...\n" );

               ret = fusion_call_init( &call, dispatch_callback, NULL, m_world );
               if (ret) {
                    D_DERROR( ret, "fusion_call_init() failed" );
                    return ret;
               }

               MSG( "Setting dispatch callback...\n" );

               ret = fusion_reactor_set_dispatch_callback( reactor, &call, NULL );
               if (ret) {
                    D_DERROR( ret, "fusion_reactor_set_dispatch_callback() failed" );
                    return ret;
               }


               MSG( "Sending message via reactor...\n" );
               fusion_reactor_dispatch( reactor, &message, true, NULL );

               usleep( 100000 );

               MSG( "Destroying reactor...\n" );
               fusion_reactor_destroy( reactor );
               MSG( "...destroyed reactor!\n" );

               usleep( 400000 );

               MSG( "Freeing reactor...\n" );
               fusion_reactor_free( reactor );
               MSG( "...freed reactor!\n" );

               break;
     }



     MSG( "Exiting from world %d (FusionID %lu, pid %d)...\n",
          fusion_world_index( m_world ), fusion_id( m_world ), getpid() );

     fusion_exit( m_world, false );

     return 0;
}
Beispiel #12
0
int
main( int argc, char *argv[] )
{
     DirectResult ret;
     pid_t        child_pid;
     TestMessage  message = {0};

     DirectFBInit( &argc, &argv );

     ret = fusion_enter( -1, 0, FER_MASTER, &m_world );
     if (ret) {
          D_DERROR( ret, "fusion_enter() failed" );
          return ret;
     }

     MSG( "Entered world %d as master (FusionID %lu, pid %d)\n",
          fusion_world_index( m_world ), fusion_id( m_world ), getpid() );


     ret = fusion_ref_init( &m_ref, "Test", m_world );
     if (ret) {
          D_DERROR( ret, "fusion_ref_init() failed" );
          return -1;
     }


     MSG( "Adding local reference...\n" );

     fusion_ref_up( &m_ref, false );


     m_reactor = fusion_reactor_new( sizeof(TestMessage), "Test", m_world );
     if (!m_reactor) {
          D_ERROR( "fusion_reactor_new() failed\n" );
          return -1;
     }


     MSG( "Attaching to reactor...\n" );

     ret = fusion_reactor_attach( m_reactor, reaction_callback, NULL, &m_reaction );
     if (ret) {
          D_DERROR( ret, "fusion_reactor_attach() failed" );
          return ret;
     }


     MSG( ".........FORKING NOW.........\n" );

     fusion_world_set_fork_action( m_world, FFA_FORK );
     child_pid = fork();
     fusion_world_set_fork_action( m_world, FFA_CLOSE );

     switch (child_pid) {
          case -1:
               D_PERROR( "fork() failed" );
               break;

          case 0:
               setsid();
               MSG( "...arrived after fork() in child (pid %d)..\n", getpid() );
               MSG( "..child (FusionID %lu).\n", fusion_id( m_world ) );
               break;

          default:
               usleep( 200000 );
               MSG( "...returned from fork() in parent, child pid %d.\n", child_pid );
               break;
     }


     MSG( "Sending message via reactor...\n" );

     fusion_reactor_dispatch( m_reactor, &message, true, NULL );

     usleep( 200000 );


     MSG( "Removing local reference...\n" );

     fusion_ref_down( &m_ref, false );

     usleep( 200000 );


     MSG( "Exiting from world %d (FusionID %lu, pid %d)...\n",
          fusion_world_index( m_world ), fusion_id( m_world ), getpid() );

     fusion_exit( m_world, false );

     return 0;
}