Exemple #1
0
static void simulate_io(void)
{
    if (io_queue_head == NULL)
        return; /* There are no I/O requests */

    if (io_queue_head->execution_time-- <= 0)
    {
        io_request *completed = io_queue_head;
        pcb_t *pcb;

        /* Move the programs "PC" to the next "instruction" */
        completed->pcb->pc = ((op_t*)completed->pcb->pc) + 1;

        /*
         * Remove the I/O request from the queue before calling the student's
         * code.  We must do this, because once we release the simulator_mutex,
         * the I/O queue may have changed.
         */
        pcb = completed->pcb;
        io_queue_head = completed->next;
        if (io_queue_head == NULL)
            io_queue_tail = NULL;
        free(completed);

        /* Call the student's wake_up() handler */
        pthread_mutex_unlock(&simulator_mutex);
        IRWL_WRITER_LOCK(student_lock);
        wake_up(pcb);
        IRWL_WRITER_UNLOCK(student_lock);
        pthread_mutex_lock(&simulator_mutex);
    }
}
Exemple #2
0
extern void force_preempt(unsigned int cpu_id)
{
    assert(cpu_id < cpu_count);

    IRWL_WRITER_UNLOCK(student_lock);
    pthread_mutex_lock(&simulator_mutex);

    /*
     * It is possible that the student's code calls force_preempt() at the
     * same time the process was already going to yield or terminate.  We
     * check for that case by only preempting if the CPU is set to CPU_RUNNING.
     */
    if (simulator_cpu_data[cpu_id].state == CPU_RUNNING)
    {
        simulator_cpu_data[cpu_id].state = CPU_PREEMPT;
        pthread_cond_signal(&simulator_cpu_data[cpu_id].wakeup);

        /* Ensure the scheduler gets run before the simulator */
        pthread_cond_wait(&simulator_cpu_data[cpu_id].wakeup,
            &simulator_mutex);
    }

    pthread_mutex_unlock(&simulator_mutex);
    IRWL_WRITER_LOCK(student_lock);
}
static void simulate_creat(void) {
  static int processes_created = 0;

  if ((simulator_time % 10) == 0 && processes_created < PROCESS_COUNT) {
    /* Call student's wake_up() handler */
    pthread_mutex_unlock(&simulator_mutex);
    IRWL_WRITER_LOCK(student_lock);
    wake_up(&processes[processes_created]);
    IRWL_WRITER_UNLOCK(student_lock);
    pthread_mutex_lock(&simulator_mutex);

    processes_created++;
  }
}
Exemple #4
0
/*
 * context_switch() and force_preempt() are the two functions available to
 * student's code.
 */
extern void context_switch(unsigned int cpu_id, pcb_t *pcb,
                           int preemption_time)
{
    assert(cpu_id < cpu_count);
    assert(pcb == NULL || (pcb >= processes && pcb <= processes +
        PROCESS_COUNT - 1));

    context_switches++;

    IRWL_WRITER_UNLOCK(student_lock);
    pthread_mutex_lock(&simulator_mutex);
    simulator_cpu_data[cpu_id].current = pcb;
    simulator_cpu_data[cpu_id].preemption_timer = preemption_time;
    pthread_mutex_unlock(&simulator_mutex);
    IRWL_WRITER_LOCK(student_lock);
}
extern void force_preempt(unsigned int cpu_id) {
  // printf("UUUUUUUUUUU-- force_preempt: %d\n", cpu_id);
  // fflush(stdout);
  assert(cpu_id < cpu_count);

  IRWL_WRITER_UNLOCK(student_lock);
  pthread_mutex_lock(&simulator_mutex);

  /*
   * It is possible that the student's code calls force_preempt() at the
   * same time the process was already going to yield or terminate.  We
   * check for that case by only preempting if the CPU is set to CPU_RUNNING.
   */
  if (simulator_cpu_data[cpu_id].state == CPU_RUNNING) {
    simulator_cpu_data[cpu_id].state = CPU_PREEMPT;
    pthread_cond_signal(&simulator_cpu_data[cpu_id].wakeup);
    // wait to make sure thread finishes preempt and context switch
    pthread_cond_wait(&thread_yielded, &simulator_mutex);
  }

  pthread_mutex_unlock(&simulator_mutex);
  IRWL_WRITER_LOCK(student_lock);
}