/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see proj13.1/kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see proj13.1/libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
     /* LAB6: YOUR CODE */
#if USE_SKEW_HEAP
     if (rq->lab6_run_pool == NULL) return NULL;
     struct proc_struct *p = le2proc(rq->lab6_run_pool, lab6_run_pool);
#else
     list_entry_t *le = list_next(&(rq->run_list));

     if (le == &rq->run_list)
          return NULL;
     
     struct proc_struct *p = le2proc(le, run_link);
     le = list_next(le);
     while (le != &rq->run_list)
     {
          struct proc_struct *q = le2proc(le, run_link);
          if ((int32_t)(p->lab6_stride - q->lab6_stride) > 0)
               p = q;
          le = list_next(le);
     }
#endif
     if (p->lab6_priority == 0)
          p->lab6_stride += BIG_STRIDE;
     else p->lab6_stride += BIG_STRIDE / p->lab6_priority;
     cprintf("%d is picked by pick_next proc_prioperty:%d proc_stride:%u \n",p->pid,p->lab6_priority,p->lab6_stride);
     return p;
}
Esempio n. 2
0
/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
     /* LAB6: YOUR CODE 
      * (1) get a  proc_struct pointer p  with the minimum value of stride
             (1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_poll
             (1.2) If using list, we have to search list to find the p with minimum stride value
      * (2) update p;s stride value: p->lab6_stride
      * (3) return p
      */
	  struct proc_struct *p;
	  if (USE_SKEW_HEAP) {
			
			if (rq->lab6_run_pool == NULL) return NULL;
			p = le2proc(rq->lab6_run_pool,lab6_run_pool);
	  } else {
			list_entry_t *le = list_next(&(rq->run_list));
     		if (le == &rq->run_list)
          		return NULL;     
     		p = le2proc(le,run_link);
     		le = list_next(le);
     		while (le != &rq->run_list)
     		{
          		struct proc_struct *q = le2proc(le,run_link);
          		if (p->lab6_stride > q->lab6_stride)
               		p = q;
          		le = list_next(le);
     		}
	  }	
	  if (p->lab6_priority == 0) {
          p->lab6_stride += BIG_STRIDE;
	  } else {
		p->lab6_stride += BIG_STRIDE / p->lab6_priority;
	  }
     return p;
}
Esempio n. 3
0
/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see proj13.1/kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see proj13.1/libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
	// rq代表就绪队列,这个函数主要用于挑选下一个要运行的进程
     /* LAB6: YOUR CODE 
      * (1) get a  proc_struct pointer p  with the minimum value of stride
             (1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_poll
             (1.2) If using list, we have to search list to find the p with minimum stride value
      * (2) update p;s stride value: p->lab6_stride
      * (3) return p
      */
#if USE_SKEW_HEAP
	if (rq->lab6_run_pool == NULL) return NULL;
	struct proc_struct *p = le2proc(rq->lab6_run_pool, lab6_run_pool); // 如果使用了优先队列的话,只需要队列的第一个就可以了
#else
     list_entry_t *le = list_next(&(rq->run_list));

     if (le == &rq->run_list)
          return NULL;
     
     struct proc_struct *p = le2proc(le, run_link);
     le = list_next(le);
     while (le != &rq->run_list)
     {
          struct proc_struct *q = le2proc(le, run_link);
          if ((int32_t)(p->lab6_stride - q->lab6_stride) > 0)
               p = q;
          le = list_next(le);
     }
