void ipc1 () { bwprintf (COM2, "ipc1: I am %d\r\n", MyTid()); bwprintf (COM2, "ipc1: Registering as LOL\r\n"); RegisterAs ("LOL"); RegisterAs ("POO"); bwprintf (COM2, "ipc1: Registration complete.\r\n"); bwprintf (COM2, "ipc1: WhoIs(\"LOL\") = %d\r\n",WhoIs("LOL")); bwprintf (COM2, "ipc1: Exiting.\r\n"); bwprintf (COM2, "ipc1: WhoIs(\"POO\") = %d\r\n",WhoIs("POO")); Exit(); }
void RPSServer_Start() { robprintfbusy((const unsigned char *)"RPSServer created tid=%d\n", MyTid()); int result = RegisterAs((char*) RPS_SERVER_NAME); assert(result == 0, "RPSServer_Start failed to register name"); ChannelDescription terminal_channel; terminal_channel.channel = COM2; terminal_channel.speed = 115200; robsetspeed( &terminal_channel); RPSServer server; RPSServer_Initialize(&server); while(1) { RPSServer_ProcessMessage(&server); if (!server.running) { break; } } robprintfbusy((const unsigned char *)"RPSServer exited\n"); NameServerMessage * name_server_message = (NameServerMessage *) server.send_buffer; NameServerMessage * reply_message = (NameServerMessage *) server.reply_buffer; name_server_message->message_type = MESSAGE_TYPE_NAME_SERVER_SHUTDOWN; Send(NAMESERVER_TID, server.send_buffer, MESSAGE_SIZE, server.reply_buffer, MESSAGE_SIZE); assert(reply_message->message_type==MESSAGE_TYPE_ACK, "RPSServer didn't get ACK from name server"); Exit(); assert(0, "Shouldn't see me\n"); }
void sensor_server() { struct SensorService service; sensorservice_initialize(&service); RegisterAs("SensorServer"); // Create the thing sending us sensor messages. Create(HIGH, sensor_notifier); tid_t stream = CreateStream("SensorServerStream"); int tid; SensorServerMessage msg, rply; for(;;) { Receive(&tid, (char *) &msg, sizeof(msg)); switch(msg.type) { case SENSOR_EVENT_REQUEST: rply.type = SENSOR_EVENT_RESPONSE; Reply(tid, (char *) &rply, sizeof(rply)); sensorservice_process_data(&service, msg.data); publish(&service, stream); break; default: ulog("Invalid SensorServer Request"); } } Exit(); }
void routeFinder( ) { track_node track[TRACK_MAX]; init_tracka(track); RegisterAs( "route" ); // int printer = MyParentTid(); ComReqStruct reply; int sender; FOREVER { Receive( &sender, (char *)&reply, sizeof(ComReqStruct) ); int src = reply.data1; // No offset right now int dest = reply.data2; // Begin finding the shortest path from the src to the dest Path shortest; route( track, &shortest, src, dest ); ComReqStruct fus, roh; fus.type = UPDATE_STAT; fus.data1 = (int *)&shortest; Send( MyParentTid(), (char *)&fus, sizeof(ComReqStruct), (char *)&roh, sizeof(ComReqStruct) ); Reply( sender, (char *)&shortest, sizeof(Path) ); } }
void plAgeLoader::Init() { RegisterAs( kAgeLoader_KEY ); plgDispatch::Dispatch()->RegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey()); plgDispatch::Dispatch()->RegisterForExactType(plClientMsg::Index(), GetKey()); plgDispatch::Dispatch()->RegisterForExactType(plResPatcherMsg::Index(), GetKey()); }
void plAutoProfileImp::IInit() { // TODO: Find a better way to grab a list of age names, since the old data server // no longer exists /*plIDataServer* dataServer = plNetClientMgr::GetInstance()->GetDataServer(); if (!dataServer) return; dataServer->GetDatasetAges(fAges);*/ // The first age we link into is AvatarCustomization, since we have a new avatar. // Coincidentally, the first age in our list is AvatarCustomization. However, // sometimes linking from ACA to ACA causes a crash. To get around that, we just // reverse the list, so it's last. std::reverse(fAges.begin(), fAges.end()); fNextAge = 0; RegisterAs(kAutoProfile_KEY); plgDispatch::Dispatch()->RegisterForExactType(plAgeBeginLoadingMsg::Index(), GetKey()); plgDispatch::Dispatch()->RegisterForExactType(plAgeLoadedMsg::Index(), GetKey()); plgDispatch::Dispatch()->RegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey()); plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey()); plConsoleMsg* consoleMsg = new plConsoleMsg(plConsoleMsg::kExecuteLine, "Camera.AlwaysCut true"); consoleMsg->Send(); }
void plInputInterfaceMgr::Init( void ) { RegisterAs( kInputInterfaceMgr_KEY ); plgDispatch::Dispatch()->RegisterForType( plInputIfaceMgrMsg::Index(), GetKey() ); plgDispatch::Dispatch()->RegisterForType( plInputEventMsg::Index(), GetKey() ); plgDispatch::Dispatch()->RegisterForType( plEvalMsg::Index(), GetKey() ); plgDispatch::Dispatch()->RegisterForExactType( plPlayerPageMsg::Index(), GetKey() ); plgDispatch::Dispatch()->RegisterForExactType( plCmdIfaceModMsg::Index(), GetKey() ); plgDispatch::Dispatch()->RegisterForExactType( plClientMsg::Index(), GetKey() ); /// Hacks (?) for now plAvatarInputInterface *avatar = new plAvatarInputInterface(); IAddInterface( avatar ); hsRefCnt_SafeUnRef( avatar ); plSceneInputInterface *scene = new plSceneInputInterface(); IAddInterface( scene ); hsRefCnt_SafeUnRef( scene ); plDebugInputInterface *camDrive = new plDebugInputInterface(); IAddInterface( camDrive ); hsRefCnt_SafeUnRef( camDrive ); }
void rps_server() { int q[50]; int start = 0; int end = 0; int p1=0, p2=0; char a1, a2; char m[2]; m[1] = 0; int tid; int nump = 0; bwprintf (COM2, "RPS server started.\r\n"); RegisterAs ("RPS"); // bwprintf (COM2, "I AM REGISTERED??? WhoIs (\"RPS\") = %d\r\n",WhoIs ("RPS")); while (1) { Receive (&tid, m, 1); // bwprintf (COM2, "dicks"); switch (m[0]) { case 'J': bwprintf (COM2, "RPS_SERVER: %d joined.\r\n", tid); q[end]=tid; end++; break; case 'R': case 'P': case 'S': if (p1 == 0 || p2 == 0) { m[0] = 'Q'; Reply (tid, m, 1); } if (p1 == tid) { bwprintf (COM2, "RPS_SERVER: Player 1 says %c.\r\n", m[0]); a1 = m[0]; } else { bwprintf (COM2, "RPS_SERVER: Player 2 says %c.\r\n", m[0]); a2 = m[0]; } break; case 'Q': bwprintf (COM2, "RPS_SERVER: %d quit.", tid); if (tid == p1) p1 = 0; else p2 = 0; p1=0;p2=0; break; } if (p1 == p2 && p1 == 0 && end-start >= 2) { p1 = q[start]; p2 = q[start+1]; start += 2; bwprintf (COM2, "\r\n RPS_SERVER: Start game: %d vs. %d.\r\n", p1, p2); nump -= 2; a1 = a2 = 0; Reply (p1, 0, 0); Reply (p2, 0, 0); } if (a1 != 0 && a2 != 0) { if (a1 == 'R' && a2 == 'R') { m[0] = 'T'; Reply (p1, m, 1); m[0] = 'T'; Reply (p2, m, 1); } else if (a1 == 'R' && a2 == 'P') { m[0] = 'L'; Reply (p1, m, 1); m[0] = 'W'; Reply (p2, m, 1); } else if (a1 == 'R' && a2 == 'S') { m[0] = 'W'; Reply (p1, m, 1); m[0] = 'L'; Reply (p2, m, 1); } else if (a1 == 'P' && a2 == 'R') { m[0] = 'W'; Reply (p1, m, 1); m[0] = 'L'; Reply (p2, m, 1); } else if (a1 == 'P' && a2 == 'P') { m[0] = 'T'; Reply (p1, m, 1); m[0] = 'T'; Reply (p2, m, 1); } else if (a1 == 'P' && a2 == 'S') { m[0] = 'L'; Reply (p1, m, 1); m[0] = 'W'; Reply (p2, m, 1); } else if (a1 == 'S' && a2 == 'R') { m[0] = 'L'; Reply (p1, m, 1); m[0] = 'W'; Reply (p2, m, 1); } else if (a1 == 'S' && a2 == 'P') { m[0] = 'W'; Reply (p1, m, 1); m[0] = 'L'; Reply (p2, m, 1); } else if (a1 == 'S' && a2 == 'S') { m[0] = 'T'; Reply (p1, m, 1); m[0] = 'T'; Reply (p2, m, 1); } a1 = a2 = 0; } } }
/*! Registers the function as a function in excel. \sa XlfExcel, XlfCmdDesc. */ int xlw::XlfFuncDesc::DoRegister(const std::string& dllName, const std::string& suggestedHelpId) const { if (returnTypeCode_.empty()) returnTypeCode_= XlfExcel::Instance().xlfOperType(); if(returnTypeCode_ == "XLW_FP") returnTypeCode_= XlfExcel::Instance().fpType(); return RegisterAs(dllName, suggestedHelpId, 1); }
static VOID SwitchpTask() { SWITCH_DIRECTION directions[NUM_SWITCHES]; VERIFY(SUCCESSFUL(RegisterAs(SWITCH_SERVER_NAME))); IO_DEVICE com1; VERIFY(SUCCESSFUL(Open(UartDevice, ChannelCom1, &com1))); for (UINT i = 0; i < NUM_SWITCHES; i++) { UCHAR sw = SwitchpFromIndex(i); VERIFY(SUCCESSFUL(SwitchpDirection(&com1, sw, SwitchCurved))); directions[i] = SwitchCurved; ShowSwitchDirection(i, sw, SwitchCurved); } VERIFY(SUCCESSFUL(SwitchpDisableSolenoid(&com1))); while (1) { INT senderId; SWITCH_REQUEST request; VERIFY(SUCCESSFUL(Receive(&senderId, &request, sizeof(request)))); switch(request.type) { case SetDirectionRequest: { VERIFY(SUCCESSFUL(SwitchpDirection(&com1, request.sw, request.direction))); VERIFY(SUCCESSFUL(SwitchpDisableSolenoid(&com1))); UINT switchIndex = SwitchpToIndex(request.sw); directions[switchIndex] = request.direction; VERIFY(SUCCESSFUL(Reply(senderId, NULL, 0))); ShowSwitchDirection(switchIndex, request.sw, request.direction); break; } case GetDirectionRequest: { UINT switchIndex = SwitchpToIndex(request.sw); SWITCH_DIRECTION direction = directions[switchIndex]; VERIFY(SUCCESSFUL(Reply(senderId, &direction, sizeof(direction)))); break; } } } }
void ClockServer_Start() { ClockServer server; ClockServer_Initialize(&server); GenericMessage * receive_msg = (GenericMessage *) server.receive_buffer; int source_tid; assert(sizeof(NotifyMessage) <= MESSAGE_SIZE, "NotifyMessage size too big"); assert(sizeof(ClockMessage) <= MESSAGE_SIZE, "ClockMessage size too big"); robprintfbusy((const unsigned char *)"ClockServer TID=%d: start\n", server.tid); int return_code = RegisterAs((char *)CLOCK_SERVER_NAME); assert(return_code == 0, "ClockServer: Failed to register name"); int tid = Create(HIGHEST, ClockNotifier_Start); assert(tid > 0, "ClockNotifier tid not positive"); // For Debugging *TIMER4_VAL_HIGH |= 1 << 8; server.last_timer_value = *TIMER4_VAL_LOW; while (server.running) { Receive(&source_tid, server.receive_buffer, MESSAGE_SIZE); //robprintfbusy((const unsigned char *)"ClockServer: received %d message type\n", receive_msg->message_type); switch(receive_msg->message_type) { case MESSAGE_TYPE_NOTIFIER: ClockServer_HandleNotifier(&server, source_tid, (NotifyMessage*) receive_msg); break; case MESSAGE_TYPE_TIME_REQUEST: ClockServer_HandleTimeRequest(&server, source_tid, (ClockMessage*) receive_msg); break; case MESSAGE_TYPE_DELAY_REQUEST: ClockServer_HandleDelayRequest(&server, source_tid, (ClockMessage*) receive_msg, 0); break; case MESSAGE_TYPE_DELAY_UNTIL_REQUEST: ClockServer_HandleDelayRequest(&server, source_tid, (ClockMessage*) receive_msg, 1); break; case MESSAGE_TYPE_SHUTDOWN: ClockServer_HandleShutdownRequest(&server, source_tid, (ClockMessage*) receive_msg); break; default: assertf(0, "ClockServer: unknown message type %d", receive_msg->message_type); break; } ClockServer_UnblockDelayedTasks(&server); Pass(); } robprintfbusy((const unsigned char *)"ClockServer TID=%d: end\n", server.tid); Exit(); }
void InputInit() { struct IOMessagebuf bufMsg; struct IOMessage *msg = (struct IOMessage *)&bufMsg; int reply, src; struct IONode nodes[100]; struct IONode *first[2] = {NULL, NULL}; struct IONode *last[2] = {NULL, NULL}; int buffer1[BUFFERSIZE]; int buffer2[BUFFERSIZE]; int bufHead[2] = {0, 0}; int bufTail[2] = {0, 0}; int notifier1Tid = Create(7, notifier); int notifier2Tid = Create(7, bufferedNotifier); int eventType = TERMIN_EVENT; Send(notifier2Tid, (char *)&eventType, sizeof(int), (char *)&reply, sizeof(int)); eventType = TRAIIN_EVENT; Send(notifier1Tid, (char *)&eventType, sizeof(int), (char *)&reply, sizeof(int)); RegisterAs("Input Server"); while(true) { Receive(&src, (char *)&bufMsg, sizeof(struct IOMessagebuf)); switch(bufMsg.type) { case IONOTIFIER: reply = 0; Reply(src, (char *)&reply, sizeof(int)); if(src == notifier1Tid){ handleNewInput(&first[0], last[0], buffer1, &bufHead[0], bufTail[0], (char)msg->data); }else if(src == notifier2Tid) { int *buffer = bufMsg.data; while(*buffer != (int)'\0') { handleNewInput(&first[1], last[1], buffer2, &bufHead[1], bufTail[1], *buffer); buffer++; } } break; case IOINPUT: nodes[src & 0x7F].tid = src; if (msg->channel == 1){ handleNewInputTask(&first[0], &last[0], buffer1, bufHead[0], &bufTail[0], &nodes[src & 0x7F]); }else if(msg->channel == 2) { handleNewInputTask(&first[1], &last[1], buffer2, bufHead[1], &bufTail[1], &nodes[src & 0x7F]); } break; } } }
void IdleTask_Start(){ RegisterAs((char*) IDLE_TASK_NAME); /* While we are waiting for events, this task and the administrator just send messages back and forth */ char send_buffer[MESSAGE_SIZE] __attribute__ ((aligned (4))); char reply_buffer[MESSAGE_SIZE] __attribute__ ((aligned (4))); GenericMessage * send_message = (GenericMessage *) send_buffer; GenericMessage * reply_message = (GenericMessage *) reply_buffer; send_message->message_type = MESSAGE_TYPE_HELLO; int admin_tid; int tid_i = 0; while (1) { admin_tid = WhoIs((char*) ADMINISTRATOR_TASK_NAME); if (admin_tid) { break; } tid_i++; assert(tid_i < 1000, "IdleTask: admin tid not found"); } int i = 0; while(1){ if (i > 5000) { Send(admin_tid, send_buffer, MESSAGE_SIZE, reply_buffer, MESSAGE_SIZE); assertf(reply_message->message_type == MESSAGE_TYPE_ACK || reply_message->message_type == MESSAGE_TYPE_SHUTDOWN, "fail\n"); if(reply_message->message_type == MESSAGE_TYPE_SHUTDOWN){ break; robprintfbusy((const unsigned char *)"IdleTask_Start: Got shutdown\n" ); } i = 0; } else { Pass(); } i++; } Exit(); assert(0,"Nope."); }
void route_server() { bwdebug( DBG_SYS, ROUTE_SRV_DEBUG_AREA, "ROUTE_SERVER: enters" ); RegisterAs( ROUTE_SERVER_NAME ); // Data structures int sender_tid; Route_msg route_msg; while(1) { bwdebug( DBG_SYS, ROUTE_SRV_DEBUG_AREA, "ROUTE_SERVER: listening for a request" ); Receive( &sender_tid, ( char * ) &route_msg, sizeof( route_msg ) ); bwdebug( DBG_SYS, ROUTE_SRV_DEBUG_AREA, "ROUTE_SERVER: Received request [ sender_tid: %d type: %d ]", sender_tid, route_msg.type ); switch( route_msg.type ){ //This message can arrive from: // Train A // Train B // Train AI case GET_SHORTEST_ROUTE_MSG: get_shortest_route( route_msg.track, route_msg.train_direction, route_msg.current_landmark, route_msg.train_shift, route_msg.target_node, route_msg.target_shift, route_msg.switches, route_msg.route_found, route_msg.landmarks, route_msg.num_landmarks, route_msg.edges); bwdebug( DBG_SYS, ROUTE_SRV_DEBUG_AREA, "ROUTE_SERVER: Replying request [ sender_tid: %d type: %d ]", sender_tid, route_msg.type ); Reply( sender_tid, 0, 0 ); break; default: bwdebug( DBG_SYS, ROUTE_SRV_DEBUG_AREA, "ROUTE_SERVER: Invalid request. [type: %d]", route_msg.type ); break; } } }
void clockServerTask() { // Initialize variables int tid = 0; unsigned int tick = 0; ClockReq req; req.type = 0; req.data = 0; DelayedQueue q; initDelayedTasks(&q); // Register with name server RegisterAs("clockServer"); // Spawn notifier Create(PRIORITY_CLOCK_NOTIFIER, &clockNotifier); // Main loop for serving requests for (;;) { Receive(&tid, &req, sizeof(req)); switch (req.type) { case NOTIFICATION: Reply(tid, 0, 0); tick++; removeExpiredTasks(&q, tick); break; case TIME: Reply(tid, &tick, sizeof(tick)); break; case DELAY: insertDelayedTask(&q, tid, req.data + tick); break; case DELAY_UNTIL: insertDelayedTask(&q, tid, req.data); break; default: bwprintf(COM2, "[Clockserver] Invalid request type: %d\n\r", req.type); for (;;); break; } } }
void routeFinder( ) { track_node track[TRACK_MAX]; init_tracka(track); RegisterAs( "route" ); int myAdmin = MyParentTid(); int monitor = WhoIs( "monitor" ); // int printer = MyParentTid(); ComReqStruct reply, reservation,send; int sender; int trains[2]; // first train use the first Path structure, second train use the second path trains[0] = 0; trains[1] = 0; Path paths[2]; FOREVER { Receive( &sender, (char *)&reply, sizeof(ComReqStruct) ); int src = reply.data1; // No offset right now int dest = reply.data2; // Begin finding the shortest path from the src to the dest int i; if ( trains[0] == 0 || sender == trains[0] ) { trains[0] = sender; i = 0; } else if ( trains[1] == 0 || sender == trains[1] ) { trains[1] = sender; i = 1; } route( track, &paths[i], src, dest ); // ComReqStruct fus, roh; // fus.type = UPDATE_STAT; // fus.data1 = (int *)&paths[i]; // Send( MyParentTid(), (char *)&fus, sizeof(ComReqStruct), (char *)&roh, sizeof(ComReqStruct) ); Reply( sender, (char *)&paths[i], sizeof(Path) ); } }
void sem_server() { Sem_request request; Semaphore* sem; int tid; int status; status = RegisterAs( SEMAPHORE_SERVER_NAME ); assert( status == REGISTER_AS_SUCCESS ); while( 1 ) { status = Receive( &tid, ( char* )&request, sizeof( request ) ); assert( status == sizeof( request ) ); sem = request.sem; switch( request.type ) { case SEM_RELEASE: sem->count += 1; status = Reply( tid, ( char* )&status, sizeof( status ) ); assert( status == SYSCALL_SUCCESS ); break; case SEM_AC_ALL: if( sem->count > 0 ) { sem->count = 1; } // Fall through case SEM_ACQUIRE: status = rbuf_put( &sem->wait_queue, ( uchar* )&tid ); assert( status == ERR_NONE ); break; } while( sem->count > 0 && ! rbuf_empty( &sem->wait_queue ) ) { sem->count -= 1; rbuf_get( &sem->wait_queue, ( uchar* )&tid ); status = Reply( tid, ( char* )&status, sizeof( status ) ); assert( status == SYSCALL_SUCCESS ); } } }
void rps_server_run() { RegisterAs("RPS Server"); int tid; rps_request req; while (1) { Receive(&tid, (char *)&req, sizeof(rps_request)); switch (req.type) { case SIGNUP: _signup(tid); break; case PLAY: _play(tid, req.move); break; case QUIT: _quit(tid); break; default: ERROR("Invalid rps request type %d\n", req.type); } } }
main() { char sendData='s'; char strWrite[20]; int tid_sensorSrv; unsigned char sensorSendData[5], sensor; RegisterAs("SensorReporter"); Delay(10); tid_sensorSrv = WhoIs( "SensorSrv"); while( 1 ) { Send(tid_sensorSrv,NULL,NULL, &sensorSendData,5*sizeof(char)); sensor = sensorSendData[0]; sprintf(strWrite,"se %c %d\n",SEN_MODULE_CHAR(sensor), SEN_NUMBER(sensor)); Write(strWrite, strLen(strWrite), WYSE); Delay( 5 ); } /* while */ }
//responsible for displaying all the necessary information to the screen many times per second. //runs at fairly low priority by design. //output includes: // * switch states // * sensor triggering timestamps // * current positions of up to 3 trains relative to parts of the track // almost never blocks, just keeps spinning when nothing higher-priority needs to run void display_server(void){ TrainState trains[MAX_TRAINS]; int train_count = 0; SensorState sensors[SENSOR_HISTORY_LEN]; int sensor_start = 0; int sensor_len = 0; SwitchState switches[18+4]; int active = 0; int i; // initialze switches 1-18 for(i=0; i < 18; i++){ switches[i].number = i+1; switches[i].state = '?'; } // and switches 153-156 for(i=0; i < 4; i++){ switches[i+18].number = i+153; switches[i+18].state = '?'; } RegisterAs("displayserver"); int clockserverTid = WhoIs("clockserver"); if(clockserverTid < 0){ bwprintf(COM2, "Display server got tid %d for clocckserver\n\r", clockserverTid); Halt(); } Create(PRIORITY_MID, &display_notifier); Create(PRIORITY_MID, &display_sensor_notifier); int tid, len; MsgPrintf msg; int printf_col = 0; // now we can start drawing and receiving messages in a loop. FOREVER { len = Receive(&tid, (char*) &msg, sizeof(msg)); if(len > 0){ // I never have a useful Reply, so Reply immediately Reply(tid, NULL, 0); switch(msg.type){ case MSG_DISPLAY_REGISTER: ; // add a train with the provided number and speed 0 // if this is the first train, initialize the display if(train_count == 0){ clear_screen(); initialize_scrolling(); refresh_switches(switches); refresh_sensors(sensors, sensor_start, sensor_len); active = 1; } MsgRegister *msgReg = (MsgRegister*) &msg; trains[train_count].number = msgReg->train; trains[train_count].speed = 0; trains[train_count].route_len = 0; train_count++; break; case MSG_DISPLAY_DEREGISTER: ; // look up the train in the trains array, and pack the ones after it // special case for the last train msgReg = (MsgRegister*) &msg; if(train_count == 1){ //clear_screen(); restore_scrolling(); move_cursor(SCREEN_BOTTOM, 1); active = 0; train_count = 0; } else if(train_count == 0){ // do nothing } else { int i = 0; for(i=0; i < train_count; i++){ if(trains[i].number == msgReg->train){ break; } } // if we find the train, shift the rest of the array down if(i < train_count){ for(i=i+1; i < train_count; i++){ //copy to the previous one trains[i-1] = trains[i]; } train_count--; } } break; case MSG_DISPLAY_SPEED: ; // update the given train's speed MsgSpeed *msgSpeed = (MsgSpeed*) &msg; // flip through my trains for this number for(i = 0; i < train_count; i++){ if(trains[i].number == msgSpeed->train){ trains[i].speed = msgSpeed->speed; break; } } // will be redisplayed below break; case MSG_DISPLAY_SWITCH: ; MsgSwitch *msgSwitch = (MsgSwitch*) &msg; if(msgSwitch->number <= 18){ switches[msgSwitch->number-1].state = msgSwitch->state; } else { switches[msgSwitch->number-153+18].state = msgSwitch->state; } if(active){ refresh_switches(switches); } break; case MSG_DISPLAY_ROUTE: ; // somewhat more complicated. copy the route for the given train // first find the train index MsgRouteSegment *msgRoute = (MsgRouteSegment*) &msg; for(i = 0; i < train_count; i++){ if(trains[i].number == msgRoute->train){ trains[i].route_len = msgRoute->route_len; int j; for(j = 0; j < msgRoute->route_len; j++){ trains[i].route[j] = msgRoute->route[j]; } } } break; case MSG_SENSOR_CLIENT: ; // message from the sensor server // work through the array from the sensor server, and update my list of sensors // remember that the sensors array starts at start and start gets decremented MsgSensorResponse *msgResp = (MsgSensorResponse*) &msg; int timestamp = Time(clockserverTid); for(i = 0; i < msgResp->length; i++){ sensor_start--; if(sensor_start < 0) sensor_start = SENSOR_HISTORY_LEN-1; if(sensor_len < SENSOR_HISTORY_LEN) sensor_len++; getSensorName(msgResp->triggered[i], &(sensors[sensor_start])); sensors[sensor_start].time = timestamp; } if(active && msgResp->length > 0){ refresh_sensors(sensors, sensor_start, sensor_len); } break; case MSG_DISPLAY_PRINTF: ; move_cursor(SCREEN_BOTTOM, printf_col); switch(msg.argc){ case 0: aprintf(COM2, msg.format); break; case 1: aprintf(COM2, msg.format, msg.argv[0]); break; case 2: aprintf(COM2, msg.format, msg.argv[0], msg.argv[1]); break; case 3: aprintf(COM2, msg.format, msg.argv[0], msg.argv[1], msg.argv[2]); break; case 4: aprintf(COM2, msg.format, msg.argv[0], msg.argv[1], msg.argv[2], msg.argv[3]); break; case 5: aprintf(COM2, msg.format, msg.argv[0], msg.argv[1], msg.argv[2], msg.argv[3], msg.argv[4]); break; default: aprintf(COM2, "Bad argc: %d\n\r", msg.argc); break; } int len = strlen(msg.format); if(msg.format[len-1] == '\n' || msg.format[len-1] == '\r'){ printf_col = 0; } else { printf_col += len; } break; case MSG_TICK: ; // display the train position // very crude for now. also only handling one train if(active){ int i; int base_row; for(i = 0; i < train_count; i++){ base_row = TRAIN_TOP + TRAIN_SIZE*i; move_and_clear(base_row, TRAIN_LEFT); aprintf(COM2, "Train %2d: ", trains[i].number); move_and_clear(base_row+1, TRAIN_LEFT); aprintf(COM2, "Speed: %2d ", trains[i].speed); if(trains[i].route_len > 0){ SensorState ss; Sensor *s = (Sensor*) (trains[i].route[0]); getSensorName(s->alignment == 'F' ? s->forward_num : s->backward_num, &ss); move_and_clear(base_row+2, TRAIN_LEFT); aprintf(COM2, "Current sensor:\t%c%2d ", ss.module, ss.number); s = (Sensor*) (trains[i].route[ trains[i].route_len-1 ]); getSensorName(s->alignment == 'F' ? s->forward_num : s->backward_num, &ss); move_and_clear(base_row+3, TRAIN_LEFT); aprintf(COM2, "Next sensor:\t%c%2d ", ss.module, ss.number); } else { move_and_clear(base_row+2, TRAIN_LEFT); aprintf(COM2, "No route supplied."); } } } break; default: ; aprintf(COM2, "Display server: bogus type %d\n\r", msg.type); } } } }
void trackServer() { RegisterAs("trackServer"); int tid = 0; TrackServerReply reply; TrackServerMessage message; initTurnouts(); for (;;) { int len = Receive(&tid, &message, sizeof(message)); uassert(len == sizeof(TrackServerMessage)); int numReserve = message.numReserve; int numRelease = message.numRelease; uassert(numReserve >= 0 && numRelease >= 0); reply = Success; // renounce ownership of each node in this array // if the caller does not own this track, then warn and do nothing // else return ReleaseSuccess for (int i = 0; i < numRelease; i++) { track_node *releaseNode = message.releaseNodes[i]; uassert(releaseNode != 0); if (releaseNode->owner != -1 && releaseNode->owner != tid) { printf(COM2, "Tid %d trying to release node %s that doesn't belong to it", tid, releaseNode->name); } releaseNode->owner = -1; } // try to reserve each node in the reserve array, // if fails, then reply ReservationFailure // else, reply ReservationSuccess for (int i = 0; i < numReserve; i++) { track_node *reserveNode = message.reserveNodes[i]; uassert(reserveNode != 0); if (!isReservable(reserveNode, tid)) { if (reserveNode->owner != -1 && reserveNode->owner != tid) { reply = ReserveFailSameDir; } else { // head on collision reply = ReserveFailOppositeDir; } break; } else { reserveNode->owner = tid; } } Reply(tid, &reply, sizeof(reply)); } Exit(); }
void RegisterMulti(int trainNum){ char name[] = MULTI_TRAIN_NAME; name[3] = '0'+trainNum/10; name[4] = '0'+trainNum%10; RegisterAs(name); }
// Entry point of track-server void track_server_entry() { RegisterAs(TRACK_SERVER); // Initialize the track track_init(); // Initialize the reservation list reservation_init(train_reservations); // So we can update our own cached copy of the switch table int switch_courier_tid = CreateSwitchCourier(PRIORITY_HIGHEST - 1); int sender_tid; // Message buffer large enough to hold the largest message request char message_buffer[32]; while (1) { Receive(&sender_tid, message_buffer, sizeof(message_buffer)); if (sender_tid == switch_courier_tid) { // This is an update from the switch server, record the switch that changed // so that our cached table of switches is in sync int reply = 0; Reply(sender_tid, (char*)&reply, sizeof(reply)); struct switch_report* report = (struct switch_report*)message_buffer; switch_table[(int)report->sw] = report->direction; } else { // API requests to the track_server struct track_reply_message reply = {-1, -1}; int op = *(int*)message_buffer; switch(op) { // Handle track reservation requests case TRACK_OP_RESERVATION: { int reply = -1; struct reservation_request_message* reservation_msg = (struct reservation_request_message*)message_buffer; // Make the location be a sensor and positive offset that fits in the edge if (normalize_location(track, switch_table, &reservation_msg->position) != -1) { // Check if we can reserve this space for the train int status = reservation_verify(reservation_msg->train, &(reservation_msg->position), reservation_msg->length, reservation_msg->branch_safety); reply = status; if (status == 0) { // We succeeded. Reserve the track // Find the train's reservation_node struct reservation_node* train_r = get_reservation(train_reservations, reservation_msg->train); if (train_r != 0) { clear_train_reservations(train_r); // Add new reservation reservation_insert(train_r, &(reservation_msg->position), reservation_msg->length, reservation_msg->branch_safety); } } else if (status == -2) { // Reached max reservation } } else { Printf("Could not normalize\r"); } Reply(sender_tid, (char*)&reply, sizeof(reply)); } break; case TRACK_OP_RESERVATION_STRING: { struct reservation_request_message* reservation_msg = (struct reservation_request_message*)message_buffer; struct reservation_node* train_r = get_reservation(train_reservations, reservation_msg->train); char buf[300]; *buf = 0; // null termination character int len = 0; if (train_r != 0) { len = reservation_print(train_r, buf); } Reply(sender_tid, (char*)buf, len); // +1 for null termination char } break; case TRACK_OP_NODE_IS_RESERVED: { struct reservation_request_message* reservation_msg = (struct reservation_request_message*)message_buffer; int reserved = node_is_reserved(reservation_msg->train, reservation_msg->position.node); Reply(sender_tid, (char*)&reserved, sizeof(reserved)); } break; // Handle requests for calculating the distance between 2 nodes case TRACK_OP_TRACK_DISTANCE: { struct track_request_message* track_msg = (struct track_request_message*)message_buffer; if (track_msg->node1 < TRACK_MAX && track_msg->node2 < TRACK_MAX) { reply.distance = dist_between_nodes(track_msg->node1, track_msg->node2); } Reply(sender_tid, (char*)&reply, sizeof(reply)); } break; case TRACK_OP_TRACK_DISTANCE_UNTIL_GOAL: { struct track_request_message* track_msg = (struct track_request_message*)message_buffer; int distance = 0; if (track_msg->node1 < TRACK_MAX && track_msg->node2 < TRACK_MAX) { distance = dist_until_goal(track_msg->node1, track_msg->offset1, track_msg->node2, track_msg->offset2, track_msg->distance); } Reply(sender_tid, (char*)&distance, sizeof(distance)); } break; // Handle requests for getting the next sensor on the track case TRACK_OP_TRACK_NEXT_SENSOR: { struct track_request_message* track_msg = (struct track_request_message*)message_buffer; if (track_msg->node1 >= A1 && track_msg->node1 <= E16) { int distance; int next_sensor = next_sensor_node(track_msg->node1, track_msg->node2, &distance); reply.node = next_sensor; reply.distance = distance; } Reply(sender_tid, (char*)&reply, sizeof(reply)); } break; case TRACK_OP_NORMALIZE: { struct track_request_message *msg = (struct track_request_message*)message_buffer; struct location loc; loc.node = msg->node1; loc.offset = msg->offset1; if (normalize_location(track, switch_table, &loc) == -1) { Reply(sender_tid, (char*)&loc, 0); // reply size 0 means error! } Reply(sender_tid, (char*)&loc, sizeof(loc)); } break; // Handle requests for getting the reverse node of a given node case TRACK_OP_TRACK_REVERSE_NODE: { struct track_request_message* track_msg = (struct track_request_message*)message_buffer; if (track_msg->node1 < TRACK_MAX) { reply.node = track[track_msg->node1].reverse->num; } Reply(sender_tid, (char*)&reply, sizeof(reply)); } break; case TRACK_OP_ROUTE: { struct track_request_message* track_msg = (struct track_request_message*)message_buffer; int train = track_msg->train; int start_node_num = track_msg->node1; int end_node_num = track_msg->node2; short path[TRACK_MAX]; int num_nodes = 0; if (IS_SENSOR(start_node_num) && IS_SENSOR(end_node_num)) { struct track_node *start_node = &track[start_node_num]; struct track_node *end_node = &track[end_node_num]; mark_path(train, track, start_node, end_node); if (end_node->routing_info.visited == 1) { // we have a path! // store all nodes, from bottom up struct track_node *cur_node = end_node; struct location loc; while (cur_node->routing_info.previous != 0 && cur_node != start_node) { node_to_location(cur_node, &loc); path[num_nodes] = loc.node; num_nodes++; if (cur_node->routing_info.previous == cur_node->reverse) { // the next node is the reverse of this node, so we squeeze in a "REVERSE" in the path path[num_nodes] = -99; // magic number for REVERSE commands num_nodes++; } cur_node = cur_node->routing_info.previous; } // we didn't store the beginning node in our path, so we should do that now if (cur_node == start_node) { node_to_location(start_node, &loc); path[num_nodes] = loc.node; num_nodes++; } } else { Printf("Could not find route! num_nodes = %d\r", num_nodes); } } Reply(sender_tid, (char*)path, sizeof(short) * num_nodes); } break; case TRACK_OP_SWITCH_DIRECTION: { struct track_request_message* track_msg = (struct track_request_message*)message_buffer; int switch_node = track_msg->node1; int next_node = track_msg->node2; AssertF(track[switch_node].type == NODE_BRANCH, "TrackSwitchDirection not given a switch node! Given node num %d, type %d", track[switch_node].num, track[switch_node].type); int reserved = node_is_reserved(track_msg->train, switch_node); if (reserved) { // Printf("Attempting to switch %s if reserved .. \r", track[switch_node].name); int direction = -1; if (track[switch_node].edge[DIR_CURVED].dest == &(track[next_node])) { direction = SWITCH_CURVED; } else { direction = SWITCH_STRAIGHT; } SwitchSetDirection(track[switch_node].num, direction, WhoIs(SWITCH_SERVER)); switch_table[track[switch_node].num] = direction; } Reply(sender_tid, (char*)&reserved, sizeof(reserved)); } break; default: AssertF(0, "Invalid message %d to the track server from %d", op, sender_tid); Reply(sender_tid, (char*)&reply, sizeof(reply)); break; } } } Assert("Track server is quitting"); Exit(); }
static void timeserver_task() { int numTick= 0; char name[] = TIMESERVER_NAME; RegisterAs(name); // Initialize stack of delay tasks. for (int i = 0; i < TIMER_SERVER_SIZE-1; i++) { RegisteredTask* t = &(taskStack[i]); t->next = &(taskStack[i+1]); t->tid = -1; } { RegisteredTask* t = &(taskStack[TIMER_SERVER_SIZE-1]); t->next = (RegisteredTask*) -1; t->tid = -1; } RegisteredTask* taskSlots = &(taskStack[0]); RegisteredTask* tasks = (RegisteredTask*)-1; int notifierId = Create(HIGHEST_PRIORITY, timernotifier_task); // Start serving.. for (;;) { int msgBuff = -1; int tid = -1; int len = Receive(&tid, (char*)&msgBuff, 4); ASSERT(len == 0 || len == 4, "Bad message to time server."); if (tid == notifierId) { numTick += 1; Reply(tid, (char*)NULL, 0); // Reply to notifier } else if (len == 0) { // Timing request Reply(tid, (char*)&numTick, 4); } else { if (msgBuff & 0xf0000000) { // Delay message msgBuff += numTick; } // Delay until message, dont need to add current time. msgBuff &= 0x00ffffff; // Insert into linked list RegisteredTask* current = tasks; RegisteredTask* previous = (RegisteredTask*)-1; while (current != (RegisteredTask*)-1 && (msgBuff > current->time)) { previous = current; current = current->next; } // Insert right before t1, which is t2 RegisteredTask* newTask = taskSlots; taskSlots = taskSlots->next; //ASSERT(newTask != (RegisteredTask*)-1); if (previous != (RegisteredTask*)-1) { previous->next = newTask; } else { tasks = newTask; } newTask->next = current; newTask->time = msgBuff; newTask->tid = tid; } // Reply to applicable queues... while (tasks != (RegisteredTask*)-1 && tasks->time <= numTick) { Reply(tasks->tid, (char*)NULL, 0); RegisteredTask* unusedTask = tasks; tasks = tasks->next; unusedTask->next = taskSlots; taskSlots = unusedTask; } } // End of serve loop }
void clockserver() { char cs_name[] = CS_REG_NAME; assert(RegisterAs(cs_name) == 0, "Clockserver register failed"); unsigned int time = 0; TimeReply reply; ClockServerMsg message; int tid; /* heap implement */ Heap minheap; HeapNode *heap_data[TASK_MAX]; heapInitial(&minheap, heap_data, TASK_MAX); HeapNode nodes[TASK_MAX]; heapNodesInitial(nodes, TASK_MAX); int tid_array[TASK_MAX]; //actual datum in HeapNode int i = -1; for (i = 0; i < TASK_MAX; i++) { tid_array[i] = -1; } int notifier_tid = Create(1, notifier); while (1) { Receive(&tid, (char *)&message, sizeof(ClockServerMsg)); if (tid == notifier_tid) { Reply(tid, NULL, 0); time++; DEBUG(DB_CS, "| CS:\tTime : %d\n", time); while (minheap.heapsize > 0 && time >= minheap.data[0]->key) { HeapNode *top = minHeapPop(&minheap); Reply(*(int *)(top->datum), NULL, 0); } continue; } switch(message.type) { case CS_QUERY_TYPE_DELAY: // delay tid_array[tid % TASK_MAX] = tid; nodes[tid % TASK_MAX].key = message.delayQuery.delay_tick + time; nodes[tid % TASK_MAX].datum = &(tid_array[tid % TASK_MAX]); minHeapInsert(&minheap, &(nodes[tid % TASK_MAX])); break; case CS_QUERY_TYPE_DELAY_UNTIL: // delay until if (message.delayUntilQuery.delay_time <= time) { Reply(tid, NULL, 0); } else { tid_array[tid % TASK_MAX] = tid; nodes[tid % TASK_MAX].key = message.delayUntilQuery.delay_time; nodes[tid % TASK_MAX].datum = &(tid_array[tid % TASK_MAX]); minHeapInsert(&minheap, &(nodes[tid % TASK_MAX])); } break; case CS_QUERY_TYPE_TIME: // time reply.time = time; Reply(tid, (char*)(&reply), sizeof(TimeReply)); break; default: assert(0, "Clockserver received unknown query type"); break; } } }
static VOID RpspServerTask ( VOID ) { INT player1; RPS_SERVER_REQUEST player1Request; INT player2; RPS_SERVER_REQUEST player2Request; RPS_SERVER_RESPONSE results[MaxMove][MaxMove]; RegisterAs(RPS_SERVER_NAME); // Set up possible results results[RockMove][RockMove] = TieResponse; results[RockMove][PaperMove] = LoseResponse; results[RockMove][ScissorsMove] = WinResponse; results[PaperMove][RockMove] = WinResponse; results[PaperMove][PaperMove] = TieResponse; results[PaperMove][ScissorsMove] = LoseResponse; results[ScissorsMove][RockMove] = LoseResponse; results[ScissorsMove][PaperMove] = WinResponse; results[ScissorsMove][ScissorsMove] = TieResponse; // Wait for players Receive(&player1, &player1Request, sizeof(player1Request)); ASSERT(SignupRequest == player1Request.type); Receive(&player2, &player2Request, sizeof(player2Request)); ASSERT(SignupRequest == player2Request.type); // Let the players know the game is about to start Reply(player1, NULL, 0); Reply(player2, NULL, 0); // Start the game while(1) { bwprintf(BWCOM2, "Server: Starting match \r\n"); // Wait for hands from both players Receive(&player1, &player1Request, sizeof(player1Request)); Receive(&player2, &player2Request, sizeof(player2Request)); // Figure out who won if(PlayRequest == player1Request.type && PlayRequest == player2Request.type) { RPS_SERVER_RESPONSE player1Response = results[player1Request.move][player2Request.move]; RPS_SERVER_RESPONSE player2Response = results[player2Request.move][player1Request.move]; Reply(player1, &player1Response, sizeof(player1Response)); Reply(player2, &player2Response, sizeof(player2Response)); } else { break; } // Wait for clients to print out results Receive(&player1, NULL, 0); Receive(&player2, NULL, 0); Reply(player1, NULL, 0); Reply(player2, NULL, 0); // Wait for the TA before starting another round bwprintf(BWCOM2, "Server: Match over. Press any key to start next match \r\n\r\n"); bwgetc(BWCOM2); } // Looks like someone quit if(QuitRequest == player1Request.type && QuitRequest == player2Request.type) { RpsServerHandleBothPlayersQuitting(player1, player2); } else if(QuitRequest == player1Request.type) { RpspServerHandleOnePlayerQuitting(player1, player2); } else if(QuitRequest == player2Request.type) { RpspServerHandleOnePlayerQuitting(player2, player1); } else { ASSERT(FALSE); } }
void rps_server () { RegisterAs("RPSServer"); RPSMessage msg, reply; tid_t tid; unsigned int num_matches = MAX_TASKS/2 + 1; RPSMatch matches[num_matches]; unsigned int i; for (i = 0; i < num_matches; ++i) { reset_match_spot(&matches[i]); } struct circular_queue waiting_for_match; circular_queue_initialize(&waiting_for_match); RPSMatch *match; while (1) { // bwprintf(COM2, "RPS Server waiting for message\n"); // Receive a request and process it Receive(&tid, (char *) &msg, sizeof(msg)); switch (msg.type) { case SIGNUP: // bwprintf(COM2, "RPS Server got a signup from %d\n", tid); // Put the task on the queue circular_queue_push(&waiting_for_match, (void *) tid); // If there are two tasks on the queue, pop them off to create a pair if (2 == circular_queue_size(&waiting_for_match)) { RPSMatch *match = find_free_match_spot(matches, num_matches); match->task1 = (tid_t) circular_queue_pop(&waiting_for_match); match->task2 = (tid_t) circular_queue_pop(&waiting_for_match); reply.type = GOAHEAD; Reply(match->task1, (char *) &reply, sizeof(reply)); Reply(match->task2, (char *) &reply, sizeof(reply)); } break; case PLAY: // bwprintf(COM2, "RPS Server got a play of %d from %d\n", msg.move, tid); // Check that the task is in a pair and we're expecting a play match = find_match_containing_tid(matches, num_matches, tid); // Register the play if (tid == match->task1) { match->t1Move = msg.move; } else { match->t2Move = msg.move; } // bwprintf(COM2, "\n\n\nStored Moves Are: \n"); // bwprintf(COM2, "%d Move: %d and %d Move: %d\n\n\n", match->task1, match->t1Move, match->task2, match->t2Move); // If both tasks in the pair have played, reply with the result if (match->t1Move != NONE && match->t2Move != NONE) { RPSMessage t1Reply; RPSMessage t2Reply; t1Reply.type = t2Reply.type = RESULT; if (match->t1Move == FORFEIT) { t2Reply.result = FORFEIT; Reply(match->task2, (char *) &t2Reply, sizeof(t2Reply)); reset_match_spot(match); break; } else if (match->t2Move == FORFEIT) { t1Reply.result = FORFEIT; Reply(match->task1, (char *) &t1Reply, sizeof(t1Reply)); reset_match_spot(match); break; } unsigned int winner = 0; if (ROCK == match->t1Move) { if (ROCK == match->t2Move) { winner = 0; } else if (PAPER == match->t2Move) { winner = 2; } else if (SCISSORS == match->t2Move) { winner = 1; } } else if (PAPER == match->t1Move) { if (ROCK == match->t2Move) { winner = 1; } else if (PAPER == match->t2Move) { winner = 0; } else if (SCISSORS == match->t2Move) { winner = 2; } } else if (SCISSORS == match->t1Move) { if (ROCK == match->t2Move) { winner = 2; } else if (PAPER == match->t2Move) { winner = 1; } else if (SCISSORS == match->t2Move) { winner = 0; } } switch (winner) { case 0: t1Reply.result = t2Reply.result = DRAW; break; case 1: t1Reply.result = WIN; t2Reply.result = LOSE; break; case 2: t1Reply.result = LOSE; t2Reply.result = WIN; break; } bwprintf (COM2, "Round ended with %d playing %s and %d playing %s\n", match->task1, MOVE_STRINGS[match->t1Move], match->task2, MOVE_STRINGS[match->t2Move]); bwprintf (COM2, "Press any key to continue "); bwgetc(COM2); bwputc(COM2, '\n'); match->t1Move = match->t2Move = NONE; Reply(match->task1, (char *) &t1Reply, sizeof(t1Reply)); Reply(match->task2, (char *) &t2Reply, sizeof(t2Reply)); } break; case QUIT: //bwprintf(COM2, "RPS Server got a QUIT from %d\n", tid); match = find_match_containing_tid(matches, num_matches, tid); if (match->task1 == tid) { match->t1Move = FORFEIT; if (match->t2Move == FORFEIT) { reset_match_spot(match); } } else { match->t2Move = FORFEIT; if (match->t1Move == FORFEIT) { reset_match_spot(match); } } reply.type = QUIT; Reply(tid, (char*) &reply, sizeof(reply)); break; default: // Error or something break; } } Exit(); }
// 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 }
void RPSServer() { char* rps_server_play_names[ 3 ]; int quit = 0; struct Group group[32] = {{0}}; int index = 0; int signup_waiter = -1; int winner = 0; int status; int i = 0; rps_server_play_names[ 0 ] = "ROCK"; rps_server_play_names[ 1 ] = "PAPER"; rps_server_play_names[ 2 ] = "SCISSORS"; bwprintf( COM2, "RPS Server start.\n" ); for ( i = 0; i < 32; i++ ){ group[i].occupied = 0; } /* Register */ status = RegisterAs( "RPSServer" ); assert( status == 0 ); while ( !quit ) { int tid; struct RPSmsg msg; struct RPSreply reply; int status = 0; status = Receive( &tid, (char*)&msg, sizeof( msg ) ); assert( status == sizeof( msg ) ); // parse command switch ( msg.command ) { case SUICIDE: if ( tid != MyParentTid() ){ bwprintf( COM2, "Receive fake suicide command from task 0x%x\n", tid ); } else { quit = 1; /* At this point all clients should have already quited */ reply.result = RESULT_QUIT; status = Reply( tid, ( char* )&reply, sizeof( reply ) ); assert( status == SYSCALL_SUCCESS ); } break; case SIGN_UP: if ( signup_waiter == -1 ) { signup_waiter = tid; } else { index = 0; while ( ( index < 32 ) && group[index].occupied ){ index++; } if ( index >= 32 ) { bwprintf( COM2, "server full.\n" ); } group[index].p = 0; group[index].occupied = 1; group[index].c = 0; reply.result = index; status = Reply( signup_waiter, (char*)&reply, sizeof( reply ) ); DEBUG_PRINT( DBG_USER, "return status = %d\n", status ); assert( status == SYSCALL_SUCCESS ); status = Reply( tid, (char*)&reply, sizeof( reply ) ); assert( status == SYSCALL_SUCCESS ); /* Reset signup_waiter */ signup_waiter = -1; } break; case QUIT: case ROCK: case PAPER: case SCISSORS: index = msg.group_num; if ( group[index].c ) { winner = ( ( group[index].c + 1 ) - ( msg.command - 2 ) ) % 3; if ( ( group[index].c == QUIT ) || ( msg.command == QUIT ) ) { // both quit reply.result = RESULT_QUIT; status = Reply( group[index].p, (char*)&reply, sizeof( reply ) ); assert( status == SYSCALL_SUCCESS ); status = Reply( tid, (char*)&reply, sizeof( reply ) ); assert( status == SYSCALL_SUCCESS ); } else if ( winner == 1 ) { reply.result = RESULT_WIN; status = Reply( group[index].p, (char*)&reply, sizeof( reply ) ); assert( status == SYSCALL_SUCCESS ); reply.result = RESULT_LOSE; status = Reply( tid, (char*)&reply, sizeof( reply ) ); assert( status == SYSCALL_SUCCESS ); } else if ( winner == 2 ) { reply.result = RESULT_LOSE; status = Reply( group[index].p, (char*)&reply, sizeof( reply ) ); assert( status == SYSCALL_SUCCESS ); reply.result = RESULT_WIN; status = Reply( tid, (char*)&reply, sizeof( reply ) ); assert( status == SYSCALL_SUCCESS ); } else { // draw reply.result = RESULT_DRAW; status = Reply( group[index].p, (char*)&reply, sizeof( reply ) ); assert( status == SYSCALL_SUCCESS ); status = Reply( tid, (char*)&reply, sizeof( reply ) ); assert( status == SYSCALL_SUCCESS ); } if( ( group[index].c == QUIT ) || ( msg.command == QUIT ) ){ bwprintf( COM2, "[ Server ] Group %d requested quit\n", index ); } else { bwprintf( COM2, "[ Server ] Group %d player %d bet %s, player %d bet %s ", index, group[ index ].p, rps_server_play_names[ group[ index ].c - ROCK ], tid, rps_server_play_names[ msg.command - ROCK ] ); if( winner == 1 ){ bwprintf( COM2, "winner %d\n", group[ index ].p ); } else if( winner == 2 ) { bwprintf( COM2, "winner %d\n", tid ); } else { bwprintf( COM2, "draw\n" ); } } /* Pause */ bwgetc( COM2 ); group[index].p = 0; group[index].c = 0; } else { group[index].p = tid; group[index].c = msg.command; } break; default: bwprintf( COM2, "Invalid command: 0x%x\n", msg.command ); break; } } bwprintf( COM2, "RPS Server exit.\n" ); Exit(); }
static void sensorServer() { char com1Name[] = IOSERVERCOM1_NAME; int com1 = WhoIs(com1Name); char sensorName[] = SENSOR_NAME; RegisterAs(sensorName); int i, j; CURR_SENSOR_BOX = 0; CURR_HIGH_BITS = 0; responseIndex = 0; for (i = 0; i < NUM_SENSOR_BOX; ++i) { for (j = 0; j < 16; ++j) { SENSOR_VALUE[i][j] = 0; } } subscriberIndex = 0; subscriberUpdateIndex = 0; sensorBufferHead = 0; sensorBufferTail = 0; int queryWorker = Create(7, sensorQueryWorker); Create(8, sensorQueryResponseWorker); int queryTimeoutWorker = Create(7, sensorQueryTimeoutWorker); int queryResponseTimeoutWorker = Create(7, sensorQueryResponseTimeoutWorker); int courier = Create(7, sensorCourier); int queryWorkerReady = 0; int queryTimeout = 0; int queryResponseTimeout = 0; int startQueryResponseTimeout = 0; int courierReady = 0; char timerName[] = TIMESERVER_NAME; int timer = WhoIs(timerName); IGNORE_RESULT = 1; // sensor server is time sensitive, it delays and tries // to avoid the initialization period where there are // a lot of chars in com1 buffer Delay(700, timer); // Clear sensor memory after reading. Putc(com1, 192); // end init for ( ;; ) { if (queryTimeout && queryWorkerReady) { queryTimeout = 0; queryWorkerReady = 0; Reply(queryWorker, (char *)NULL, 0); Reply(queryTimeoutWorker, (char *)NULL, 0); } int tid = -1; SensorMsg msg; Receive(&tid, (char*)&msg, sizeof(SensorMsg)); switch (msg.type) { case QUERY_WORKER: { queryWorkerReady = 1; break; } case QUERY_RESPONSE_WORKER: { Reply(tid, (char *)NULL, 0); char response = msg.data; if (responseIndex == 0) { if (queryResponseTimeout) { queryResponseTimeout = 0; Reply(queryResponseTimeoutWorker, (char *)NULL, 0); } else { startQueryResponseTimeout = 1; } } responseBuffer[responseIndex++] = response; if (responseIndex == 10) { for (int i = 0; i < 10; i++) { sensorResponded(responseBuffer[i], msg.time); } responseIndex = 0; } break; } case QUERY_TIMEOUT_WORKER: { queryTimeout = 1; break; } case QUERY_RESPONSE_TIMEOUT_WORKER: { if (startQueryResponseTimeout) { startQueryResponseTimeout = 0; Reply(queryResponseTimeoutWorker, (char *)NULL, 0); } else { queryResponseTimeout = 1; responseIndex = 0; CURR_SENSOR_BOX = 0; CURR_HIGH_BITS = 0; } break; } case QUERY_RECENT: { sensorSubscriber[subscriberIndex++] = tid; Reply(tid, (char *)NULL, 0); break; } case SENSOR_COURIER: { courierReady = 1; break; } case FAKE_TRIGGER: { Reply(tid, (char *)NULL, 0); Sensor s; s.box = msg.box; s.val = msg.data; s.time = msg.time; add_to_buffer(s); break; } default: { ASSERT(FALSE, "invalid sensor msg type."); } } if (courierReady && !buffer_empty() && subscriberIndex != 0) { Sensor s = sensorBuffer[sensorBufferTail]; SensorWorkUnit work; work.sensor = s; work.tid = sensorSubscriber[subscriberUpdateIndex++]; Reply(courier, (char *)&work, sizeof(SensorWorkUnit)); if (subscriberUpdateIndex == subscriberIndex) { subscriberUpdateIndex = 0; remove_from_buffer(); } } } }