dhilst

Fake kernel ..

This is the implementations of this and I know,
it's realy bad coded ..

files:
common.c -> common functions
scheduler.c -> scheduler functions
process.c -> process functions
filequeue.c -> queue functions
fakek.h -> where all stuff is declared
main.c -> the main program
Makefile -> the make file :P

/*
* file: common.c
*/
#include <dirent.h>
#include <stdlib.h>
#include <string.h>

void *
xmalloc (size_t size)
{
void * pool = malloc (size);
if (pool == NULL)
err (1, "xmalloc");
return pool;
}

DIR *
xopendir (const char * dirname)
{
DIR * dp = opendir (dirname);
if (dp == NULL)
err (1, "xopendir");
return dp;
}

int
xopen (const char * filename, int state, mode_t mode)
{
int fd = open (filename, state, mode);
if (fd == -1)
err (1, "xopen\n");
return fd;
}

char *
create_filepath (const char * dir, const char * file)
{
char * path = (char *) xmalloc ((size_t) strlen (dir) + strlen (file) +1);
memset (path, 0, strlen (dir) + strlen (file) +1);
strncpy (path, dir, strlen (dir));
strncat (path, file, strlen (file));
return path;
}

void xrename (const char * old, const char * new)
{
int rval = rename (old, new);
if (rval == -1)
err (1, "xrename");
}


/*
* file scheduler.c
*/
#include "fakek.h"


queue_type QBuffer;
const char * userdir = "./fstack/User/";
const char * sysdir = "./fstack/System/";
const char * rdir = "./fstack/Running/";

/* Save function to queue process */
void
Sched_writebuf (unsigned int pid, unsigned int state, unsigned int fork,
unsigned int stopline, unsigned int spendtime,
unsigned int priority, char * filename)
{
/* Write here */
QBuffer.proc.pid = pid;
QBuffer.proc.state = state;
QBuffer.proc.fork = fork;
QBuffer.proc.stopline = stopline;
QBuffer.proc.spendtime = spendtime;
QBuffer.proc.priority = priority;
// QBuffer.proc.filename = (char *) xmalloc (strlen (filename) + 1);
/* This will be freed with q_read() */
strncpy (QBuffer.proc.filename, filename, strlen (filename));
QBuffer.proc.filename [strlen (filename)] = '\0';
/* Send to Queue, the q_write increments QSize */
q_write (& QBuffer);
}


/*
* return a regular file entry
* consecutive calls return consecutive file entries
* it uses Scheddir poiter, that must be a non-NULL pointer
* otherwise the behavior is undefined
*/
struct dirent *
Sched_getrfile (DIR * dirp)
{
struct dirent * entry_ptr;
while (entry_ptr = readdir (dirp))
if (entry_ptr->d_type & DT_REG)
return entry_ptr;
/* There is no regular files in this diretory */
return NULL;
}


/* This is the scheduler itself */
void *
Scheduler_thread (void * unused)
{
struct timespec time = { 0, 1000 };
struct dirent * entry_ptr;
int sys_switch;
char * snew, * sold;
DIR * tmpdir_ptr;
/* While forever */
while (1) {
/* Search first for System process after User process */
sys_switch = 0;
while (1) {
pthread_mutex_lock (&mutex);
printf ("SCHEDULER LOOP START\n");
/* open system dir */
tmpdir_ptr = xopendir (sysdir);
entry_ptr = Sched_getrfile (tmpdir_ptr);
closedir (tmpdir_ptr);
if (entry_ptr != NULL) {
/* We got one system process */
sys_switch++;
pthread_mutex_unlock (&mutex);
break;
}
/* open user dir */
tmpdir_ptr = xopendir (userdir);
entry_ptr = Sched_getrfile (tmpdir_ptr);
closedir (tmpdir_ptr);
if (entry_ptr != NULL) {
/* We got one user process */
pthread_mutex_unlock (&mutex);
break;
}
/* There is no more process */
sleep (1);
printf ("SCHEDULER LOOP /* NO NEW PROCESS */\n");
pthread_mutex_unlock (&mutex);
/* Wait 1000 nanoseconds to search again */
nanosleep (&time, NULL);
}
pthread_mutex_lock (&mutex);
sleep (1);
printf ("\E[31mNew process arise: %s\n\E[0m", entry_ptr->d_name);
sleep (1);
if (sys_switch) {
sold = create_filepath (sysdir, entry_ptr->d_name);
snew = create_filepath (rdir, entry_ptr->d_name);
printf ("\E[31mmoving %s -> %s\n\E[0m", sold, snew);
sleep (1);
rename (sold, snew);
free (sold);
free (snew);
printf ("\E[31mScheduling system proc Pid:%d\n\E[0m", 10 + PidCounter);
sleep (1);
/* pid, state, fork, stopline, spendtime, priority, filename */
Sched_writebuf (10 + PidCounter, 0, 0, 1, 0, 4, entry_ptr->d_name);
PidCounter++;
printf ("\E[31mQueueSize = %d\n\E[0m", QSize);
sleep (1);
}
else {
sold = create_filepath (userdir, entry_ptr->d_name);
snew = create_filepath (rdir, entry_ptr->d_name);
sleep (1);
printf ("\E[31mmoving %s -> %s\n\E[0m", sold, snew);
rename (sold, snew);
free (sold);
free (snew);
sleep (1);
printf ("\E[32mScheduling it Pid:%d\n\E[0m", 10 + PidCounter);
/* pid, state, fork, stopline, spendtime, priority, filename */
Sched_writebuf (10 + PidCounter, 0, 0, 1, 0, 1, entry_ptr->d_name);
PidCounter++;
sleep (1);
printf ("\E[32mQueueSize = %d\n\E[0m", QSize);
}
sleep (1);
printf ("SCHEDULER LOOP FINISH\n");
pthread_mutex_unlock (&mutex);
nanosleep (&time, NULL);
}
}

