update name of code to labcodes
This commit is contained in:
196
labcodes/lab7/kern/sync/check_sync.c
Normal file
196
labcodes/lab7/kern/sync/check_sync.c
Normal file
@@ -0,0 +1,196 @@
|
||||
#include <stdio.h>
|
||||
#include <proc.h>
|
||||
#include <sem.h>
|
||||
#include <monitor.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define N 5 /* 哲学家数目 */
|
||||
#define LEFT (i-1+N)%N /* i的左邻号码 */
|
||||
#define RIGHT (i+1)%N /* i的右邻号码 */
|
||||
#define THINKING 0 /* 哲学家正在思考 */
|
||||
#define HUNGRY 1 /* 哲学家想取得叉子 */
|
||||
#define EATING 2 /* 哲学家正在吃面 */
|
||||
#define TIMES 4 /* 吃4次饭 */
|
||||
#define SLEEP_TIME 10
|
||||
|
||||
//---------- philosophers problem using semaphore ----------------------
|
||||
int state_sema[N]; /* 记录每个人状态的数组 */
|
||||
/* 信号量是一个特殊的整型变量 */
|
||||
semaphore_t mutex; /* 临界区互斥 */
|
||||
semaphore_t s[N]; /* 每个哲学家一个信号量 */
|
||||
|
||||
struct proc_struct *philosopher_proc_sema[N];
|
||||
|
||||
void phi_test_sema(i) /* i:哲学家号码从0到N-1 */
|
||||
{
|
||||
if(state_sema[i]==HUNGRY&&state_sema[LEFT]!=EATING
|
||||
&&state_sema[RIGHT]!=EATING)
|
||||
{
|
||||
state_sema[i]=EATING;
|
||||
up(&s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void phi_take_forks_sema(int i) /* i:哲学家号码从0到N-1 */
|
||||
{
|
||||
down(&mutex); /* 进入临界区 */
|
||||
state_sema[i]=HUNGRY; /* 记录下哲学家i饥饿的事实 */
|
||||
phi_test_sema(i); /* 试图得到两只叉子 */
|
||||
up(&mutex); /* 离开临界区 */
|
||||
down(&s[i]); /* 如果得不到叉子就阻塞 */
|
||||
}
|
||||
|
||||
void phi_put_forks_sema(int i) /* i:哲学家号码从0到N-1 */
|
||||
{
|
||||
down(&mutex); /* 进入临界区 */
|
||||
state_sema[i]=THINKING; /* 哲学家进餐结束 */
|
||||
phi_test_sema(LEFT); /* 看一下左邻居现在是否能进餐 */
|
||||
phi_test_sema(RIGHT); /* 看一下右邻居现在是否能进餐 */
|
||||
up(&mutex); /* 离开临界区 */
|
||||
}
|
||||
|
||||
int philosopher_using_semaphore(void * arg) /* i:哲学家号码,从0到N-1 */
|
||||
{
|
||||
int i, iter=0;
|
||||
i=(int)arg;
|
||||
cprintf("I am No.%d philosopher_sema\n",i);
|
||||
while(iter++<TIMES)
|
||||
{ /* 无限循环 */
|
||||
cprintf("Iter %d, No.%d philosopher_sema is thinking\n",iter,i); /* 哲学家正在思考 */
|
||||
do_sleep(SLEEP_TIME);
|
||||
phi_take_forks_sema(i);
|
||||
/* 需要两只叉子,或者阻塞 */
|
||||
cprintf("Iter %d, No.%d philosopher_sema is eating\n",iter,i); /* 进餐 */
|
||||
do_sleep(SLEEP_TIME);
|
||||
phi_put_forks_sema(i);
|
||||
/* 把两把叉子同时放回桌子 */
|
||||
}
|
||||
cprintf("No.%d philosopher_sema quit\n",i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------philosopher problem using monitor ------------
|
||||
/*PSEUDO CODE :philosopher problem using monitor
|
||||
* monitor dp
|
||||
* {
|
||||
* enum {thinking, hungry, eating} state[5];
|
||||
* condition self[5];
|
||||
*
|
||||
* void pickup(int i) {
|
||||
* state[i] = hungry;
|
||||
* if ((state[(i+4)%5] != eating) && (state[(i+1)%5] != eating)) {
|
||||
* state[i] = eating;
|
||||
* else
|
||||
* self[i].wait();
|
||||
* }
|
||||
*
|
||||
* void putdown(int i) {
|
||||
* state[i] = thinking;
|
||||
* if ((state[(i+4)%5] == hungry) && (state[(i+3)%5] != eating)) {
|
||||
* state[(i+4)%5] = eating;
|
||||
* self[(i+4)%5].signal();
|
||||
* }
|
||||
* if ((state[(i+1)%5] == hungry) && (state[(i+2)%5] != eating)) {
|
||||
* state[(i+1)%5] = eating;
|
||||
* self[(i+1)%5].signal();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* void init() {
|
||||
* for (int i = 0; i < 5; i++)
|
||||
* state[i] = thinking;
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
struct proc_struct *philosopher_proc_condvar[N]; // N philosopher
|
||||
int state_condvar[N]; // the philosopher's state: EATING, HUNGARY, THINKING
|
||||
monitor_t mt, *mtp=&mt; // monitor
|
||||
|
||||
void phi_test_condvar (i) {
|
||||
if(state_condvar[i]==HUNGRY&&state_condvar[LEFT]!=EATING
|
||||
&&state_condvar[RIGHT]!=EATING) {
|
||||
cprintf("phi_test_condvar: state_condvar[%d] will eating\n",i);
|
||||
state_condvar[i] = EATING ;
|
||||
cprintf("phi_test_condvar: signal self_cv[%d] \n",i);
|
||||
cond_signal(&mtp->cv[i]) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void phi_take_forks_condvar(int i) {
|
||||
down(&(mtp->mutex));
|
||||
//--------into routine in monitor--------------
|
||||
// LAB7 EXERCISE1: YOUR CODE
|
||||
// I am hungry
|
||||
// try to get fork
|
||||
//--------leave routine in monitor--------------
|
||||
if(mtp->next_count>0)
|
||||
up(&(mtp->next));
|
||||
else
|
||||
up(&(mtp->mutex));
|
||||
}
|
||||
|
||||
void phi_put_forks_condvar(int i) {
|
||||
down(&(mtp->mutex));
|
||||
|
||||
//--------into routine in monitor--------------
|
||||
// LAB7 EXERCISE1: YOUR CODE
|
||||
// I ate over
|
||||
// test left and right neighbors
|
||||
//--------leave routine in monitor--------------
|
||||
if(mtp->next_count>0)
|
||||
up(&(mtp->next));
|
||||
else
|
||||
up(&(mtp->mutex));
|
||||
}
|
||||
|
||||
//---------- philosophers using monitor (condition variable) ----------------------
|
||||
int philosopher_using_condvar(void * arg) { /* arg is the No. of philosopher 0~N-1*/
|
||||
|
||||
int i, iter=0;
|
||||
i=(int)arg;
|
||||
cprintf("I am No.%d philosopher_condvar\n",i);
|
||||
while(iter++<TIMES)
|
||||
{ /* iterate*/
|
||||
cprintf("Iter %d, No.%d philosopher_condvar is thinking\n",iter,i); /* thinking*/
|
||||
do_sleep(SLEEP_TIME);
|
||||
phi_take_forks_condvar(i);
|
||||
/* need two forks, maybe blocked */
|
||||
cprintf("Iter %d, No.%d philosopher_condvar is eating\n",iter,i); /* eating*/
|
||||
do_sleep(SLEEP_TIME);
|
||||
phi_put_forks_condvar(i);
|
||||
/* return two forks back*/
|
||||
}
|
||||
cprintf("No.%d philosopher_condvar quit\n",i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void check_sync(void){
|
||||
|
||||
int i;
|
||||
|
||||
//check semaphore
|
||||
sem_init(&mutex, 1);
|
||||
for(i=0;i<N;i++){
|
||||
sem_init(&s[i], 0);
|
||||
int pid = kernel_thread(philosopher_using_semaphore, (void *)i, 0);
|
||||
if (pid <= 0) {
|
||||
panic("create No.%d philosopher_using_semaphore failed.\n");
|
||||
}
|
||||
philosopher_proc_sema[i] = find_proc(pid);
|
||||
set_proc_name(philosopher_proc_sema[i], "philosopher_sema_proc");
|
||||
}
|
||||
|
||||
//check condition variable
|
||||
monitor_init(&mt, N);
|
||||
for(i=0;i<N;i++){
|
||||
state_condvar[i]=THINKING;
|
||||
int pid = kernel_thread(philosopher_using_condvar, (void *)i, 0);
|
||||
if (pid <= 0) {
|
||||
panic("create No.%d philosopher_using_condvar failed.\n");
|
||||
}
|
||||
philosopher_proc_condvar[i] = find_proc(pid);
|
||||
set_proc_name(philosopher_proc_condvar[i], "philosopher_condvar_proc");
|
||||
}
|
||||
}
|
||||
59
labcodes/lab7/kern/sync/monitor.c
Normal file
59
labcodes/lab7/kern/sync/monitor.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#include <stdio.h>
|
||||
#include <monitor.h>
|
||||
#include <kmalloc.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
// Initialize monitor.
|
||||
void
|
||||
monitor_init (monitor_t * mtp, size_t num_cv) {
|
||||
int i;
|
||||
assert(num_cv>0);
|
||||
mtp->next_count = 0;
|
||||
mtp->cv = NULL;
|
||||
sem_init(&(mtp->mutex), 1); //unlocked
|
||||
sem_init(&(mtp->next), 0);
|
||||
mtp->cv =(condvar_t *) kmalloc(sizeof(condvar_t)*num_cv);
|
||||
assert(mtp->cv!=NULL);
|
||||
for(i=0; i<num_cv; i++){
|
||||
mtp->cv[i].count=0;
|
||||
sem_init(&(mtp->cv[i].sem),0);
|
||||
mtp->cv[i].owner=mtp;
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock one of threads waiting on the condition variable.
|
||||
void
|
||||
cond_signal (condvar_t *cvp) {
|
||||
//LAB7 EXERCISE1: YOUR CODE
|
||||
cprintf("cond_signal begin: cvp %x, cvp->count %d, cvp->owner->next_count %d\n", cvp, cvp->count, cvp->owner->next_count);
|
||||
/*
|
||||
* cond_signal(cv) {
|
||||
* if(cv.count>0) {
|
||||
* mt.next_count ++;
|
||||
* signal(cv.sem);
|
||||
* wait(mt.next);
|
||||
* mt.next_count--;
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
cprintf("cond_signal end: cvp %x, cvp->count %d, cvp->owner->next_count %d\n", cvp, cvp->count, cvp->owner->next_count);
|
||||
}
|
||||
|
||||
// Suspend calling thread on a condition variable waiting for condition Atomically unlocks
|
||||
// mutex and suspends calling thread on conditional variable after waking up locks mutex. Notice: mp is mutex semaphore for monitor's procedures
|
||||
void
|
||||
cond_wait (condvar_t *cvp) {
|
||||
//LAB7 EXERCISE1: YOUR CODE
|
||||
cprintf("cond_wait begin: cvp %x, cvp->count %d, cvp->owner->next_count %d\n", cvp, cvp->count, cvp->owner->next_count);
|
||||
/*
|
||||
* cv.count ++;
|
||||
* if(mt.next_count>0)
|
||||
* signal(mt.next)
|
||||
* else
|
||||
* signal(mt.mutex);
|
||||
* wait(cv.sem);
|
||||
* cv.count --;
|
||||
*/
|
||||
cprintf("cond_wait end: cvp %x, cvp->count %d, cvp->owner->next_count %d\n", cvp, cvp->count, cvp->owner->next_count);
|
||||
}
|
||||
90
labcodes/lab7/kern/sync/monitor.h
Normal file
90
labcodes/lab7/kern/sync/monitor.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef __KERN_SYNC_MONITOR_CONDVAR_H__
|
||||
#define __KERN_SYNC_MOINTOR_CONDVAR_H__
|
||||
|
||||
#include <sem.h>
|
||||
/* In [OS CONCEPT] 7.7 section, the accurate define and approximate implementation of MONITOR was introduced.
|
||||
* INTRODUCTION:
|
||||
* Monitors were invented by C. A. R. Hoare and Per Brinch Hansen, and were first implemented in Brinch Hansen's
|
||||
* Concurrent Pascal language. Generally, a monitor is a language construct and the compiler usually enforces mutual exclusion. Compare this with semaphores, which are usually an OS construct.
|
||||
* DEFNIE & CHARACTERISTIC:
|
||||
* A monitor is a collection of procedures, variables, and data structures grouped together.
|
||||
* Processes can call the monitor procedures but cannot access the internal data structures.
|
||||
* Only one process at a time may be be active in a monitor.
|
||||
* Condition variables allow for blocking and unblocking.
|
||||
* cv.wait() blocks a process.
|
||||
* The process is said to be waiting for (or waiting on) the condition variable cv.
|
||||
* cv.signal() (also called cv.notify) unblocks a process waiting for the condition variable cv.
|
||||
* When this occurs, we need to still require that only one process is active in the monitor. This can be done in several ways:
|
||||
* on some systems the old process (the one executing the signal) leaves the monitor and the new one enters
|
||||
* on some systems the signal must be the last statement executed inside the monitor.
|
||||
* on some systems the old process will block until the monitor is available again.
|
||||
* on some systems the new process (the one unblocked by the signal) will remain blocked until the monitor is available again.
|
||||
* If a condition variable is signaled with nobody waiting, the signal is lost. Compare this with semaphores, in which a signal will allow a process that executes a wait in the future to no block.
|
||||
* You should not think of a condition variable as a variable in the traditional sense.
|
||||
* It does not have a value.
|
||||
* Think of it as an object in the OOP sense.
|
||||
* It has two methods, wait and signal that manipulate the calling process.
|
||||
* IMPLEMENTATION:
|
||||
* monitor mt {
|
||||
* ----------------variable------------------
|
||||
* semaphore mutex;
|
||||
* semaphore next;
|
||||
* int next_count;
|
||||
* condvar {int count, sempahore sem} cv[N];
|
||||
* other variables in mt;
|
||||
* --------condvar wait/signal---------------
|
||||
* cond_wait (cv) {
|
||||
* cv.count ++;
|
||||
* if(mt.next_count>0)
|
||||
* signal(mt.next)
|
||||
* else
|
||||
* signal(mt.mutex);
|
||||
* wait(cv.sem);
|
||||
* cv.count --;
|
||||
* }
|
||||
*
|
||||
* cond_signal(cv) {
|
||||
* if(cv.count>0) {
|
||||
* mt.next_count ++;
|
||||
* signal(cv.sem);
|
||||
* wait(mt.next);
|
||||
* mt.next_count--;
|
||||
* }
|
||||
* }
|
||||
* --------routines in monitor---------------
|
||||
* routineA_in_mt () {
|
||||
* wait(mt.mutex);
|
||||
* ...
|
||||
* real body of routineA
|
||||
* ...
|
||||
* if(next_count>0)
|
||||
* signal(mt.next);
|
||||
* else
|
||||
* signal(mt.mutex);
|
||||
* }
|
||||
*/
|
||||
|
||||
typedef struct monitor monitor_t;
|
||||
|
||||
typedef struct condvar{
|
||||
semaphore_t sem; // the sem semaphore is used to down the waiting proc, and the signaling proc should up the waiting proc
|
||||
int count; // the number of waiters on condvar
|
||||
monitor_t * owner; // the owner(monitor) of this condvar
|
||||
} condvar_t;
|
||||
|
||||
typedef struct monitor{
|
||||
semaphore_t mutex; // the mutex lock for going into the routines in monitor, should be initialized to 1
|
||||
semaphore_t next; // the next semaphore is used to down the signaling proc itself, and the other OR wakeuped waiting proc should wake up the sleeped signaling proc.
|
||||
int next_count; // the number of of sleeped signaling proc
|
||||
condvar_t *cv; // the condvars in monitor
|
||||
} monitor_t;
|
||||
|
||||
// Initialize variables in monitor.
|
||||
void monitor_init (monitor_t *cvp, size_t num_cv);
|
||||
// Unlock one of threads waiting on the condition variable.
|
||||
void cond_signal (condvar_t *cvp);
|
||||
// Suspend calling thread on a condition variable waiting for condition atomically unlock mutex in monitor,
|
||||
// and suspends calling thread on conditional variable after waking up locks mutex.
|
||||
void cond_wait (condvar_t *cvp);
|
||||
|
||||
#endif /* !__KERN_SYNC_MONITOR_CONDVAR_H__ */
|
||||
77
labcodes/lab7/kern/sync/sem.c
Normal file
77
labcodes/lab7/kern/sync/sem.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include <defs.h>
|
||||
#include <wait.h>
|
||||
#include <atomic.h>
|
||||
#include <kmalloc.h>
|
||||
#include <sem.h>
|
||||
#include <proc.h>
|
||||
#include <sync.h>
|
||||
#include <assert.h>
|
||||
|
||||
void
|
||||
sem_init(semaphore_t *sem, int value) {
|
||||
sem->value = value;
|
||||
wait_queue_init(&(sem->wait_queue));
|
||||
}
|
||||
|
||||
static __noinline void __up(semaphore_t *sem, uint32_t wait_state) {
|
||||
bool intr_flag;
|
||||
local_intr_save(intr_flag);
|
||||
{
|
||||
wait_t *wait;
|
||||
if ((wait = wait_queue_first(&(sem->wait_queue))) == NULL) {
|
||||
sem->value ++;
|
||||
}
|
||||
else {
|
||||
assert(wait->proc->wait_state == wait_state);
|
||||
wakeup_wait(&(sem->wait_queue), wait, wait_state, 1);
|
||||
}
|
||||
}
|
||||
local_intr_restore(intr_flag);
|
||||
}
|
||||
|
||||
static __noinline uint32_t __down(semaphore_t *sem, uint32_t wait_state) {
|
||||
bool intr_flag;
|
||||
local_intr_save(intr_flag);
|
||||
if (sem->value > 0) {
|
||||
sem->value --;
|
||||
local_intr_restore(intr_flag);
|
||||
return 0;
|
||||
}
|
||||
wait_t __wait, *wait = &__wait;
|
||||
wait_current_set(&(sem->wait_queue), wait, wait_state);
|
||||
local_intr_restore(intr_flag);
|
||||
|
||||
schedule();
|
||||
|
||||
local_intr_save(intr_flag);
|
||||
wait_current_del(&(sem->wait_queue), wait);
|
||||
local_intr_restore(intr_flag);
|
||||
|
||||
if (wait->wakeup_flags != wait_state) {
|
||||
return wait->wakeup_flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
up(semaphore_t *sem) {
|
||||
__up(sem, WT_KSEM);
|
||||
}
|
||||
|
||||
void
|
||||
down(semaphore_t *sem) {
|
||||
uint32_t flags = __down(sem, WT_KSEM);
|
||||
assert(flags == 0);
|
||||
}
|
||||
|
||||
bool
|
||||
try_down(semaphore_t *sem) {
|
||||
bool intr_flag, ret = 0;
|
||||
local_intr_save(intr_flag);
|
||||
if (sem->value > 0) {
|
||||
sem->value --, ret = 1;
|
||||
}
|
||||
local_intr_restore(intr_flag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
19
labcodes/lab7/kern/sync/sem.h
Normal file
19
labcodes/lab7/kern/sync/sem.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef __KERN_SYNC_SEM_H__
|
||||
#define __KERN_SYNC_SEM_H__
|
||||
|
||||
#include <defs.h>
|
||||
#include <atomic.h>
|
||||
#include <wait.h>
|
||||
|
||||
typedef struct {
|
||||
int value;
|
||||
wait_queue_t wait_queue;
|
||||
} semaphore_t;
|
||||
|
||||
void sem_init(semaphore_t *sem, int value);
|
||||
void up(semaphore_t *sem);
|
||||
void down(semaphore_t *sem);
|
||||
bool try_down(semaphore_t *sem);
|
||||
|
||||
#endif /* !__KERN_SYNC_SEM_H__ */
|
||||
|
||||
31
labcodes/lab7/kern/sync/sync.h
Normal file
31
labcodes/lab7/kern/sync/sync.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __KERN_SYNC_SYNC_H__
|
||||
#define __KERN_SYNC_SYNC_H__
|
||||
|
||||
#include <x86.h>
|
||||
#include <intr.h>
|
||||
#include <mmu.h>
|
||||
#include <assert.h>
|
||||
#include <atomic.h>
|
||||
#include <sched.h>
|
||||
|
||||
static inline bool
|
||||
__intr_save(void) {
|
||||
if (read_eflags() & FL_IF) {
|
||||
intr_disable();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__intr_restore(bool flag) {
|
||||
if (flag) {
|
||||
intr_enable();
|
||||
}
|
||||
}
|
||||
|
||||
#define local_intr_save(x) do { x = __intr_save(); } while (0)
|
||||
#define local_intr_restore(x) __intr_restore(x);
|
||||
|
||||
#endif /* !__KERN_SYNC_SYNC_H__ */
|
||||
|
||||
122
labcodes/lab7/kern/sync/wait.c
Normal file
122
labcodes/lab7/kern/sync/wait.c
Normal file
@@ -0,0 +1,122 @@
|
||||
#include <defs.h>
|
||||
#include <list.h>
|
||||
#include <sync.h>
|
||||
#include <wait.h>
|
||||
#include <proc.h>
|
||||
|
||||
void
|
||||
wait_init(wait_t *wait, struct proc_struct *proc) {
|
||||
wait->proc = proc;
|
||||
wait->wakeup_flags = WT_INTERRUPTED;
|
||||
list_init(&(wait->wait_link));
|
||||
}
|
||||
|
||||
void
|
||||
wait_queue_init(wait_queue_t *queue) {
|
||||
list_init(&(queue->wait_head));
|
||||
}
|
||||
|
||||
void
|
||||
wait_queue_add(wait_queue_t *queue, wait_t *wait) {
|
||||
assert(list_empty(&(wait->wait_link)) && wait->proc != NULL);
|
||||
wait->wait_queue = queue;
|
||||
list_add_before(&(queue->wait_head), &(wait->wait_link));
|
||||
}
|
||||
|
||||
void
|
||||
wait_queue_del(wait_queue_t *queue, wait_t *wait) {
|
||||
assert(!list_empty(&(wait->wait_link)) && wait->wait_queue == queue);
|
||||
list_del_init(&(wait->wait_link));
|
||||
}
|
||||
|
||||
wait_t *
|
||||
wait_queue_next(wait_queue_t *queue, wait_t *wait) {
|
||||
assert(!list_empty(&(wait->wait_link)) && wait->wait_queue == queue);
|
||||
list_entry_t *le = list_next(&(wait->wait_link));
|
||||
if (le != &(queue->wait_head)) {
|
||||
return le2wait(le, wait_link);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wait_t *
|
||||
wait_queue_prev(wait_queue_t *queue, wait_t *wait) {
|
||||
assert(!list_empty(&(wait->wait_link)) && wait->wait_queue == queue);
|
||||
list_entry_t *le = list_prev(&(wait->wait_link));
|
||||
if (le != &(queue->wait_head)) {
|
||||
return le2wait(le, wait_link);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wait_t *
|
||||
wait_queue_first(wait_queue_t *queue) {
|
||||
list_entry_t *le = list_next(&(queue->wait_head));
|
||||
if (le != &(queue->wait_head)) {
|
||||
return le2wait(le, wait_link);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wait_t *
|
||||
wait_queue_last(wait_queue_t *queue) {
|
||||
list_entry_t *le = list_prev(&(queue->wait_head));
|
||||
if (le != &(queue->wait_head)) {
|
||||
return le2wait(le, wait_link);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
wait_queue_empty(wait_queue_t *queue) {
|
||||
return list_empty(&(queue->wait_head));
|
||||
}
|
||||
|
||||
bool
|
||||
wait_in_queue(wait_t *wait) {
|
||||
return !list_empty(&(wait->wait_link));
|
||||
}
|
||||
|
||||
void
|
||||
wakeup_wait(wait_queue_t *queue, wait_t *wait, uint32_t wakeup_flags, bool del) {
|
||||
if (del) {
|
||||
wait_queue_del(queue, wait);
|
||||
}
|
||||
wait->wakeup_flags = wakeup_flags;
|
||||
wakeup_proc(wait->proc);
|
||||
}
|
||||
|
||||
void
|
||||
wakeup_first(wait_queue_t *queue, uint32_t wakeup_flags, bool del) {
|
||||
wait_t *wait;
|
||||
if ((wait = wait_queue_first(queue)) != NULL) {
|
||||
wakeup_wait(queue, wait, wakeup_flags, del);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wakeup_queue(wait_queue_t *queue, uint32_t wakeup_flags, bool del) {
|
||||
wait_t *wait;
|
||||
if ((wait = wait_queue_first(queue)) != NULL) {
|
||||
if (del) {
|
||||
do {
|
||||
wakeup_wait(queue, wait, wakeup_flags, 1);
|
||||
} while ((wait = wait_queue_first(queue)) != NULL);
|
||||
}
|
||||
else {
|
||||
do {
|
||||
wakeup_wait(queue, wait, wakeup_flags, 0);
|
||||
} while ((wait = wait_queue_next(queue, wait)) != NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wait_current_set(wait_queue_t *queue, wait_t *wait, uint32_t wait_state) {
|
||||
assert(current != NULL);
|
||||
wait_init(wait, current);
|
||||
current->state = PROC_SLEEPING;
|
||||
current->wait_state = wait_state;
|
||||
wait_queue_add(queue, wait);
|
||||
}
|
||||
|
||||
48
labcodes/lab7/kern/sync/wait.h
Normal file
48
labcodes/lab7/kern/sync/wait.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef __KERN_SYNC_WAIT_H__
|
||||
#define __KERN_SYNC_WAIT_H__
|
||||
|
||||
#include <list.h>
|
||||
|
||||
typedef struct {
|
||||
list_entry_t wait_head;
|
||||
} wait_queue_t;
|
||||
|
||||
struct proc_struct;
|
||||
|
||||
typedef struct {
|
||||
struct proc_struct *proc;
|
||||
uint32_t wakeup_flags;
|
||||
wait_queue_t *wait_queue;
|
||||
list_entry_t wait_link;
|
||||
} wait_t;
|
||||
|
||||
#define le2wait(le, member) \
|
||||
to_struct((le), wait_t, member)
|
||||
|
||||
void wait_init(wait_t *wait, struct proc_struct *proc);
|
||||
void wait_queue_init(wait_queue_t *queue);
|
||||
void wait_queue_add(wait_queue_t *queue, wait_t *wait);
|
||||
void wait_queue_del(wait_queue_t *queue, wait_t *wait);
|
||||
|
||||
wait_t *wait_queue_next(wait_queue_t *queue, wait_t *wait);
|
||||
wait_t *wait_queue_prev(wait_queue_t *queue, wait_t *wait);
|
||||
wait_t *wait_queue_first(wait_queue_t *queue);
|
||||
wait_t *wait_queue_last(wait_queue_t *queue);
|
||||
|
||||
bool wait_queue_empty(wait_queue_t *queue);
|
||||
bool wait_in_queue(wait_t *wait);
|
||||
void wakeup_wait(wait_queue_t *queue, wait_t *wait, uint32_t wakeup_flags, bool del);
|
||||
void wakeup_first(wait_queue_t *queue, uint32_t wakeup_flags, bool del);
|
||||
void wakeup_queue(wait_queue_t *queue, uint32_t wakeup_flags, bool del);
|
||||
|
||||
void wait_current_set(wait_queue_t *queue, wait_t *wait, uint32_t wait_state);
|
||||
|
||||
#define wait_current_del(queue, wait) \
|
||||
do { \
|
||||
if (wait_in_queue(wait)) { \
|
||||
wait_queue_del(queue, wait); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* !__KERN_SYNC_WAIT_H__ */
|
||||
|
||||
Reference in New Issue
Block a user