#endif
	if (p->lab6_priority == 0)
		p->lab6_stride += BIG_STRIDE; // 将优先级提升至最高?
	else p->lab6_stride += BIG_STRIDE / p->lab6_priority;
	return p;
}
Esempio n. 4
0
/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
     /* LAB6: 2014210912  
      * (1) get a  proc_struct pointer p  with the minimum value of stride
             (1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_poll
             (1.2) If using list, we have to search list to find the p with minimum stride value
      * (2) update p;s stride value: p->lab6_stride
      * (3) return p
      */
	struct proc_struct *tmp;
	struct list_entry* le=list_next(&(rq->run_list));
	if(le==&rq->run_list)
		return NULL;
	struct proc_struct *p=le2proc(le,run_link);
	while(le->next!=&rq->run_list){
		le=le->next;
		tmp=le2proc(le,run_link);
		if((int32_t)(p->lab6_stride-tmp->lab6_stride)>0)
			p=tmp;
	}
	if(p->lab6_priority==0)
		p->lab6_stride+=BIG_STRIDE;
	else
		p->lab6_stride+=BIG_STRIDE/p->lab6_priority;
	return p;
}
Esempio n. 5
0
/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
     /* LAB6: 2013011377 
      * (1) get a  proc_struct pointer p  with the minimum value of stride
             (1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_poll
             (1.2) If using list, we have to search list to find the p with minimum stride value
      * (2) update p;s stride value: p->lab6_stride
      * (3) return p
      */
    struct proc_struct *p = NULL;
#if USE_SKEW_HEAP
    if(!rq->lab6_run_pool) return NULL;
    p = le2proc(rq->lab6_run_pool, lab6_run_pool);
#else
    list_entry_t *le = list_next(&rq->run_list);
    while ((le = list_next(le)) != &rq->run_list) {
        struct proc_struct *cnt = le2proc(le, run_link);
        if (!p || proc_stride_comp_f(&p->lab6_run_pool, &cur->lab6_run_pool))
            p = cur;
    }
#endif
    if (p)
        p->lab6_stride += BIG_STRIDE / (p->lab6_priority == 0? 1: p->lab6_priority);
    return p;
}
/* The compare function for two skew_heap_node_t's and the
 * corresponding procs*/
static int
proc_stride_comp_f(void *a, void *b)
{
     struct proc_struct *p = le2proc(a, lab6_run_pool);
     struct proc_struct *q = le2proc(b, lab6_run_pool);
     int32_t c = p->lab6_stride - q->lab6_stride;
     if (c > 0) return 1;
     else if (c == 0) return 0;
     else return -1;
}
Esempio n. 7
0
void
schedule(void) {
    bool intr_flag;
    list_entry_t *le, *last;
    struct proc_struct *next = NULL;
    local_intr_save(intr_flag);
    {
        current->need_resched = 0;
        last = (current == idleproc) ? &proc_list : &(current->list_link);
        le = last;
        do {
            if ((le = list_next(le)) != &proc_list) {
                next = le2proc(le, list_link);
                if (next->state == PROC_RUNNABLE) {
                    break;
                }
            }
        } while (le != last);
        if (next == NULL || next->state != PROC_RUNNABLE) {
            next = idleproc;
        }
        next->runs ++;
        if (next != current) {
        	//proc_print(next);
        	cprintf("sche! proc %d, pc=%08x\n\n",next->pid,next->context.pc);
            //cprintf("sp=%08x\n\n",read_sp());
            proc_run(next);
        }
    }
    local_intr_restore(intr_flag);
}
Esempio n. 8
0
// get_pid - alloc a unique pid for process
static int
get_pid(void) {
    static_assert(MAX_PID > MAX_PROCESS);
    struct proc_struct *proc;
    list_entry_t *list = &proc_list, *le;
    static int next_safe = MAX_PID, last_pid = MAX_PID;
    if (++ last_pid >= MAX_PID) {
        last_pid = pls_read(lcpu_count);
        goto inside;
    }
    if (last_pid >= next_safe) {
    inside:
        next_safe = MAX_PID;
    repeat:
        le = list;
        while ((le = list_next(le)) != list) {
            proc = le2proc(le, list_link);
            if (proc->pid == last_pid) {
                if (++ last_pid >= next_safe) {
                    if (last_pid >= MAX_PID) {
                        last_pid = 1;
                    }
                    next_safe = MAX_PID;
                    goto repeat;
                }
            }
            else if (proc->pid > last_pid && next_safe > proc->pid) {
                next_safe = proc->pid;
            }
        }
    }
    return last_pid;
}
Esempio n. 9
0
void
schedule(void) {
    bool intr_flag;
    list_entry_t *le, *last;
    struct proc_struct *next = NULL;
    local_intr_save(intr_flag);
    {
        current->need_resched = 0;
        last = (current == idleproc) ? &proc_list : &(current->list_link);
        le = last;
        do {
            if ((le = list_next(le)) != &proc_list) {
                next = le2proc(le, list_link);
                if (next->state == PROC_RUNNABLE) {
                    break;
                }
            }
        } while (le != last);
        if (next == NULL || next->state != PROC_RUNNABLE) {
            next = idleproc;
        }
        next->runs ++;
        if (next != current) {
            proc_run(next);
        }
    }
    local_intr_restore(intr_flag);
}
Esempio n. 10
0
static struct proc_struct *
RR_pick_next(struct run_queue *rq) {
    list_entry_t *le = list_next(&(rq->run_list));
    if (le != &(rq->run_list)) {
        return le2proc(le, run_link);
    }
    return NULL;
}
Esempio n. 11
0
// find_proc - find proc frome proc hash_list according to pid
struct proc_struct *
find_proc(int pid) {
    if (0 < pid && pid < MAX_PID) {
        list_entry_t *list = hash_list + pid_hashfn(pid), *le = list;
        while ((le = list_next(le)) != list) {
            struct proc_struct *proc = le2proc(le, hash_link);
            if (proc->pid == pid) {
                return proc;
            }
        }
    }
    return NULL;
}
Esempio n. 12
0
// check if there is a RT process in run queue with earlier deadline
// necessary on each tick, because at any time a new process may have joined
// combine with tick_decrease_RT_pt eventually
bool rq_exist_earlier_deadline(struct run_queue *rq, int deadline) {
	struct proc_struct *proc;			// proc iterator
	list_entry_t *le;					// list iterator
	list_entry_t *start = list_next(&(rq->run_list));	// temporary use
	for(le = list_next(&(rq->run_list)); le->next != start; le = list_next(le)) {
		proc = le2proc(le, run_link);
			if (proc->isRT) {
				if (proc->pt < deadline)
					return TRUE;
			}
	}
	return FALSE;
}
Esempio n. 13
0
/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
     /* LAB6: 2013011400
      * (1) get a  proc_struct pointer p  with the minimum value of stride
             (1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_poll
             (1.2) If using list, we have to search list to find the p with minimum stride value
      * (2) update p;s stride value: p->lab6_stride
      * (3) return p
      */
    list_entry_t *le = list_next(&rq->run_list);
    if (le == &rq->run_list)
        return NULL;
    struct proc_struct *p = le2proc(le, run_link);
    for (le = list_next(le); le != &rq->run_list; le = list_next(le))
    {
        struct proc_struct *q = le2proc(le, run_link);
        if ((int32_t)(p->lab6_stride - q->lab6_stride) > 0)
            p = q;
    }

    p->lab6_stride += BIG_STRIDE / (p->lab6_priority ? p->lab6_priority : 1);
    return p;
}
Esempio n. 14
0
// do_exit - kill a thread group, called by syscall or trap handler
int
do_exit(int error_code) {
    bool intr_flag;
    local_intr_save(intr_flag);
    {
        list_entry_t *list = &(current->thread_group), *le = list;
        while ((le = list_next(le)) != list) {
            struct proc_struct *proc = le2proc(le, thread_group);
            __do_kill(proc, error_code);
        }
    }
    local_intr_restore(intr_flag);
    return do_exit_thread(error_code);
}
Esempio n. 15
0
/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
     /* LAB6: 2012012017
      * (1) get a  proc_struct pointer p  with the minimum value of stride
             (1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_poll
             (1.2) If using list, we have to search list to find the p with minimum stride value
      * (2) update p;s stride value: p->lab6_stride
      * (3) return p
      */
