ChorusOS IOM Tutorial
October 2000
This document is available in PDF
.
Tell us what you think.
How to create a new system call in the IOM
This tutorial is a step-by-step explanation of how to add a system call to the IOM module of ChorusOS 4.0 and 4.0.1 versions.
1. Getting Started
Product version:
This tutorial refers to ChorusOS 4.0 and 4.0.1. The tutorial is cross platform, but the source example and some of the pathnames used relate specifically to the UltraSPARC target delivery. In order to implement all of the steps described in the tutorial you also need to have the complete source version of ChorusOS, not only the source of the IOM.
Pre-Requisites:
You must have an understanding of kernel programming and, in particular, FreeBSD file system semantics.
Pathnames:
All pathnames in this tutorial are related to the default installation directory of the Sun Embedded Workshop 4.0.1 product:
/opt/SUNWconn/SEW/4.0.1/chorus-usparc/src
Since the patching mechanism depends on the ChorusOS source tree being untouched, always keep an untouched reference copy of the
source tree of the product; otherwise you will not be able to apply any patches from Sun. Before you start following the example, make sure that you use a working copy of the whole product and not just a copy of the Build directory.
The following steps must be taken to add a system call to the IOM:
- Declare the new call
- Match the call interface to a new LAP entry point
- Define the new LAP call
- Declare the system call the array of module services
- Code the system call
- Reconfigure the OS and build a new archive
Back to Top
2. A Simple Example
This tutorial shows you how to add a new system call named getinode() to the IOM that returns the inode of a given file.
Note: The code for getinode() is simple, but since it is only here
as an example, the code itself is not explained.
Contrary to the normal BSD convention of one big array of system calls, in ChorusOS 4.0 and 4.0.1, system calls are
accessed through a two-level array structure with one array of system calls per module. Actors will invoke the IOM system calls using a LAP invocation mechanism. The IOM defines eleven modules:
GENERIC
SOCKET
FILEIO
NFSSERVER
MAPPER
SHM
MQ
SIGNAL
DEVICE
IPC
OSI
Each of these modules in turn defines and exports a set of system calls. This is done in the file os/common/src/bsd/include/bsdSysCalls.h
In the next steps, the getinode() system call will be added to the calls of the FILEIO module. Therefore, you first need to add an entry for your new system call (IOM_GETINODE) and increase the number of system calls defined for the FILEIO module (IOM_FILEIO_NUMBER) by one:
[...]
#define IOM_UNMOUNT
ENCODE_CALL (IOM_FILEIO_MODULE, 35)
#define IOM_UMASK
ENCODE_CALL (IOM_FILEIO_MODULE, 36)
/* HR_CTRL-IOM update
to current rootvnode */
#define IOM_ROOTUPD
ENCODE_CALL (IOM_FILEIO_MODULE, 37)
#define IOM_GETINODE
ENCODE_CALL (IOM_FILEIO_MODULE, 38)
#define IOM_FILEIO_NUMBER 39
[...]
Back to Top
3. The iomcalls Library
The iomcalls library provides actors with the IOM entry points
for all regular BSD system calls (file, sockets, and so on).
You need to define the LAP entry point for your new call. This is first
done in os/common/src/iom/lib/iomcalls.h where you match the userland interface of the call getinode() to the
LAP as follows:
/*
* Posix-FileIO
*/
[...]
#define IOMUNMOUNT unmount
#define IOMUMASK
umask
#define IOMGETINODE
getinode
[...]
Next, each LAP is declared in a special file in the same directory os/common/src/iom/lib/ following a set framework (or set of rules). And each of the LAPs already defined as part of the product have a similar file associated with them.
The argument of the system call must be copied into a default ScLapArg
structure defined in os/common/src/include/cx/lapLibCall.h
To do this, create a file named iomgetinode.c that contains
the following:
#include "iomcalls.h"
long
IOMGETINODE(char *path)
{
ScLapArg arg;
LIBIOMINIT(long);
SET_HEADER(IOM_GETINODE);
arg.a1.a1p = path;
INVOKE(&scIomLap);
if (arg.header.error)
return -1L;
else
return arg.header.result;
}
Finally, to complete this step you must instruct the compiler to add
this new function to the IOM Direct Invocation Library. For that purpose,
you need to add an entry for iomgetinode.c in os/common/src/iom/lib/common.mf
#****************************************************************
#
# Component =
#
# Synopsis = common makefile
#
# Copyright 1994-2004 Sun Microsystems, Inc. All rights reserved.
#
#****************************************************************
#
# #ident "@(#)common.mf 1.24 99/11/24
SMI"
#
#****************************************************************
C__SRCS = \
[..]
iommakedev.c \
sysCtxInherit.c \
sysRootUpdate.c \
iomgetinode.c
Back to Top
4. Code the Actual System Call
Since you have chosen to add your system call to the FILEIO module of
the IOM, you will place your code in directory iom/src/os/iom/sys/bsd/kern/vfs
and, most important, update the array of functions defined for this module
in iom/src/os/iom/sys/bsd/kern/vfs/vfs_syscalls.c.
/*
* POSIX-FILEIO Module initialization
*/
extern long getinode();
[...]
static int (*iom_fileio_services[IOM_FILEIO_NUMBER])() = {
access
/* 0 */
,chdir
/* 1 */
,chflags
/* 2 */
[...]
,(int (*)())umask
/* 36 */
,sysRootUpdate
/* 37 */
,getinode
/* 38 */
};
In this same directory, create a file called get_inode.c and
input the following lines of code:
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/namei.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/proc.h>
#include <sys/ucred.h>
struct getinode_args {
char *path;
};
long
getinode(p, uap, retval)
struct proc *p;
struct getinode_args *uap;
long *retval;
{
struct vnode *vp;
register int error = 0;
struct nameidata nd;
struct vattr *vap;
struct ucred *pcred = p->p_cred->pc_ucred;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE,
uap->path, p);
error = namei(&nd);
if (error)
return error;
error = VOP_GETATTR(nd.ni_vp, vap, pcred, p);
if (error)
return error;
*retval = vap->va_fileid;
return(error);
}
Back to Top
5. Reconfigure the Build Directory, Compile and Rebuild the Archive
Finally, you need to add this file to the IOM binary by updating the
file iom/src/os/iom/sys/bsd/kern/vfs/common.mf as follows:
##############################################################################
#
# Component = AFM BSD kernel code.
# Module = makeTarget
#
# Synopsis = specific makefile.
#
# Copyright 1994-2004 Sun Microsystems, Inc. All rights reserved.
#
#
##############################################################################
#
# #ident "@(#)common.mf 1.6 99/10/10 SMI"
#
##############################################################################
C__SRCS = \
vfs_bio.c \
vfs_cache.c \
vfs_init.c \
vfs_lookup.c \
vfs_subr.c \
vfs_syscalls.c \
vfs_vnops.c \
kern_physio.c \
get_inode.c
Then, with BUILD_DIR being set to point to the Chorus build
directory, rebuild the iomcalls library and the N_iom.r
binary (the IOM):
$ cd $BUILD_DIR/build-OS
$ rm DONE
$ make merge
# To generate the links for the newly added files
$ make Makefiles # To
generate a new set of Makefiles
$ make
Once this is done, the iomcalls library is generated and you
can recompile the IOM:
$ cd $BUILD_DIR/build-IOM
$ rm DONE
$ make merge
# To generate the links for the newly added files
$ make Makefiles # To
generate a new set of Makefiles
$ make
Finally, regenerate the chorus archive:
$ cd $BUILD_DIR
$ make
Back to Top
6. Testing getinode()
Once your UltraSPARC target has been rebooted with the new archive,
you can test your new system call with a simple little actor such as this
one:
/***** test_iom_call.c *****/
#include <stdio.h>
main(int argc, char **argv)
{
long inode;
if (argc != 2) {
printf("Usage: %s filename\n",
argv[0]);
exit(-1);
}
inode = getinode(argv[1]);
if ( inode < 0 ) {
printf("Error in getinode(%s)
: %d\n", argv[1], inode);
exit(-1);
}
else
printf("%s : %ld\n",argv[1],
inode);
}
Here's a sample output from this test:
$ rsh $TARGET arun ls -li /dummy.c
started aid = 20
395466 -rw-rw-r-- 1 74137 50001 16972 Sep
6 07:59 /dummy.c
$ rsh $TARGET arun /test_iom_call /dummy.c
started aid = 20
/dummy.c : 395466
Back to Top
Appendix
List of modified files:
os/common/src/bsd/include/bsdSysCalls.h
os/common/src/iom/lib/iomcalls.h
os/common/src/iom/lib/common.mf
iom/src/os/iom/sys/bsd/kern/vfs/vfs_syscalls.c
iom/src/os/iom/sys/bsd/kern/vfs/common.mf
List of created files:
os/common/src/iom/lib/iomgetinode.c
iom/src/os/iom/sys/bsd/kern/vfs/get_inode.c
Back to Top