/*
* file: process.c
*/
#define MAXPIDNUM 99
#define THREADMAXNANOTIME 1000
#include "fakek.h"

queue_type PBuffer;
pthread_mutex_t Proc_readbuf_mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned int MaxTime;
unsigned int Elapsed = 0;
static char pid_array[MAXPIDNUM + 1];
const char * fdir = "./fstack/Finished/";


void *
Timer_thread (void * unused)
{
struct timespec ttime = {
0, THREADMAXNANOTIME
};
int oldcancelstate;
while (Elapsed < MaxTime) {
nanosleep (&ttime, NULL);
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldcancelstate);
Elapsed++;
pthread_setcancelstate (oldcancelstate, NULL);
}
}

char
Proc_setline (int fd, unsigned int stopline)
{
char ch = 0;
signed int nbytes;
unsigned int currentline = 1;
while (currentline != stopline) {
nbytes = read (fd, &ch, 1);
if (nbytes == 0)
return EOF;
else if (nbytes == -1)
err (1, "Proc_setline");

if (ch == '\n')
currentline++;
}
}

char
Proc_readline (int fd)
{
int rval;
char line[7];
if (PBuffer.proc.state != 0)
/* The process is waiting for other process */
if (pid_array[PBuffer.proc.state] != 0)
/* that not occored yet */
return 1;
lseek (fd, 0, SEEK_SET);
rval = Proc_setline (fd, PBuffer.proc.stopline);
if (rval == EOF)
return EOF;
read (fd, line, 7);
line[7] = '\0';
printf ("\E[33m\tExecuting line %d (%s) from file %s\n\E[0m",
PBuffer.proc.stopline, line, PBuffer.proc.filename);
if (strcmp (line, "wait") > 0) {
/* wait found */
int pid_to_wait;
sscanf (line, "wait %d", &pid_to_wait);
PBuffer.proc.state = pid_to_wait;
/* This will be 0 again when the process
`pid_to_wait' ends */
pid_array[pid_to_wait] = PBuffer.proc.pid;
PBuffer.proc.stopline++;
return 1;
}
else if (strcmp (line, "fork 00") == 0) {
/* fork found */
PBuffer.proc.stopline++;
return 2;
}
PBuffer.proc.stopline++;
return 0;
}


