adding to proc struct in proc.h

1,420 views
Skip to first unread message

Leonard Nemoy

unread,
Oct 27, 2011, 2:57:49 PM10/27/11
to minix3
Whenever I define a variable in the proc structure in proc.h and try
to initialize it in do_fork.c my kernel crashes upon booting. Any
idea what causes this? I am using Minix 3.1.7

proc.h

struct proc{

int numTickets;
}

do_forck.c

do_fork(){

proc *rpc; /* child process */
rpc->numTickets=5;

}

Tomas Hruby

unread,
Oct 27, 2011, 3:01:38 PM10/27/11
to min...@googlegroups.com
Hi,

From the posted code, it looks like rpc is uninitialized therefore it
craches when you dereference a random pointer. Whether it is really
the problem I am not able to say since the amount of information you
are providing is small :( and I doubt the actuall code is so simple :)

T.

Roberto Waltman

unread,
Oct 27, 2011, 3:12:17 PM10/27/11
to min...@googlegroups.com
Leonard Nemoy wrote:
> Whenever I define a variable in the proc structure in proc.h and try
> to initialize it in do_fork.c my kernel crashes upon booting. Any
> idea what causes this? I am using Minix 3.1.7
>
> proc.h
>
> struct proc{
>
> int numTickets;
> }
(Adding the missing ';' )
That doesn't define a variable, it defines a structure, a "data type".
(In the general case, a good thing. If you define a variable in a
header file multiple instances of that variable would be created by
each source file including the header.)

> do_forck.c
>
> do_fork(){
>
> proc *rpc; /* child process */

This should not compile (if you are using C and not C++)

struct proc *rpc; /* child process */

This (which compiles) creates a pointer to a proc struct.
You do not initialize it, so it is pointing to a random place in
memory, or to 0 if it is a global variable.

> rpc->numTickets=5;

And here you try to store the value 5 into some random location, hence
the crash.
What you are missing is allocating storage for the struct proc and
assigning its address to rpc, or making rpc point to an existing valid
structure before assigning to it.

>
> }
>

Leonard Nemoy

unread,
Oct 27, 2011, 3:13:48 PM10/27/11
to minix3
sorry I didnt want to clutter the post with the actual code. I used
the rpc defined in the original code of do_fork.c Before I added
anything, the function already initialized several variables of rpc.
Here is a snippet from the actual code:

proc.h (my added part is the first 5 lines after 'struct proc{'; the
'int style' I had added before and it ran with no problems)

#ifndef PROC_H
#define PROC_H

#include <minix/const.h>

#ifndef __ASSEMBLY__

/* Here is the declaration of the process table. It contains all
process
* data, including registers, flags, scheduling priority, memory map,
* accounting, message passing (IPC) information, and so on.
*
* Many assembly code routines reference fields in it. The offsets to
these
* fields are defined in the assembler include file sconst.h. When
changing
* struct proc, be sure to change sconst.h to match.
*/
#include <minix/com.h>
#include <minix/portio.h>
#include "const.h"
#include "priv.h"

int style; /* changes scheduling algorithm */

