Пример #1
0
void customer_function(void *arg) {
    customer_data *customer = (customer_data *)arg;

    syscall_lock_acquire(&barber_lock);

    printf("Customer #%d arrives\n", customer->id);

    if (sitting + standing >= MAX_WAITING) {
        printf("Barbershop full. Customer #%d leaving\n", customer->id);
        syscall_lock_release(&barber_lock);
        syscall_exit(0);
    }

    if (sitting >= MAX_SITTING) {
        printf("Chairs occupied. Customer #%d standing in line\n", customer->id);
        standing++;
        syscall_condition_wait(&standing_cond, &barber_lock);
        standing--;
    }

    if (sitting <= MAX_SITTING && next_customer != NULL) {
        printf("Customer #%d takes a seat\n", customer->id);
        sitting++;
        syscall_condition_wait(&sitting_cond, &barber_lock);
        sitting--;
    }

    printf("Customer #%d is being serviced\n", customer->id);

    next_customer = customer;
    syscall_condition_signal(&barber_cond, &barber_lock);
    syscall_condition_wait(&customer->cond, &barber_lock);
    syscall_lock_release(&barber_lock);
    syscall_exit(0);
}
Пример #2
0
void barber_function(void *arg) {
    barber_data *barber = (barber_data *)arg;
    customer_data *customer;

    syscall_lock_acquire(&barber_lock);

    while (1) {
        printf("Barber #%d looking for new customers\n", barber->id);

        if (next_customer == NULL) {
            syscall_condition_signal(&sitting_cond, &barber_lock);
            syscall_condition_signal(&standing_cond, &barber_lock);

            printf("Barber #%d sleeping\n", barber->id);
            syscall_condition_wait(&barber_cond, &barber_lock);
            printf("Barber #%d got woken up!\n", barber->id);
        } 
        
        customer = next_customer;
        next_customer = NULL;
        printf("Barber #%d servicing customer #%d\n", barber->id, customer->id);
        syscall_lock_release(&barber_lock);
        simulatedwait(100000);
        syscall_lock_acquire(&barber_lock);
        
        printf("Barber #%d done servicing customer #%d\n", barber->id, customer->id);
        syscall_condition_signal(&customer->cond, &barber_lock);
    }
}
Пример #3
0
/*-----------------------------------------------------------------------------------*/
static u32_t
cond_wait(cond_t *cond, mutex_t *mutex, u32_t timeout)
{
  int tdiff;
/*   unsigned long sec, usec; */
/*   struct timeval rtime1, rtime2; */
/*   struct timespec ts; */
/*   struct timezone tz; */
  intptr_t retval;
  uint64_t start, end;

  if (timeout > 0) {
    /* Get a timestamp and add the timeout value. */
/*     gettimeofday(&rtime1, &tz); */
/*     sec = rtime1.tv_sec; */
/*     usec = rtime1.tv_usec; */
/*     usec += timeout % 1000 * 1000; */
/*     sec += (int)(timeout / 1000) + (int)(usec / 1000000); */
/*     usec = usec % 1000000; */
/*     ts.tv_nsec = usec * 1000; */
/*     ts.tv_sec = sec; */
    start = syscall_now_in_nanosec();
    retval = syscall_condition_wait_timeout(cond, mutex, timeout);

    if (retval == M_TIMED_OUT) {
      return SYS_ARCH_TIMEOUT;
    } else {
      /* Calculate for how long we waited for the cond. */
      end = syscall_now_in_nanosec();
/*       gettimeofday(&rtime2, &tz); */
/*       tdiff = (rtime2.tv_sec - rtime1.tv_sec) * 1000 + */
/*         (rtime2.tv_usec - rtime1.tv_usec) / 1000; */
      tdiff = (end - start) / 1000 / 1000;

      if (tdiff <= 0) {
        return 0;
      }

      return tdiff;
    }
  } else {
    syscall_condition_wait(cond, mutex);
    return SYS_ARCH_TIMEOUT;
  }
}
Пример #4
0
void thread_function(void *arg){
    thread_data *data = (thread_data *)arg;
    while(1) {
      syscall_lock_acquire(&baton_lock);
        // Wait until baton is non-zero (meaning that the thread
        // has the baton)
        while(data->baton == 0) {
          syscall_condition_wait(&data->cond, &baton_lock);
        }

        // First thread should perform countdown
        if(data->id == 0) {
            printf("\n%d: New round\n", data->id);
            if(--data->countdown == 0) {
                data->baton = -1; // create a stop baton
            }
        }

        // Pass the baton on to the next thread
        printf("%d: passing the baton on to %d\n", data->id,
                data->next->id);
        data->next->baton = data->baton;

        // Quit if the baton was a stop baton
        if(data->baton < 0){
            printf("%d: I quit.\n",data->id);
            syscall_condition_signal(&data->next->cond,
                    &baton_lock);
            syscall_lock_release(&baton_lock);
            syscall_exit(0);
        }

        //Remove baton from self and signal the next thread
        data->baton = 0;
        syscall_condition_signal(&data->next->cond, &baton_lock);
        syscall_lock_release(&baton_lock);
    }
}
Пример #5
0
/**
 * Handle system calls. Interrupts are enabled when this function is
 * called.
 *
 * @param user_context The userland context (CPU registers as they
 * where when system call instruction was called in userland)
 */
