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;
    }
}
示例#2
0
文件: reserve.c 项目: shepheb/kernel
// 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);
}