0
\$\begingroup\$

I have developed a program that implements the First Come First Served scheduling algorithm. The total number of processes is read directly from the input standard, and for each process the arrival time and execution time are specified. The average response time is also calculated, the average waiting time and the order of execution of the processes is displayed.

My question is whether this solution is optimal. What can I improve? What problems may arise?

code:

#include <sys/types.h>
#include <sys/wait.h>
#include "lab.h"
void assignValue(int*, int**, int**, int**);
void averages(int*, int**, int**, int**);
void completionTime(int*, int**, int**, int**);
void swap(int*, int*, int*);
void sort(int*, int**, int**, int**);
void fcfs(int*, int**, int**, int**, int**);
int main(void)
{
    int numProcesses;
    
    do
    {
        printf("Total number of processes: ");
        if(scanf("%d", &numProcesses) != 1)
        {
            err_msg("Failed to read integer!");
exit(1);
        }
    } while (numProcesses < 0);

    int* processesNum = (int*)malloc(numProcesses * sizeof(int));
    int* arrival = (int*)malloc(numProcesses * sizeof(int));
    int* burst = (int*)malloc(numProcesses * sizeof(int));
    int* completion = (int*)malloc(numProcesses * sizeof(int));
    assignValue(&numProcesses, &arrival, &burst, &processesNum);
    fcfs(&numProcesses, &arrival, &burst, &processesNum, &completion);
    
    free(processesNum);
    free(arrival);
    free(burst);
    free(completion);
    return 0;
}
void fcfs(int *numProcesses, int**arrival, int **burst, int **processesNum, int **completion)
{
    sort(numProcesses, &(*arrival), &(*burst), &(*processesNum));
    completionTime(numProcesses, &(*arrival), &(*burst), &(*completion));
    averages(numProcesses, &(*arrival), &(*burst), &(*completion));    
}
void averages(int *numProcesses, int **arrival, int **burst, int **completion)
{
    double averageTurn = 0;
    double averageWait = 0;
    
    for(int i=0; i < *numProcesses; i++)
    {
        if(i == 0 && *(*arrival + i) != 0)
        {
            for(int i = 0; i < *numProcesses; i++)
                *(*arrival + i) = 0;
        }
averageTurn += *(*completion + i) - *(*arrival + i);
        averageWait += ( *(*completion + i) - *(*arrival + i)) - *(*burst + i);
    }
    printf("\nAverage TurnAroundTime: %.2f", averageTurn / *numProcesses);
    printf("\nAverage WaitingTime: %.2f", averageWait / *numProcesses);
}
void completionTime(int *numProcesses, int **arrival, int **burst, int **completion)
{   
int temp = *(*burst + 0);
    for(int i=1; i <= *numProcesses; i++)
    {
*(*completion + (i-1)) = temp;
        if(temp < *(*arrival + i)) 
{
            temp = *(*arrival + i) + *(*burst + i);
            continue;
        }
        else if(temp > *(*arrival + i))
            temp = temp + *(*burst + i); 
    }
    printf("\nCompletion Time: \n");
for(int i=0; i < *numProcesses; i++)
        printf("%d ", *(*completion + i));
}
void swap(int *v1, int *v2, int *temp)
{
    *temp = *v1;
    *v1 = *v2;
    *v2 = *temp; 
}
void sort(int *numProcesses, int **arrival, int **burst, int **processesNum)
{
    int temp;
    for(int i=0;i < *numProcesses; i++)
    {
        for(int j=0;j <= i; j++)
        {
if(*(*arrival + i) < *(*arrival + j))
            {
                swap((*arrival + i), (*arrival + j), &temp);
                swap((*burst + i), (*burst + j), &temp);
swap((*processesNum + i), (*processesNum + j), &temp);
            }
        }
    }
    for(int i=0; i <= *numProcesses; i++)
    {
        for(int j=i+1; j <= *numProcesses - 1; j++)
{
            if(*(*arrival + i) == *(*arrival + j))
 {
                printf("arrival[%d]=%d, arrival[%d]=%d \n", i, *(*arrival + i), j, *(*arrival + j));

                if(*(*processesNum + i) > *(*processesNum + j))
{
                    swap((*arrival + i), (*arrival + j), &temp);
swap((*burst + i), (*burst + j), &temp);
                    swap((*processesNum + i), (*processesNum + j), &temp);
                }
            }                
        }
    }
    printf("\n\nAfter sorting in ascending order");

    printf("\nBursts:\n");
    for(int i=0; i < *numProcesses; i++)
        printf("%d ", *(*burst + i));
    printf("\nArrivals:\n");
    for(int i=0; i < *numProcesses; i++)
        printf("%d ", *(*arrival + i));
    
    printf("\nProcesses:\n");
    for(int i=0; i < *numProcesses; i++)
        printf("%d ", *(*processesNum + i));
}
void assignValue(int *numProcesses, int **arrival, int **burst, int **processesNum)
{
    for(int i=0; i < *numProcesses; i++)
    {
        *(*processesNum + i) = i+1;
        do
        {
 printf("Arrival time for P[%d]: ", i+1);
            if(scanf("%d", &(*(*arrival + i))) != 1)
            {
                err_msg("Failed to read integer!\n");
exit(1);
            }
        } while (*(*arrival + i) < 0);
do
        {
            printf("Burst time for P[%d]: ", i+1);
            if(scanf("%d", &(*(*burst + i))) != 1)
            {
                err_msg("Failed to read integer!\n");
exit(1);
            }
        } while (*(*burst + i) < 0);
    }
    printf("\nProcesses ID are: \n");
    for(int i=0; i < *numProcesses; i++)
        printf("%d ", *(*processesNum + i));
    printf("\nArrival times for processes:\n");
    for(int i=0; i < *numProcesses; i++)
        printf("%d ", *(*arrival + i));
    printf("\nBurst times for processes:\n");
    for(int i=0; i< *numProcesses; i++)
        printf("%d ", *(*burst + i));
    printf("\n");
}

