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.othats it