/* Broadcast a frame in the network. In most cases, the frame should be able to * reach every node in the network, but no guarantee about this. */ uintx flood_broadcast( TiFloodNetwork * net, TiFrame * frame, uint8 option ) { uintx count=0; uintx i = 0;//todo char * pc; /* This function will try to put the frame into TiFloodNetwork's internal TX buffer. * The real sending processing is in flood_evolve(). */ i = frame_length( frame);//todo if (frame_empty(net->txque)) { net->txque->option = option; count = frame_totalcopyfrom( net->txque, frame ); frame_skipouter( net->txque, 4, 0 );//todo 执行这一局后frame_length又变回0了! frame_setlength( net->txque,(i+4));//todo // assert( frame_skipouter must be success ); pc = frame_startptr( net->txque ); PACKET_SET_HOPCOUNT( pc,0 ); PACKET_SET_MAX_HOPCOUNT(pc , CONFIG_FLOOD_MAX_COUNT ); PACKET_SET_CURSEQID(pc, net->seqid ); } flood_evolve( net, NULL ); return count; }
// Transfers the arguments from the top of the previous piece (which the frame // points to) to the bottom of the new stack segment. static void transfer_top_arguments(value_t new_piece, frame_t *frame, size_t arg_count) { frame_t new_frame = frame_empty(); open_stack_piece(new_piece, &new_frame); for (size_t i = 0; i < arg_count; i++) { value_t value = frame_peek_value(frame, arg_count - i - 1); frame_push_value(&new_frame, value); } close_frame(&new_frame); }
/* Check for arrived frames, no matter who send them. The frame will be returned * through the parameter "frame" only when the frame's destination matches the current * node. The other frames will be forwarded or discarded. */ uintx flood_recv( TiFloodNetwork * net, TiFrame * frame, uint8 option ) { uintx count=0; flood_evolve( net, NULL ); if (!frame_empty( net->rxque)) { count = frame_totalcopyfrom( frame, net->rxque ); frame_bufferclear( net->rxque ); } return count; }
static void push_stack_piece_bottom_frame(runtime_t *runtime, value_t stack_piece, value_t arg_map) { frame_t bottom = frame_empty(); value_t code_block = ROOT(runtime, stack_piece_bottom_code_block); // The transferred arguments are going to appear as if they were arguments // passed from this frame so we have to "allocate" enough room for them on // the stack. open_stack_piece(stack_piece, &bottom); size_t arg_count = get_array_length(arg_map); bool pushed = try_push_new_frame(&bottom, get_code_block_high_water_mark(code_block) + arg_count, ffSynthetic | ffStackPieceBottom, false); CHECK_TRUE("pushing bottom frame", pushed); frame_set_code_block(&bottom, code_block); frame_set_argument_map(&bottom, arg_map); close_frame(&bottom); }
frame_t open_stack(value_t stack) { CHECK_FAMILY(ofStack, stack); frame_t result = frame_empty(); open_stack_piece(get_stack_top_piece(stack), &result); return result; }
// Runs the given stack within the given ambience until a condition is // encountered or evaluation completes. This function also bails on and leaves // it to the surrounding code to report error messages. static value_t run_stack_pushing_signals(value_t ambience, value_t stack) { CHECK_FAMILY(ofAmbience, ambience); CHECK_FAMILY(ofStack, stack); runtime_t *runtime = get_ambience_runtime(ambience); frame_t frame = open_stack(stack); code_cache_t cache; code_cache_refresh(&cache, &frame); E_BEGIN_TRY_FINALLY(); while (true) { opcode_t opcode = (opcode_t) read_short(&cache, &frame, 0); TOPIC_INFO(Interpreter, "Opcode: %s (%i)", get_opcode_name(opcode), opcode_counter++); IF_EXPENSIVE_CHECKS_ENABLED(MAYBE_INTERRUPT()); switch (opcode) { case ocPush: { value_t value = read_value(&cache, &frame, 1); frame_push_value(&frame, value); frame.pc += kPushOperationSize; break; } case ocPop: { size_t count = read_short(&cache, &frame, 1); for (size_t i = 0; i < count; i++) frame_pop_value(&frame); frame.pc += kPopOperationSize; break; } case ocCheckStackHeight: { size_t expected = read_short(&cache, &frame, 1); size_t height = frame.stack_pointer - frame.frame_pointer; CHECK_EQ("stack height", expected, height); frame.pc += kCheckStackHeightOperationSize; break; } case ocNewArray: { size_t length = read_short(&cache, &frame, 1); E_TRY_DEF(array, new_heap_array(runtime, length)); for (size_t i = 0; i < length; i++) { value_t element = frame_pop_value(&frame); set_array_at(array, length - i - 1, element); } frame_push_value(&frame, array); frame.pc += kNewArrayOperationSize; break; } case ocInvoke: { // Look up the method in the method space. value_t tags = read_value(&cache, &frame, 1); CHECK_FAMILY(ofCallTags, tags); value_t fragment = read_value(&cache, &frame, 2); CHECK_FAMILY(ofModuleFragment, fragment); value_t helper = read_value(&cache, &frame, 3); CHECK_FAMILY(ofSignatureMap, helper); value_t arg_map; value_t method = lookup_method_full(ambience, fragment, tags, &frame, helper, &arg_map); if (in_condition_cause(ccLookupError, method)) { log_lookup_error(method, tags, &frame); E_RETURN(method); } // The lookup may have failed with a different condition. Check for that. E_TRY(method); E_TRY_DEF(code_block, ensure_method_code(runtime, method)); // We should now have done everything that can fail so we advance the // pc over this instruction. In reality we haven't, the frame push op // below can fail so we should really push the next frame before // storing the pc for this one. Laters. frame.pc += kInvokeOperationSize; // Push a new activation. E_TRY(push_stack_frame(runtime, stack, &frame, get_code_block_high_water_mark(code_block), arg_map)); frame_set_code_block(&frame, code_block); code_cache_refresh(&cache, &frame); break; } case ocSignalContinue: case ocSignalEscape: { // Look up the method in the method space. value_t tags = read_value(&cache, &frame, 1); CHECK_FAMILY(ofCallTags, tags); frame.pc += kSignalEscapeOperationSize; value_t arg_map = whatever(); value_t handler = whatever(); value_t method = lookup_signal_handler_method(ambience, tags, &frame, &handler, &arg_map); bool is_escape = (opcode == ocSignalEscape); if (in_condition_cause(ccLookupError, method)) { if (is_escape) { // There was no handler for this so we have to escape out of the // interpreter altogether. Push the signal frame onto the stack to // record the state of it for the enclosing code. E_TRY(push_stack_frame(runtime, stack, &frame, 1, nothing())); // The stack tracing code expects all frames to have a valid code block // object. The rest makes less of a difference. frame_set_code_block(&frame, ROOT(runtime, empty_code_block)); E_RETURN(new_signal_condition(is_escape)); } else { // There was no handler but this is not an escape so we skip over // the post-handler goto to the default block. CHECK_EQ("signal not followed by goto", ocGoto, read_short(&cache, &frame, 0)); frame.pc += kGotoOperationSize; } } else { // We found a method. Invoke it. E_TRY(method); E_TRY_DEF(code_block, ensure_method_code(runtime, method)); E_TRY(push_stack_frame(runtime, stack, &frame, get_code_block_high_water_mark(code_block), arg_map)); frame_set_code_block(&frame, code_block); CHECK_TRUE("subject not null", is_null(frame_get_argument(&frame, 0))); frame_set_argument(&frame, 0, handler); code_cache_refresh(&cache, &frame); } break; } case ocGoto: { size_t delta = read_short(&cache, &frame, 1); frame.pc += delta; break; } case ocDelegateToLambda: case ocDelegateToBlock: { // This op only appears in the lambda and block delegator methods. // They should never be executed because the delegation happens during // method lookup. If we hit here something's likely wrong with the // lookup process. UNREACHABLE("delegate to lambda"); return new_condition(ccWat); } case ocBuiltin: { value_t wrapper = read_value(&cache, &frame, 1); builtin_method_t impl = (builtin_method_t) get_void_p_value(wrapper); builtin_arguments_t args; builtin_arguments_init(&args, runtime, &frame); E_TRY_DEF(result, impl(&args)); frame_push_value(&frame, result); frame.pc += kBuiltinOperationSize; break; } case ocBuiltinMaybeEscape: { value_t wrapper = read_value(&cache, &frame, 1); builtin_method_t impl = (builtin_method_t) get_void_p_value(wrapper); builtin_arguments_t args; builtin_arguments_init(&args, runtime, &frame); value_t result = impl(&args); if (in_condition_cause(ccSignal, result)) { // The builtin failed. Find the appropriate signal handler and call // it. The invocation record is at the top of the stack. value_t tags = frame_pop_value(&frame); CHECK_FAMILY(ofCallTags, tags); value_t arg_map = whatever(); value_t handler = whatever(); value_t method = lookup_signal_handler_method(ambience, tags, &frame, &handler, &arg_map); if (in_condition_cause(ccLookupError, method)) { // Push the record back onto the stack to it's available to back // tracing. frame_push_value(&frame, tags); frame.pc += kBuiltinMaybeEscapeOperationSize; // There was no handler for this so we have to escape out of the // interpreter altogether. Push the signal frame onto the stack to // record the state of it for the enclosing code. E_TRY(push_stack_frame(runtime, stack, &frame, 1, nothing())); // The stack tracing code expects all frames to have a valid code block // object. The rest makes less of a difference. frame_set_code_block(&frame, ROOT(runtime, empty_code_block)); E_RETURN(new_signal_condition(true)); } // Either found a signal or encountered a different condition. E_TRY(method); // Skip forward to the point we want the signal to return to, the // leave-or-fire-barrier op that will do the leaving. size_t dest_offset = read_short(&cache, &frame, 2); frame.pc += dest_offset; // Run the handler. E_TRY_DEF(code_block, ensure_method_code(runtime, method)); E_TRY(push_stack_frame(runtime, stack, &frame, get_code_block_high_water_mark(code_block), arg_map)); frame_set_code_block(&frame, code_block); CHECK_TRUE("subject not null", is_null(frame_get_argument(&frame, 0))); frame_set_argument(&frame, 0, handler); code_cache_refresh(&cache, &frame); } else { // The builtin didn't cause a condition so we can just keep going. E_TRY(result); frame_push_value(&frame, result); frame.pc += kBuiltinMaybeEscapeOperationSize; } break; } case ocReturn: { value_t result = frame_pop_value(&frame); frame_pop_within_stack_piece(&frame); code_cache_refresh(&cache, &frame); frame_push_value(&frame, result); break; } case ocStackBottom: { value_t result = frame_pop_value(&frame); validate_stack_on_normal_exit(&frame); E_RETURN(result); } case ocStackPieceBottom: { value_t top_piece = frame.stack_piece; value_t result = frame_pop_value(&frame); value_t next_piece = get_stack_piece_previous(top_piece); set_stack_top_piece(stack, next_piece); frame = open_stack(stack); code_cache_refresh(&cache, &frame); frame_push_value(&frame, result); break; } case ocSlap: { value_t value = frame_pop_value(&frame); size_t argc = read_short(&cache, &frame, 1); for (size_t i = 0; i < argc; i++) frame_pop_value(&frame); frame_push_value(&frame, value); frame.pc += kSlapOperationSize; break; } case ocNewReference: { // Create the reference first so that if it fails we haven't clobbered // the stack yet. E_TRY_DEF(ref, new_heap_reference(runtime, nothing())); value_t value = frame_pop_value(&frame); set_reference_value(ref, value); frame_push_value(&frame, ref); frame.pc += kNewReferenceOperationSize; break; } case ocSetReference: { value_t ref = frame_pop_value(&frame); CHECK_FAMILY(ofReference, ref); value_t value = frame_peek_value(&frame, 0); set_reference_value(ref, value); frame.pc += kSetReferenceOperationSize; break; } case ocGetReference: { value_t ref = frame_pop_value(&frame); CHECK_FAMILY(ofReference, ref); value_t value = get_reference_value(ref); frame_push_value(&frame, value); frame.pc += kGetReferenceOperationSize; break; } case ocLoadLocal: { size_t index = read_short(&cache, &frame, 1); value_t value = frame_get_local(&frame, index); frame_push_value(&frame, value); frame.pc += kLoadLocalOperationSize; break; } case ocLoadGlobal: { value_t ident = read_value(&cache, &frame, 1); CHECK_FAMILY(ofIdentifier, ident); value_t fragment = read_value(&cache, &frame, 2); CHECK_FAMILY(ofModuleFragment, fragment); value_t module = get_module_fragment_module(fragment); E_TRY_DEF(value, module_lookup_identifier(runtime, module, get_identifier_stage(ident), get_identifier_path(ident))); frame_push_value(&frame, value); frame.pc += kLoadGlobalOperationSize; break; } case ocLoadArgument: { size_t param_index = read_short(&cache, &frame, 1); value_t value = frame_get_argument(&frame, param_index); frame_push_value(&frame, value); frame.pc += kLoadArgumentOperationSize; break; } case ocLoadRefractedArgument: { size_t param_index = read_short(&cache, &frame, 1); size_t block_depth = read_short(&cache, &frame, 2); value_t subject = frame_get_argument(&frame, 0); frame_t home = frame_empty(); get_refractor_refracted_frame(subject, block_depth, &home); value_t value = frame_get_argument(&home, param_index); frame_push_value(&frame, value); frame.pc += kLoadRefractedArgumentOperationSize; break; } case ocLoadRefractedLocal: { size_t index = read_short(&cache, &frame, 1); size_t block_depth = read_short(&cache, &frame, 2); value_t subject = frame_get_argument(&frame, 0); frame_t home = frame_empty(); get_refractor_refracted_frame(subject, block_depth, &home); value_t value = frame_get_local(&home, index); frame_push_value(&frame, value); frame.pc += kLoadRefractedLocalOperationSize; break; } case ocLoadLambdaCapture: { size_t index = read_short(&cache, &frame, 1); value_t subject = frame_get_argument(&frame, 0); CHECK_FAMILY(ofLambda, subject); value_t value = get_lambda_capture(subject, index); frame_push_value(&frame, value); frame.pc += kLoadLambdaCaptureOperationSize; break; } case ocLoadRefractedCapture: { size_t index = read_short(&cache, &frame, 1); size_t block_depth = read_short(&cache, &frame, 2); value_t subject = frame_get_argument(&frame, 0); frame_t home = frame_empty(); get_refractor_refracted_frame(subject, block_depth, &home); value_t lambda = frame_get_argument(&home, 0); CHECK_FAMILY(ofLambda, lambda); value_t value = get_lambda_capture(lambda, index); frame_push_value(&frame, value); frame.pc += kLoadRefractedLocalOperationSize; break; } case ocLambda: { value_t space = read_value(&cache, &frame, 1); CHECK_FAMILY(ofMethodspace, space); size_t capture_count = read_short(&cache, &frame, 2); value_t captures; E_TRY_DEF(lambda, new_heap_lambda(runtime, space, nothing())); if (capture_count == 0) { captures = ROOT(runtime, empty_array); frame.pc += kLambdaOperationSize; } else { E_TRY_SET(captures, new_heap_array(runtime, capture_count)); // The pc gets incremented here because it is after we've done all // the allocation but before anything has been popped off the stack. // This way all the above is idempotent, and the below is guaranteed // to succeed. frame.pc += kLambdaOperationSize; for (size_t i = 0; i < capture_count; i++) set_array_at(captures, i, frame_pop_value(&frame)); } set_lambda_captures(lambda, captures); frame_push_value(&frame, lambda); break; } case ocCreateBlock: { value_t space = read_value(&cache, &frame, 1); CHECK_FAMILY(ofMethodspace, space); // Create the block object. E_TRY_DEF(block, new_heap_block(runtime, nothing())); // Create the stack section that describes the block. value_t section = frame_alloc_derived_object(&frame, get_genus_descriptor(dgBlockSection)); set_barrier_state_payload(section, block); refraction_point_init(section, &frame); set_block_section_methodspace(section, space); set_block_section(block, section); value_validate(block); value_validate(section); // Push the block object. frame_push_value(&frame, block); frame.pc += kCreateBlockOperationSize; break; } case ocCreateEnsurer: { value_t code_block = read_value(&cache, &frame, 1); value_t section = frame_alloc_derived_object(&frame, get_genus_descriptor(dgEnsureSection)); set_barrier_state_payload(section, code_block); refraction_point_init(section, &frame); value_validate(section); frame_push_value(&frame, section); frame.pc += kCreateEnsurerOperationSize; break; } case ocCallEnsurer: { value_t value = frame_pop_value(&frame); value_t shard = frame_pop_value(&frame); frame_push_value(&frame, value); frame_push_value(&frame, shard); CHECK_GENUS(dgEnsureSection, shard); value_t code_block = get_barrier_state_payload(shard); CHECK_FAMILY(ofCodeBlock, code_block); // Unregister the barrier before calling it, otherwise if we leave // by escaping we'll end up calling it over again. barrier_state_unregister(shard, stack); frame.pc += kCallEnsurerOperationSize; value_t argmap = ROOT(runtime, array_of_zero); push_stack_frame(runtime, stack, &frame, get_code_block_high_water_mark(code_block), argmap); frame_set_code_block(&frame, code_block); code_cache_refresh(&cache, &frame); break; } case ocDisposeEnsurer: { // Discard the result of the ensure block. If an ensure blocks needs // to return a useful value it can do it via an escape. frame_pop_value(&frame); value_t shard = frame_pop_value(&frame); CHECK_GENUS(dgEnsureSection, shard); value_t value = frame_pop_value(&frame); frame_destroy_derived_object(&frame, get_genus_descriptor(dgEnsureSection)); frame_push_value(&frame, value); frame.pc += kDisposeEnsurerOperationSize; break; } case ocInstallSignalHandler: { value_t space = read_value(&cache, &frame, 1); CHECK_FAMILY(ofMethodspace, space); size_t dest_offset = read_short(&cache, &frame, 2); // Allocate the derived object that's going to hold the signal handler // state. value_t section = frame_alloc_derived_object(&frame, get_genus_descriptor(dgSignalHandlerSection)); // Initialize the handler. set_barrier_state_payload(section, space); refraction_point_init(section, &frame); // Bring the frame state to the point we'll want to escape to (modulo // the destination offset). frame_push_value(&frame, section); frame.pc += kInstallSignalHandlerOperationSize; // Finally capture the escape state. capture_escape_state(section, &frame, dest_offset); value_validate(section); break; } case ocUninstallSignalHandler: { // The result has been left at the top of the stack. value_t value = frame_pop_value(&frame); value_t section = frame_pop_value(&frame); CHECK_GENUS(dgSignalHandlerSection, section); barrier_state_unregister(section, stack); frame_destroy_derived_object(&frame, get_genus_descriptor(dgSignalHandlerSection)); frame_push_value(&frame, value); frame.pc += kUninstallSignalHandlerOperationSize; break; } case ocCreateEscape: { size_t dest_offset = read_short(&cache, &frame, 1); // Create an initially empty escape object. E_TRY_DEF(escape, new_heap_escape(runtime, nothing())); // Allocate the escape section on the stack, hooking the barrier into // the barrier chain. value_t section = frame_alloc_derived_object(&frame, get_genus_descriptor(dgEscapeSection)); // Point the state and object to each other. set_barrier_state_payload(section, escape); set_escape_section(escape, section); // Get execution ready for the next operation. frame_push_value(&frame, escape); frame.pc += kCreateEscapeOperationSize; // This is the execution state the escape will escape to (modulo the // destination offset) so this is what we want to capture. capture_escape_state(section, &frame, dest_offset); break; } case ocLeaveOrFireBarrier: { size_t argc = read_short(&cache, &frame, 1); // At this point the handler has been set as the subject of the call // to the handler method. Above the arguments are also two scratch // stack entries. value_t handler = frame_peek_value(&frame, argc + 2); CHECK_GENUS(dgSignalHandlerSection, handler); if (maybe_fire_next_barrier(&cache, &frame, runtime, stack, handler)) { // Pop the scratch entries off. frame_pop_value(&frame); frame_pop_value(&frame); // Pop the value off. value_t value = frame_pop_value(&frame); // Escape to the handler's home. restore_escape_state(&frame, stack, handler); code_cache_refresh(&cache, &frame); // Push the value back on, now in the handler's home frame. frame_push_value(&frame, value); } else { // If a barrier was fired we'll want to let the interpreter loop // around again so just break without touching .pc. } break; } case ocFireEscapeOrBarrier: { value_t escape = frame_get_argument(&frame, 0); CHECK_FAMILY(ofEscape, escape); value_t section = get_escape_section(escape); // Fire the next barrier or, if there are no more barriers, apply the // escape. if (maybe_fire_next_barrier(&cache, &frame, runtime, stack, section)) { value_t value = frame_get_argument(&frame, 2); restore_escape_state(&frame, stack, section); code_cache_refresh(&cache, &frame); frame_push_value(&frame, value); } else { // If a barrier was fired we'll want to let the interpreter loop // around again so just break without touching .pc. } break; } case ocDisposeEscape: { value_t value = frame_pop_value(&frame); value_t escape = frame_pop_value(&frame); CHECK_FAMILY(ofEscape, escape); value_t section = get_escape_section(escape); value_validate(section); barrier_state_unregister(section, stack); on_escape_section_exit(section); frame_destroy_derived_object(&frame, get_genus_descriptor(dgEscapeSection)); frame_push_value(&frame, value); frame.pc += kDisposeEscapeOperationSize; break; } case ocDisposeBlock: { value_t value = frame_pop_value(&frame); value_t block = frame_pop_value(&frame); CHECK_FAMILY(ofBlock, block); value_t section = get_block_section(block); barrier_state_unregister(section, stack); on_block_section_exit(section); frame_destroy_derived_object(&frame, get_genus_descriptor(dgBlockSection)); frame_push_value(&frame, value); frame.pc += kDisposeBlockOperationSize; break; } default: ERROR("Unexpected opcode %i", opcode); UNREACHABLE("unexpected opcode"); break; } } E_FINALLY(); close_frame(&frame); E_END_TRY_FINALLY(); }
/* This function receive event from other services/objects and drive the evolution * of the TiFloodNetwork service. * * This function can also be the listener of the MAC layer, Though it's not mandatory. * * @attention: * This function cannot run in the interrupt mode. */ void flood_evolve( void * netptr, TiEvent * e ) { TiFloodNetwork * net = (TiFloodNetwork *)netptr; uint8 len, count, cur_hopcount, max_hopcount; bool done = true, cont= false; char * pc; aloha_evolve( net->mac,e ); // This event is sent from MAC layer. // // @todo // Currently, all the frames from MAC layer will submitted the listener function. // Actually, this isn't necessary. Only those to this node should submitted to // the listener. // if (e->id == EVENT_DATA_ARRIVAL) { if (net->listener != NULL) { net->listener( net->lisowner, e ); return; } } do{ switch (net->state) { // IDLE is the initial and default state of this state machine. case FLOOD_STATE_IDLE: // Check if the TX queue is empty. If not then try to send the frame. if (!frame_empty(net->txque)) { len = aloha_broadcast( net->mac, net->txque, net->txque->option ); if (len > 0) { frame_bufferclear( net->txque ); } // @attention // @todo: if the aloha_send() is non-blocked operation, then you should // transfer to FLOOD_STATE_WAITFOR_TXREPLY state to wait. You should empty // the buffer only when this service receives the reply from MAC layer. //net->state = FLOOD_STATE_WAIT_TXREPLY done = true; } // Check if the RX queue is empty, then try to receive one from MAC layer if ((frame_empty(net->rxbuf)) && frame_empty(net->rxque)) { cont = true; count = aloha_recv( net->mac, net->rxbuf, 0x00 ); if (count <= 0) cont = false; // Check: whether the same frame has already been received. This // is by searching it in the cache. If it cannot find it in the // cache, then put the frame in the cache. // // @modified by zhangwei on 2011.03.14 // - we use the first 4 bytes in the frame (which is essentially // the header of flood protocol as the key to visit the cache. // if (cont) { if (flood_cache_visit( net->cache, (char*)frame_startptr(net->rxbuf) ))//todo 我将CONFIG_FLOOD_CACHE_CAPACITY改成了1原先为8,不改的话不再接收新的帧. { frame_bufferclear( net->rxbuf ); cont = false; } } if (cont) { frame_totalcopyto( net->rxbuf, net->rxque ); // Check whether this frame has reaches its maximum hopcount. // Discard this frame if this is true. char * pc; pc = frame_startptr( net->rxbuf); cur_hopcount = PACKET_CUR_HOPCOUNT( pc ); max_hopcount = PACKET_MAX_HOPCOUNT( pc); cur_hopcount ++; if (cur_hopcount > max_hopcount) frame_bufferclear( net->rxbuf ); else PACKET_SET_HOPCOUNT( pc, cur_hopcount ); } done = true; } // Check whether there's frame pending for forwarding if ((!frame_empty(net->rxbuf)) && frame_empty(net->txque)) { pc = frame_startptr( net->txque); // move the frame from rxbuf to txque. For efficiency reasons, this is implmented // by switching the two pointers. _switch_ptr( &(net->rxbuf), &(net->txque) ); // @attention // generally, you should change the frame in "txque" with the PAN id // and BROADCAST_ADDRESS configured in this flood component. However, // here we assume the low level medium access protocol helps us to do so. cur_hopcount = PACKET_CUR_HOPCOUNT( pc ); PACKET_SET_HOPCOUNT( pc, cur_hopcount++ ); done = false; } break; // This's the state waiting for MAC layer's reply. The sending process of the // MAC layer may last for quite a long time due to re-transmission. Only at the // end of the transmission, the MAC layer does possible to notify the NET layer // the transmission results of the sending request. // /*case FLOOD_STATE_WAITFOR_TXREPLY: ioresult = aloha_ioresult(net->mac); if ioresult == IDLE|TXDONE { opf_clear( net->txque ); net->state = FLOOD_STATE_IDLE; } // if ioresult indicate there's error or failure // report to the master program by call net->listener net->state = FLOOD_STATE_IDLE; break;*/ default: net->state = FLOOD_STATE_IDLE; } }while (!done); return; }