lab.h content:

/* Our own header, to be included *after* all standard system headers */

#ifndef __ourhdr_h
#define __ourhdr_h

#include    <sys/types.h>   /* required for some of our prototypes */
#include    <stdio.h>       /* for convenience */
#include    <stdlib.h>      /* for convenience */
#include    <string.h>      /* for convenience */
#include    <unistd.h>      /* for convenience */

#define MAXLINE 4096            /* max line length */

#define FILE_MODE   (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
                    /* default file access permissions for new files */
#define DIR_MODE    (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)
                    /* default permissions for new directories */

typedef void    Sigfunc(int);   /* for signal handlers */

                    /* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
#if defined(SIG_IGN) && !defined(SIG_ERR)
#define SIG_ERR ((Sigfunc *)-1)
#endif

#define min(a,b)    ((a) < (b) ? (a) : (b))
#define max(a,b)    ((a) > (b) ? (a) : (b))

                    /* prototypes for our own functions */
char    *path_alloc(int *);         /* {Prog pathalloc} */
int      open_max(void);            /* {Prog openmax} */
void     clr_fl(int, int);          /* {Prog setfl} */
void     set_fl(int, int);          /* {Prog setfl} */
void     pr_exit(int);              /* {Prog prexit} */
void     pr_mask(const char *);     /* {Prog prmask} */
Sigfunc *signal_intr(int, Sigfunc *);/* {Prog signal_intr_function} */

int      tty_cbreak(int);           /* {Prog raw} */
int      tty_raw(int);              /* {Prog raw} */
int      tty_reset(int);            /* {Prog raw} */
void     tty_atexit(void);          /* {Prog raw} */
#ifdef  ECHO    /* only if <termios.h> has been included */
struct termios  *tty_termios(void); /* {Prog raw} */
#endif

void     sleep_us(unsigned int);    /* {Ex sleepus} */
ssize_t  readn(int, void *, size_t);/* {Prog readn} */
ssize_t  writen(int, const void *, size_t);/* {Prog writen} */
int      daemon_init(void);         /* {Prog daemoninit} */