void *
Process_thread (void * unused)
{
struct timespec process_time = { 0, 1000 };
pthread_t timer_thread_id;
int fd;
char rval, * old, * new;

START_PROCESS: while (1) {

/* While Queue is empty, Wait */

while (QSize == 0)
nanosleep (&process_time, NULL);

pthread_mutex_lock (&mutex);
printf ("\tPROCESS LOOP START\n");
sleep (1);
/* Read a process from queue */
q_read (&PBuffer);
printf ("\E[35m\tTaked a process from queue pid:%d | filename %s\n\E[0m",
PBuffer.proc.pid, PBuffer.proc.filename);
printf ("\E[34m\t QueueSize = %d\n", QSize);
sleep (1);
/* Start Timer according wiht priority */
MaxTime = PBuffer.proc.priority;
char * filename = create_filepath (rdir, PBuffer.proc.filename);
printf ("\E[33m\topening file %s\n\E[0m", filename);
fd = xopen (filename, O_RDONLY, 0);
free (filename);
printf ("\E[35m\tStarting timer\n\E[0m");
pthread_create (&timer_thread_id, NULL, &Timer_thread, NULL);
/* Until EOF */
while ((rval = Proc_readline(fd)) != EOF) {
if (rval == 1) {
/*
* This process was set to wait for other process
* reshedule it util the wait process ends
*/
pthread_cancel (timer_thread_id);
pthread_join (timer_thread_id, NULL);
close (fd);
Elapsed = 0;
printf ("\E[32m\tWaiting for pid:%d\n\E[0m", PBuffer.proc.state);
Sched_writebuf (PBuffer.proc.pid, PBuffer.proc.state, PBuffer.proc.fork,
PBuffer.proc.stopline, Elapsed * 1000, PBuffer.proc.priority,
PBuffer.proc.filename);
printf ("\tPROCESS FINISH\n");
sleep (1);
pthread_mutex_unlock (&mutex);
nanosleep (&process_time, NULL);
goto START_PROCESS;
}
else if (rval == 2) {
/* fork found */
char * wholefname, * fname, pidchar[2], buf[100];
int newfiled, nbytes;
fname = create_filepath ("F", (PBuffer.proc.filename+1));
wholefname = create_filepath (rdir, fname);
/* Copy the file */
printf ("\E[32m\tCopying file %s%s -> %s\n\E[0m",
rdir, PBuffer.proc.filename, wholefname);
newfiled = xopen (wholefname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
lseek (fd, 1, SEEK_CUR);
while ((nbytes = read (fd, buf, 100)) > 0)
write (newfiled, buf, nbytes);
if (nbytes == -1)
errx (1, "read error");
/* End of copy file */
printf ("\E[32m\tFork found making a copy of process. Pid: %d\n\E[0m",
PidCounter + 10);
Sched_writebuf (PidCounter + 10, PBuffer.proc.state, 2, 1,
0, PBuffer.proc.priority, fname);
free (fname);
free (wholefname);
PidCounter++;
PBuffer.proc.fork = 1; /* this is the original one */
}
/* if Time Out, reschedule */
else if (Elapsed == MaxTime) {
pthread_join (timer_thread_id, NULL);
printf ("\E[31m\tTime exceded at priority %d, rescheduling pid:%d %s\n\E[0m",
PBuffer.proc.priority, PBuffer.proc.pid, PBuffer.proc.filename);
Sched_writebuf (PBuffer.proc.pid, PBuffer.proc.state, PBuffer.proc.fork,
PBuffer.proc.stopline, Elapsed * 1000 + PBuffer.proc.spendtime
, PBuffer.proc.priority, PBuffer.proc.filename);
close (fd);
Elapsed = 0;
printf ("\tPROCESS FINISH\n");
sleep (1);
pthread_mutex_unlock (&mutex);
nanosleep (&process_time, NULL);
goto START_PROCESS;
}
}
/* The curret process ends */
close (fd);
printf ("\E[31m\tEOF %s\n\E[0m", PBuffer.proc.filename);
/* if was some other waiting for it .. release */
if (pid_array[PBuffer.proc.pid] != 0) {
printf ("\E[32m\tReleazing process pid:%d\n\E[0m", pid_array[PBuffer.proc.pid]);
pid_array[PBuffer.proc.pid] = 0;
}
printf ("\E[31m\tTime expense %d nanoseconds at prioriry %d\n",
PBuffer.proc.spendtime + (1000 * Elapsed), PBuffer.proc.priority);
pthread_cancel (timer_thread_id);
pthread_join (timer_thread_id, NULL);
Elapsed = 0;
new = create_filepath (fdir, PBuffer.proc.filename);
old = create_filepath (rdir, PBuffer.proc.filename);
sleep (1);
printf ("\E[32m\tmoving %s -> %s\n\E[0m", old, new);
xrename (old, new);
free (old);
free (new);
sleep (1);
printf ("\tPROCESS LOOP FINISH\n");
pthread_mutex_unlock (&mutex);
nanosleep (&process_time, NULL);
}
}

/*
* file: filequeue.c
*/
#include <err.h>
#include <stdlib.h>
#include <string.h>

#include "fakek.h"

/* Init Global variables */
queue_type * GFirst = NULL;
queue_type * GLast = NULL;
unsigned int QSize = 0;
unsigned int PidCounter = 0;

void *
q_write (queue_type * buf)
{
queue_type * new = (queue_type *) malloc (sizeof (queue_type));
if (new == NULL)
errx (2, "q_write (malloc fail)");
/* Set data */
memcpy (new, buf, sizeof (queue_type));
new->next = NULL;
/* Set Globals */
if (QSize == 0)
GFirst = GLast = new;
else {
GLast->next = new;
GLast = new;
}
QSize++;
}

void *
q_read (queue_type * buf)
{
if (QSize < 1)
errx (1, "Queue is empty, wrong q_read call");
/* Save data */
memcpy (buf, GFirst, sizeof (queue_type));
/* Set Globals */
queue_type * tmp = GFirst;
GFirst = GFirst->next;
/* Free the read data */
free (tmp);
/* Set the queue size need be last thing to do
to avoid race conditions */
QSize--;
}

void *
q_destroy (void)
{
unsigned int released_items = 0;
queue_type * tmp;
while ((tmp = GFirst) != NULL) {
GFirst = GFirst->next;
free (tmp);
released_items++;
}
GLast = NULL;
QSize = 0;
return (void *) released_items;
}

/*
* file: fakek.h
*/
#ifndef FAKEK_H
#define FAKEK_H

#include <dirent.h>
#include <err.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>


/*
* Defined in filequeue.c
*/
typedef struct proc_strc {
unsigned int pid;
unsigned int state;
unsigned int fork;
unsigned int stopline;
unsigned int spendtime;
unsigned int priority;
char filename[5];
} proc_type;

typedef struct queue_strc {
proc_type proc;
struct queue_strc * next;
} queue_type;

/* Global First and Last processs in Queue */
extern queue_type * GFirst;
extern queue_type * GLast;
/* Queue Size */
extern unsigned int QSize;

/* pid counter */
extern unsigned int PidCounter;

/* Fifo like functions */
extern void * q_write (queue_type *);
extern void * q_read (queue_type *);
extern void * q_destroy (void);


/*
* Defined in common.c
*/
extern DIR * xopendir (const char *);
extern void * xmalloc (size_t);
extern int xopen (const char *, int, mode_t);
extern char * create_filepath (const char *, const char *);

/*
* Defined in scheduler.c
*/
extern const char * userdir;
extern const char * sysdir;
extern const char * rdir;
extern queue_type QBuffer;
extern void Sched_writebuf (unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int, char *);
extern struct dirent * Sched_getrfile (DIR *);
extern void * Scheduler_thread (void *);

/*
* Defined int process.c
*/
extern const char * fdir;
extern queue_type PBuffer;
extern unsigned int MaxTime;
extern unsigned int Elapsed;
extern void * Timer_thread (void *);
extern char Proc_setline (int, unsigned int);
extern char Proc_readline (int fd);
extern void * Process_thread (void *);
#endif

/*
* Defined in main
*/
extern pthread_mutex_t mutex;


/*
* file: main.c
*/
#include "fakek.h"
#include <pthread.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int
main (void)
{
pthread_t Scheduler_id, Process_id;
pthread_create (&Process_id, NULL, &Process_thread, NULL);
pthread_create (&Scheduler_id, NULL, &Scheduler_thread, NULL);
pthread_join (Scheduler_id, NULL);
pthread_join (Process_id, NULL);

return 0;
}

fakek: main.c common.o filequeue.o process.o scheduler.o fakek.h
gcc $(CFLAGS) -o fakek main.c common.o filequeue.o process.o scheduler.o fakek.h -lpthread
mkdir -p ./fstack/System ./fstack/User ./fstack/Running ./fstack/Finished

common.o: common.c fakek.h
gcc $(CFLAGS) -c common.c

filequeue.o: filequeue.c fakek.h
gcc $(CFLAGS) -c filequeue.c

process.o: process.c fakek.h
gcc $(CFLAGS) -c process.c

scheduler.o: scheduler.c fakek.h
gcc $(CFLAGS) -c scheduler.c

clean:
rm -vf common.o fakek filequeue.o process.o scheduler.o
thats it