Based on your new code [and the pick_proc
function body], the only possible failures are the ones I've described above in my top comments.
That is, proc_ptr
must be valid (i.e. non-NULL) and proc_ptr->p_nr
must be in range to prevent UB.
What are the NR_TASKS
and NR_PROCS
values? Can recent_time
fit on the stack? Stack size in a kernel is usually very limited. For example, under linux, you can only have about 4KB of stack.
So, if NR_PROCS
was (e.g.) 32767, then recent_time
could not be placed on the stack.
And, I don't see a reason the have an independent array for this on the stack as it won't persist past the call.
So, to aid in debug, I'd add static
to the recent_time
definition
You'll need to add some debug code to see what the issue is.
Here's a sample. Adjust the printf
et. al. to suit the minux
kernel's print mechanism [assuming you can print at the state your code is called in]:
#ifdef DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
PRIVATE void
pick_proc()
{
register struct proc *rp; /* process to run */
int q; /* iterate over queues */
/* Modified Code here */
int realtime;
static clock_t recent_time[NR_TASKS + NR_PROCS];
clock_t stopwatch;
do {
// bad pointer
dbgprt("pick_proc: proc_ptr=%p\n",proc_ptr);
if (proc_ptr == NULL)
break;
// out of range process number
dbgprt("pick_proc: p_nr=%u\n",proc_ptr->p_nr);
if (proc_ptr->p_nr >= NR_PROCS)
break;
realtime = getuptime();
dbgprt("pick_proc: realtime=%d\n",realtime);
recent_time[proc_ptr->p_nr + NR_TASKS] = realtime - stopwatch;
stopwatch = realtime;
} while (0);
for (q = 0; q < NR_SCHED_QUEUES; q++) {
if ((rp = rdy_head[q]) != NIL_PROC) {
next_ptr = rp;
if (priv(rp)->s_flags & BILLABLE)
bill_ptr = rp;
return;
}
}
}
UPDATE:
I can't emphasize enough the importance of assert
and/or if
statements to pre-validate anything you do to prevent UB. And, debug printf
, such as:
TRACE(VF_PICKPROC,printf("hello world\n"););
BTW, I pulled the minix
source code from github:
git clone https://github.com/Stichting-MINIX-Research-Foundation/minix.git
It appears that you may have outdated source because the pick_proc
in that repo has more SMP related code.
The NR_TASKS + NR_PROCS should be the time quanta taken from the process table. I orginally declared the Array and stopwatch in proc.h but the pic_proc function did not have access to them.
You really want to either use the existing fields in struct proc
or add some of your own vs. creating a separate array [indexed by process number].
I added some screen shots of code that calls pic_proc. I think i need to modify sched and leave pic_proc alone. The array in pic_proc should be getting the time quanta from each process from the process table
Yes, hopefully elapsed CPU time for each process is in struct proc
. If not, you'll have to add a field. I suspect that p_user_time
[and/or p_sys_time
] may be what you want. And, maybe, p_cpu_time_left
. Other possibilities: p_accounting.time_in_queue
. Or, p_cycles
pick_proc
just looks at the head of a given run queue. So, you may need to change the code that actually inserts a given process into that queue. That might be enqueue
and/or dequeue
. They appear to honor process priority [p_priority
] and preemption.
I've skimmed the kernel code, and at a guess, sched_proc
may be of interest.
But, I really think you'll need to examine the kernel code more closely to see what functions actually add a process to a given run queue. And, how they select a process and from which queue.
When adding a process, it may just append to the tail. That code would need to scan the queue and [assuming the priority is the same], insert based on lowest CPU usage.