struct proc {
int numTickets; /* number of "tickets" the process has */
int blocked; /* determines whether or not a process has been
blocked during execution */
int stride; /* for stride scheduling */
int pass; /* for stride scheduling */
int strideConst; /* constant stride variable */
struct stackframe_s p_reg; /* process' registers saved in stack
frame */
struct fpu_state_s p_fpu_state; /* process' fpu_regs saved lazily */
struct segframe p_seg; /* segment descriptors */
proc_nr_t p_nr; /* number of this process (for fast access) */
struct priv *p_priv; /* system privileges structure */
short p_rts_flags; /* process is runnable only if zero */
short p_misc_flags; /* flags that do not suspend the process */

char p_priority; /* current process priority */
u64_t p_cpu_time_left; /* time left to use the cpu */
unsigned p_quantum_size_ms; /* assigned time quantum in ms
FIXME remove this */






and my do_fork.c (full file code; my added lines are at the very end,
right before 'return r')

/
*===========================================================================*
* do_fork *

*===========================================================================*/
PUBLIC int do_fork(struct proc * caller, message * m_ptr)
{
/* Handle sys_fork(). PR_ENDPT has forked. The child is PR_SLOT. */
#if (_MINIX_CHIP == _CHIP_INTEL)
reg_t old_ldt_sel;
void *old_fpu_save_area_p;
#endif
register struct proc *rpc; /* child process pointer */
struct proc *rpp; /* parent process pointer */
struct mem_map *map_ptr; /* virtual address of map inside caller
(PM) */
int gen, r;
int p_proc;

if(!isokendpt(m_ptr->PR_ENDPT, &p_proc))
return EINVAL;

rpp = proc_addr(p_proc);
rpc = proc_addr(m_ptr->PR_SLOT);
if (isemptyp(rpp) || ! isemptyp(rpc)) return(EINVAL);

assert(!(rpp->p_misc_flags & MF_DELIVERMSG));

/* needs to be receiving so we know where the message buffer is */
if(!RTS_ISSET(rpp, RTS_RECEIVING)) {
printf("kernel: fork not done synchronously?\n");
return EINVAL;
}

map_ptr= (struct mem_map *) m_ptr->PR_MEM_PTR;

/* make sure that the FPU context is saved in parent before copy */
if (fpu_owner == rpp) {
disable_fpu_exception();
save_fpu(rpp);
}
/* Copy parent 'proc' struct to child. And reinitialize some fields.
*/
gen = _ENDPOINT_G(rpc->p_endpoint);
#if (_MINIX_CHIP == _CHIP_INTEL)
old_ldt_sel = rpc->p_seg.p_ldt_sel; /* backup local descriptors */
old_fpu_save_area_p = rpc->p_fpu_state.fpu_save_area_p;
#endif
*rpc = *rpp; /* copy 'proc' struct */
#if (_MINIX_CHIP == _CHIP_INTEL)
rpc->p_seg.p_ldt_sel = old_ldt_sel; /* restore descriptors */
rpc->p_fpu_state.fpu_save_area_p = old_fpu_save_area_p;
if(proc_used_fpu(rpp))
memcpy(rpc->p_fpu_state.fpu_save_area_p,
rpp->p_fpu_state.fpu_save_area_p,
FPU_XFP_SIZE);
#endif
if(++gen >= _ENDPOINT_MAX_GENERATION) /* increase generation */
gen = 1; /* generation number wraparound */
rpc->p_nr = m_ptr->PR_SLOT; /* this was obliterated by copy */
rpc->p_endpoint = _ENDPOINT(gen, rpc->p_nr); /* new endpoint of slot
*/

rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
rpc->p_user_time = 0; /* set all the accounting times to 0 */
rpc->p_sys_time = 0;

rpc->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
rpc->p_misc_flags &= ~(MF_VIRT_TIMER | MF_PROF_TIMER | MF_SC_TRACE);
rpc->p_virt_left = 0; /* disable, clear the process-virtual timers
*/
rpc->p_prof_left = 0;

/* the child process is not runnable until it's scheduled. */
RTS_SET(rpc, RTS_NO_QUANTUM);

make_zero64(rpc->p_cpu_time_left);
make_zero64(rpc->p_cycles);

/* If the parent is a privileged process, take away the privileges
from the
* child process and inhibit it from running by setting the NO_PRIV
flag.
* The caller should explicitely set the new privileges before
executing.
*/
if (priv(rpp)->s_flags & SYS_PROC) {
rpc->p_priv = priv_addr(USER_PRIV_ID);
rpc->p_rts_flags |= RTS_NO_PRIV;
}

/* Calculate endpoint identifier, so caller knows what it is. */
m_ptr->PR_ENDPT = rpc->p_endpoint;
m_ptr->PR_FORK_MSGADDR = (char *) rpp->p_delivermsg_vir;

/* Install new map */
r = newmap(caller, rpc, map_ptr);

/* Don't schedule process in VM mode until it has a new pagetable.
*/
if(m_ptr->PR_FORK_FLAGS & PFF_VMINHIBIT) {
RTS_SET(rpc, RTS_VMINHIBIT);
}

/*
* Only one in group should have RTS_SIGNALED, child doesn't inherit
tracing.
*/
RTS_UNSET(rpc, (RTS_SIGNALED | RTS_SIG_PENDING | RTS_P_STOP));
(void) sigemptyset(&rpc->p_pending);

rpc->p_seg.p_cr3 = 0;
rpc->p_seg.p_cr3_v = NULL;

/* initialize lottery/stride scheduling variables */
rpc->numTickets=5;
rpc->blocked=0;
rpc->strideConst=1,000;
rpc->stride=(rpc->strideConst/rpc->numTickets);
rpc->pass=rpc->stride;

return r;
}

#endif /* USE_FORK */

Tomas Hruby

unread,
Oct 27, 2011, 3:22:14 PM10/27/11
to min...@googlegroups.com
Hi,

does not seem that the initialization is the problem. What does the
kernel print when it crashes? It tells you some reason, doesn't it?

You can put some prints around your code to see how far it gets. Does
it really crash in do_fork() or later?

> rpc->strideConst=1,000;

I don't think that this code does what you think it does. Do you use
this value as a divisor anywhere?

T.

Leonard Nemoy

unread,
Oct 27, 2011, 3:34:37 PM10/27/11
to minix3



> does not seem that the initialization is the problem. What does the
> kernel print when it crashes? It tells you some reason, doesn't it?

here is a screen shot of what it says:
http://imgur.com/edS0x


> You can put some prints around your code to see how far it gets. Does
> it really crash in do_fork() or later?
>
> >    rpc->strideConst=1,000;
>
> I don't think that this code does what you think it does. Do you use
> this value as a divisor anywhere?


I only use it to determine the variable stride. I divide strideConst
by the number of tickets the process has.

Tomas Hruby

unread,
Oct 27, 2011, 4:02:35 PM10/27/11
to min...@googlegroups.com
In what function is instruction pointer 0x51de (the first addrres
after kernel: in the screenshot you've posted) You can use the unstack
utility.

unstack kernel <address>

in the kernel/ directory of your tree

How do you use ->stride?

> rpc->strideConst=1,000;
> rpc->stride=(rpc->strideConst/rpc->numTickets);

The first like sets ->strideConst to 1 so ->stride will be zero after
division by 5 ...

T.

Leonard Nemoy

unread,
Oct 27, 2011, 7:14:52 PM10/27/11
to minix3


On Oct 27, 4:02 pm, Tomas Hruby <thr...@gmail.com> wrote:
> In what function is instruction pointer 0x51de (the first addrres
> after kernel: in the screenshot you've posted) You can use the unstack
> utility.
>
> unstack kernel <address>
>
> in the kernel/ directory of your tree

I get:

_panic+0x5e
_excepti+0x1c7
exceptio+0x10

> How do you use ->stride?
>
> >    rpc->strideConst=1,000;
> >    rpc->stride=(rpc->strideConst/rpc->numTickets);
>
> The first like sets ->strideConst to 1 so ->stride will be zero after
> division by 5 ...

strideConst is 1,000 not 1 though and I have only initialized the
variables. I don't use any of them as I only get the errors from
trying to initialize them.

Tomas Hruby

unread,
Oct 31, 2011, 4:50:05 AM10/31/11
to min...@googlegroups.com
On Thu, Oct 27, 2011 at 04:14:52PM -0700, Leonard Nemoy wrote:
>
>
> On Oct 27, 4:02�pm, Tomas Hruby <thr...@gmail.com> wrote:
> > In what function is instruction pointer 0x51de (the first addrres
> > after kernel: in the screenshot you've posted) You can use the unstack
> > utility.
> >
> > unstack kernel <address>
> >
> > in the kernel/ directory of your tree
>
> I get:
>
> _panic+0x5e
> _excepti+0x1c7
> exceptio+0x10

that does not say much.

>
> > How do you use ->stride?
> >
> > > � �rpc->strideConst=1,000;
> > > � �rpc->stride=(rpc->strideConst/rpc->numTickets);
> >
> > The first like sets ->strideConst to 1 so ->stride will be zero after
> > division by 5 ...
>
> strideConst is 1,000 not 1 though and I have only initialized the
> variables.

1,000 is NOT 1000, it sets the variable to 1.

> I don't use any of them as I only get the errors from
> trying to initialize them.

Because you don't use them anywhere in your code or because you think
it crashes in do_fork()?

T.

Reply all
Reply to author
Forward
0 new messages