📄 bombillacore.nc
字号:
initializeContext(&onceContext); analyzeCapsuleVars(state.capsules, which); for (i = 0; i < BOMB_CAPSULE_SUB3; i++) { analyzeCapsuleCalls(state.capsules, BOMB_CAPSULE_SUB0); analyzeCapsuleCalls(state.capsules, BOMB_CAPSULE_SUB1); analyzeCapsuleCalls(state.capsules, BOMB_CAPSULE_SUB2); analyzeCapsuleCalls(state.capsules, BOMB_CAPSULE_SUB3); } analyzeCapsuleCalls(state.capsules, BOMB_CAPSULE_CLOCK_INDEX); analyzeCapsuleCalls(state.capsules, BOMB_CAPSULE_SEND_INDEX); analyzeCapsuleCalls(state.capsules, BOMB_CAPSULE_RECV_INDEX); analyzeCapsuleCalls(state.capsules, BOMB_CAPSULE_ONCE_INDEX); } else if (which == BOMB_CAPSULE_CLOCK) { int capsuleIndex = BOMB_CAPSULE_CLOCK_INDEX; initializeContext(&clockContext); analyzeCapsuleVars(state.capsules, capsuleIndex); analyzeCapsuleCalls(state.capsules, capsuleIndex); } else if (which == BOMB_CAPSULE_SEND) { int capsuleIndex = BOMB_CAPSULE_SEND_INDEX; initializeContext(&sendContext); analyzeCapsuleVars(state.capsules, capsuleIndex); analyzeCapsuleCalls(state.capsules, capsuleIndex); } else if (which == BOMB_CAPSULE_RECV) { int capsuleIndex = BOMB_CAPSULE_RECV_INDEX; initializeContext(&recvContext); analyzeCapsuleVars(state.capsules, capsuleIndex); analyzeCapsuleCalls(state.capsules, capsuleIndex); } else if (which == BOMB_CAPSULE_ONCE) { int capsuleIndex = BOMB_CAPSULE_ONCE_INDEX; /* !!! This doesn't look right: analysis can occur even when a capsule isn't installed (e.g., subroutine install). */ dbg(DBG_USR1, "VM: Installing once capsule, resuming.\n"); initializeContext(&onceContext); analyzeCapsuleVars(state.capsules, capsuleIndex); analyzeCapsuleCalls(state.capsules, capsuleIndex); //resumeContext(&onceContext, &onceContext); } } event TOS_MsgPtr ReceivePacket.receive(TOS_MsgPtr msg) { if (!msg->crc) {return msg;} if (recvContext.state != BOMB_STATE_HALT) { dbg(DBG_USR1, "VM: Received packet, receive context busy, drop.\n"); } else { int i; BombillaPacket* packet = (BombillaPacket*)(msg->data); BombillaDataBuffer* buffer = (BombillaDataBuffer*)&(packet->payload); dbg(DBG_USR1, "VM: Received packet, enqueuing receive context to run.\n"); dbg(DBG_USR1, "VM: Copying %i bytes of header over:\n ", sizeof(recvContext.header)); for (i = 0; i < sizeof(recvContext.header); i++) { dbg_clear(DBG_USR1, "%02hhx", packet->header[i]); } dbg_clear(DBG_USR1, "\n->"); nmemcpy(&(recvContext.header), packet->header, sizeof(recvContext.header)); for (i = 0; i < sizeof(recvContext.header); i++) { dbg_clear(DBG_USR1, "%02hhx", ((uint8_t*)recvContext.header)[i]); } dbg_clear(DBG_USR1, "\n"); nmemcpy(&(state.recvBuffer), buffer, sizeof(BombillaDataBuffer)); initializeContext(&recvContext); call Stacks.pushBuffer(&recvContext, &state.recvBuffer); resumeContext(&recvContext, &recvContext); } return msg; } event result_t sendDone() { // Generic sendDone BombillaContext* sender; dbg(DBG_USR1, "VM: Send done event fired.\n"); if (call Queue.empty(&state.sendWaitQueue)) {return FAIL;} sender = call Queue.dequeue(&clockContext, &state.sendWaitQueue); if (sender->state != BOMB_STATE_SEND_WAIT) { call BombillaError.error(sender, BOMB_ERROR_QUEUE_INVALID); } sender->state = BOMB_STATE_RUN; call executeContext(sender); return SUCCESS; } void execute0ClassInstruction(BombillaContext* context, uint8_t instr) { switch(instr) { case OPhalt: dbg(DBG_USR1, "VM (%i): Halting.\n", (int)context->which); haltContext(context); break; case OPid: dbg(DBG_USR1, "VM (%i): Pushing local address: %i.\n", (int)context->which, (int)TOS_LOCAL_ADDRESS); call Stacks.pushValue(context, (int16_t)(TOS_LOCAL_ADDRESS & 0xffff)); break; case OPrand: { uint16_t rval = call Random.rand(); dbg(DBG_USR1, "VM (%i): Pushing random number: %hu.\n", (int)context->which, rval); call Stacks.pushValue(context, (int16_t)(rval & 0xff)); break; } case OPctrue: dbg(DBG_USR1, "VM (%i): Setting condition to be true.\n", (int)context->which); context->condition = 1; break; case OPcfalse: dbg(DBG_USR1, "VM (%i): Setting condition to be false.\n", (int)context->which); context->condition = 0; break; case OPcpush: dbg(DBG_USR1, "VM (%i): Pushing condition onto the stack: %i.\n", (int)context->which, (int)context->condition); call Stacks.pushValue(context, (int16_t)context->condition); break; case OPlogp: dbg(DBG_USR1, "VM (%i): Pushing logline onto stack (NOT IMPLEMENTED): %i\n", context->which, 0); call Stacks.pushValue(context, 0); break; case OPbpush0: dbg(DBG_USR1, "VM (%i): Pushing buffer 0 onto stack\n", context->which); call Stacks.pushBuffer(context, &state.buffer0); break; case OPbpush1: dbg(DBG_USR1, "VM (%i): Pushing buffer 1 onto stack\n", context->which); call Stacks.pushBuffer(context, &state.buffer1); break; case OPdepth: { uint8_t depth = call Stacks.getOpStackDepth(context); dbg(DBG_USR1, "VM (%i): Pushing op stack depth onto stack: %i\n", context->which, (int)depth); call Stacks.pushValue(context, (int16_t)depth); break; } case OPerr: call BombillaError.error(context, BOMB_ERROR_TRIGGERED); break; case OPret: dbg(DBG_USR1, "VM (%i): Returning from subroutine.\n", (int)context->which); call Stacks.popReturnAddr(context); break; case OPcall0: case OPcall1: case OPcall2: case OPcall3: dbg(DBG_USR1, "VM (%i): Calling subroutine %hhu\n", (int)context->which, (uint8_t)(instr & 0x3)); call Stacks.pushReturnAddr(context); context->capsule = &(state.capsules[instr & 0x3]); context->pc = 0; break; default: call BombillaError.error(context, BOMB_ERROR_INVALID_INSTRUCTION); dbg(DBG_USR1|DBG_ERROR, "VM (%i): Unrecognized class 0 instruction: %hhx\n", (int)TOS_LOCAL_ADDRESS, instr); } } void execute1ClassInstruction(BombillaContext* context, uint8_t instr) { BombillaStackVariable* arg = call Stacks.popOperand(context); switch(instr) { case OPinv: dbg(DBG_USR1, "VM (%i): Inverting top of stack.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_V)) {return;} arg->value.var = -(arg->value.var); call Stacks.pushOperand(context, arg); break; case OPcpull: dbg(DBG_USR1, "VM (%i): Pulling top of stack to condition.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_V)) {return;} context->condition = arg->value.var; break; case OPnot: dbg(DBG_USR1, "VM (%i): Logical not of top of stack.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_V)) {return;} arg->value.var = (arg->value.var)? 0:1; call Stacks.pushOperand(context, arg); break; case OPlnot: dbg(DBG_USR1, "VM (%i): Logical not of top of stack.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_V)) {return;} arg->value.var = ~(arg->value.var); call Stacks.pushOperand(context, arg); break; case OPsense: dbg(DBG_USR1, "VM (%i): Sensing.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_V)) {return;} executeSense(context, (uint8_t)arg->value.var); call Synch.releaseLocks(context, context, state.locks); yieldContext(context); break; case OPsend: dbg(DBG_USR1, "VM (%i): Sending packet with built-in ad-hoc routing.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} else if (!call isAdHocActive()) { dbg(DBG_ERROR, "VM (%i): Cannot send: ad-hoc layer not active.\n", (int)context->which); return; } else { BombillaDataBuffer* buffer = arg->buffer.var; uint8_t len = buffer->size * sizeof(buffer->entries[0]); len += sizeof(buffer->type) + sizeof(buffer->size); if (call SendAdHoc.send((uint8_t*)buffer, len)) { state.sendingContext = context; context->state = BOMB_STATE_SENDING; } else { // Back up context so on being resumed it will try to send again context->pc--; call Stacks.pushOperand(context, arg); call Queue.enqueue(context, &state.sendWaitQueue, context); context->state = BOMB_STATE_SEND_WAIT; } call Synch.releaseLocks(context, context, state.locks); yieldContext(context); } break; case OPsendr: dbg(DBG_USR1, "VM (%i): Executing sendr.\n", (int)context->which); if (context->which == BOMB_CAPSULE_SEND) { executeSendr(context, arg); } else if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} //There's a problem here -- what if send context // won't issue a send done? else if (sendContext.state == BOMB_STATE_HALT) { nmemcpy(&state.sendrBuffer, arg->buffer.var, sizeof(BombillaDataBuffer)); //call Stacks.resetStacks(&sendContext); initializeContext(&sendContext); call Stacks.pushBuffer(&sendContext, &state.sendrBuffer); //initializeContext(&sendContext); resumeContext(context, &sendContext); // This yield/resume allows locks to be yielded to the send context, // and if none are shared, then it will just continue executing if (context->releaseSet) { call Synch.releaseLocks(context, context, state.locks); yieldContext(context); resumeContext(context, context); } } else { // Don't send, fail silently -- send context busy } break; case OPuart: { if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} else { int i; BombillaDataBuffer* buffer = arg->buffer.var; uint8_t len = buffer->size * sizeof(buffer->entries[0]); len += sizeof(buffer->type) + sizeof(buffer->size); for (i = 0; i < len; i++) { context->msg.data[i] = ((uint8_t*)(buffer))[i]; } if (call SendPacket.send(TOS_UART_ADDR, len, &context->msg)) { dbg(DBG_USR1, "VM (%i): Sending packet to UART.\n", (int)context->which); state.sendingContext = context; context->state = BOMB_STATE_SENDING; } else { dbg(DBG_USR1, "VM (%i): UART send request refused. Enqueue and wait.\n", (int)context->which); // Back up context so on being resumed it will try to send again context->pc--; call Stacks.pushOperand(context, arg); call Queue.enqueue(context, &state.sendWaitQueue, context); context->state = BOMB_STATE_SEND_WAIT; } call Synch.releaseLocks(context, context, state.locks); yieldContext(context); } break; } case OPlogw: dbg(DBG_ERROR, "VM (%i): logw not supported yet\n", (int)context->which); break; case OPbhead: dbg(DBG_USR1, "VM (%i): Yanking head of buffer.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} else { BombillaStackVariable var; call Buffer.yank(context, arg->buffer.var, 0, &var); call Stacks.pushOperand(context, arg); call Stacks.pushOperand(context, &var); } break; case OPbtail: dbg(DBG_USR1, "VM (%i): Yanking tail of buffer.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} else { BombillaStackVariable var; call Buffer.yank(context, arg->buffer.var, arg->buffer.var->size -1, &var); call Stacks.pushOperand(context, arg); call Stacks.pushOperand(context, &var); } break; case OPbclear: dbg(DBG_USR1, "VM (%i): Clearing buffer.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} call Buffer.clear(context, arg->buffer.var); call Stacks.pushOperand(context, arg); break; case OPbsize: dbg(DBG_USR1, "VM (%i): Pushing size of buffer.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} call Stacks.pushOperand(context, arg); call Stacks.pushValue(context, arg->buffer.var->size); break; case OPcopy: dbg(DBG_USR1, "VM (%i): Copying top of stack.\n", (int)context->which); call Stacks.pushOperand(context, arg); call Stacks.pushOperand(context, arg); break; case OPpop: break; default: call BombillaError.error(context, BOMB_ERROR_INVALID_INSTRUCTION); dbg(DBG_ERROR, "VM (%i): Unrecognized class 1 instruction: 0x%hhx.\n", (int)context->which, instr); } } void execute2ClassInstruction(BombillaContext* context, uint8_t instr) { BombillaStackVariable* arg = call Stacks.popOperand(context); switch(instr) { case OPbsorta: dbg(DBG_USR1, "VM (%i): Sorting buffer ascending.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} call Buffer.sortAscending(context, arg->buffer.var); call Stacks.pushOperand(context, arg); break; case OPbsortd: dbg(DBG_USR1, "VM (%i): Sorting buffer descending.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} call Buffer.sortDescending(context, arg->buffer.var); call Stacks.pushOperand(context, arg); break; case OPbfull: dbg(DBG_USR1, "VM (%i): Checking if buffer full.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_B)) {return;} call Stacks.pushValue(context, (arg->buffer.var->size == BOMB_BUF_LEN)? 1: 0); call Stacks.pushOperand(context, arg); break; case OPputled: dbg(DBG_USR1, "VM (%i): Setting LEDs.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_V)) {return;} ledOP(arg->value.var); break; case OPcast: dbg(DBG_USR1, "VM (%i): Casting.\n", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_S)) {return;} call Stacks.pushValue(context, arg->sense.var); break; case OPunlock: dbg(DBG_USR1, "VM (%i): Yielding lock", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_V)) {return;} if (arg->value.var >= BOMB_HEAPSIZE || arg->value.var < 0) { call BombillaError.error(context, BOMB_ERROR_INVALID_LOCK); return; } dbg_clear(DBG_USR1, " %i\n", (int)arg->value.var); context->releaseSet |= (1 << arg->value.var); context->acquireSet |= (1 << arg->value.var); break; case OPunlockb: { dbg(DBG_USR1, "VM (%i): Yielding locks", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_V)) {return;} if ((arg->value.var & context->heldSet) != arg->value.var) { call BombillaError.error(context, BOMB_ERROR_UNLOCK_INVALID); return; } dbg_clear(DBG_USR1, " 0x%hx\n", arg->value.var); context->releaseSet |= arg->value.var; context->acquireSet |= arg->value.var; break; } case OPpunlock: dbg(DBG_USR1, "VM (%i): Releasing lock", (int)context->which); if (!checkTypes(context, arg, BOMB_VAR_V)) {return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -