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.