Click to See Complete Forum and Search --> : Problem with adding a system call


newcat1
05-31-2004, 08:18 AM
Hello all,

I tried to add 4 system call to my kernel on redhat 9.

This is what I did :

In /usr/src/linux-2.4/include/linux/wait.h, I added

struct evnt_queue
{
struct evnt_queue *next_event;
wait_queue_head_t waitq;
int eid;
};

In /usr/src/linux-2.4/arch/i386/kernel/entry.S I added
.long SYMBOL_NAME(sys_evntopen)
.long SYMBOL_NAME(sys_evntclose) /* 260 */
.long SYMBOL_NAME(sys_evntwait)
.long SYMBOL_NAME(sys_evntsig)

In /usr/src/linux-2.4/include/asm/unistd.h I added

#define __NR_evntopen 259
#define __NR_evntclose 260
#define __NR_evntwait 261
#define __NR_evntsig 262

In /usr/src/linux-2.4/init/main.c I added

struct evnt_queue *eq;

static void __init event_init(void)
{
eq=(struct evnt_queue *)kmalloc(
sizeof(struct evnt_queue), GFP_KERNEL);
eq->next_event=NULL;
eq->eid=0;
init_waitqueue_head(&(eq->waitq));
}
asmlinkage void __init start_kernel(void)
{
......
event_init(); /* last statement */
}


In /usr/src/linux/kernel/sys.c : I add the code of the new system call
asmlinkage int sys_eventopen(int eid)
{
int newid=-1;
struct event_queue *temp;

printk("sys_eventopen");
if (eq==NULL)
{
eq=(struct event_queue *)kmalloc(
sizeof(struct event_queue), GFP_KERNEL);
eq->next_event=NULL;
eq->eid=0;
init_waitqueue_head(&(eq->waitq));
}

temp=eq->next_event;
if (eid>0)
{
while ((temp!=NULL)&&(temp->eid!=eid))
{
temp=temp->next_event;
}
if ((temp!=NULL)&&(temp->eid==eid)) newid=eid;
}
else if (eid==0)
{
while (temp!=NULL)
{
if (newid<temp->eid) newid=temp->eid;
temp=temp->next_event;
}
newid++;
if (newid<1) newid=1;
temp=(struct event_queue *)kmalloc(
sizeof(struct event_queue), GFP_KERNEL);
if (temp==NULL) newid=-1;
else
{
temp->eid=newid;
temp->next_event=eq->next_event;
eq->next_event=temp;
init_waitqueue_head(&(temp->waitq));
}
}

return(newid);
}

asmlinkage int sys_eventclose(int eid)
{
int result=-1;
struct event_queue *prev, *temp;

printk("sys_eventclose");
prev=eq;
temp=prev->next_event;
while ((temp!=NULL)&&(temp->eid!=eid))
{
prev=temp;
temp=prev->next_event;
}

if ((temp!=NULL)&&(waitqueue_active(&(temp->waitq))))
wake_up_interruptible(&(temp->waitq));
if (temp!=NULL)
{
result=0;
prev->next_event=temp->next_event;
kfree(temp);
}

return(result);
}

asmlinkage int sys_eventwait(int eid)
{

int result=-1;
struct event_queue *temp;

printk("sys_eventwait");
temp=eq->next_event;
while ((temp!=NULL)&&(temp->eid!=eid))
{
temp=temp->next_event;
}

if (temp!=NULL)
{
result=0;
interruptible_sleep_on(&(temp->waitq));
}

return(result);
}

asmlinkage int sys_eventsig(int eid)
{

int result=-1;
struct event_queue *temp;

printk("sys_eventsig");
temp=eq->next_event;
while ((temp!=NULL)&&(temp->eid!=eid))
{
temp=temp->next_event;
}

if (temp!=NULL)
{
result=0;
wake_up_interruptible(&(temp->waitq));
}

return(result);
}


