up(sem_t &sem) { disable_interrupts(); acquire_spinlock(mu); sem->val++; if (not_empty(queue)) { // threads are waiting - wake one up other_thread = dequeue(queue); other_thread->state = READY; add_to_ready_queue(other_thread); } release_spinlock(mu); enable_interrupts(); }
/** * Used for interrupt handler. According to the action the process wants to take, * do the corresponding work and call dispatcher to schedule the processes. * @param device_id: The id of the device obtained from interrupt handler. */ void read_write_scheduler(INT32 device_id) { PCB *pcb; INT16 disk_id; switch (device_id) { case 5: disk_id = 1; break; case 6: disk_id = 2; break; case 7: disk_id = 3; break; default: error_message("Illegal device id."); break; } pcb = remove_from_suspend_queue_by_disk_id(disk_id); if (pcb != NULL) { // If the process needs to write, then write data to specific sector. if (pcb->operation == WRITE_ONE) { INT32 status; write_to_memory(Z502DiskSetID, & pcb->disk); read_from_memory(Z502DiskStatus, &status); if (status == DEVICE_FREE) { write_to_memory(Z502DiskSetSector, & pcb->sector); write_to_memory(Z502DiskSetBuffer, (INT32 *) pcb->disk_data); status = 1; // Specify a write. write_to_memory(Z502DiskSetAction, &status); status = 0; // Must be set to 0. write_to_memory(Z502DiskStart, &status); pcb->operation = WRITE_TWO; enqueue_suspend_queue_reversly(pcb); pcb->suspend = TRUE; print_scheduling_info(ACTION_NAME_WRITE, pcb, NORMAL_INFO); } else { enqueue_suspend_queue_reversly(pcb); pcb->suspend = TRUE; print_scheduling_info(ACTION_NAME_WRITE, pcb, NORMAL_INFO); } } // If the process needs to read, then read data from specific sector. else if (pcb->operation == READ_ONE) { INT32 status; write_to_memory(Z502DiskSetID, & pcb->disk); read_from_memory(Z502DiskStatus, &status); if (status == DEVICE_FREE) { write_to_memory(Z502DiskSetSector, & pcb->sector); write_to_memory(Z502DiskSetBuffer, (INT32 *) pcb->disk_data); status = 0; // Specify a read. write_to_memory(Z502DiskSetAction, &status); status = 0; // Must be set to 0. write_to_memory(Z502DiskStart, &status); pcb->operation = READ_TWO; enqueue_suspend_queue_reversly(pcb); pcb->suspend = TRUE; print_scheduling_info(ACTION_NAME_READ, pcb, NORMAL_INFO); } else { // If in use, add it reversely. enqueue_suspend_queue_reversly(pcb); pcb->suspend = TRUE; print_scheduling_info(ACTION_NAME_READ, pcb, NORMAL_INFO); } } else { add_to_ready_queue(pcb); pcb->suspend = FALSE; print_scheduling_info(ACTION_NAME_READY, pcb, NORMAL_INFO); } } }