2

So I'm trying to create a new system call on PM server. My question is, how can I send some kind of message to function.

in IPC server all I had to do is add my system call to the list, because all functions there were defined as (*func)(message *)

(...)/servers/ipc/main.c
static struct {
    int type;
    int (*func)(message *);
    int reply;  /* whether the reply action is passed through */
} ipc_calls[] = {
    (...)
    { IPC_MYNEWSIGNAL,  do_something,   1 },
};

but in PM in table.c functions are defined as

(...)/servers/pm/table.c
int (* const call_vec[NR_PM_CALLS])(void) = {
(...)
CALL(PM_GETSYSINFO) = do_getsysinfo
}

and if I try to pass function with signature

int do_something(message *m)

I will get error:

Incompatible pointer types: initializing int (*const)(void) with int (message *)

What is the correct way to create signal on PM server if I need to receive some kind of information?

Blomex
  • 305
  • 2
  • 12
  • If you need this for SO :) I think you don't need to register any function in that array. Instead, the array `mproc[NR_PROCS]` is needed just to get the info about the relationship between processes, or maybe you can even add some fields in the struct `mproc` to track the time :) – samvel1024 Apr 19 '19 at 21:49

1 Answers1

1

As far as I understood from the question, you want to receive arguments inside the syscall handler. Let's take as an example the library function clock_settime from libc.

int clock_settime(clockid_t clock_id, const struct timespec *ts)
{
  message m;

  memset(&m, 0, sizeof(m));
  m.m_lc_pm_time.clk_id = clock_id;
  m.m_lc_pm_time.now = 1; /* set time immediately. don't use adjtime() method. */
  m.m_lc_pm_time.sec = ts->tv_sec;
  m.m_lc_pm_time.nsec = ts->tv_nsec;

  if (_syscall(PM_PROC_NR, PM_CLOCK_SETTIME, &m) < 0)
    return -1;

  return 0;
}

As you can see it writes the args inside message struct and passes to _syscall. OK, now have a look at syscall handler for PM_CLOCK_SETTIME which is mounted in table.c.

int do_gettime()
{
  clock_t ticks, realtime, clock;
  time_t boottime;
  int s;

  if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK)
    panic("do_time couldn't get uptime: %d", s);

  switch (m_in.m_lc_pm_time.clk_id) {
    case CLOCK_REALTIME:
        clock = realtime;
        break;
    case CLOCK_MONOTONIC:
        clock = ticks;
        break;
    default:
        return EINVAL; /* invalid/unsupported clock_id */
  }

  mp->mp_reply.m_pm_lc_time.sec = boottime + (clock / system_hz);
  mp->mp_reply.m_pm_lc_time.nsec =
    (uint32_t) ((clock % system_hz) * 1000000000ULL / system_hz);

  return(OK);
}

It becomes clear that the argument is a global variable named m_in. A little bit more search shows that it comes from glo.h

/* The parameters of the call are kept here. */
EXTERN message m_in;        /* the incoming message itself is kept here. */

I suppose that MINIX will handle setting and accessing the global variable, so you don't need to explicitly write to it.

Have a look at point 7 Passing a parameter to a system call here. To understand how to compile the kernel correctly refer to this post.

samvel1024
  • 1,123
  • 4
  • 15
  • 39