#if USE_SKEW_HEAP
    if (!rq->lab6_run_pool) return NULL;
    struct proc_struct *p = le2proc(rq->lab6_run_pool, lab6_run_pool);
#else
    list_entry_t *le;
    struct proc_struct *p = 0;
    for (le = list_next(&rq->run_list); le != &rq->run_list; le = list_next(le)) {
        struct proc_struct *q = le2proc(le, run_link);
        if (!p || proc_stride_comp_f(&p->lab6_run_pool, &q->lab6_run_pool) == 1) p = q;
    }
#endif
    if (p) p->lab6_stride += BIG_STRIDE / p->lab6_priority;
    return p;
}
Esempio n. 16
0
/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
     /* LAB6: 2012011383
      * (1) get a  proc_struct pointer p  with the minimum value of stride
             (1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_poll
             (1.2) If using list, we have to search list to find the p with minimum stride value
      * (2) update p;s stride value: p->lab6_stride
      * (3) return p
      */
  if (rq->lab6_run_pool == NULL)
    return NULL;
  struct proc_struct *p = le2proc(rq->lab6_run_pool, lab6_run_pool);
  return p;
}
Esempio n. 17
0
/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
     /* LAB6: YOUR CODE 
      * (1) get a  proc_struct pointer p  with the minimum value of stride
             (1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_poll
             (1.2) If using list, we have to search list to find the p with minimum stride value
      * (2) update p;s stride value: p->lab6_stride
      * (3) return p
      */
	if (rq->lab6_run_pool == NULL)
		return NULL;
	skew_heap_entry_t *s = rq->lab6_run_pool;
	struct proc_struct *proc = le2proc(s,lab6_run_pool);
	proc->lab6_stride += BIG_STRIDE / proc->lab6_priority;
	return proc;
}
Esempio n. 18
0
// do_wait - wait one OR any children with PROC_ZOMBIE state, and free memory space of kernel stack
//         - proc struct of this child.
// NOTE: only after do_wait function, all resources of the child proces are free.
int
do_wait(int pid, int *code_store) {
    struct proc_struct *proc;
    bool intr_flag, haskid;
repeat:
	cprintf("do_wait: begin\n");
    haskid = 0;
	list_entry_t *list = &proc_list,  *le = list;
	while ((le = list_next(le)) != list) {
		proc = le2proc(le, list_link);
		if (proc != NULL) {
			 haskid = 1;
		    if (proc->state == PROC_ZOMBIE) {
			     goto found;
		   }
		}
	}
    if (haskid) {
		cprintf("do_wait: has kid begin\n");
        cprintf("proc_wait:: pid: %d, name: %s from PROC_RUNABLE to PROC_SLEEPING\n",current->pid, current->name);
        current->state = PROC_SLEEPING;
        current->wait_state = WT_CHILD;
        schedule();
        goto repeat;
    }
    return -E_BAD_PROC;

found:
	cprintf("do_wait: has kid find child  pid%d\n",proc->pid);
    cprintf("proc_exit:: pid: %d, name: %s from PROC_ZOMBIE to exit\n",proc->pid, proc->name);
    if (proc == idleproc ) {
        panic("wait idleproc \n");
    }

    local_intr_save(intr_flag);
    {
        remove_links(proc);
    }
    local_intr_restore(intr_flag);
    put_kstack(proc);
    kfree(proc);
    return 0;
}
Esempio n. 19
0
// decrease the pt of all RT procs in runqueue
// assume all process are RT
void tick_decrease_RT_pt(struct run_queue *rq, struct proc_struct *currentproc) {
	struct proc_struct *proc;			// proc iterator
	list_entry_t *le;					// list iterator
	list_entry_t *start = list_next(&(rq->run_list));	// temporary use
	bool noRTprocs = TRUE;		// see if there are still RT procs in the run queue. Otherwise exist. Helps debugging
	for(le = list_next(&(rq->run_list)); le->next != start; le = list_next(le)) {
		proc = le2proc(le, run_link);
		if (proc->isRT) {
			noRTprocs = FALSE;
			proc->pt--;		// for all RT procs the pt has decreased one!
			if (proc->pt == 0 && proc->ct  < proc->compute_time)
				panic("pt of proc %d == 0 but ct == %d (process in run queue)", proc->pid, proc->ct);
			if (proc->pt < 0)
				panic("pt of RT proc %d < 0! RT schedule failure!", proc->pid);
		}
	}
	//if (noRTprocs && currentproc->isRT == FALSE)		// init proc
//		panic("no RT procs left. Exiting");
}
Esempio n. 20
0
/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
	/* LAB6: 2009011419
	 * (1) get a  proc_struct pointer p  with the minimum value of stride
	 (1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_poll
	 (1.2) If using list, we have to search list to find the p with minimum stride value
	 * (2) update p;s stride value: p->lab6_stride
	 * (3) return p
	 */

	if (!rq->lab6_run_pool) {
		return NULL ;
	}

	struct proc_struct *p = le2proc((rq->lab6_run_pool), lab6_run_pool);

	p->lab6_stride += (BIG_STRIDE / p->lab6_priority);

	return p;
}
/*
 * stride_pick_next pick the element from the ``run-queue'', with the
 * minimum value of stride, and returns the corresponding process
 * pointer. The process pointer would be calculated by macro le2proc,
 * see kern/process/proc.h for definition. Return NULL if
 * there is no process in the queue.
 *
 * When one proc structure is selected, remember to update the stride
 * property of the proc. (stride += BIG_STRIDE / priority)
 *
 * hint: see libs/skew_heap.h for routines of the priority
 * queue structures.
 */
