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