/* PROGRAM: fibo_task This program will repeatedly receive synchronously a positive value k and compute the k-th fibonacci number. Each computed fibonacci number is sent to the "printer" message queue. It exits if it receives k==-1 */ int fibo_task(int argl, void* args) { unsigned int k,f; long msg; char *prbuf = malloc(1024); Pid_t pid; sprintf(prbuf,"Hello from fibo_task process %d.\n",GetPid()); print_string(prbuf); while(1) { // Wait for a request to compute a Fibonacci number. pid = ReceivePort(&msg, 1); assert(pid == GetPPid()); if(msg<0) { sprintf(prbuf, "fibo_task exiting (pid = %d). Bye!\n", GetPid()); print_string(prbuf); free(prbuf); Exit(0); /* Test Exit! */ } k = msg; sprintf(prbuf,"I will compute the %d-th Fibonacci number\n",k); print_string(prbuf); f = fibo(k); sprintf(prbuf,"The %d-th Fibonacci number is %d.\n",k,f); print_string(prbuf); } return 0; }
/* * This is the initial task, which starts all the other tasks (except for the idle task). */ int boot_task(int argl, void* args) { int i,ntasks,ncalls; int status; long msg; Message m; Pid_t pid; Pid_t printer; Pid_t* pids; ntasks = ((int*)args)[0]; ncalls = ((int*)args)[1]; pids = malloc(sizeof(Pid_t)*ntasks); /* Launch child processes */ printer = Exec(printer_task,0,NULL); ReceivePort(&msg,1); /* Wait until it is ready to print */ for(i=0; i<ntasks; i++) { pids[i] = pid = Exec(fibodriver_task,sizeof(ncalls),&ncalls); printf("boot_task: executed fibodriver %d pid=%d\n",i+1,pid); } /* Wait for child processes */ for(i=0;i<ntasks;i++) { Pid_t pid = WaitChild(NOPROC, &status); printf("boot_task: Process %d exited with exit value %d.\n",pid,status); } /* Tell printer to exit */ m.type = PRINTER_QUIT; m.data = NULL; m.len = 0; SendMail("printer",&m); /* Loop until all children have exited */ while(WaitChild(NOPROC,NULL) != NOPROC) printf("boot_task: child exited.\n"); printf("boot_task: exiting!\n"); return 0; }
// // The CommThread Function. // UINT CSerialPort::CommThread(LPVOID pParam) { // Cast the void pointer passed to the thread back to // a pointer of CSerialPort class CSerialPort *port = (CSerialPort*)pParam; // Set the status variable in the dialog class to // TRUE to indicate the thread is running. port->m_bThreadAlive = TRUE; // Misc. variables DWORD BytesTransfered = 0; DWORD Event = 0; DWORD CommEvent = 0; DWORD dwError = 0; static COMSTAT comstat; BOOL bResult = TRUE; // Clear comm buffers at startup if (port->m_hComm) // check if the port is opened PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // begin forever loop. This loop will run as long as the thread is alive. for (;;) { // Make a call to WaitCommEvent(). This call will return immediatly // because our port was created as an async port (FILE_FLAG_OVERLAPPED // and an m_OverlappedStructerlapped structure specified). This call will cause the // m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to // be placed in a non-signeled state if there are no bytes available to be read, // or to a signeled state if there are bytes available. If this event handle // is set to the non-signeled state, it will be set to signeled when a // character arrives at the port. // we do this for each port! bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov); if (!bResult) { // If WaitCommEvent() returns FALSE, process the last error to determin // the reason.. switch (dwError = GetLastError()) { case ERROR_IO_PENDING: { // This is a normal return value if there are no bytes // to read at the port. // Do nothing and continue break; } case 87: { // Under Windows NT, this value is returned for some reason. // I have not investigated why, but it is also a valid reply // Also do nothing and continue. break; } default: { // All other error codes indicate a serious error has // occured. Process this error. port->ProcessErrorMessage(4);//"WaitCommEvent()" break; } } } else { // If WaitCommEvent() returns TRUE, check to be sure there are // actually bytes in the buffer to read. // // If you are reading more than one byte at a time from the buffer // (which this program does not do) you will have the situation occur // where the first byte to arrive will cause the WaitForMultipleObjects() // function to stop waiting. The WaitForMultipleObjects() function // resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state // as it returns. // // If in the time between the reset of this event and the call to // ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again // to the signeled state. When the call to ReadFile() occurs, it will // read all of the bytes from the buffer, and the program will // loop back around to WaitCommEvent(). // // At this point you will be in the situation where m_OverlappedStruct.hEvent is set, // but there are no bytes available to read. If you proceed and call // ReadFile(), it will return immediatly due to the async port setup, but // GetOverlappedResults() will not return until the next character arrives. // // It is not desirable for the GetOverlappedResults() function to be in // this state. The thread shutdown event (event 0) and the WriteFile() // event (Event2) will not work if the thread is blocked by GetOverlappedResults(). // // The solution to this is to check the buffer with a call to ClearCommError(). // This call will reset the event handle, and if there are no bytes to read // we can loop back through WaitCommEvent() again, then proceed. // If there are really bytes to read, do nothing and proceed. bResult = ClearCommError(port->m_hComm, &dwError, &comstat); if (comstat.cbInQue == 0) continue; } // end if bResult // Main wait function. This function will normally block the thread // until one of nine events occur that require action. Sleep(20); Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE); switch (Event) { case 0: { // Shutdown event. This is event zero so it will be // the higest priority and be serviced first. SetCommMask(port->m_hComm, 0); CloseHandle(port->m_hComm); port->m_hComm=NULL; port->m_bThreadAlive = FALSE; // Kill this thread. break is not needed, but makes me feel better. TRACE(_T("Exit CommThread \n")); AfxEndThread(100); break; } case 1: // read event { GetCommMask(port->m_hComm, &CommEvent); if (CommEvent & EV_RXCHAR) { // Receive character event from port. Sleep(10); TRACE(_T("*** Receive data ***\n")); ReceivePort(port, comstat); } break; } case 2: // write event { // Write character event from port WriteData(port); break; } } // end switch } // close forever loop return 0; }