csystem-callsminix

How to send messages in PM server Minix


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?


Solution

  • 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.