BOOL CDOSObjectProxyService::OnRun() { FUNCTION_BEGIN; EXCEPTION_CATCH_START m_ThreadPerformanceCounter.DoPerformanceCount(); int ProcessCount=CNetService::Update(); LPVOID Pos=m_ConnectionPool.GetFirstObjectPos(); while(Pos) { CDOSProxyConnection * pConnection=m_ConnectionPool.GetNext(Pos); if(pConnection->IsConnected()) ProcessCount+=pConnection->Update(); else DeleteConnection(pConnection); } ProcessCount+=DoMessageProcess(); if(ProcessCount==0) { DoSleep(1); } EXCEPTION_CATCH_END return TRUE; FUNCTION_END; return FALSE; }
bool Platform_Windows::Update() { //If the game isn't running anymore, return false if(m_IsRunning == false) { return false; } //Sleep the game timer DoSleep(); //Handle video mode changes if(m_VideoModeChangeInfo.needsChange == true) { ApplyVideoModeChanges(&m_VideoModeChangeInfo); m_VideoModeChangeInfo.needsChange = false; } //Safety check the game window and handle controller input if(m_GameWindow != nullptr) { m_GameWindow->HandleControllerInput(); } //Calculate the tick (milleseconds since last update) and update the game Tick(); //Return wether the game is still running or not return m_IsRunning; }
BOOL CNetServer::OnRun() { if(!CBaseServer::OnRun()) return FALSE; if(Update()==0) { DoSleep(1); } return TRUE; }
BOOL CDOSObjectGroup::OnRun() { FUNCTION_BEGIN; if(!CEasyThread::OnRun()) return FALSE; int ProcessCount=0; ProcessCount+=ProcessObjectRegister(); void * Pos=m_ObjectPool.GetFirstObjectPos(); while(Pos) { DOS_OBJECT_INFO * pObjectInfo=m_ObjectPool.GetNext(Pos); if(pObjectInfo) { UINT64 CPUCost=0; if(m_StatObjectCPUCost) CPUCost=CEasyTimerEx::GetTimeOrigin(); ProcessCount+=pObjectInfo->pObject->DoCycle(); if(m_StatObjectCPUCost) { CPUCost=CEasyTimerEx::GetTimeOrigin()-CPUCost; AddObjectCPUCost(pObjectInfo->ObjectID,CPUCost); } } } ProcessCount+=ProcessObjectUnregister(); m_ThreadPerformanceCounter.DoPerformanceCount(); if(ProcessCount==0) { DoSleep(1); } return TRUE; FUNCTION_END; return FALSE; }
/************************************************** * Secondary threads main function * **************************************************/ void* DoNewThread(void* threadNumArg) { int threadNum = *((int*)threadNumArg); Print(roleStrings[threadNum] + " thread was created succesfully."); // FOR DEBUG IncThreads(); switch (threadNum) { case ROLE_WAIT: DoSleep(1000); ErrorExit(RES_EXIT_TIMEOUT); // the ROLE_WAIT thread reached its timeout of 1000 seconds - something is wrong case ROLE_LOOP: while (1); // never exits from here break; case ROLE_FINISH: break; // exits normally, process continues case ROLE_EXIT: if (exitType == EXIT_SEC_EXIT) { while (NumOfThreads() != ROLE_SIZE) { DoYield(); // wait here until all threads are ready } Print("ROLE_EXIT thread is calling exit()"); // FOR DEBUG // exit and kill the entire process exit(RES_SUCCESS); // never returns } // thread exits but process continues ThreadExit(); // never returns case ROLE_CANCELED: // On Windows, this thread will be canceled using the TerminateThread API. The documentation states that // it is unsafe to use this function if the target thread is executing certain kernel32 calls etc. // On Linux, the thread must enter a function which is defined as a cancellation point. See pthreads entry // in the chapter 7 of the manual for further details. readyToCancel = true; EnterSafeCancellationPoint(); } return NULL; }
/************************************************** * Main * **************************************************/ int main() { InitLocks(); if (!createThreads(numOfFirstCreateLoop, (void*)DoDummyThread)) { // create first batch of dummy threads ErrorExit(RES_CREATE_FAILED); } Print("Creating the exit thread"); if (!createThreads(1, (void*)DoExitThread)) { // create the exit thread ErrorExit(RES_CREATE_FAILED); } if (!createThreads(numOfSecondCreateLoop, (void*)DoDummyThread)) { // create second batch of dummy threads ErrorExit(RES_CREATE_FAILED); } DoSleep(1000); // wait here to be terminated // Failsafe - this should not be reached but we want to avoid a hung test. ErrorExit(RES_EXIT_TIMEOUT); // never returns // This can't be reached, simply for successful compilation. return RES_SUCCESS; }
void sample_code(void) { INT32 i, j, k; /* Index & counters */ long Value; INT32 disk_id, sector; /* Used for disk requests */ char disk_buffer_write[PGSIZE ]; char disk_buffer_read[PGSIZE ]; char physical_memory_write[PGSIZE ]; char physical_memory_read[PGSIZE ]; void *context_pointer; /* Used for context commands*/ void *starting_address; BOOL kernel_or_user; short random_buckets[NUM_RAND_BUCKETS]; INT32 LockResult; INT32 Status; INT32 Temp, Temp1; /********************************************************************* Show the interface to the delay timer. Eventually the timer will interrupt ( in base.c there's a handler for this ), but here in sample_code.c we're merely showing the interface to start the call. *********************************************************************/ MEM_READ(Z502TimerStatus, &Status); if (Status == DEVICE_FREE) printf("Got expected result for Status of Timer\n"); else printf("Got erroneous result for Status of Timer\n"); Temp = 777; /* You pick the time units */ MEM_WRITE(Z502TimerStart, &Temp); MEM_READ(Z502TimerStatus, &Status); if (Status == DEVICE_IN_USE) printf("Got expected result for Status of Timer\n"); else printf("Got erroneous result for Status of Timer\n"); printf("The next output from the Interrupt Handler should report that \n"); printf(" interrupt of device 4 has occurred with no error.\n"); Z502Idle(); // Let the interrupt for this timer occur // Now we're going to try an illegal time and ensure that the fault // handler reports an illegal status. Temp = -77; /* You pick the time units */ printf("The next output from the Interrupt Handler should report that \n"); printf( " interrupt of device 4 has occurred with an ERR_BAD_PARAM = 1.\n"); MEM_WRITE(Z502TimerStart, &Temp); MEM_READ(Z502TimerStatus, &Status); if (Status == DEVICE_FREE) // Bogus value shouldn't start timer printf("Got expected result for Status of Timer\n"); else printf("Got erroneous result for Status of Timer\n"); fflush(stdout); // ZCALL( Z502_IDLE() ); // Let the interrupt for this timer occur /* The interrupt handler will have exercised the code doing Z502InterruptDevice, Z502InterruptStatus, and Z502InterruptClear. But they will have been tested only for "correct" usage. Let's try a few erroneous/illegal operations. */ // Set an illegal device as target of our query Temp = LARGEST_STAT_VECTOR_INDEX + 1; MEM_WRITE(Z502InterruptDevice, &Temp); // Now read the status of this device MEM_READ(Z502InterruptStatus, &Status); if (Status == ERR_BAD_DEVICE_ID) printf("Got expected result for Status of Illegal Device\n"); else printf("Got erroneous result for Status of Illegal Device\n"); /********************************************************************* Show the interface to the Z502_CLOCK. This is easy - all we're going to do is read it twice and make sure the time is incrementing. *********************************************************************/ MEM_READ(Z502ClockStatus, &Temp); MEM_READ(Z502ClockStatus, &Temp1); if (Temp1 > Temp) printf("The clock time incremented correctly - %d1, %d2\n", Temp, Temp1); else printf("The clock time did NOT increment correctly - %d1, %d2\n", Temp, Temp1); /********************************************************************* Show the interface to the disk read and write. Eventually the disk will interrupt ( in base.c there's a handler for this ), but here in sample_code.c we're merely showing the interface to start the call. *********************************************************************/ disk_id = 1; /* Pick arbitrary disk location */ sector = 3; /* Put data into the buffer being written */ strncpy(disk_buffer_write, "123456789abcdef", 15); /* Do the hardware call to put data on disk */ MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); if (Temp == DEVICE_FREE) // Disk hasn't been used - should be free printf("Got expected result for Disk Status\n"); else printf("Got erroneous result for Disk Status - Device not free.\n"); MEM_WRITE(Z502DiskSetSector, §or); MEM_WRITE(Z502DiskSetBuffer, (INT32 * )disk_buffer_write); Temp = 1; // Specify a write MEM_WRITE(Z502DiskSetAction, &Temp); Temp = 0; // Must be set to 0 MEM_WRITE(Z502DiskStart, &Temp); // Disk should now be started - let's see MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); if (Temp == DEVICE_IN_USE) // Disk should report being used printf("Got expected result for Disk Status\n"); else printf("Got erroneous result for Disk Status\n"); /* Wait until the disk "finishes" the write. the write is an "unpended-io", meaning the call returns before the work is completed. By doing the IDLE here, we wait for the disk action to complete. */ MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); while (Temp != DEVICE_FREE) { Z502Idle(); MEM_READ(Z502DiskStatus, &Temp); } /* Now we read the data back from the disk. If we're lucky, we'll read the same thing we wrote! */ MEM_WRITE(Z502DiskSetSector, §or); MEM_WRITE(Z502DiskSetBuffer, (INT32 * )disk_buffer_read); Temp = 0; // Specify a read MEM_WRITE(Z502DiskSetAction, &Temp); Temp = 0; // Must be set to 0 MEM_WRITE(Z502DiskStart, &Temp); /* wait for the disk action to complete. */ MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); while (Temp != DEVICE_FREE) { Z502Idle(); MEM_READ(Z502DiskStatus, &Temp); } printf("\n\nThe disk data written is: %s\n", disk_buffer_write); printf("The disk data read is: %s\n", disk_buffer_read); /********************************************************************* Let's try some intentional errors to see what happens *********************************************************************/ Temp = 0; // Must be set to 0 MEM_WRITE(Z502DiskStart, &Temp); // Try reading the status without setting an ID MEM_READ(Z502DiskStatus, &Temp); if (Temp == ERR_BAD_DEVICE_ID) printf("Got expected result for Disk Status when using no ID\n"); else printf("Got erroneous result for Disk Status when using no ID\n"); // Try entering a bad ID and then reading the status disk_id = 999; MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); if (Temp == ERR_BAD_DEVICE_ID) printf("Got expected result for Disk Status when using bad ID\n"); else printf("Got erroneous result for Disk Status when using bad ID\n"); // Try doing everything right EXCEPT entering the buffer address, disk_id = 1; /* Pick arbitrary disk location */ sector = 3; MEM_WRITE(Z502DiskSetID, &disk_id); MEM_WRITE(Z502DiskSetSector, §or); // Don't do this -> MEM_WRITE( Z502DiskSetBuffer, (INT32 *)disk_buffer_write ); Temp = 1; // Specify a write MEM_WRITE(Z502DiskSetAction, &Temp); Temp = 0; // Must be set to 0 MEM_WRITE(Z502DiskStart, &Temp); // Disk should now not be started - it was missing vital info MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); if (Temp == DEVICE_FREE) // Disk should report being free printf("Got expected result for Disk Status when missing data\n"); else printf("Got erroneous result for Disk Status when missing data\n"); /********************************************************************* Some of the tests put thousands of pages of data on the disk. Let's see if we can do that here. The pages ARE being written to the disk, but the interrupt handler doesn't show all of them happening because it's not catching multiple interrupts. *********************************************************************/ disk_id = 1; sector = 0; printf("The following section will take a few seconds\n"); for (j = 0; j < VIRTUAL_MEM_PGS + 100 /* arbitrary # */; j++) { MEM_WRITE(Z502DiskSetID, &disk_id); MEM_WRITE(Z502DiskSetSector, §or); MEM_WRITE(Z502DiskSetBuffer, (INT32 * )disk_buffer_write); Temp = 1; // Specify a write MEM_WRITE(Z502DiskSetAction, &Temp); Temp = 0; // Start the disk MEM_WRITE(Z502DiskStart, &Temp); MEM_WRITE(Z502DiskSetID, &disk_id); MEM_READ(Z502DiskStatus, &Temp); while (Temp == DEVICE_IN_USE) // Disk should report being used { //printf( "Got erroneous result for Disk Status when writing lots of blocks\n" ); Temp = 5; /* You pick the time units */ MEM_WRITE(Z502TimerStart, &Temp); MEM_READ(Z502DiskStatus, &Temp); } sector++; if (sector >= NUM_LOGICAL_SECTORS) { sector = 0; disk_id++; } } /********************************************************************* Do a physical memory access to check out that it works. *********************************************************************/ printf("\nStarting test of physical memory write and read.\n"); for (i = 0; i < PGSIZE ; i++) { physical_memory_write[i] = i; } Z502WritePhysicalMemory(17, (char *) physical_memory_write); Z502ReadPhysicalMemory(17, (char *) physical_memory_read); for (i = 0; i < PGSIZE ; i++) { if (physical_memory_write[i] != physical_memory_read[i]) printf("Error in Physical Memory Access\n"); } printf("Completed test of physical memory write and read.\n"); /********************************************************************* Start all of the disks at the same time and see what happens. *********************************************************************/ /* sector = 0; for ( disk_id = 1; disk_id <= MAX_NUMBER_OF_DISKS ; disk_id++ ) { MEM_WRITE( Z502DiskSetID, &disk_id ); MEM_WRITE( Z502DiskSetSector, §or ); MEM_WRITE( Z502DiskSetBuffer, (INT32 *)disk_buffer_write ); Temp = 1; // Specify a write MEM_WRITE( Z502DiskSetAction, &Temp ); Temp = 0; // Start the disk MEM_WRITE( Z502DiskStart, &Temp ); sector++; } // Now wait until all disks have finished for ( disk_id = 1; disk_id <= MAX_NUMBER_OF_DISKS ; disk_id++ ) { MEM_WRITE( Z502DiskSetID, &disk_id ); MEM_READ( Z502DiskStatus, &Temp ); while ( Temp == DEVICE_IN_USE ) // Disk should report being used { //ZCALL( Z502_IDLE() ); DoSleep(50); } } */ printf("Disk multiple-block test is complete\n\n"); /********************************************************************* Show the interface to read and write of real memory It turns out, that though these are hardware calls, the Z502 assumes the calls are being made in user mode. Because the process we're running here in "sample" is in kernel mode, the calls don't work correctly. For working examples of these calls, see test2a. *********************************************************************/ Z502_PAGE_TBL_LENGTH = 64; Z502_PAGE_TBL_ADDR = (UINT16 *) calloc(sizeof(UINT16), Z502_PAGE_TBL_LENGTH); i = PTBL_VALID_BIT; Z502_PAGE_TBL_ADDR[0] = (UINT16) i; i = 73; MEM_WRITE(0, &i); MEM_READ(0, &j); /* WE expect the data read back to be the same as what we wrote */ if (i == j) printf("Memory write and read completed successfully\n"); else printf("Memory write and read were NOT successful.\n"); /********************************************************************* This is the interface to the locking mechanism. These are hardware interlocks. We need to test that they work here. This is the interface we'll be using. void Z502_READ_MODIFY( INT32 VirtualAddress, INT32 NewLockValue, INT32 Suspend, INT32 *LockResult ) We've defined these above to help remember them. #define DO_LOCK 1 #define DO_UNLOCK 0 #define SUSPEND_UNTIL_LOCKED TRUE #define DO_NOT_SUSPEND FALSE *********************************************************************/ printf("++++ Starting Hardware Interlock Testing ++++\n"); // TRY A SERIES OF CALLS AS DESCRIBED HERE printf("These tests map into the matrix describing the Z502_READ_MODIFY\n"); printf(" described in Appendix A\n\n"); printf( "1. Start State = Unlocked: Action (Thread 1) = Lock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "2. Start State = locked(1): Action (Thread 1) = unLock: End State = UnLocked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "3. Start State = Unlocked: Action (Thread 1) = unLock: End State = UnLocked\n"); printf(" An Error is Expected\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "4. Start State = unlocked: Action (Thread 1) = tryLock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, DO_NOT_SUSPEND, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "5. Start State = Locked(1): Action (Thread 1) = tryLock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, DO_NOT_SUSPEND, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "6. Start State = locked(1): Action (Thread 1) = unLock: End State = UnLocked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "7. Start State = Unlocked: Action (Thread 1) = Lock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); // A thread that locks an item it has already locked will succeed printf( "8. Start State = locked(1): Action (Thread 1) = Lock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); // Locking a thread that's already locked - but do it with a thread // other than the one that did the locking. printf( "9. Start State = Locked(1): Action (Thread 2) = tryLock: End State = Locked\n"); printf(" An Error is Expected\n"); Status = CreateAThread((int *) DoOnelock, &Temp); DoSleep(100); /* Wait for that thread to finish */ // Unlock a thread that's already locked - but unlock it with a thread // other than the one that did the locking. printf( "10. Start State = Locked(1): Action (Thread 2) = unLock: End State = Locked\n"); printf(" An Error is Expected\n"); Status = CreateAThread((int *) DoOneUnlock, &Temp); DoSleep(100); /* Wait for that thread to finish */ // The second thread will try to get the lock held by the first thread. This is OK // but the second thread will suspend until the first thread releases the lock. printf( "11. Start State = Locked(1): Action (Thread 2) = Lock: End State = Locked\n"); Status = CreateAThread((int *) DoOneTrylock, &Temp); DoSleep(100); /* Wait for that thread to finish */ // The first thread does an unlock. This means the second thread is now able to get // the lock so there is a "relock" when thread two succeeds. printf( "12. Start State = locked(1): Action (Thread 1) = unLock: End State = Locked(by 2)\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); DoSleep(100); /* Wait for locking action of 2nd thread to finish */ printf( "13. Start State = Locked(2): Action (Thread 3) = unLock: End State = Locked(2)\n"); printf(" An Error is Expected\n"); Status = CreateAThread((int *) DoOneUnlock, &Temp); DoSleep(100); /* Wait for that thread to finish */ printf( "14. Start State = Locked(2): Action (Thread 1) = tryLock: End State = Locked(2)\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, DO_NOT_SUSPEND, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "15. Start State = locked(2): Action (Thread 1) = unLock: End State = Locked(2)\n"); printf(" An Error is Expected\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf("++++ END of hardware interlock code ++++\n\n"); /********************************************************************* Show the interface to the CONTEXT calls. We aren't going to do a SWITCH_CONTEXT here, because that would cause us to start a process in a strange place and we might never return here. But we do all the setup required. *********************************************************************/ /* The context_pointer is returned by the MAKE_CONTEXT call. */ starting_address = (void *) starting_point_for_new_context; kernel_or_user = USER_MODE; Z502MakeContext(&context_pointer, starting_address, kernel_or_user); Z502DestroyContext(&context_pointer); /********************************************************************* Show the interface to the scheduler printer. *********************************************************************/ CALL(SP_setup( SP_TIME_MODE, 99999 )); CALL(SP_setup_action( SP_ACTION_MODE, "CREATE" )); CALL(SP_setup( SP_TARGET_MODE, 99L )); CALL(SP_setup( SP_RUNNING_MODE, 99L )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_READY_MODE, j )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_WAITING_MODE, j+20 )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_SUSPENDED_MODE, j+40 )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_SWAPPED_MODE, j+60 )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_TERMINATED_MODE, j+80 )); for (j = 0; j < SP_MAX_NUMBER_OF_PIDS ; j++) CALL(SP_setup( SP_NEW_MODE, j+50 )); CALL(SP_print_header()); CALL(SP_print_line()); /********************************************************************* Show the interface to the memory_printer. *********************************************************************/ for (j = 0; j < 64; j = j + 2) { MP_setup((INT32) (j), (INT32) (j / 2) % 10, (INT32) j * 16 + 10, (INT32) (j / 2) % 8); } MP_print_line(); /********************************************************************* Show how the skewed random numbers work on this platform. *********************************************************************/ for (j = 0; j < NUM_RAND_BUCKETS; j++) random_buckets[j] = 0; for (j = 0; j < 100000; j++) { get_skewed_random_number(&Value, NUM_RAND_BUCKETS); random_buckets[Value]++; } printf("\nTesting that your platform produces correctly skewed random\n"); printf("numbers. Each row should have higher count than the previous.\n"); printf(" Range: Counts in this range.\n"); for (j = 0; j < NUM_RAND_BUCKETS; j = j + 8) { k = 0; for (i = j; i < j + 8; i++) k += random_buckets[i]; printf("%3d - %3d: %d\n", j, j + 7, k); } /********************************************************************* Show the interface to the Z502Halt. Note that the program will end NOW, since we don't return from the command. *********************************************************************/ Z502Halt(); }
void ParseCommand(char *string) { char Command; char Command2 = 0; unsigned int Params[MAX_COMMAND_PARAMS]; unsigned int NumParams=0; /* UsartWriteString("Command Received: "); UsartWriteString(string); UsartWriteString("\n\r"); */ // assume commands are single character followed by numerical parameters sep by spaces // e.g. "s 1 5", "b 7", "b 100 120 001 212 123" Command = string[0]; if(IsAlpha(string[1])) // multi-char command (e.g. pa, oa, ia, etc) Command2 = string[1]; if(Command != 0) { NumParams=GetParams(string,Params); // read any optional parameters after command /* UsartWriteString("CommandID: "); UsartWriteChar(Command); if(Command2 != 0) UsartWriteChar(Command2); UsartWriteString(" #Params: "); UsartWriteChar(48+NumParams); UsartWriteString("\n\r"); */ } else { UsartWriteString("No Command\n\r"); }; unsigned short lcdDataIn; static char buffer[10]; switch(Command) { case 'a': // ADC do immediate conversion PORTQ.OUTCLR = PIN0_bm | PIN2_bm; //ENCODE pins _delay_ms(1); PORTQ.OUTSET = PIN0_bm | PIN2_bm; _delay_ms(1); char value = PORTD.IN; IntToString(value,&buffer[0]); UsartWriteLine(buffer); break; case 'b': // read imager flag PORTA.DIR &= ~0x01; char bb6 = PORTA.IN & 0x01; IntToString(bb6,&buffer[0]); UsartWriteLine(buffer); break; case 'y': // Start Image frame = 0; start_interrupts(); break; case 'z': // Stop Image stop_interrupts(); break; case 'l': lcdDataIn = TSLCDInDat(); IntToString(lcdDataIn,&buffer[0]); UsartWriteLine(buffer); break; case 'x': IntToString(4,&buffer[0]); UsartWriteLine(buffer); break; case 'T': // Usart TX test DoUsartTx(Command2,Params[0],"0123456789"); break; case 'S': // Config SPI port DoSpiConfig(Command2,Params[0]); break; case 'X': // SPI TX test DoSpiTx(Command2,"0123456789"); break; case 's': // Sleep CPU DoSleep(Params[0]); // this will not return break; case 'O': // Set oscillator source DoOscillator(Params[0]); // this will not return break; case 'h': // Usage break; }; return; };
int luaSleep(lua_State* L) { DoSleep(luaL_optnumber(L, 1, 100)); return 0; }
void SampleCode(void) { INT32 i, j, k; // Index & counters INT32 Counter = 0; long Value; MEMORY_MAPPED_IO mmio; // Structure used for hardware interface short *PAGE_TBL_ADDR; INT32 disk_id, sector; /* Used for disk requests */ char disk_buffer_write[PGSIZE ]; char disk_buffer_read[PGSIZE ]; char physical_memory_write[PGSIZE ]; char physical_memory_read[PGSIZE ]; short random_buckets[NUM_RAND_BUCKETS]; INT32 LockResult; SP_INPUT_DATA SPData; // Used to feed SchedulerPrinter MP_INPUT_DATA MPData; // Used to feed MemoryPrinter INT32 Status; INT32 Temp, Temp1; // INT32 mode; /********************************************************************* Show the interface to the delay timer. Eventually the timer will interrupt ( in base.c there's a handler for this ), but here in sample.c we're merely showing the interface to start the call. *********************************************************************/ // Check the status of the timer - is it running or not mmio.Mode = Z502Status; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Timer, &mmio); Status = mmio.Field1; if (Status == DEVICE_FREE) printf("Got expected (DEVICE_FREE) result for Status of Timer\n"); else printf("Got erroneous result for Status of Timer\n"); // Start the timer - here's the sequence to use mmio.Mode = Z502Start; mmio.Field1 = 777; // You pick the time units mmio.Field2 = mmio.Field3 = 0; MEM_WRITE(Z502Timer, &mmio); // Check the status of the timer - is it running or not mmio.Mode = Z502Status; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Timer, &mmio); Status = mmio.Field1; if (Status == DEVICE_IN_USE) printf("Got expected result (DEVICE_IN_USE) for Status of Timer\n"); else printf("Got erroneous result for Status of Timer\n"); printf( "\nThe next output from the Interrupt Handler should report that \n"); printf(" interrupt of device 4 has occurred with no error.\n"); // Go idle until the interrupt occurs mmio.Mode = Z502Action; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_WRITE(Z502Idle, &mmio); // Let the interrupt for this timer occur DoSleep(10); // Give it a little more time // Now we're going to try an illegal time and ensure that the fault // handler reports an illegal status. It's important to try to start the time // and then do the printf here. That gives the interrupt handler a chance to // run before we get the status here. mmio.Mode = Z502Start; mmio.Field1 = -77; // You pick the time units - but it's illegal mmio.Field2 = mmio.Field3 = 0; MEM_WRITE(Z502Timer, &mmio); printf( "\nThe next output from the Interrupt Handler should report that \n"); printf(" the interrupt handler found device ID 4 with status %d.\n", (int) ERR_BAD_PARAM); DoSleep(10); // Give it a little more time printf("\n"); // Check the status of the timer - is it running or not mmio.Mode = Z502Status; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Timer, &mmio); Status = mmio.Field1; if (Status == DEVICE_FREE) printf("Got expected result for Status of Timer\n"); else printf("Got erroneous result for Status of Timer\n"); fflush(stdout); /* The interrupt handler will have exercised the code doing Z502InterruptDevice - getting information about the interrupt and then clearing it. But they will have been tested only for "correct" usage. Let's try a few erroneous/illegal operations. */ // Get cause of interrupt - there should be no interrupt that // is waiting so we should get an error. Check it. mmio.Mode = Z502GetInterruptInfo; MEM_READ(Z502InterruptDevice, &mmio); mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; if (mmio.Field4 == ERR_NO_DEVICE_FOUND) printf("Got expected result for Status when no DeviceFound \n"); else printf("Got erroneous result for Status when no DeviceFound\n"); // Set an illegal device as target of our query mmio.Mode = Z502ClearInterruptStatus; mmio.Field1 = LARGEST_STAT_VECTOR_INDEX + 1; mmio.Field2 = mmio.Field3 = 0; MEM_WRITE(Z502InterruptDevice, &mmio); if (mmio.Field4 == ERR_BAD_DEVICE_ID) printf("Got expected result for Status of Illegal Device\n"); else printf("Got erroneous result for Status of Illegal Device\n"); /********************************************************************* Show the interface to the Z502_CLOCK. This is easy - all we're going to do is read it twice and make sure the time is incrementing. *********************************************************************/ mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Clock, &mmio); Temp = mmio.Field1; mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Clock, &mmio); Temp1 = mmio.Field1; if (Temp1 > Temp) printf("\nThe clock time incremented correctly - %d1, %d2\n", Temp, Temp1); else printf("\nThe clock time did NOT increment correctly - %d1, %d2\n", Temp, Temp1); /********************************************************************* Show the interface to the disk read and write. Eventually the disk will interrupt ( in base.c there's a handler for this ), but here in sample.c we're merely showing the interface to start the call. *********************************************************************/ #define SAMPLE_LEGAL_DISK_ID 1 #define SAMPLE_LEGAL_SECTOR_LOCATION 3 // Now see that the disk IS NOT running mmio.Mode = Z502Status; mmio.Field1 = SAMPLE_LEGAL_DISK_ID; mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Disk, &mmio); if (mmio.Field2 == DEVICE_FREE) // Disk hasn't been used - should be free printf("Disk Test 1: Got expected result for Disk Status\n"); else printf( "Disk Test 1: Got erroneous result for Disk Status - Device not free.\n"); // Start the disk by writing a block of data mmio.Mode = Z502DiskWrite; mmio.Field1 = SAMPLE_LEGAL_DISK_ID; mmio.Field2 = SAMPLE_LEGAL_SECTOR_LOCATION; mmio.Field3 = (long) disk_buffer_write; // Put data into the buffer being written strncpy(disk_buffer_write, "123456789abcdef", 15); // Do the hardware call to put data on disk MEM_WRITE(Z502Disk, &mmio); // Now see that the disk IS running mmio.Mode = Z502Status; mmio.Field1 = SAMPLE_LEGAL_DISK_ID; mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Disk, &mmio); if (mmio.Field2 == DEVICE_IN_USE) // Disk should report being used printf("Disk Test 2: Got expected result for Disk Status\n"); else printf("Disk Test 2: Got erroneous result for Disk Status\n"); /* Wait until the disk "finishes" the write. the write is an "unpended-io", meaning the hardware call returns before the work is completed. By doing the IDLE here, we wait for the disk action to complete. */ // Go idle until the interrupt occurs mmio.Mode = Z502Action; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_WRITE(Z502Idle, &mmio); // The disk should now be done. Make sure it's idle mmio.Mode = Z502Status; mmio.Field1 = SAMPLE_LEGAL_DISK_ID; mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Disk, &mmio); if (mmio.Field2 == DEVICE_FREE) // Disk should be free printf("Disk Test 3: Got expected result for Disk Status\n"); else printf( "Disk Test 3: Got erroneous result for Disk Status - Device not free.\n"); /* Now we read the data back from the disk. If we're lucky, we'll read the same thing we wrote! */ // Start the disk by reading a block of data mmio.Mode = Z502DiskRead; mmio.Field1 = SAMPLE_LEGAL_DISK_ID; // Pick same disk location mmio.Field2 = SAMPLE_LEGAL_SECTOR_LOCATION; mmio.Field3 = (long) disk_buffer_read; // Do the hardware call to read data from disk MEM_WRITE(Z502Disk, &mmio); // Wait for the disk action to complete. // (Note - students should NEVER write OS code this way, but // instead should use the Z502Idle hardware request mmio.Field2 = DEVICE_IN_USE; while (mmio.Field2 != DEVICE_FREE) { mmio.Mode = Z502Status; mmio.Field1 = SAMPLE_LEGAL_DISK_ID; mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Disk, &mmio); } printf("\nThe disk data written is: %s\n", disk_buffer_write); printf("The disk data read is: %s\n", disk_buffer_read); /********************************************************************* Let's try some intentional errors to see what happens *********************************************************************/ #define SAMPLE_ILLEGAL_DISK_ID MAX_NUMBER_OF_DISKS + 2 #define SAMPLE_ILLEGAL_SECTOR_LOCATION NUM_LOGICAL_SECTORS + 1 // Try an illegal Disk ID mmio.Mode = Z502DiskWrite; mmio.Field1 = SAMPLE_ILLEGAL_DISK_ID; mmio.Field2 = SAMPLE_LEGAL_SECTOR_LOCATION; mmio.Field3 = (long) disk_buffer_write; MEM_WRITE(Z502Disk, &mmio); if (mmio.Field4 == ERR_BAD_PARAM) printf( "Disk Test 4: Got expected result for Disk when using illegal ID\n"); else printf( "Disk Test 4: Got erroneous result for Disk when using illegal ID\n"); mmio.Mode = Z502DiskWrite; mmio.Field1 = SAMPLE_LEGAL_DISK_ID; mmio.Field2 = SAMPLE_ILLEGAL_SECTOR_LOCATION; mmio.Field3 = (long) disk_buffer_write; MEM_WRITE(Z502Disk, &mmio); if (mmio.Field4 == ERR_BAD_PARAM) printf( "Disk Test 5: Got expected result for Disk when using bad parameter\n"); else printf( "Disk Test 5: Got erroneous result for Disk when using bad parameter\n"); mmio.Mode = Z502Status; mmio.Field1 = SAMPLE_ILLEGAL_DISK_ID; mmio.Field2 = 0; mmio.Field3 = 0; MEM_WRITE(Z502Disk, &mmio); if (mmio.Field4 == ERR_BAD_DEVICE_ID) printf( "Disk Test 6: Expected result for Disk Status when using bad ID\n"); else printf( "Disk Test 6: Erroneous result for Disk Status when using bad ID\n"); /********************************************************************* Some of the tests put thousands of pages of data on the disk. Let's see if we can do that here. The pages ARE being written to the disks, but the interrupt handler doesn't show all of them happening because it's not catching multiple interrupts. NOTE: This test should have all the disks in action at the same time *********************************************************************/ disk_id = 0; sector = 1; printf("\nThe following section tests multiple disks in operation\n"); printf("at the same time. It will take a few seconds\n"); for (j = 0; j < VIRTUAL_MEM_PAGES + 100 /* arbitrary # */; j++) { if (disk_id > MAX_NUMBER_OF_DISKS - 1) { disk_id = 0; sector++; } disk_id++; // First make sure the disk is free - it may be in use from // a previous request. mmio.Field2 = DEVICE_IN_USE; Counter = 0; while (mmio.Field2 == DEVICE_IN_USE) { mmio.Mode = Z502Action; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_WRITE(Z502Idle, &mmio); // Now go back and see if disk is done mmio.Mode = Z502Status; mmio.Field1 = disk_id; mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Disk, &mmio); if (Counter > 100) { printf("PANIC 1: Error in multiple disk test in sample.c\n"); } Counter++; } mmio.Mode = Z502DiskWrite; mmio.Field1 = disk_id; mmio.Field2 = sector; mmio.Field3 = (long) disk_buffer_write; MEM_WRITE(Z502Disk, &mmio); if (mmio.Field4 != ERR_SUCCESS) { printf("PANIC 2: Error in multiple disk test in sample.c\n"); } } // End of for j // Give things a chance to settle down - any last interrupts left? mmio.Mode = Z502Action; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_WRITE(Z502Idle, &mmio); mmio.Mode = Z502Action; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_WRITE(Z502Idle, &mmio); printf("End of multi-disk test\n"); /********************************************************************* Do a physical memory access to check out that it works. This is a mechanism that allows the OS to access physical memory directly without using a page table. *********************************************************************/ printf("\nStarting test of physical memory write and read.\n"); for (i = 0; i < PGSIZE ; i++) { physical_memory_write[i] = i; } Z502WritePhysicalMemory(17, (char *) physical_memory_write); Z502ReadPhysicalMemory(17, (char *) physical_memory_read); for (i = 0; i < PGSIZE ; i++) { if (physical_memory_write[i] != physical_memory_read[i]) printf("Error in Physical Memory Access\n"); } printf("Completed test of physical memory write and read.\n"); /********************************************************************* Show the interface to read and write of real memory It turns out, that though these are hardware calls, the Z502 assumes the calls are being made in user mode. Remember that this code Sample is running in Kernel Mode so the results will look different from a memory request that is initiated in User Mode in Test2a. What you see here IS the way that the OS can manipulate page tables and access memory. *********************************************************************/ mmio.Mode = Z502GetPageTable; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Context, &mmio); PAGE_TBL_ADDR = (short *) mmio.Field1; // Gives us the page table // Set to VALID the logical page 0 and have it point at physical // frame 0. i = PTBL_VALID_BIT; PAGE_TBL_ADDR[0] = (UINT16) i; i = 73; // Data to be written MEM_WRITE(0, &i); MEM_READ(0, &j); // Now read it back // WE expect the data read back to be the same as what we wrote if (i == j) printf("Memory write and read completed successfully\n"); else printf("Memory write and read were NOT successful.\n"); /********************************************************************* This is the interface to the locking mechanism. These are hardware interlocks. We need to test that they work here. This is the interface we'll be using. void Z502_READ_MODIFY( INT32 VirtualAddress, INT32 NewLockValue, INT32 Suspend, INT32 *LockResult ) We've defined these above to help remember them. #define DO_LOCK 1 #define DO_UNLOCK 0 #define SUSPEND_UNTIL_LOCKED TRUE #define DO_NOT_SUSPEND FALSE *********************************************************************/ printf("++++ Starting Hardware Interlock Testing ++++\n"); // TRY A SERIES OF CALLS AS DESCRIBED HERE printf("These tests map into the matrix describing the Z502_READ_MODIFY\n"); printf(" described in Appendix A\n\n"); printf( "1. Start State = Unlocked: Action (Thread 1) = Lock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "2. Start State = locked(1): Action (Thread 1) = unLock: End State = UnLocked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "3. Start State = Unlocked: Action (Thread 1) = unLock: End State = UnLocked\n"); printf(" An Error is Expected\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "4. Start State = unlocked: Action (Thread 1) = tryLock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, DO_NOT_SUSPEND, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "5. Start State = Locked(1): Action (Thread 1) = tryLock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, DO_NOT_SUSPEND, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "6. Start State = locked(1): Action (Thread 1) = unLock: End State = UnLocked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "7. Start State = Unlocked: Action (Thread 1) = Lock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); // A thread that locks an item it has already locked will succeed printf( "8. Start State = locked(1): Action (Thread 1) = Lock: End State = Locked\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); // Locking a thread that's already locked - but do it with a thread // other than the one that did the locking. printf( "9. Start State = Locked(1): Action (Thread 2) = tryLock: End State = Locked\n"); printf(" An Error is Expected\n"); Status = CreateAThread((int *) DoOnelock, &Temp); DoSleep(100); /* Wait for that thread to finish */ // Unlock a thread that's already locked - but unlock it with a thread // other than the one that did the locking. printf( "10. Start State = Locked(1): Action (Thread 2) = unLock: End State = Locked\n"); printf(" An Error is Expected\n"); Status = CreateAThread((int *) DoOneUnlock, &Temp); DoSleep(100); /* Wait for that thread to finish */ // The second thread will try to get the lock held by the first thread. This is OK // but the second thread will suspend until the first thread releases the lock. printf( "11. Start State = Locked(1): Action (Thread 2) = Lock: End State = Locked\n"); Status = CreateAThread((int *) DoOneTrylock, &Temp); DoSleep(100); /* Wait for that thread to finish */ // The first thread does an unlock. This means the second thread is now able to get // the lock so there is a "relock" when thread two succeeds. printf( "12. Start State = locked(1): Action (Thread 1) = unLock: End State = Locked(by 2)\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); DoSleep(100); /* Wait for locking action of 2nd thread to finish */ printf( "13. Start State = Locked(2): Action (Thread 3) = unLock: End State = Locked(2)\n"); printf(" An Error is Expected\n"); Status = CreateAThread((int *) DoOneUnlock, &Temp); DoSleep(100); /* Wait for that thread to finish */ printf( "14. Start State = Locked(2): Action (Thread 1) = tryLock: End State = Locked(2)\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_LOCK, DO_NOT_SUSPEND, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf( "15. Start State = locked(2): Action (Thread 1) = unLock: End State = Locked(2)\n"); printf(" An Error is Expected\n"); READ_MODIFY(MEMORY_INTERLOCK_BASE, DO_UNLOCK, SUSPEND_UNTIL_LOCKED, &LockResult); printf("%s\n", &(Success[SPART * LockResult])); printf("++++ END of hardware interlock code ++++\n\n"); /********************************************************************* Show the interface to the CONTEXT calls. The best place to see this usage is in os_init in base.c *********************************************************************/ /********************************************************************* Show the interface to the scheduler printer. The main job here is to fill in the structure that is passed to the printer. *********************************************************************/ memset(&SPData, 0, sizeof(SP_INPUT_DATA)); strcpy(SPData.TargetAction, "Create"); SPData.CurrentlyRunningPID = 2; SPData.TargetPID = 3; // The NumberOfRunningProcesses as used here is for a future implementation // when we are running multiple processors. For right now, set this to 0 // so it won't be printed out. SPData.NumberOfRunningProcesses = 0; SPData.NumberOfReadyProcesses = 3; // Processes ready to run for (i = 0; i <= SPData.NumberOfReadyProcesses; i++) { SPData.ReadyProcessPIDs[i] = i; } SPData.NumberOfProcSuspendedProcesses = 4; for (i = 0; i <= SPData.NumberOfProcSuspendedProcesses; i++) { SPData.ProcSuspendedProcessPIDs[i] = i + 3; } SPData.NumberOfMessageSuspendedProcesses = 2; for (i = 0; i <= SPData.NumberOfMessageSuspendedProcesses; i++) { SPData.MessageSuspendedProcessPIDs[i] = i + 16; } SPData.NumberOfTimerSuspendedProcesses = 6; for (i = 0; i <= SPData.NumberOfTimerSuspendedProcesses; i++) { SPData.TimerSuspendedProcessPIDs[i] = i + 8; } SPData.NumberOfDiskSuspendedProcesses = 1; for (i = 0; i <= SPData.NumberOfDiskSuspendedProcesses; i++) { SPData.DiskSuspendedProcessPIDs[i] = i + 15; } SPData.NumberOfTerminatedProcesses = 0; // Not used at this time CALL(SPPrintLine(&SPData)); /********************************************************************* Show the interface to the memory_printer. We're just inputting random values here to show the interface. *********************************************************************/ memset(&MPData, 0, sizeof(MP_INPUT_DATA)); // Good practice - clean up for (j = 0; j < PHYS_MEM_PGS ; j = j + 2) { MPData.frames[j].InUse = TRUE; MPData.frames[j].Pid = (j / 2) % 10; MPData.frames[j].LogicalPage = j * 16 + 10; MPData.frames[j].State = (j / 2) % 8; } MPPrintLine(&MPData); /********************************************************************* Show how the skewed random numbers work on this platform. *********************************************************************/ for (j = 0; j < NUM_RAND_BUCKETS; j++) random_buckets[j] = 0; for (j = 0; j < 100000; j++) { GetSkewedRandomNumber(&Value, NUM_RAND_BUCKETS); random_buckets[Value]++; } printf("\nTesting that your platform produces correctly skewed random\n"); printf("numbers. Each row should have higher count than the previous.\n"); printf(" Range: Counts in this range.\n"); for (j = 0; j < NUM_RAND_BUCKETS; j = j + 8) { k = 0; for (i = j; i < j + 8; i++) k += random_buckets[i]; printf("%3d - %3d: %d\n", j, j + 7, k); } /********************************************************************* Show the interface to the Z502Halt. Note that the program will end NOW, since we don't return from the command. *********************************************************************/ MEM_WRITE(Z502Halt, 0); }
extern "C" void TcpIpServerThread(void* dummy) { char* ipaddress; int bytesSent; int bytesRecv; SOCKET m_socket; SOCKET save_m_socket; sockaddr_in service; hostent* localHost; SOCKET AcceptSocket; int iResult,displayed_message = 0; int ii; unsigned char waitingForResponseFromStack = FALSE; unsigned char socketReady = FALSE; unsigned long waitingForResponseFromStackStart = 0; (void)dummy; iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); if ( iResult != NO_ERROR ) printf("Error in WSAStartup() = %d\n", WSAGetLastError()); // Create a socket. m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if ( m_socket == INVALID_SOCKET ) { printf( "Error in socket(): %ld\n", WSAGetLastError() ); WSACleanup(); return; } // Bind the socket. service.sin_family = AF_INET; // Get the local host information localHost = gethostbyname(""); ipaddress = inet_ntoa (*(struct in_addr *)*localHost->h_addr_list); printf("Using ip address = '%s'\n", ipaddress); //service.sin_addr.s_addr = inet_addr( ipaddress ); service.sin_addr.s_addr = htonl( INADDR_ANY ); service.sin_port = htons( (unsigned short)g_server_port ); if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) { printf( "bind() failed error=%d.\n", WSAGetLastError() ); closesocket(m_socket); return; } // Listen on the socket. if ( listen( m_socket, 1 ) == SOCKET_ERROR ) printf( "Error listening on socket. Error=%d\n", WSAGetLastError()); // Accept connections. //printf( "Waiting for a client to connect...\n" ); save_m_socket = m_socket; while(1) { if ( !socketReady ) { if(displayed_message == 0){ printf( "TCP : Waiting for a client to connect...\n" ); displayed_message = 1; } AcceptSocket = accept(m_socket, NULL, NULL ); if ( AcceptSocket != SOCKET_ERROR ) { m_socket = AcceptSocket; socketReady = TRUE; } displayed_message = 0; } if ( g_sendReady && socketReady ) { memcpy(sendbuf, g_sendBuffer, g_sendLength); bytesSent = send( m_socket, sendbuf, g_sendLength, 0); if ( bytesSent == SOCKET_ERROR || bytesSent < 0 ) { printf("socket error in send = %d\n", WSAGetLastError()); m_socket = save_m_socket; socketReady = FALSE; } else { strcpy(traceBuffer,"Tx->\n"); for ( ii=0; ii<g_sendLength; ii++ ) { sprintf(myBuffer, " %02X", g_sendBuffer[ii] & 0xFF); strcat(traceBuffer, myBuffer); if ( ii%20 == 19 ) { printf("%s\n", traceBuffer); strcpy(traceBuffer,""); } } printf("%s\n",traceBuffer); if ( separateReply ) { m_socket = save_m_socket; socketReady = FALSE; } } waitingForResponseFromStack = FALSE; g_sendReady = FALSE; } if ( socketReady && !waitingForResponseFromStack ) { // lets see if there is a message for me bytesRecv = recv( m_socket, (char*)recvbuf, 1000, MSG_PEEK ); if ( bytesRecv != SOCKET_ERROR ) { if ( bytesRecv > 0 ) bytesRecv = recv( m_socket, (char*)recvbuf, bytesRecv, 0); if ( bytesRecv > 0 ) { strcpy(traceBuffer,"Rx<-\n"); for ( ii=0; ii<bytesRecv; ii++ ) { sprintf(myBuffer, " %02X", recvbuf[ii]&0xFF); strcat(traceBuffer, myBuffer); if ( ii%20 == 19 ) { printf("%s\n", traceBuffer); strcpy(traceBuffer,""); } } printf("%s\n", traceBuffer); waitingForResponseFromStack = doCMProcessReceivedStreamBytes(recvbuf, bytesRecv); if ( waitingForResponseFromStack ) waitingForResponseFromStackStart = C1222Misc_GetFreeRunningTimeInMS(); if ( waitingForResponseFromStack && separateReply ) waitingForResponseFromStack = FALSE; } receivedChunks++; totalReceivedBytes += bytesRecv; if ( bytesRecv == 0 ) { printf("socket closed\n"); m_socket = save_m_socket; socketReady = FALSE; } else if ( bytesRecv < 0 ) { printf("socket error in recv1 = %d\n", WSAGetLastError()); m_socket = save_m_socket; socketReady = FALSE; } } else { printf("socket error in recv = %d\n", WSAGetLastError()); m_socket = save_m_socket; socketReady = FALSE; } } if ( waitingForResponseFromStack ) { if ( (C1222Misc_GetFreeRunningTimeInMS()-waitingForResponseFromStackStart) > 60000L ) waitingForResponseFromStack = FALSE; } DoSleep(100); } }
/*! * \brief Open a serial port * * The serial port is only opened if it was not locked. Locking is * achieved by creating a file in /var/lock named after the serial port: * LCK..<name> where <name> is the basename of the device path. * * The lock file contains a string representation of the process id of the * process which has opened the file. * * The opened serial port is set to 8 bits, no parity, 1 stop bit and raw mode. * Hardware flow control is enabled. * * \param dev: a device name, as in open() * \param flags: the open flags, as in open() * \returns -1 on error, an open file descriptor on success */ int openSerialPort(const char *dev, int flags) { #ifdef WIN32 return -1; #else const char *locktail = dev; char tmpname[64]; char tmp[64]; int fd; int len; struct termios options; int maxtries = 10; struct seradm *newser = calloc(1, sizeof(struct seradm)); if (!newser) return -1; // get the lock in /var/lock while (*locktail) locktail++; while (locktail > dev && *locktail != '/') locktail--; if (*locktail == '/') locktail++; sprintf(newser->lockname,"/var/lock/LCK..%s", locktail); strcpy(tmpname, "/var/lock/LCK..TMXXXXXX"); if ((fd = mkstemp(tmpname)) < 0) { free(newser); return -1; } chmod(tmpname, 0644); len = sprintf(tmp, "%10d\n", getpid()); if (write(fd, tmp,len) != len) { close(fd); unlink(tmpname); free(newser); return -1; } close(fd); while (link(tmpname, newser->lockname) < 0) { // lock taken by someone else? int lockedpid; if (errno != EEXIST) { // some strange error, bail out unlink(tmpname); free(newser); return -1; } if ( ( (fd = open(newser->lockname, O_RDONLY)) < 0) || ( (len = read(fd, tmp, sizeof(tmp)-1)) < 0)) { // cannot open or read lock file, bail out unlink(tmpname); if (fd >= 0) close(fd); free(newser); return -1; } close(fd); tmp[len] = 0; if (sscanf(tmp, " %d", &lockedpid) != 1) { unlink(tmpname); free(newser); return -1; // no pid in lockfile? } if (lockedpid == getpid()) break; // lock already taken by us, probably double open if (kill(lockedpid, 0) < 0 && errno == ESRCH) { // stale lock file, remove it if (unlink(newser->lockname) < 0 && errno != EINTR && errno != ENOENT) { // cannot remove the stale lockfile, give up unlink(tmpname); free(newser); return -1; } syslog(LOG_INFO, "removed stale lock file %s\n", newser->lockname); } if (--maxtries < 0) { unlink(tmpname); free(newser); return -1; } DoSleep(100); // sleep 100ms } unlink(tmpname); // now the lockfile is written, really open the device if ((fd = open(dev, flags)) < 0) { unlink(newser->lockname); free(newser); return -1; } // get the parameters tcgetattr(fd, &options); cfmakeraw(&options); // Enable the receiver options.c_cflag |= CREAD; // No parity (8N1): options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; // enable hardware flow control (CNEW_RTCCTS) options.c_cflag |= CRTSCTS; // Set the new options for the port... tcsetattr(fd, TCSANOW, &options); newser->serialfd = fd; if (pthread_mutex_lock(&mutex) != 0) { close(fd); unlink(newser->lockname); free(newser); return -1; } newser->next = serlist; serlist = newser; pthread_mutex_unlock(&mutex); return fd; #endif }