void syscall_handle(context_t *user_context)
{
    /* When a syscall is executed in userland, register a0 contains
     * the number of the syscall. Registers a1, a2 and a3 contain the
     * arguments of the syscall. The userland code expects that after
     * returning from the syscall instruction the return value of the
     * syscall is found in register v0. Before entering this function
     * the userland context has been saved to user_context and after
     * returning from this function the userland context will be
     * restored from user_context.
     */
    switch(user_context->cpu_regs[MIPS_REGISTER_A0]) {
    case SYSCALL_HALT:
        halt_kernel();
        break;
    case SYSCALL_EXIT:
        syscall_exit(user_context->cpu_regs[MIPS_REGISTER_A1]);
        break;
    case SYSCALL_WRITE:
        user_context->cpu_regs[MIPS_REGISTER_V0] =
            syscall_write(user_context->cpu_regs[MIPS_REGISTER_A1],
                          (char*)user_context->cpu_regs[MIPS_REGISTER_A2],
                          (user_context->cpu_regs[MIPS_REGISTER_A3]));
        break;
    case SYSCALL_READ:
        user_context->cpu_regs[MIPS_REGISTER_V0] =
            syscall_read(user_context->cpu_regs[MIPS_REGISTER_A1],
                         (char*)user_context->cpu_regs[MIPS_REGISTER_A2],
                         (user_context->cpu_regs[MIPS_REGISTER_A3]));
        break;
    case SYSCALL_JOIN:
        user_context->cpu_regs[MIPS_REGISTER_V0] =
          syscall_join(user_context->cpu_regs[MIPS_REGISTER_A1]);
        break;
    case SYSCALL_EXEC:
        user_context->cpu_regs[MIPS_REGISTER_V0] =
            syscall_exec((char*)user_context->cpu_regs[MIPS_REGISTER_A1]);
        break;
    case SYSCALL_FORK:
        user_context->cpu_regs[MIPS_REGISTER_V0] =
            syscall_fork((void (*)(int))user_context->cpu_regs[MIPS_REGISTER_A1],
                         user_context->cpu_regs[MIPS_REGISTER_A2]);
        break;
    case SYSCALL_LOCK_CREATE:
        user_context->cpu_regs[MIPS_REGISTER_V0] =
            syscall_lock_create((lock_t*) user_context->cpu_regs[MIPS_REGISTER_A1]);
        break;
    case SYSCALL_LOCK_ACQUIRE:
        syscall_lock_acquire((lock_t*) user_context->cpu_regs[MIPS_REGISTER_A1]);
        break;
    case SYSCALL_LOCK_RELEASE:
        syscall_lock_release((lock_t*) user_context->cpu_regs[MIPS_REGISTER_A1]);
        break;
    case SYSCALL_CONDITION_CREATE:
        user_context->cpu_regs[MIPS_REGISTER_V0] =
            syscall_condition_create((cond_t*) user_context->cpu_regs[MIPS_REGISTER_A1]);
        break;
    case SYSCALL_CONDITION_WAIT:
        syscall_condition_wait((cond_t*) user_context->cpu_regs[MIPS_REGISTER_A1],
                (lock_t*) user_context->cpu_regs[MIPS_REGISTER_A2]);
        break;
    case SYSCALL_CONDITION_SIGNAL:
        syscall_condition_signal((cond_t*) user_context->cpu_regs[MIPS_REGISTER_A1],
                (lock_t*) user_context->cpu_regs[MIPS_REGISTER_A2]);
        break;
    case SYSCALL_CONDITION_BROADCAST:
        syscall_condition_broadcast((cond_t*) user_context->cpu_regs[MIPS_REGISTER_A1],
                (lock_t*) user_context->cpu_regs[MIPS_REGISTER_A2]);
        break;
    default:
        KERNEL_PANIC("Unhandled system call\n");
    }
    /* Move to next instruction after system call */
    user_context->pc += 4;
}