DirectResult fusion_ref_up (FusionRef *ref, bool global) { D_ASSERT( ref != NULL ); D_DEBUG_AT( Fusion_Ref, "fusion_ref_up( %p [%d]%s )\n", ref, ref->multi.id, global ? " GLOBAL" : "" ); while (ioctl (_fusion_fd( ref->multi.shared ), global ? FUSION_REF_UP_GLOBAL : FUSION_REF_UP, &ref->multi.id)) { switch (errno) { case EINTR: continue; case EAGAIN: return DR_LOCKED; case EINVAL: D_ERROR ("Fusion/Reference: invalid reference\n"); return DR_DESTROYED; default: break; } if (global) D_PERROR ("FUSION_REF_UP_GLOBAL"); else D_PERROR ("FUSION_REF_UP"); return DR_FAILURE; } D_DEBUG_AT( Fusion_Ref, " -> %d references now\n", ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_STAT, &ref->multi.id ) ); return DR_OK; }
DirectResult fusion_skirmish_notify( FusionSkirmish *skirmish ) { D_ASSERT( skirmish != NULL ); if (skirmish->single) { pthread_cond_broadcast( &skirmish->single->cond ); return DR_OK; } while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_NOTIFY, &skirmish->multi.id)) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Lock: invalid skirmish\n"); return DR_DESTROYED; } D_PERROR ("FUSION_SKIRMISH_NOTIFY"); return DR_FUSION; } return DR_OK; }
DirectResult fusion_skirmish_destroy (FusionSkirmish *skirmish) { D_ASSERT( skirmish != NULL ); D_DEBUG_AT( Fusion_Skirmish, "fusion_skirmish_destroy( %p [%d] )\n", skirmish, skirmish->multi.id ); if (skirmish->single) { int retval; pthread_cond_broadcast( &skirmish->single->cond ); pthread_cond_destroy( &skirmish->single->cond ); retval = pthread_mutex_destroy( &skirmish->single->lock ); D_FREE( skirmish->single ); return errno2result( retval ); } while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_DESTROY, &skirmish->multi.id )) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Lock: invalid skirmish\n"); return DR_DESTROYED; } D_PERROR ("FUSION_SKIRMISH_DESTROY"); return DR_FUSION; } return DR_OK; }
DirectResult fusion_ref_set_name (FusionRef *ref, const char *name) { FusionEntryInfo info; D_ASSERT( ref != NULL ); D_ASSERT( name != NULL ); info.type = FT_REF; info.id = ref->multi.id; direct_snputs( info.name, name, sizeof(info.name) ); while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_ENTRY_SET_INFO, &info)) { switch (errno) { case EINTR: continue; case EAGAIN: return DR_LOCKED; case EINVAL: D_ERROR ("Fusion/Reference: invalid reference\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_ENTRY_SET_NAME"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_skirmish_swoop( FusionSkirmish *skirmish ) { D_ASSERT( skirmish != NULL ); if (skirmish->single) { if (pthread_mutex_trylock( &skirmish->single->lock )) return errno2result( errno ); skirmish->single->count++; return DR_OK; } while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_SWOOP, &skirmish->multi.id)) { switch (errno) { case EINTR: continue; case EAGAIN: return DR_BUSY; case EINVAL: D_ERROR ("Fusion/Lock: invalid skirmish\n"); return DR_DESTROYED; } D_PERROR ("FUSION_SKIRMISH_SWOOP"); return DR_FUSION; } return DR_OK; }
DirectResult fusion_skirmish_wait( FusionSkirmish *skirmish, unsigned int timeout ) { FusionSkirmishWait wait; D_ASSERT( skirmish != NULL ); wait.id = skirmish->multi.id; wait.timeout = timeout; wait.lock_count = 0; while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_WAIT, &wait)) { switch (errno) { case EINTR: continue; case ETIMEDOUT: return DR_TIMEOUT; case EINVAL: D_ERROR ("Fusion/Lock: invalid skirmish\n"); return DR_DESTROYED; } D_PERROR ("FUSION_SKIRMISH_WAIT"); return DR_FUSION; } return DR_OK; }
DirectResult fusion_skirmish_dismiss (FusionSkirmish *skirmish) { D_ASSERT( skirmish != NULL ); if (skirmish->single) { skirmish->single->count--; if (pthread_mutex_unlock( &skirmish->single->lock )) return errno2result( errno ); return DR_OK; } while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_DISMISS, &skirmish->multi.id)) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Lock: invalid skirmish\n"); return DR_DESTROYED; } D_PERROR ("FUSION_SKIRMISH_DISMISS"); return DR_FUSION; } return DR_OK; }
DirectResult fusion_ref_watch (FusionRef *ref, FusionCall *call, int call_arg) { FusionRefWatch watch; D_ASSERT( ref != NULL ); D_ASSERT( call != NULL ); watch.id = ref->multi.id; watch.call_id = call->call_id; watch.call_arg = call_arg; while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_WATCH, &watch)) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Reference: invalid reference\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_REF_WATCH"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_skirmish_lock_count( FusionSkirmish *skirmish, int *lock_count ) { int data[2]; D_ASSERT( skirmish != NULL ); data[0] = skirmish->multi.id; data[1] = 0; while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_LOCK_COUNT, data)) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Lock: invalid skirmish\n"); return DR_DESTROYED; } D_PERROR ("FUSION_SKIRMISH_LOCK_COUNT"); return DR_FUSION; } *lock_count = data[1]; return DR_OK; }
DirectResult fusion_call_set_quota( FusionCall *call, FusionID fusion_id, unsigned int limit ) { FusionCallSetQuota set_quota; D_DEBUG_AT( Fusion_Call, "%s( %p, fusion_id %lu, limit %u )\n", __FUNCTION__, call, fusion_id, limit ); D_ASSERT( call != NULL ); set_quota.call_id = call->call_id; set_quota.fusion_id = fusion_id; set_quota.limit = limit; while (ioctl (_fusion_fd( call->shared ), FUSION_CALL_SET_QUOTA, &set_quota)) { switch (errno) { case EINTR: continue; default: break; } D_PERROR ("FUSION_CALL_SET_QUOTA"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_ref_stat (FusionRef *ref, int *refs) { int val; D_ASSERT( ref != NULL ); D_ASSERT( refs != NULL ); while ((val = ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_STAT, &ref->multi.id)) < 0) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Reference: invalid reference\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_REF_STAT"); return DR_FAILURE; } *refs = val; return DR_OK; }
DirectResult fusion_ref_zero_trylock (FusionRef *ref) { D_ASSERT( ref != NULL ); while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_ZERO_TRYLOCK, &ref->multi.id)) { switch (errno) { case EINTR: continue; case ETOOMANYREFS: return DR_BUSY; case EINVAL: D_ERROR ("Fusion/Reference: invalid reference\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_REF_ZERO_TRYLOCK"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_ref_catch (FusionRef *ref) { D_ASSERT( ref != NULL ); if (ref->multi.id == fusion_config->trace_ref) { D_INFO( "Fusion/Ref: 0x%08x catch\n", ref->multi.id ); direct_trace_print_stack( NULL ); } while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_CATCH, &ref->multi.id)) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Reference: invalid reference\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_REF_CATCH"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_ref_throw (FusionRef *ref, FusionID catcher) { FusionRefThrow throw_; D_ASSERT( ref != NULL ); if (ref->multi.id == fusion_config->trace_ref) { D_INFO( "Fusion/Ref: 0x%08x throw\n", ref->multi.id ); direct_trace_print_stack( NULL ); } throw_.id = ref->multi.id; throw_.catcher = catcher; while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_THROW, &throw_)) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Reference: invalid reference\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_REF_THROW"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_call_add_permissions( FusionCall *call, FusionID fusion_id, FusionCallPermissions call_permissions ) { FusionEntryPermissions permissions; permissions.type = FT_CALL; permissions.id = call->call_id; permissions.fusion_id = fusion_id; permissions.permissions = 0; if (call_permissions & FUSION_CALL_PERMIT_EXECUTE) { FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_CALL_EXECUTE ); FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_CALL_EXECUTE2 ); FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_CALL_EXECUTE3 ); } while (ioctl( _fusion_fd( call->shared ), FUSION_ENTRY_ADD_PERMISSIONS, &permissions ) < 0) { if (errno != EINTR) { D_PERROR( "Fusion/Call: FUSION_ENTRY_ADD_PERMISSIONS( id %d ) failed!\n", call->call_id ); return DR_FAILURE; } } return DR_OK; }
DirectResult fusion_call_execute (FusionCall *call, FusionCallExecFlags flags, int call_arg, void *call_ptr, int *ret_val) { D_DEBUG_AT( Fusion_Call, "%s( %p, 0x%x, %d, %p )\n", __FUNCTION__, call, flags, call_arg, call_ptr ); D_ASSERT( call != NULL ); if (!call->handler) return DR_DESTROYED; D_DEBUG_AT( Fusion_Call, " -> %s\n", direct_trace_lookup_symbol_at( call->handler ) ); if (!(flags & FCEF_NODIRECT) && call->fusion_id == _fusion_id( call->shared )) { int ret; FusionCallHandlerResult result; result = call->handler( _fusion_id( call->shared ), call_arg, call_ptr, call->ctx, 0, &ret ); if (result != FCHR_RETURN) D_WARN( "local call handler returned FCHR_RETAIN, need FCEF_NODIRECT" ); if (ret_val) *ret_val = ret; } else { FusionCallExecute execute; execute.call_id = call->call_id; execute.call_arg = call_arg; execute.call_ptr = call_ptr; execute.flags = flags; while (ioctl( _fusion_fd( call->shared ), FUSION_CALL_EXECUTE, &execute )) { switch (errno) { case EINTR: continue; case EINVAL: // D_ERROR ("Fusion/Call: invalid call\n"); return DR_INVARG; case EIDRM: return DR_DESTROYED; default: break; } D_PERROR ("FUSION_CALL_EXECUTE"); return DR_FAILURE; } if (ret_val) *ret_val = execute.ret_val; } return DR_OK; }
DirectResult fusion_call_destroy (FusionCall *call) { D_DEBUG_AT( Fusion_Call, "%s( %p )\n", __FUNCTION__, call ); D_ASSERT( call != NULL ); D_ASSERT( call->handler != NULL || call->handler3 != NULL ); 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->handler ) ); while (ioctl (_fusion_fd( call->shared ), FUSION_CALL_DESTROY, &call->call_id)) { switch (errno) { case EINTR: continue; case EINVAL: //FIXME: kernel module destroys calls from exiting process already D_ERROR ("Fusion/Call: invalid call\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_CALL_DESTROY"); return DR_FAILURE; } call->handler = NULL; return DR_OK; }
DirectResult fusion_ref_inherit (FusionRef *ref, FusionRef *from) { FusionRefInherit inherit; D_ASSERT( ref != NULL ); D_ASSERT( from != NULL ); inherit.id = ref->multi.id; inherit.from = from->multi.id; while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_INHERIT, &inherit)) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Reference: invalid reference\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_REF_INHERIT"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_call_get_owner( FusionCall *call, FusionID *ret_fusion_id ) { FusionCallGetOwner get_owner; D_DEBUG_AT( Fusion_Call, "%s( %p )\n", __FUNCTION__, call ); D_ASSERT( call != NULL ); D_ASSERT( ret_fusion_id != NULL ); get_owner.call_id = call->call_id; while (ioctl (_fusion_fd( call->shared ), FUSION_CALL_GET_OWNER, &get_owner)) { switch (errno) { case EINTR: continue; default: break; } D_PERROR ("FUSION_CALL_GET_OWNER"); return DR_FAILURE; } *ret_fusion_id = get_owner.fusion_id; return DR_OK; }
DirectResult fusion_call_set_name( FusionCall *call, const char *name ) { FusionEntryInfo info; D_ASSERT( call != NULL ); D_ASSERT( name != NULL ); info.type = FT_CALL; info.id = call->call_id; direct_snputs( info.name, name, sizeof(info.name) ); while (ioctl (_fusion_fd( call->shared ), FUSION_ENTRY_SET_INFO, &info)) { perror("FUSION_ENTRY_SET_INFO"); switch (errno) { case EINTR: continue; case EAGAIN: return DR_LOCKED; case EINVAL: D_ERROR ("Fusion/Call: invalid call\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_ENTRY_SET_NAME"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_ref_destroy (FusionRef *ref) { D_ASSERT( ref != NULL ); D_DEBUG_AT( Fusion_Ref, "fusion_ref_destroy( %p [%d] )\n", ref, ref->multi.id ); fusion_world_flush_calls( _fusion_world( ref->multi.shared ), 1 ); while (ioctl (_fusion_fd( ref->multi.shared ), FUSION_REF_DESTROY, &ref->multi.id)) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Reference: invalid reference\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_REF_DESTROY"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_property_lease (FusionProperty *property) { D_ASSERT( property != NULL ); while (ioctl (_fusion_fd( property->multi.shared ), FUSION_PROPERTY_LEASE, &property->multi.id)) { switch (errno) { case EINTR: continue; case EAGAIN: return DR_BUSY; case EINVAL: D_ERROR ("Fusion/Property: invalid property\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_PROPERTY_LEASE"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_call_destroy (FusionCall *call) { D_DEBUG_AT( Fusion_Call, "%s( %p )\n", __FUNCTION__, call ); D_ASSERT( call != NULL ); D_ASSERT( call->handler != NULL ); D_DEBUG_AT( Fusion_Call, " -> %s\n", direct_trace_lookup_symbol_at( call->handler ) ); while (ioctl (_fusion_fd( call->shared ), FUSION_CALL_DESTROY, &call->call_id)) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Call: invalid call\n"); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_CALL_DESTROY"); return DR_FAILURE; } call->handler = NULL; return DR_OK; }
DirectResult fusion_ref_down (FusionRef *ref, bool global) { D_ASSERT( ref != NULL ); D_DEBUG_AT( Fusion_Ref, "fusion_ref_down( %p [%d]%s )\n", ref, ref->multi.id, global ? " GLOBAL" : "" ); if (ref->multi.id == fusion_config->trace_ref) { D_INFO( "Fusion/Ref: 0x%08x down (%s)\n", ref->multi.id, global ? "global" : "local" ); direct_trace_print_stack( NULL ); } fusion_world_flush_calls( _fusion_world( ref->multi.shared ), 1 ); while (ioctl (_fusion_fd( ref->multi.shared ), global ? FUSION_REF_DOWN_GLOBAL : FUSION_REF_DOWN, &ref->multi.id)) { switch (errno) { case EINTR: continue; case EINVAL: D_ERROR ("Fusion/Reference: invalid reference\n"); return DR_DESTROYED; default: break; } if (global) D_PERROR ("FUSION_REF_DOWN_GLOBAL"); else D_PERROR ("FUSION_REF_DOWN"); return DR_FAILURE; } // FIMXE: the following had to be commented out as the ref down may cause a ref watcher to free the memory of 'ref' (via ioctl) #if 0 if (ref->multi.shared) D_DEBUG_AT( Fusion_Ref, " -> %d references now\n", ioctl( _fusion_fd( ref->multi.shared ), FUSION_REF_STAT, &ref->multi.id ) ); else D_DEBUG_AT( Fusion_Ref, " -> destroyed\n" ); #endif return DR_OK; }
DirectResult fusion_ref_add_permissions( FusionRef *ref, FusionID fusion_id, FusionRefPermissions ref_permissions ) { FusionEntryPermissions permissions; permissions.type = FT_REF; permissions.id = ref->multi.id; permissions.fusion_id = fusion_id; permissions.permissions = 0; if (ref_permissions & FUSION_REF_PERMIT_REF_UNREF_LOCAL) { FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_UP ); FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_DOWN ); } if (ref_permissions & FUSION_REF_PERMIT_REF_UNREF_GLOBAL) { FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_UP_GLOBAL ); FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_DOWN_GLOBAL ); } if (ref_permissions & FUSION_REF_PERMIT_ZERO_LOCK_UNLOCK) { FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_ZERO_LOCK ); FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_ZERO_TRYLOCK ); FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_UNLOCK ); } if (ref_permissions & FUSION_REF_PERMIT_WATCH) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_WATCH ); if (ref_permissions & FUSION_REF_PERMIT_INHERIT) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_INHERIT ); if (ref_permissions & FUSION_REF_PERMIT_DESTROY) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_DESTROY ); if (ref_permissions & FUSION_REF_PERMIT_CATCH) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_CATCH ); if (ref_permissions & FUSION_REF_PERMIT_THROW) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_REF_THROW ); while (ioctl( _fusion_fd( ref->multi.shared ), FUSION_ENTRY_ADD_PERMISSIONS, &permissions ) < 0) { if (errno != EINTR) { D_PERROR( "Fusion/Reactor: FUSION_ENTRY_ADD_PERMISSIONS( id %d ) failed!\n", ref->multi.id ); return DR_FAILURE; } } return DR_OK; }
DirectResult fusion_skirmish_wait( FusionSkirmish *skirmish, unsigned int timeout ) { FusionSkirmishWait wait; D_ASSERT( skirmish != NULL ); if (skirmish->single) { if (timeout) { struct timespec ts; struct timeval tv; int ret; gettimeofday( &tv, NULL ); ts.tv_nsec = tv.tv_usec*1000 + (timeout%1000)*1000000; ts.tv_sec = tv.tv_sec + timeout/1000 + ts.tv_nsec/1000000000; ts.tv_nsec = ts.tv_nsec % 1000000000; ret = pthread_cond_timedwait( &skirmish->single->cond, &skirmish->single->lock, &ts ); return (ret == ETIMEDOUT) ? DR_TIMEOUT : DR_OK; } return pthread_cond_wait( &skirmish->single->cond, &skirmish->single->lock ); } wait.id = skirmish->multi.id; wait.timeout = timeout; wait.lock_count = 0; while (ioctl (_fusion_fd( skirmish->multi.shared ), FUSION_SKIRMISH_WAIT, &wait)) { switch (errno) { case EINTR: continue; case ETIMEDOUT: return DR_TIMEOUT; case EINVAL: D_ERROR ("Fusion/Lock: invalid skirmish\n"); return DR_DESTROYED; } D_PERROR ("FUSION_SKIRMISH_WAIT"); return DR_FUSION; } return DR_OK; }
DirectResult fusion_call_return3( FusionCall *call, unsigned int serial, void *ptr, unsigned int length ) { FusionCallReturn3 call_ret; D_DEBUG_AT( Fusion_Call, "%s( %p, serial %u, ptr %p, length %u )\n", __FUNCTION__, call, serial, ptr, length ); D_ASSERT( call != NULL ); 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->handler ) ); D_ASSUME( serial != 0 ); if (!serial) return DR_UNSUPPORTED; call_ret.call_id = call->call_id; call_ret.serial = serial; call_ret.ptr = ptr; call_ret.length = length; fusion_world_flush_calls( _fusion_world( call->shared ), 1 ); while (ioctl (_fusion_fd( call->shared ), FUSION_CALL_RETURN3, &call_ret)) { switch (errno) { case EINTR: continue; case EIDRM: D_WARN( "caller withdrawn (signal?)" ); return DR_NOCONTEXT; case EINVAL: D_ERROR( "Fusion/Call: invalid call\n" ); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_CALL_RETURN3"); return DR_FAILURE; } return DR_OK; }
DirectResult fusion_skirmish_add_permissions( FusionSkirmish *skirmish, FusionID fusion_id, FusionSkirmishPermissions skirmish_permissions ) { FusionEntryPermissions permissions; if (skirmish->single) return DR_OK; permissions.type = FT_SKIRMISH; permissions.id = skirmish->multi.id; permissions.fusion_id = fusion_id; permissions.permissions = 0; if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_PREVAIL) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_PREVAIL ); if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_SWOOP) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_SWOOP ); if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_DISMISS) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_DISMISS ); if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_LOCK_COUNT) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_LOCK_COUNT ); if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_WAIT) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_WAIT ); if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_NOTIFY) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_NOTIFY ); if (skirmish_permissions & FUSION_SKIRMISH_PERMIT_DESTROY) FUSION_ENTRY_PERMISSIONS_ADD( permissions.permissions, FUSION_SKIRMISH_DESTROY ); while (ioctl( _fusion_fd( skirmish->multi.shared ), FUSION_ENTRY_ADD_PERMISSIONS, &permissions ) < 0) { if (errno != EINTR) { D_PERROR( "Fusion/Reactor: FUSION_ENTRY_ADD_PERMISSIONS( id %d ) failed!\n", skirmish->multi.id ); return DR_FAILURE; } } return DR_OK; }
DirectResult fusion_call_return( FusionCall *call, unsigned int serial, int val ) { struct sockaddr_un addr; FusionCallReturn callret; D_ASSERT( call != NULL ); addr.sun_family = AF_UNIX; snprintf( addr.sun_path, sizeof(addr.sun_path), "/tmp/.fusion-%d/call.%x.%x", call->shared->world_index, call->call_id, serial ); callret.type = FMT_CALLRET; callret.val = val; return _fusion_send_message( _fusion_fd( call->shared ), &callret, sizeof(callret), &addr ); }
DirectResult fusion_call_return( FusionCall *call, unsigned int serial, int val ) { FusionCallReturn call_ret; D_DEBUG_AT( Fusion_Call, "%s( %p, %u, %d )\n", __FUNCTION__, call, serial, val ); D_ASSERT( call != NULL ); D_DEBUG_AT( Fusion_Call, " -> %s\n", direct_trace_lookup_symbol_at( call->handler ) ); D_ASSUME( serial != 0 ); if (!serial) return DR_UNSUPPORTED; call_ret.call_id = call->call_id; call_ret.val = val; call_ret.serial = serial; while (ioctl (_fusion_fd( call->shared ), FUSION_CALL_RETURN, &call_ret)) { switch (errno) { case EINTR: continue; case EIDRM: D_WARN( "caller withdrawn (signal?)" ); return DR_NOCONTEXT; case EINVAL: D_ERROR( "Fusion/Call: invalid call\n" ); return DR_DESTROYED; default: break; } D_PERROR ("FUSION_CALL_RETURN"); return DR_FAILURE; } return DR_OK; }