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;
}
Exemple #2
0
static void
bench_reactor()
{
     FusionReactor  *reactor;
     Reaction        reaction;
     Reaction        reaction2;
     GlobalReaction  global_reaction;

     reactor = fusion_reactor_new( 16, "Benchmark", world );
     if (!reactor) {
          fprintf( stderr, "Fusion Error\n" );
          return;
     }


     /* reactor attach/detach */
     BENCH_START();

     BENCH_LOOP() {
          fusion_reactor_attach( reactor, reaction_callback, NULL, &reaction );
          fusion_reactor_detach( reactor, &reaction );
     }

     BENCH_STOP();

     printf( "reactor attach/detach                 -> %8.2f k/sec\n", BENCH_RESULT() );


     /* reactor attach/detach (2nd) */
     fusion_reactor_attach( reactor, reaction_callback, NULL, &reaction );

     BENCH_START();

     BENCH_LOOP() {
          fusion_reactor_attach( reactor, reaction_callback, NULL, &reaction2 );
          fusion_reactor_detach( reactor, &reaction2 );
     }

     BENCH_STOP();

     fusion_reactor_detach( reactor, &reaction );

     printf( "reactor attach/detach (2nd)           -> %8.2f k/sec\n", BENCH_RESULT() );


     /* reactor attach/detach (global) */
     fusion_reactor_attach( reactor, reaction_callback, NULL, &reaction );

     BENCH_START();

     BENCH_LOOP() {
          fusion_reactor_attach_global( reactor, 0, NULL, &global_reaction );
          fusion_reactor_detach_global( reactor, &global_reaction );
     }

     BENCH_STOP();

     fusion_reactor_detach( reactor, &reaction );

     printf( "reactor attach/detach (global)        -> %8.2f k/sec\n", BENCH_RESULT() );


     /* reactor dispatch */
     fusion_reactor_attach( reactor, reaction_callback, NULL, &reaction );

     BENCH_START();

     BENCH_LOOP() {
          char msg[16];

          fusion_reactor_dispatch( reactor, msg, true, NULL );
     }

     BENCH_STOP();

     printf( "reactor dispatch                      -> %8.2f k/sec\n", BENCH_RESULT() );


     fusion_reactor_detach( reactor, &reaction );


     fusion_reactor_free( reactor );

     printf( "\n" );
}
Exemple #3
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;
}
Exemple #4
0
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;
}