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; }
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" ); }
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; }
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; }