int      s_pipe(int *);             /* {Progs svr4_spipe bsd_spipe} */
int      recv_fd(int, ssize_t (*func)(int, const void *, size_t));
                                    /* {Progs recvfd_svr4 recvfd_43bsd} */
int      send_fd(int, int);         /* {Progs sendfd_svr4 sendfd_43bsd} */
int      send_err(int, int, const char *);/* {Prog senderr} */
int      serv_listen(const char *); /* {Progs servlisten_svr4 servlisten_44bsd} */
int      serv_accept(int, uid_t *); /* {Progs servaccept_svr4 servaccept_44bsd} */
int      cli_conn(const char *);    /* {Progs cliconn_svr4 cliconn_44bsd} */
int      buf_args(char *, int (*func)(int, char **));
                                    /* {Prog bufargs} */

int      ptym_open(char *);         /* {Progs ptyopen_svr4 ptyopen_44bsd} */
int      ptys_open(int, char *);    /* {Progs ptyopen_svr4 ptyopen_44bsd} */
#ifdef  TIOCGWINSZ
pid_t    pty_fork(int *, char *, const struct termios *,
                  const struct winsize *);  /* {Prog ptyfork} */
#endif

int     lock_reg(int, int, int, off_t, int, off_t);
                                    /* {Prog lockreg} */
#define read_lock(fd, offset, whence, len) \
            lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len)
#define readw_lock(fd, offset, whence, len) \
            lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len)
#define write_lock(fd, offset, whence, len) \
            lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len)
#define writew_lock(fd, offset, whence, len) \
            lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len)
#define un_lock(fd, offset, whence, len) \
            lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len)

pid_t   lock_test(int, int, off_t, int, off_t);
                                    /* {Prog locktest} */

#define is_readlock(fd, offset, whence, len) \
            lock_test(fd, F_RDLCK, offset, whence, len)
#define is_writelock(fd, offset, whence, len) \
            lock_test(fd, F_WRLCK, offset, whence, len)

void    err_dump(const char *, ...);    /* {App misc_source} */
void    err_msg(const char *, ...);
void    err_quit(const char *, ...);
void    err_ret(const char *, ...);
void    err_sys(const char *, ...);
void    err_init(const char *);

void    log_msg(const char *, ...);     /* {App misc_source} */
void    log_open(const char *, int, int);
void    log_quit(const char *, ...);
void    log_ret(const char *, ...);
void    log_sys(const char *, ...);

void    TELL_WAIT(void);        /* parent/child from {Sec race_conditions} */
void    TELL_PARENT(pid_t);
void    TELL_CHILD(pid_t);
void    WAIT_PARENT(void);
void    WAIT_CHILD(void);

#endif  /* __ourhdr_h */
```
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

there seems to be a lot of function prototypes in the lab.h header file that are not used/defined in the posted code.

For readability and ease of understanding:

  1. please consistently indent the code. indent after every opening brace {. unindent before every closing brace }. Suggest each indent level be 4 spaces (do not use tabs for indenting as not everyone uses 8 spaces for the tab width)
  2. separate code blocks (for, if, else, do...while, while, etc.) by a single blank line
  3. separate functions by 2 or 3 blank lines (be consistent)

The posted code does not seem to be complete.

strongly suggest using a circular queue to start the next process when the prior process exits,

why are you sorting the list of processes?

regarding lines like:

#ifndef __ourhdr_h  

1)  leading underscores are for the implementation not for user code
2) the defined name is expected to reflect the header file name and be capitalized,  Suggest: 

#ifndef LAB_H

regarding statements like:

int* burst = (int*)malloc(numProcesses * sizeof(int));  

1) in C, the returned type is `void*` which can be assigned to any pointer.  Casting just clutters the code and is error prone.   
2) for robust code, always check the returned status of system functions to assure they were successful and if not successful, then announce to the user through `sysout`, 
3) when errors cannot be recovered, suggest code similar to::

 int* burst = malloc(numProcesses * sizeof(int));
 if( ! burst )
 {
     perror( "malloc for numProcesses failed" 
     // cleanup allocated memory, close files, etc then
     exit( EXIT_FAILURE );
 }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.