Beispiel #1
0
void fault_handler(void)
{
    INT32 device_id;
    INT32 status;
    INT32 Index = 0;
    static INT32 how_many_interrupt_entries = 0;

    // Get cause of interrupt
    read_from_memory(Z502InterruptDevice, &device_id);
    // Set this device as target of our query
    write_to_memory(Z502InterruptDevice, &device_id);
    // Now read the status of this device
    read_from_memory(Z502InterruptStatus, &status);

    if (ConfigArgument->show_other_output == Full)
    {
        printf("Fault_handler: Found vector type %d with value %d\n", device_id, status);
    }
    else if (ConfigArgument->show_other_output == Limited)
    {
        how_many_interrupt_entries++;
        if (how_many_interrupt_entries < 10)
        {
            printf("Fault_handler: Found vector type %d with value %d\n", device_id, status);
        }
    }

    if (status >= 1024)
    {
        printf("Invalid address: virtual page number out of range!\n");
        shut_down();
    }

    frame_scheduler(status);

    // Conditional output.
    if (ConfigArgument->show_memory_output == Full)
    {
        int idx;
        for (idx = 0; idx < NUM_OF_FRAMES; idx++)
        {
            if (shadow_pg_tbl[idx] != NULL)
            {
                MP_setup((INT32) ((*shadow_pg_tbl[idx]) & PTBL_FRAME_BITS), (INT32) process_holder[idx],
                         (INT32) (shadow_pg_tbl[idx] - address_holder[process_holder[idx]]),
                         (INT32) ((*shadow_pg_tbl[idx]) & PTBL_STATE_BITS) >> 13);
            }
        }
Beispiel #2
0
/************************************************************************
 INTERRUPT_HANDLER
 When the Z502 gets a hardware interrupt, it transfers control to
 this routine in the OS.
 ************************************************************************/
void interrupt_handler(void)
{
    INT32 status;
    INT32 device_id;
    INT32 Index = 0;

    static BOOL remove_this_in_your_code = TRUE;
    static INT32 how_many_interrupt_entries = 0;

    // Get cause of interrupt
    read_from_memory(Z502InterruptDevice, &device_id);
    // Set this device as target of our query
    write_to_memory(Z502InterruptDevice, &device_id);
    // Now read the status of this device
    read_from_memory(Z502InterruptStatus, &status);

    // Conditional output.
    if (ConfigArgument->show_other_output == Full)
    {
        printf("Interrupt_handler: Found device ID %d with status %d\n",
               device_id, status);
    }
    else if (ConfigArgument->show_other_output == Limited)
    {
        how_many_interrupt_entries++; /** TEMP **/
        if (remove_this_in_your_code && (how_many_interrupt_entries < 10))
        {
            printf("Interrupt_handler: Found device ID %d with status %d\n",
                   device_id, status);
        }
    }
    
    if (device_id == 4)
    {
        os_make_ready_to_run();
    }
    else if (device_id >= 5 || device_id <= 7)
    {
        read_write_scheduler(device_id);
    }

    Index = 0;
    write_to_memory(Z502InterruptClear, &Index);
    read_from_memory(Z502InterruptDevice, &device_id);
    // Clear out this device - we're done with it
    write_to_memory(Z502InterruptClear, &Index);
} /* End of interrupt_handler */
Beispiel #3
0
/**
 * Read data from the specific position indicated by the disk id and sector id.
 * @param disk_id: Indicates which disk to read from. 
 * @param sector: Indicates which sector to read from. 
 * @param buffer: The buffer to hold the data.
 */
void os_disk_read(INT32 disk_id, INT32 sector, char *buffer)
{
    INT32 status;
    int result;

    write_to_memory(Z502DiskSetID, &disk_id);
    read_from_memory(Z502DiskStatus, &status);
    // Disk hasn't been used - should be free
    if (status == DEVICE_FREE)
    {
        write_to_memory(Z502DiskSetSector, &sector);
        write_to_memory(Z502DiskSetBuffer, (INT32 *) buffer);
        status = 0; // Specify a read
        write_to_memory(Z502DiskSetAction, &status);
        status = 0; // Must be set to 0
        write_to_memory(Z502DiskStart, &status);

        CurrentPCB->disk_id = disk_id;
        CurrentPCB->operation = -1;

        get_data_lock(SUSPEND_QUEUE_LOCK);
        result = add_to_suspend_queue(CurrentPCB);
        release_data_lock(SUSPEND_QUEUE_LOCK);
        if (result)
        {
            CurrentPCB->suspend = TRUE;
            print_scheduling_info(ACTION_NAME_READ, CurrentPCB, NORMAL_INFO);
        }
        else
        {
            error_message("add_to_suspend_queue");
            shut_down();
        }
        os_dispatcher();
    }
    else if (status == DEVICE_IN_USE)
    {
        CurrentPCB->disk_id = disk_id;
        CurrentPCB->operation = READ_ONE;
        CurrentPCB->disk = disk_id;
        CurrentPCB->sector = sector;
        CurrentPCB->disk_data = (DISK_DATA *) buffer;

        get_data_lock(SUSPEND_QUEUE_LOCK);
        result = add_to_suspend_queue(CurrentPCB);
        release_data_lock(SUSPEND_QUEUE_LOCK);
        if (result)
        {
            CurrentPCB->suspend = TRUE;
            print_scheduling_info(ACTION_NAME_READ, CurrentPCB, NORMAL_INFO);
        }
        else
        {
            error_message("add_to_suspend_queue");
            shut_down();
        }
        os_dispatcher();
    }
}
Beispiel #4
0
ViewReaction * Calculator::proceed_to_next_state(INPUT_TYPES input_type, OPERATION_MODE operation_mode, int number)
{
    switch (input_type)
    {
        case INPUT_TYPES::OPERAND_CHARACTER:
            on_character_insertion(input_type);
            break;
        case INPUT_TYPES::OPERATOR:
            execute_operation(operation_mode, number, input_type);
            break;
        case INPUT_TYPES::MEMORY_SAVE:
            save_in_memory(number, input_type);
            break;
        case INPUT_TYPES::MEMORY_READ:
            read_from_memory(input_type);
            break;
        case INPUT_TYPES::CLEAR_HISTORY:
            clear_history(input_type);
            break;
    }
}
Beispiel #5
0
int main (int argc, char* argv[])
{
  char** array;
  unsigned array_size;
  char command[32];
  unsigned array_index;
  char command_letter;
  int size_or_position;
  int error = 0;

#ifdef MTRACE
  mtrace ();
#endif /* MTRACE */

  if (argc != 2) {
    fprintf (stderr, "%s: array-size\n", argv[0]);
    return 1;
  }
  
  array_size = strtoul (argv[1], 0, 0);
  array = (char **) calloc (array_size, sizeof (char *));
  assert (array != 0);

  /* Follow the user's commands.  */
  while (!error) {
    printf ("Please enter a command: ");
    command_letter = getchar ();
    assert (command_letter != EOF);
    switch (command_letter) {

    case 'a':
      fgets (command, sizeof (command), stdin);
      if (sscanf (command, "%u %i", &array_index, &size_or_position) == 2 
	  && array_index < array_size)
	allocate (&(array[array_index]), size_or_position);
      else
	error = 1;
      break;

    case 'd':
      fgets (command, sizeof (command), stdin);
      if (sscanf (command, "%u", &array_index) == 1
	  && array_index < array_size)
	deallocate (&(array[array_index]));
      else
	error = 1;
      break;

    case 'r':
      fgets (command, sizeof (command), stdin);
      if (sscanf (command, "%u %i", &array_index, &size_or_position) == 2
	  && array_index < array_size)
	read_from_memory (array[array_index], size_or_position);
      else
	error = 1;
      break;

    case 'w':
      fgets (command, sizeof (command), stdin);
      if (sscanf (command, "%u %i", &array_index, &size_or_position) == 2
	  && array_index < array_size)
	write_to_memory (array[array_index], size_or_position);
      else
	error = 1;
      break;

    case 'q':
      free ((void *) array);
      return 0;

    default:
      error = 1;
    }
  }

  free ((void *) array);
  return 1;
}
Beispiel #6
0
/**
 * Write data into the specific position indicated by the disk id and sector id.
 * @param disk_id: Indicates which disk to write to. 
 * @param sector: Indicates which sector to write to. 
 * @param buffer: The data needs to be written.
 */
void os_disk_write(INT32 disk_id, INT32 sector, char *buffer)
{
    INT32 status;
    int result;

    /* Do the hardware call to put data on disk */
    write_to_memory(Z502DiskSetID, &disk_id);
    read_from_memory(Z502DiskStatus, &status);

    // If the disk is free, indicates success in writing.
    if (status == DEVICE_FREE)
    {
        write_to_memory(Z502DiskSetSector, &sector);
        write_to_memory(Z502DiskSetBuffer, (INT32 *) buffer);
        status = 1; // Specify a write
        write_to_memory(Z502DiskSetAction, &status);
        status = 0; // Must be set to 0
        write_to_memory(Z502DiskStart, &status);

        CurrentPCB->disk_id = disk_id;
        CurrentPCB->operation = -1;

        get_data_lock(SUSPEND_QUEUE_LOCK);
        result = add_to_suspend_queue(CurrentPCB);
        release_data_lock(SUSPEND_QUEUE_LOCK);
        if (result)
        {
            CurrentPCB->suspend = TRUE;
            print_scheduling_info(ACTION_NAME_SUSPEND, CurrentPCB, NORMAL_INFO);
        }
        else
        {
            error_message("add_to_suspend_queue");
            shut_down();
        }
        os_dispatcher();
        return;
    }
    // If the disk is busy, indicates failure in writing.
    else if (status == DEVICE_IN_USE)
    {
        DISK_DATA *disk_data;
        disk_data = (DISK_DATA *) calloc(1, sizeof ( DISK_DATA));

        CurrentPCB->disk_id = disk_id;
        CurrentPCB->operation = WRITE_ONE;
        CurrentPCB->disk = disk_id;
        CurrentPCB->sector = sector;
        memcpy(disk_data, buffer, sizeof (DISK_DATA));
        CurrentPCB->disk_data = disk_data;
        result = add_to_suspend_queue(CurrentPCB);
        if (result)
        {
            CurrentPCB->suspend = TRUE;
            print_scheduling_info(ACTION_NAME_WRITE, CurrentPCB, NORMAL_INFO);
        }
        else
        {
            error_message("add_to_suspend_queue");
            shut_down();
        }
        os_dispatcher();
        return;
    }
    else
    {
        printf("some error not processed in os_disk_write!\n");
    }
}
Beispiel #7
0
/**
 * 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);
        }
    }
}
Beispiel #8
0
// Evict Page returns the location of the lowest open slot in the provided memory level
// If there are no open spots, it uses the paging algorithm to evict one page from the memlev
// and move it to the next one. 
int evict_page(Memlev memlev) {
	// printf("Trying to evict a page.\n");

	// Interate through the entire page table
	// If there is still room available in ram
	// find the lowest available location and return the data
	int i;
	int max_elements = 0;

	// This switch case determines the memory level the eviction is on
	// if the provided memlevel is "nul" or "hdd", not page can be 
	// evicted and an error value of -2 is returned.
	switch(memlev){
		case ram:
			// printf("Trying to evict page from ram\n");
			max_elements = MAXRAM;
			break;
		case ssd:
			// printf("Trying to evict page from ssd\n");
			max_elements = MAXSSD;
			break;
		case hdd:
			// printf("Trying to evict page from hdd\n");
			max_elements = MAXHDD;
			break;
		default:
			printf("Trying to evict page from the 'nul' level\n");
			return -2;
			break;
		break;
	}

	// This is the list of all the available pageframes in a memlev
	// 1 = taken, 0 = available
	int slots[max_elements];

	// Iterate through the entire page table, marking all the taken pageframes
	for(int i = 0; i < max_elements; i++){
		slots[i] = 0;
	}

	// Iterate through the entire page table, marking all the taken pageframes
	for(i = 0; i < MAXADDR; i++){
		if(page_table[i].memlev == memlev && page_table[i].empty == 0){
			slots[page_table[i].location] = 1;
		}
	}

	// Once all the take page frames are marked, see if any are still available
	for(i = 0; i < max_elements; i++){
		// If there is a pageframe available
		// update the location with the ram information and return it.
		if(slots[i] == 0){
			switch(memlev){
				case ram:
					// printf("Trying to lock ram slot %i\n", i);
					if(pthread_mutex_trylock(&(lock_ram[i])) == 0){
						// printf("Successfully locked ram slot %i\n", i);
						return i;
					}
					// printf("Failed to lock ram slot %i\n", i);
					break;
				case ssd:
					if(pthread_mutex_trylock(&(lock_ssd[i])) == 0){
						return i;
					}
					break;
				case hdd:
					if(pthread_mutex_trylock(&(lock_hdd[i])) == 0){
						return i;
					}
					break;
				break;
			}
		}
	}


	// If there are no spots in this memory level,
	// then we will have to move a page out
	// and into the higher memory level

	// Here we call evict on the next memory level
	// to find a place to move the evicted page
	// printf("'We need to go deeper'\n");
	int new_slot = evict_page(memlev + 1);

	if(new_slot < 0){
		printf("There is a serious problem\n");	
	}

	// We call our custom algorithm to find a page to evict
	vAddr temp_page = page_to_remove(memlev, type_r);

	// finally we move the content to the higher memory level
	switch(memlev) {
		case ram:
			write_to_memory(ssd, new_slot, read_from_memory(ram, page_table[temp_page].location));
			break;
		case ssd:
			write_to_memory(hdd, new_slot, read_from_memory(ssd, page_table[temp_page].location));
			break;
		break;
	}

	// update it's paging information to reflect the new position
	page_table[temp_page].memlev = memlev + 1;
	int result = page_table[temp_page].location;
	page_table[temp_page].location = new_slot;

	// Unlock the modified page
	pthread_mutex_unlock(&(page_table[temp_page].lock));

	// And return the newly opened pageframe
	return result;
}
Beispiel #9
0
// This method takes in a page address and content
// and tries to put the content in the desired page
// If the page is not in RAM, a page fault is generated and the page is moved into ram
// Error = 0, success
// Error = 1, desired page is outside page table range
// Error = 2, Requested page is empty
int store_value(vAddr address, content c) {
	if(printing == 2){
		printf("Storing value %i in page %i\n", c, address);
	}

	if((address > MAXADDR) || (address < 0)){
		if(printing == 2){
			printf("Page Fault: Tried to access an page outside range: %d\n",address);
		}
		return 1;
	}

	// return the result
	if(page_table[address].empty) {
		if(printing == 2){
			printf("Page Fault: Requested page is empty: %d\n",address);
		}
		return 2;
	}
	// Lock this page to prevent other threads from manipulating it
	pthread_mutex_lock(&(page_table[address].lock));

	// check if the desired page is in RAM
	if(page_table[address].memlev != ram) {
		if(printing == 2){
			printf("Page Fault: requested page not in RAM\n");
		}

		int new_location = evict_page(ram);

		write_to_memory(ram, new_location, read_from_memory(page_table[address].memlev, page_table[address].location));

		// Unlock the now free pageframe in the previous memory level
		switch(page_table[address].memlev){
			case ssd:
				pthread_mutex_unlock(&(lock_ssd[page_table[address].location]));
				break;
			case hdd:
				pthread_mutex_unlock(&(lock_hdd[page_table[address].location]));
				break;
			break;
		}

		// update the information for the page
		page_table[address].memlev = ram;
		page_table[address].location = new_location;
		page_table[address].referenced++;

		if(printing == 2){
			printf("Recovered from Page Fault: requested page not in RAM\n");
		}
	}

	// write the information to the ram location
	write_to_memory(ram, page_table[address].location, c);

	if(printing == 2){
		printf("\n");
	}

	// Unlock the page
	pthread_mutex_unlock(&(page_table[address].lock));

	return 0;
}