static struct proc_struct *
stride_pick_next(struct run_queue *rq) {
     /* LAB6: 2013011356
      * (1) get a  proc_struct pointer p  with the minimum value of stride
             (1.1) If using skew_heap, we can use le2proc get the p from rq->lab6_run_pool
             (1.2) If using list, we have to search list to find the p with minimum stride value
      * (2) update p;s stride value: p->lab6_stride
      * (3) return p
      */
    // assert(rq != NULL);
    if (rq->lab6_run_pool == NULL) {
        return NULL;
    } else {
        struct proc_struct *proc = le2proc(rq->lab6_run_pool, lab6_run_pool);
        assert (proc->lab6_priority > 0);
        proc->lab6_stride += BIG_STRIDE / proc->lab6_priority;
        // cprintf("next is pid %d, stride is %d, priority is %d\n", proc->pid, proc->lab6_stride, proc->lab6_priority);
        return proc;
    }
}
Esempio n. 22
0
/**
 * Find a proc_struct whose mm->pgdir is @pgdir.
 * Note that if multiple proc_structs have the same pgdir, then they must be threads of the same group,
 *     and thus are in the same container process.
 * @param pgdir the 'hint' page table for finding the target proc_struct
 * @return the pointer to the proc_struct found,
 *             or NULL if the map/uemap should be done in the main process
 */
