static void transferBasisRelease (BREthereumTransferBasis *basis) { switch (basis->type) { case TRANSFER_BASIS_TRANSACTION: transactionRelease (basis->u.transaction); basis->u.transaction = NULL; break; case TRANSFER_BASIS_LOG: logRelease (basis->u.log); basis->u.log = NULL; break; } }
// reservation server protocol: // send a MSG_RESERVE_REQUEST with the list of nodes you want to reserve // if blocking, you'll block until the nodes are all available, at which point you'll get an ok // if non-blocking, you'll immediately either get an ok or a fail, depending on whether the request is satisfiable // when you want to unreserve, send a MSG_RESERVE_RELEASE with the nodes you want to release; you'll get NOTHING BACK void reservation_server(void) { // allocate a list of blocked tasks and the requests they made BlockList bl[MAX_ENGINEERS]; // initialize all of the bl elements to invalid int blIndex; for (blIndex=0; blIndex<MAX_ENGINEERS; blIndex++) { bl[blIndex].tid = -1; // tid == -1 means invalid } // deadlock detection algorithm: // * maintain hold list (hl) in addition to bl. // * accomodateRequest also returns a list of engineers I'm waiting on // * if I do need to block, this list is necessarily non-empty // * then check the block lists for these same engineers and see if they're blocked on anything I hold // * if so, that's a deadlock. // but there's no way I can implement this tonight. RegisterAs("reservationserver"); FOREVER { // receive buffers int tid; MsgReservation request; MsgReservation reply; Receive(&tid, (char *)&request, sizeof(MsgReservation)); switch(request.type) { case MSG_RESERVE_REQUEST_BLOCKING: ; Node *rcNode = resConflict(request.numNodes, request.nodes, tid); if (rcNode == NULL) { // if the request can be accomodated, log it logReservation(request.numNodes, request.nodes, tid, request.iAmPacman, request.trainNum, request.curDir); } else { // else if the request cannot be accomodated // deadlock detection printf0("Res Serv.: Checking for deadlock...\n\r"); // the tid of the task that currently has this reservation int otherTid = (rcNode->type == NODE_SWITCH) ? ((Switch *)(rcNode))->reserverTid : ((Sensor *)(rcNode))->reserverTid; int blIndex = findTidInBlockList(otherTid, bl); printf2("Res Serv.: otherTid: %d, otherIsblocked? %d!\n\r", otherTid, blIndex != -1); // if this other tid is blocked and wants a node we own, that's a deadlock if (blIndex != -1 && blWantsNodeHeldBy(bl[blIndex], tid)) { // we now know we have a deadlock, so it's time to resolve it printf2("Res Serv.: DEADLOCK between tr. %d and tr. %d!\n\r", request.trainNum, bl[blIndex].trainNum); // if we're the pacman or // the other one isn't a pacman and we have the lower train number if (request.iAmPacman || (!((rcNode->type == NODE_SWITCH) ? ((Switch *)rcNode)->reserverIAmPacman : ((Sensor *)rcNode)->reserverIAmPacman) && (request.trainNum <= ((rcNode->type == NODE_SWITCH) ? ((Switch *)rcNode)->reserverTrainNum : ((Sensor *)rcNode)->reserverTrainNum) ))) { // find a node to move to Node *nodeToMoveTo = moveAway(request.trainLoc, request.curDir == 'F' ? 'B' : 'F'); printf1("Res Serv.: GTFO self (train %d) to ", request.trainNum); if (nodeToMoveTo == NULL) { printf0("NULL"); } else { printNode2(nodeToMoveTo); } printf1(", curDir %c!\n\r", (int)request.curDir); if (nodeToMoveTo == NULL) { // if we can't move away, it's the game over case printf0("res. serv.: case 1.\n\r"); int pacmanServerTid = WhoIs("pacmanserver"); char c = MSG_PACMAN_GAMEOVER; int retVal = Send(pacmanServerTid, &c, 1, NULL, 0); printf1("res. serv.: retVal from Reply to PMS: %d\n\r", retVal); reply.type = MSG_RESERVE_GAMEOVER; retVal = Reply(tid, (char *)&reply, sizeof(MsgReservation)); printf1("res. serv.: retVal from Reply to train: %d\n\r", retVal); int i; for (i=0; i<MAX_ENGINEERS; i++) { if (bl[i].tid != -1) { reply.type = MSG_RESERVE_GAMEOVER; retVal = Reply(bl[blIndex].tid, (char *)&reply, sizeof(MsgReservation)); printf1("res. serv.: retVal from Reply to train: %d\n\r", retVal); } } } else { // else if we can move away, send the move reply reply.type = MSG_RESERVE_MOVE; reply.numNodes = 1; reply.nodes[0] = nodeToMoveTo; printf0("res. serv.: about to reply case 2.\n\r"); int retVal = Reply(tid, (char *)&reply, sizeof(MsgReservation)); printf1("res. serv.: retVal from Reply to train: %d\n\r", retVal); } } else { // else the other train needs to move out of the way // find a node to move to Node *nodeToMoveTo = moveAway(bl[blIndex].trainLoc, bl[blIndex].curDir == 'F' ? 'B' : 'F'); printf1("Res Serv.: GTFO other (train %d) to ", bl[blIndex].trainNum); if (nodeToMoveTo == NULL) { printf0("NULL"); } else { printNode2(nodeToMoveTo); } printf1(", curDir %c!\n\r", (int)bl[blIndex].curDir); if (nodeToMoveTo == NULL) { // if we can't move away, it's the game over case printf0("res. serv.: case 1.\n\r"); int pacmanServerTid = WhoIs("pacmanserver"); char c = MSG_PACMAN_GAMEOVER; int retVal = Send(pacmanServerTid, &c, 1, NULL, 0); printf1("res. serv.: retVal from Reply to PMS: %d\n\r", retVal); reply.type = MSG_RESERVE_GAMEOVER; retVal = Reply(tid, (char *)&reply, sizeof(MsgReservation)); printf1("res. serv.: retVal from Reply to train: %d\n\r", retVal); int i; for (i=0; i<MAX_ENGINEERS; i++) { if (bl[i].tid != -1) { reply.type = MSG_RESERVE_GAMEOVER; retVal = Reply(bl[blIndex].tid, (char *)&reply, sizeof(MsgReservation)); printf1("res. serv.: retVal from Reply to train: %d\n\r", retVal); } } } else { // else if we can move away, send the move reply reply.type = MSG_RESERVE_MOVE; reply.numNodes = 1; reply.nodes[0] = nodeToMoveTo; printf0("res. serv.: about to reply case 2.\n\r"); int retVal = Reply(bl[blIndex].tid, (char *)&reply, sizeof(MsgReservation)); printf1("res. serv.: retVal from Reply to train: %d\n\r", retVal); // remove the other train from the block list, since he's no longer going to be blocked bl[blIndex].tid = -1; // now, block the current train, waiting for the other one to get ouf of the way blockTask(tid, request.iAmPacman, request.trainNum, request.trainLoc, request.curDir, request.numNodes, request.nodes, bl); } } } else { // else if it's not a deadlock, just a reservation conflict, handle it normally by blocking blockTask(tid, request.iAmPacman, request.trainNum, request.trainLoc, request.curDir, request.numNodes, request.nodes, bl); } } break; case MSG_RESERVE_REQUEST_NONBLOCKING: if (resConflict(request.numNodes, request.nodes, tid) == NULL) { // if the request can be accomodated, log it and reply logReservation(request.numNodes, request.nodes, tid, request.iAmPacman, request.trainNum, request.curDir); reply.type = MSG_RESERVE_OK; Reply(tid, (char *)&reply, sizeof(MsgReservation)); } else { // else if the request cannot be accomodated, send a fail message back reply.type = MSG_RESERVE_FAIL; Reply(tid, (char *)&reply, sizeof(MsgReservation)); } break; case MSG_RESERVE_RELEASE: logRelease(request.numNodes, request.nodes, request.trainNum); // log the release Reply(tid, NULL, 0); // reply with a NULL buffer // now, check if any waiting task can now be awoken due to the release for (blIndex = 0; blIndex<MAX_ENGINEERS; blIndex++) { // if the bl entry is valid and we can now accomodate it, do so if (bl[blIndex].tid != -1 && resConflict(bl[blIndex].numNodes, bl[blIndex].nodes, bl[blIndex].tid) == NULL) { // log the reservation logReservation(bl[blIndex].numNodes, bl[blIndex].nodes, bl[blIndex].tid, bl[blIndex].iAmPacman, bl[blIndex].trainNum, bl[blIndex].curDir); // reply to the task, telling it the reserve has finally been processed reply.type = MSG_RESERVE_OK; Reply(bl[blIndex].tid, (char *)&reply, sizeof(MsgReservation)); // ...and invalidate its entry in the block list bl[blIndex].tid = -1; } } break; default: bwprintf(COM2, "ERROR: illegal reservation request type %d! Halt!!!", request.type); Halt(); break; } // switch } // FOREVER return; // can't happen due to above FOREVER loop }
static void ewmHandleLogEventDestroyer (BREthereumHandleLogEvent *event) { logRelease(event->log); }