And this is the test programm which use the system call :

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <linux/unistd.h>
#include <linux/wait.h>


_syscall1(int, eventopen, int, eid);
_syscall1(int, eventclose, int, eid);
_syscall1(int, eventwait, int, eid);
_syscall1(int, eventsig, int, eid);


void *task_wait(void *eid) /* eventwait */
{
printf("event %d waiting\n", eid);
eventwait((int)eid);
printf("event %d waked up\n", eid);
}


void *task_signal(void *eid) /* eventsig */
{
printf("event %d signaling\n", eid);
eventsig((int)eid);
}


int main(int arg, char ** argv)
{
int i, k, n;
int eids[10];
pthread_t tasks[10];

n=3; /* open 3 threads */

for (i=0; i<n; i++)
{
eids[i]=eventopen(0); /* open events */
if (eids[i]>0) printf("event %d opened\n", eids[i]);
else printf("event #%d could not open\n", i);
}

for (i=0; i<n; i++)
{
/* creat threads */
pthread_create(&tasks[i], NULL, task_wait, (void *)eids[i]);
sleep(2);
}

for (i=n-1; i>=0; i--)
{
pthread_create(&tasks[i], NULL, task_signal, (void *)eids[i]);
sleep(2);
}

for (i=0; i<n; i++)
{
k=eventclose(eids[i]); /* test eventclose */
if (k==0) printf("event %d closed\n", eids[i]);
else printf("event %d could not close\n", eids[i]);
}

for (i=0; i<n; i++)
{
pthread_join(tasks[i], NULL);
}

return(0);
}

Everything seems to be OK but when I try to run the test program only
sys_eventopen was called and printed in the log file.

Could anyone help me ?

Thanks a lot

newcat1

bwkaz
05-31-2004, 08:30 AM
Ah, much better. Now that there are [code] tags around your code, it's actually readable. ;)

As for your problem... hmm. I think it's doing much more than "just logging sys_eventopen". I think your program is probably printing something -- it HAS to be. What?

newcat1
05-31-2004, 02:28 PM
In my log file (/var/log/message) only sys_eventopen was printed. sys_eventclose, sys_eventsig, sys_eventwait were not printed in the log file:

"May 30 01:57:10 localhost kernel: sys_eventopen
May 30 01:57:10 localhost kernel: last message repeated 2 times"

Thanks,

newcat

bwkaz
05-31-2004, 03:46 PM
Yeah, but what did your program print as it was running?

The kernel isn't going to log what userspace sends to printf()...

newcat1
05-31-2004, 05:55 PM
The output of the program is:

"event 1 opened
event 2 opened
event 3 opened
event 1 waiting
event 1 waked up
event 2 waiting
event 2 waked up
event 3 waiting
event 3 waked up
event 3 signaling
event 2 signaling
event 1 signaling
event 1 could not close
event 2 could not close
event 3 could not close"

newcat1

newcat1
05-31-2004, 07:27 PM
I used strace and find out that:

sys_eventopen works fine.

"open("etc/ld.so.preload",O_READONLY)=-1 ENOENT (No such file or directory)"

sys_eventwait and sys_eventsig are not even called.

sys_eventclose gets error:

"SYS_260(ox2, 0x40032280, 0, 0x40015360, 0x80487a0) = -1
ENOSYS(Function not implemented)"

newcat1

bwkaz
05-31-2004, 09:02 PM
Originally posted by newcat1
"open("etc/ld.so.preload",O_READONLY)=-1 ENOENT (No such file or directory)" Yeah, that's normal. It's from glibc trying to find out which shared libs it should preload (stuff like strace uses this feature of the runtime linker).

sys_eventclose gets error:

"SYS_260(ox2, 0x40032280, 0, 0x40015360, 0x80487a0) = -1
ENOSYS(Function not implemented)" Well, there you go, the kernel is returing -ENOSYS when you try to use your new syscall. ;)

