void Dispatcher(){ MEMORY_MAPPED_IO mmio; struct ready_PCB *runningPCB; int runnningPID; // runningPcb = FindCurrent(runningProcessPid); runningPCB=Get_R_Head(); while(runningPCB==NULL) { // if(GetHead(&pcb_timer_queue)!= NULL || GetHead(&pcb_disk_queue!=NULL)) { // mmio.Mode=Z502Action; // mmio.Field1=mmio.Field2=mmio.Field3=0; // MEM_WRITE(Z502Idle, &mmio); // // } CALL(WasteTime()); } //pcb not null, start PCB if pcb is null call idle runnningPID = runningPCB->pid; Queue_R_Dequeue(); mmio.Mode = Z502StartContext; mmio.Field1 =runningPCB->context.Field1; mmio.Field2 = START_NEW_CONTEXT_AND_SUSPEND; MEM_WRITE(Z502Context, &mmio); }
bool SoundCardPMO::WaitForDrain(void) { unsigned iLoop, iNumHeadersPending = 0; for(; !m_bExit && !m_bPause; ) { g_pHeaderMutex->Acquire(); for(iLoop = 0, iNumHeadersPending = 0; iLoop < m_num_headers; iLoop++) { if ((int)m_wavehdr_array[iLoop].dwUser > 0) iNumHeadersPending++; } g_pHeaderMutex->Release(); if (iNumHeadersPending == 0) { return true; } WasteTime(); HandleTimeInfoEvent(NULL); } return false; }
int main() { time_t t1, t2; time(&t1); WasteTime(19); time(&t2); printf("%u", t2-t1); }
// PORTING: This function returns when the sound card is done playing, or // when exit or pause is signaled. Returns true if the card naturally ran // out of things to play. False if m_bExit or m_bPause became true bool SoundCardPMO::WaitForDrain(void) { struct audio_info info; for(; !m_bExit && !m_bPause; ) { ioctl(audio_fd, AUDIO_GETINFO, &info); if (info.play.error) { return true; } WasteTime(); } return false; }
bool AlsaPMO::WaitForDrain(void) { snd_pcm_channel_status_t ainfo; for(; !m_bExit && !m_bPause; ) { ainfo.channel = SND_PCM_CHANNEL_PLAYBACK; snd_pcm_channel_status(m_handle,&ainfo); if (ainfo.underrun || ainfo.status == SND_PCM_STATUS_UNDERRUN) { return true; } WasteTime(); } return false; }
void AlsaPMO::WorkerThread(void) { void *pBuffer; Error eErr; int iRet = -1; Event *pEvent; snd_pcm_channel_status_t ainfo; // Don't do anything until resume is called. m_pPauseSem->Wait(); // Sleep for a pre buffer period PreBuffer(); // The following should be abstracted out into the general thread // classes: #ifdef __linux__ struct sched_param sParam; sParam.sched_priority = sched_get_priority_max(SCHED_OTHER); pthread_setschedparam(pthread_self(), SCHED_OTHER, &sParam); #endif ainfo.channel = SND_PCM_CHANNEL_PLAYBACK; for(; !m_bExit;) { if (m_bPause) { m_pPauseSem->Wait(); continue; } // Loop until we get an Init event from the LMC if (!m_properlyInitialized) { pEvent = ((EventBuffer *)m_pInputBuffer)->GetEvent(); if (pEvent == NULL) { m_pLmc->Wake(); WasteTime(); continue; } if (pEvent->Type() == PMO_Init) { if (IsError(Init(((PMOInitEvent *)pEvent)->GetInfo()))) { delete pEvent; break; } } delete pEvent; continue; } // Set up reading a block from the buffer. If not enough bytes are // available, sleep for a little while and try again. for(;;) { eErr = ((EventBuffer *)m_pInputBuffer)->BeginRead(pBuffer, m_iDataSize); if (eErr == kError_EndOfStream || eErr == kError_Interrupt) break; if (eErr == kError_NoDataAvail) { m_pLmc->Wake(); CheckForBufferUp(); WasteTime(); continue; } // Is there an event pending that we need to take care of // before we play this block of samples? if (eErr == kError_EventPending) { pEvent = ((EventBuffer *)m_pInputBuffer)->PeekEvent(); if (pEvent == NULL) continue; if (pEvent->Type() == PMO_Quit && ((EventBuffer *)m_pInputBuffer)->GetNumBytesInBuffer() > 0) { if (WaitForDrain()) { Reset(true); m_pTarget->AcceptEvent(new Event(INFO_DoneOutputting)); return; } continue; } pEvent = ((EventBuffer *)m_pInputBuffer)->GetEvent(); if (pEvent->Type() == PMO_Init) Init(((PMOInitEvent *)pEvent)->GetInfo()); if (pEvent->Type() == PMO_Reset) Reset(false); if (pEvent->Type() == PMO_Info) HandleTimeInfoEvent((PMOTimeInfoEvent *)pEvent); if (pEvent->Type() == PMO_Quit) { delete pEvent; m_pTarget->AcceptEvent(new Event(INFO_DoneOutputting)); return; } delete pEvent; continue; } if (IsError(eErr)) { ReportError("Internal error occured."); m_pContext->log->Error("Cannot read from buffer in PMO " "worker tread: %d\n", eErr); break; } break; } // Now write the block to the audio device. If the block doesn't // all fit, pause and loop until the entire block has been played. // This loop could be written using non-blocking io... for(;!m_bExit && !m_bPause;) { iRet = snd_pcm_write(m_handle,pBuffer,m_iDataSize); if (iRet == -EAGAIN) { CheckForBufferUp(); WasteTime(); continue; } if (iRet == -EIO) { snd_pcm_channel_prepare(m_handle, SND_PCM_CHANNEL_PLAYBACK); continue; } break; } if (m_bExit) { m_pInputBuffer->EndRead(0); return; } if (m_bPause) { if (iRet == -EAGAIN) m_pInputBuffer->EndRead(0); else { m_pInputBuffer->EndRead(iRet); UpdateBufferStatus(); } continue; } if (iRet < 0) { m_pInputBuffer->EndRead(0); ReportError("Could not write sound data to the soundcard."); m_pContext->log->Error("Failed to write to the soundcard: %s\n", strerror(errno)); break; } m_pInputBuffer->EndRead(iRet); m_pLmc->Wake(); UpdateBufferStatus(); } }
void SoundCardPMO::WorkerThread(void) { void *pBuffer; Error eErr; size_t iRet; Event *pEvent; // audio_info info; bool bPerfWarn = false; // Don't do anything until resume is called. m_pPauseSem->Wait(); // Wait a specified prebuffer time... PreBuffer(); // The following should be abstracted out into the general thread // classes: #ifdef __linux__ struct sched_param sParam; sParam.sched_priority = sched_get_priority_max(SCHED_OTHER); pthread_setschedparam(pthread_self(), SCHED_OTHER, &sParam); #endif for(; !m_bExit;) { if (m_bPause) { m_pPauseSem->Wait(); continue; } // Loop until we get an Init event from the LMC if (!m_properlyInitialized) { pEvent = ((EventBuffer *)m_pInputBuffer)->GetEvent(); if (pEvent == NULL) { m_pLmc->Wake(); WasteTime(); continue; } if (pEvent->Type() == PMO_Init) { if (IsError(Init(((PMOInitEvent *)pEvent)->GetInfo()))) { delete pEvent; break; } } delete pEvent; continue; } // Set up reading a block from the buffer. If not enough bytes are // available, sleep for a little while and try again. for(;;) { eErr = ((EventBuffer *)m_pInputBuffer)->BeginRead(pBuffer, m_iDataSize); if (eErr == kError_EndOfStream || eErr == kError_Interrupt) break; if (eErr == kError_NoDataAvail) { m_pLmc->Wake(); if (!bPerfWarn) { time_t t; time(&t); m_pContext->log->Log(LogPerf, "Output buffer underflow: %s", ctime(&t)); bPerfWarn = true; } WasteTime(); continue; } // Is there an event pending that we need to take care of // before we play this block of samples? if (eErr == kError_EventPending) { pEvent = ((EventBuffer *)m_pInputBuffer)->GetEvent(); if (pEvent->Type() == PMO_Init) Init(((PMOInitEvent *)pEvent)->GetInfo()); if (pEvent->Type() == PMO_Reset) Reset(false); if (pEvent->Type() == PMO_Info) HandleTimeInfoEvent((PMOTimeInfoEvent *)pEvent); if (pEvent->Type() == PMO_Quit) { delete pEvent; if (WaitForDrain()) m_pTarget->AcceptEvent(new Event(INFO_DoneOutputting)); return; } delete pEvent; continue; } if (IsError(eErr)) { ReportError("Internal error occured."); m_pContext->log->Error("Cannot read from buffer in PMO " "worker tread: %d\n", eErr); break; } bPerfWarn = false; break; } // Now write the block to the audio device. If the block doesn't // all fit, pause and loop until the entire block has been played. // This loop could be written using non-blocking io... for(;;) { if (m_bExit || m_bPause) break; // ioctl(audio_fd, AUDIO_GETINFO, &info); if (0) //((unsigned)(info.fragments * info.fragsize) < m_iDataSize) { WasteTime(); continue; } break; } if (m_bExit || m_bPause) { m_pInputBuffer->EndRead(0); continue; } iRet = write(audio_fd, pBuffer, m_iDataSize); // write(audio_fd, pBuffer, 0); // for WaitForDrain(), maybe? if (iRet < 0) { m_pInputBuffer->EndRead(0); ReportError("Could not write sound data to the soundcard."); m_pContext->log->Error("Failed to write to the soundcard: %s\n", strerror(errno)); break; } m_iTotalBytesWritten += iRet; m_pInputBuffer->EndRead(iRet); m_pLmc->Wake(); UpdateBufferStatus(); } }
void svc(SYSTEM_CALL_DATA *SystemCallData) { short call_type; static short do_print = 10; short i; INT32 Time; int Status; void *PageTable; char* processName; MEMORY_MAPPED_IO mmio; call_type = (short) SystemCallData->SystemCallNumber; if (do_print > 0) { printf("SVC handler: %s\n", call_names[call_type]); for (i = 0; i < SystemCallData->NumberOfArguments - 1; i++) { //Value = (long)*SystemCallData->Argument[i]; printf("Arg %d: Contents = (Decimal) %8ld, (Hex) %8lX\n", i, (unsigned long) SystemCallData->Argument[i], (unsigned long) SystemCallData->Argument[i]); } do_print--; } // printf((char *) SystemCallData->Argument[i]); switch (call_type) { //get time service call case SYSNUM_GET_TIME_OF_DAY: mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Clock, &mmio); *(long *) SystemCallData->Argument[0] = mmio.Field1; break; //system sleep call case SYSNUM_SLEEP: mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Clock, &mmio); Time = (long) SystemCallData->Argument[0]; pcb = FindCurrent(runningProcessPid); pcb->wakeUpTimer = Time; EnTimerQueue(&pcb_timer_queue, pcb); //start timer headPCB = GetHead(&pcb_timer_queue)->data; if (pcb == headPCB) { mmio.Mode = Z502Start; mmio.Field1 = (long) SystemCallData->Argument[0]; mmio.Field2 = mmio.Field3 = 0; MEM_WRITE(Z502Timer, &mmio); } Dispatcher(); break; //system create process case SYSNUM_CREATE_PROCESS: if ((long) SystemCallData->Argument[2] < 0) { *SystemCallData->Argument[4] = ERR_BAD_PARAM; } else { PageTable = (void *) calloc(2, NUMBER_VIRTUAL_PAGES); mmio.Mode = Z502InitializeContext; mmio.Field1 = 0; mmio.Field2 = (long) SystemCallData->Argument[1]; mmio.Field3 = (long) PageTable; MEM_WRITE(Z502Context, &mmio); pcb = OSCreateProcess((char*) SystemCallData->Argument[0], (long) mmio.Field1, (long) SystemCallData->Argument[2], (long) SystemCallData->Argument[3], (long) SystemCallData->Argument[4]); if (pcb != NULL) { EnQueue(&pcb_ready_queue, (void*) pcb); *SystemCallData->Argument[3] = pcb->pid; *SystemCallData->Argument[4] = ERR_SUCCESS; } else { *SystemCallData->Argument[4] = ERR_BAD_PARAM; } } break; //system get process id case SYSNUM_GET_PROCESS_ID: processName = (char*) SystemCallData->Argument[0]; if (strlen(processName) == 0) { *SystemCallData->Argument[1] = runningProcessPid; *SystemCallData->Argument[2] = ERR_SUCCESS; } else { pcb = FindPCBByName(processName); } if (pcb != NULL) { *SystemCallData->Argument[1] = pcb->pid; *SystemCallData->Argument[2] = ERR_SUCCESS; } else { *SystemCallData->Argument[2] = ERR_BAD_PARAM; } break; case SYSNUM_PHYSICAL_DISK_READ: do { mmio.Mode = Z502Status; mmio.Field1 = (long) SystemCallData->Argument[0]; mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Disk, &mmio); CALL(WasteTime()); } while (mmio.Field2 != DEVICE_FREE); pcb = FindCurrent(runningProcessPid); if (pcb != NULL) { pcb->diskID = (int) SystemCallData->Argument[0]; pcb->sectorID = (int) SystemCallData->Argument[1]; pcb->memoryBuffer = (void*) SystemCallData->Argument[2]; EnQueue(&(pcb_disk_queue[pcb->diskID]), (void*) pcb); } mmio.Mode = Z502DiskRead; mmio.Field1 = (long) SystemCallData->Argument[0]; mmio.Field2 = (long) SystemCallData->Argument[1]; mmio.Field3 = (long) SystemCallData->Argument[2]; mmio.Field4 = 0; MEM_READ(Z502Disk, &mmio); do { mmio.Mode = Z502Status; mmio.Field1 = (long) SystemCallData->Argument[0]; mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Disk, &mmio); CALL(WasteTime()); } while (mmio.Field2 != DEVICE_FREE); Dispatcher(); break; case SYSNUM_PHYSICAL_DISK_WRITE: do { mmio.Mode = Z502Status; mmio.Field1 = (long) SystemCallData->Argument[0]; mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Disk, &mmio); CALL(WasteTime()); } while (mmio.Field2 != DEVICE_FREE); pcb = FindCurrent(runningProcessPid); if (pcb != NULL) { pcb->diskID = (int) SystemCallData->Argument[0]; pcb->sectorID = (int) SystemCallData->Argument[1]; pcb->memoryBuffer = (void*) SystemCallData->Argument[2]; EnQueue(&(pcb_disk_queue[pcb->diskID]), (void*) pcb); } mmio.Mode = Z502DiskWrite; mmio.Field1 = (long) SystemCallData->Argument[0]; mmio.Field2 = (long) SystemCallData->Argument[1]; mmio.Field3 = (long) SystemCallData->Argument[2]; MEM_WRITE(Z502Disk, &mmio); // mmio.Mode = Z502Action; // mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; // MEM_WRITE(Z502Idle, &mmio); do { mmio.Mode = Z502Status; mmio.Field1 = (long) SystemCallData->Argument[0]; mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Disk, &mmio); CALL(WasteTime()); } while (mmio.Field2 != DEVICE_FREE); Dispatcher(); break; //system terminate call case SYSNUM_TERMINATE_PROCESS: //If ProcessID = -1, then terminate self if ((long) SystemCallData->Argument[0] == -1) { pcb = FindCurrent(runningProcessPid); if (pcb != NULL) { // ReleasePCB(); // RemovePCB(&pcb_ready_queue,(void*)pcb); // RemovePCB(&pcb_timer_queue,(void*)pcb); // *SystemCallData->Argument[1] = ERR_SUCCESS; if (pcb_ready_queue.size == 0 && pcb_timer_queue.size == 0) { mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = mmio.Field4 = 0; MEM_WRITE(Z502Halt, &mmio); *SystemCallData->Argument[1] = ERR_SUCCESS; } else { Dispatcher(); } } else { ReleasePCB(); mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = mmio.Field4 = 0; MEM_WRITE(Z502Halt, &mmio); *SystemCallData->Argument[1] = ERR_SUCCESS; } } else if ((long) SystemCallData->Argument[0] == -2) { // terminite all halt ReleasePCB(); mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = mmio.Field4 = 0; MEM_WRITE(Z502Halt, &mmio); *SystemCallData->Argument[1] = ERR_SUCCESS; // pcb = FindCurrent(runningProcessPid); // RemovePCB(&pcb_ready_queue, (void*) pcb); // RemovePCB(&pcb_timer_queue, (void*) pcb); // RemovePCB(&pcb_ready_queue, (void*) pcb->childProcesses); // RemovePCB(&pcb_timer_queue, (void*) pcb->childProcesses); } else { pcb = FindPCBByPID(SystemCallData->Argument[0]); RemovePCB(&pcb_ready_queue, (void*) pcb); *SystemCallData->Argument[1] = ERR_SUCCESS; } break; defaut: printf("ERROR! call_type not recognized!\n"); printf("Call_type is %i\n", call_type); } } // End of svc
void SoundCardPMO::WorkerThread(void) { void *pBuffer; Error eErr; size_t iRet; Event *pEvent; audio_buf_info info; bool bPerfWarn = false; // Don't do anything until resume is called. m_pPauseSem->Wait(); //CheckForBufferUp(); // Wait a specified prebuffer time... PreBuffer(); for(; !m_bExit;) { if (m_bPause) { m_pPauseSem->Wait(); continue; } // Loop until we get an Init event from the LMC if (!m_properlyInitialized) { pEvent = ((EventBuffer *)m_pInputBuffer)->GetEvent(); if (pEvent == NULL) { m_pLmc->Wake(); WasteTime(); continue; } if (pEvent->Type() == PMO_Init) { if (IsError(Init(((PMOInitEvent *)pEvent)->GetInfo()))) { delete pEvent; break; } } delete pEvent; continue; } // Set up reading a block from the buffer. If not enough bytes are // available, sleep for a little while and try again. for(;;) { eErr = ((EventBuffer *)m_pInputBuffer)->BeginRead(pBuffer, m_iDataSize); if (eErr == kError_EndOfStream || eErr == kError_Interrupt) break; if (eErr == kError_NoDataAvail) { m_pLmc->Wake(); CheckForBufferUp(); if (!bPerfWarn) { time_t t; time(&t); m_pContext->log->Log(LogPerf, "Output buffer underflow: %s", ctime(&t)); bPerfWarn = true; } WasteTime(); continue; } // Is there an event pending that we need to take care of // before we play this block of samples? if (eErr == kError_EventPending) { pEvent = ((EventBuffer *)m_pInputBuffer)->PeekEvent(); if (pEvent == NULL) continue; if (pEvent->Type() == PMO_Quit && ((EventBuffer *)m_pInputBuffer)->GetNumBytesInBuffer() > 0) { if (WaitForDrain()) { m_pTarget->AcceptEvent(new Event(INFO_DoneOutputting)); return; } continue; } pEvent = ((EventBuffer *)m_pInputBuffer)->GetEvent(); if (pEvent->Type() == PMO_Init) Init(((PMOInitEvent *)pEvent)->GetInfo()); if (pEvent->Type() == PMO_Reset) Reset(false); if (pEvent->Type() == PMO_Info) HandleTimeInfoEvent((PMOTimeInfoEvent *)pEvent); if (pEvent->Type() == PMO_Quit) { delete pEvent; m_pTarget->AcceptEvent(new Event(INFO_DoneOutputting)); return; } delete pEvent; continue; } if (IsError(eErr)) { ReportError("Internal error occured."); m_pContext->log->Error("Cannot read from buffer in PMO " "worker tread: %d\n", eErr); break; } bPerfWarn = false; break; } if (m_bExit || m_bPause) { m_pInputBuffer->EndRead(0); continue; } iRet = ALwritesamps(outaudioport, pBuffer, m_iDataSize); if ((int)iRet < 0) { m_pInputBuffer->EndRead(0); ReportError("Could not write sound data to the soundcard."); m_pContext->log->Error("Failed to write to the soundcard: %s\n", strerror(errno)); break; } m_iTotalBytesWritten += iRet; m_pInputBuffer->EndRead(iRet); m_pLmc->Wake(); UpdateBufferStatus(); } }