static struct proc_struct*
find_proc_by_pgdir (pde_t *pgdir) {
    /* Some special occasions:
     *     1. current == NULL means we're work in test functions.
     *            Then the map/unmap belongs to the main process (we only have it at that time).
     *     2. current->mm == NULL means current is a kernel thread.
     *            The only kernel thread which needs to modify user address space is kswapd
     *                 for it should invalidate the page which has been swapped out.
     *            The others should be only occured when creating a user process by 'do_execve'
     *                 and the work belongs to the host process.
     *     3. if current->mm->pgdir = @pgdir, which is commonly the case,
     *            'current' is obviously what we are looking for.
     *            This is just for speeding up.
     */
    if (current != kswapd) {
        if (current == NULL || current->mm == NULL)
            return NULL;
        if (pgdir == current->mm->pgdir)
            return current;
    }

    /* Search for a proc_sturct by brute force,
     *     iterating the proc list and ask everyone.
     */
    list_entry_t *le = &proc_list;
    if (list_next(le) == 0)		/* not initialized. this happens when kswapd is initializing */
        return NULL;
    struct proc_struct *proc;
    while (( le = list_next(le) ) != &proc_list) {
        proc = le2proc(le, list_link);
        if (proc->mm != NULL && proc->mm->pgdir == pgdir) {
            return proc;
        }
    }
    return NULL;
}
Esempio n. 23
0
// next_thread - get the next thread "proc" from thread_group list
static struct proc_struct *
next_thread(struct proc_struct *proc) {
    return le2proc(list_next(&(proc->thread_group)), thread_group);
}
Esempio n. 24
0
void
schedule(void) {
  /* schedule in irq ctx is not allowed */
  assert(!ucore_in_interrupt());
  bool intr_flag;
  struct proc_struct *next;
#ifndef MT_SUPPORT
  list_entry_t head;
  int lapic_id = pls_read(lapic_id);
#endif

  local_intr_save(intr_flag);
  int lcpu_count = pls_read(lcpu_count);
  {
    current->need_resched = 0;
#ifndef MT_SUPPORT
    if (current->mm)
    {
      assert(current->mm->lapic == lapic_id);
      current->mm->lapic = -1;
    }
#endif
    if (current->state == PROC_RUNNABLE && current->pid >= lcpu_count) {
      sched_class_enqueue(current);
    }
#ifndef MT_SUPPORT
    list_init(&head);
    while (1)
    {
      next = sched_class_pick_next();
      if (next != NULL) sched_class_dequeue(next);

      if (next && next->mm && next->mm->lapic != -1)
      {
        list_add(&head, &(next->run_link));
      }
      else
      {
        list_entry_t *cur;
        while ((cur = list_next(&head)) != &head)
        {
          list_del_init(cur);
          sched_class_enqueue(le2proc(cur, run_link));
        }

        break;
      }
    }
#else
    next = sched_class_pick_next();
    if (next != NULL)
      sched_class_dequeue(next);
#endif  /* !MT_SUPPORT */
    if (next == NULL) {
      next = idleproc;
    }
    next->runs ++;
    /* Collect information here*/
    if (sched_collect_info) {
      int lcpu_count = pls_read(lcpu_count);
      int lcpu_idx = pls_read(lcpu_idx);
      int loc = sched_info_head[lcpu_idx];
      int prev = sched_info_pid[loc*lcpu_count + lcpu_idx];
      if (next->pid == prev)
        sched_info_times[loc*lcpu_count + lcpu_idx] ++;
      else {
        sched_info_head[lcpu_idx] ++;
        if (sched_info_head[lcpu_idx] >= PGSIZE / sizeof(uint16_t) / lcpu_count)
          sched_info_head[lcpu_idx] = 0;
        loc = sched_info_head[lcpu_idx];
        uint16_t prev_pid = sched_info_pid[loc*lcpu_count + lcpu_idx];
        uint16_t prev_times = sched_info_times[loc*lcpu_count + lcpu_idx];
        if (prev_times > 0 && prev_pid >= lcpu_count + 2)
          sched_slices[lcpu_idx][prev_pid % SLICEPOOL_SIZE] += prev_times;
        sched_info_pid[loc*lcpu_count + lcpu_idx] = next->pid;
        sched_info_times[loc*lcpu_count + lcpu_idx] = 1;
      }
    }
#ifndef MT_SUPPORT
    assert(!next->mm || next->mm->lapic == -1);
    if (next->mm)
      next->mm->lapic = lapic_id;
#endif
    if (next != current) {
#if 0
      kprintf("N %d to %d\n", current->pid, next->pid);
#endif
      proc_run(next);
    }
  }
  local_intr_restore(intr_flag);
}