But it would help to see all of the strace log...

newcat1
05-31-2004, 10:20 PM
bwkaz,

Here it is:

a. strace log with -c option:

execve("./a.out", ["./a.out"], [/* 33 vars */]) = 0
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
38.62 0.000509 85 6 write
23.14 0.000305 102 3 SYS_259
6.45 0.000085 14 6 clone
5.69 0.000075 11 7 mmap2
4.78 0.000063 16 4 1 open
4.78 0.000063 7 9 old_mmap
3.41 0.000045 8 6 mprotect
3.11 0.000041 3 13 rt_sigprocmask
1.97 0.000026 13 2 munmap
1.52 0.000020 3 7 rt_sigaction
1.44 0.000019 5 4 fstat64
1.37 0.000018 9 2 read
1.21 0.000016 3 5 brk
0.53 0.000007 2 3 close
0.46 0.000006 6 1 uname
0.46 0.000006 1 6 nanosleep
0.38 0.000005 5 1 set_thread_area
0.38 0.000005 2 3 3 SYS_260
0.15 0.000002 2 1 getrlimit
0.15 0.000002 2 1 set_tid_address
------ ----------- ----------- --------- --------- ----------------
100.00 0.001318 90 4 total

b. strace log with no option:

execve("./a.out", ["./a.out"], [/* 33 vars */]) = 0
uname({sys="Linux", node="localhost.localdomain", ...}) = 0
brk(0) = 0x80499cc
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40016000
open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=53695, ...}) = 0
old_mmap(NULL, 53695, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40017000
close(3) = 0
open("/lib/tls/libpthread.so.0", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\32 0>\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=79744, ...}) = 0
old_mmap(NULL, 50040, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x40025000
old_mmap(0x4002f000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xa000) = 0x4002f000
old_mmap(0x40030000, 4984, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40030000
close(3) = 0
open("/lib/tls/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0`V\ 1B4\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1531064, ...}) = 0
old_mmap(0x42000000, 1257224, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x42000000
old_mmap(0x4212e000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x12e000) = 0x4212e000
old_mmap(0x42131000, 7944, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x42131000
close(3) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40032000
set_thread_area({entry_number:-1 -> 6, base_addr:0x40032280, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0x40017000, 53695) = 0
set_tid_address(0x400322c8) = 3572
rt_sigaction(SIGRTMIN, {0x40028e30, [], SA_RESTORER, 0x4002e618}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN], NULL, 8) = 0
getrlimit(0x3, 0xbfffde84) = 0
SYS_259(0, 0x42015554, 0x40032468, 0x40015360, 0x80487a0) = 1
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40017000
write(1, "event 1 opened\n", 15) = 15
SYS_259(0, 0x40032280, 0xf, 0x40015360, 0x80487a0) = 2
write(1, "event 2 opened\n", 15) = 15
SYS_259(0, 0x40032280, 0xf, 0x40015360, 0x80487a0) = 3
write(1, "event 3 opened\n", 15) = 15
mmap2(NULL, 8388608, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40033000
brk(0) = 0x80499cc
brk(0x804a9cc) = 0x804a9cc
brk(0) = 0x804a9cc
brk(0x804b000) = 0x804b000
mprotect(0x40033000, 4096, PROT_NONE) = 0
clone(child_stack=0x408328d0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND| CLONE_THREAD|CLONE_SETTLS|CLONE_PARENT_SETTID|CLON E_CHILD_CLEARTID|CLONE_DETACHED, [3573], {entry_number:6, base_addr:0x40832cc0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 3573
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({2, 0}, {2, 0}) = 0
mmap2(NULL, 8388608, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40833000
mprotect(0x40833000, 4096, PROT_NONE) = 0
clone(child_stack=0x41032850, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND| CLONE_THREAD|CLONE_SETTLS|CLONE_PARENT_SETTID|CLON E_CHILD_CLEARTID|CLONE_DETACHED, [3574], {entry_number:6, base_addr:0x41032c40, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 3574
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({2, 0}, {2, 0}) = 0
mmap2(NULL, 8388608, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x41033000
mprotect(0x41033000, 4096, PROT_NONE) = 0
clone(child_stack=0x418327d0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND| CLONE_THREAD|CLONE_SETTLS|CLONE_PARENT_SETTID|CLON E_CHILD_CLEARTID|CLONE_DETACHED, [3575], {entry_number:6, base_addr:0x41832bc0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 3575
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({2, 0}, {2, 0}) = 0
mmap2(NULL, 8388608, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x42133000
mprotect(0x42133000, 4096, PROT_NONE) = 0
clone(child_stack=0x42932750, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND| CLONE_THREAD|CLONE_SETTLS|CLONE_PARENT_SETTID|CLON E_CHILD_CLEARTID|CLONE_DETACHED, [3576], {entry_number:6, base_addr:0x42932b40, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 3576
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({2, 0}, {2, 0}) = 0
mmap2(NULL, 8388608, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x42933000
mprotect(0x42933000, 4096, PROT_NONE) = 0
clone(child_stack=0x431326d0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND| CLONE_THREAD|CLONE_SETTLS|CLONE_PARENT_SETTID|CLON E_CHILD_CLEARTID|CLONE_DETACHED, [3577], {entry_number:6, base_addr:0x43132ac0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 3577
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({2, 0}, {2, 0}) = 0
mmap2(NULL, 8388608, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x43133000
mprotect(0x43133000, 4096, PROT_NONE) = 0
clone(child_stack=0x43932650, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND| CLONE_THREAD|CLONE_SETTLS|CLONE_PARENT_SETTID|CLON E_CHILD_CLEARTID|CLONE_DETACHED, [3578], {entry_number:6, base_addr:0x43932a40, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 3578
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({2, 0}, {2, 0}) = 0
SYS_260(0x1, 0x40032280, 0, 0x40015360, 0x80487a0) = -1 ENOSYS (Function not implemented)
write(1, "event 1 could not close\n", 24) = 24
SYS_260(0x2, 0x40032280, 0x18, 0x40015360, 0x80487a0) = -1 ENOSYS (Function not implemented)
write(1, "event 2 could not close\n", 24) = 24
SYS_260(0x3, 0x40032280, 0x18, 0x40015360, 0x80487a0) = -1 ENOSYS (Function not implemented)
write(1, "event 3 could not close\n", 24) = 24
munmap(0x40017000, 4096) = 0
exit_group(0) = ?

thanks,

newcat1

newcat1
06-01-2004, 05:43 AM
bwkaz,

Just let you know that we have solved the problem. This is because
we declared
.long SYMBOL_NAME(sys_evntopen)
.long SYMBOL_NAME(sys_evntclose) /* 260 */
.long SYMBOL_NAME(sys_evntwait)
.long SYMBOL_NAME(sys_evntsig)

in entry.S

but there is a

#define NR_syscalls 260 in /usr/src/linux-2.4/include/linux/sys.h

//Redhat 9 kernel 2.4

There is confliction so that the system calls above 260 would not work.

Thank you for your responding,

newcat1

bwkaz
06-01-2004, 06:48 PM
Oh, OK, that would make sense.

I thought it might be that your glibc didn't match your kernel, and so syscall() (the function that _syscall1 #defines to) wasn't able to generate the new syscall code correctly. But that makes even more sense.

newcat1
06-02-2004, 03:13 AM
Strange thing is one of my classmates does not have the problem (with same project). He has Redhat 9 with kernel 2.4 but the version is slightly later than my kernel version(mine is 2.4.20-8).

newkat1

maccorin
06-02-2004, 05:32 AM
it's 270 in 2.6.6 (just checked), thanks for posting what your problem was... I never answered, cause I didn't know :D, now i do