/* Shaun Cooper September 2, 2000 simple implementation of mergesort. Input: from STDIN, integers in unsorted fashion. Data ends when a 0 (zero) is read. Output: the data in sorted order Notes: Since mergesort actually relies upon external storage to store the merge of two segments, we use an additional array to store the merge called "out[]" and then place the results back into "in[]" for subsequent merges. */ #include #include #include #include #include /* value to size the arrays */ #define MAXNUM 10000 /* define the two arrays */ /* a pointer to the shared memory segment */ int *in; /* the internal array for merging */ int out[MAXNUM]; /* subroutine which takes locations and merges the results into "out[]" and then places the result into "in[]". Note that this routine uses two global vectors and this routine assumes that it can work with both of them */ void merge(int loc1,int loc2,int loc3,int loc4) { /* variable i is used to index in the first half variable j is used to index the second half variable inser is used to keep trak in the out[] vector in inserts */ int i,j,k,insert; insert=loc1; i=loc1; j=loc3; /* merge the two sublists -- we assume the lists are contiguous */ while ( (i <= loc2) && ( j <= loc4)) { if ( in[i] > in[j]) out[insert++]=in[j++]; else out[insert++]=in[i++]; } /* take care of any of the remainder in first segment */ for(k=i;k<=loc2;k++) out[insert++]=in[k]; /* take care of any of the remainder in second segment */ for(k=j;k<=loc4;k++) out[insert++]=in[k]; /* transfer the merged data back to the original vector */ for(i=loc1;i<=loc4;i++) in[i]=out[i]; } /* recursive calls to sort: break the vector up into single units. subroutine merge is then used to place the results back together */ void sort(int loc1, int loc2) { int mid; /* base case */ if (loc1 >=loc2) return; /* recursive call, calculate mid point, and bisect the segment */ else { mid=((loc1 + loc2)/2); sort(loc1,mid); sort(mid+1,loc2); merge(loc1,mid,mid+1,loc2); } } /* helper subroutine to print out the results of the in[] vector, one line at a time */ void printar(int NUM) { int i; for(i=0;i<=NUM;i++) printf("%d\n",in[i]); printf("\n"); } main() { int status1, status2; int i,j; int done; int beg,mid,end; int level; int share_key_in; int share_key_out; pid_t child1, child2; struct shmid_ds item; /* define shared memory */ if ( (share_key_in=shmget(IPC_PRIVATE,MAXNUM * 4 , IPC_CREAT|0666)) < 0) perror("Cannot get shared memory\n"); /* attach shared memory segment */ if ( (in=shmat(share_key_in,(void *) 0, SHM_RND)) == (void *) -1) perror("cannot attach to shared memory\n"); done=0; i=-1; /* read in the data from input */ while (! done ) { scanf("%d",&j); if ( j == 0 ) done =1; else in[++i]=j; } /* print before sort */ printar(i); /* too few items, no need to fork */ if ( i <= 8 ) { sort(0,i); printar(i); shmctl(share_key_in,IPC_RMID,&item); } /* we need to fork processes and then do the work. STUDENTS: This is where you will make changes to support 8 processes */ else { mid=i/2; beg=0; end=i; child1=fork(); if ( child1==0) { /* attach shared memory for first child */ if ( (in=shmat(share_key_in,(void *) 0,SHM_RND)) == (void *) -1) perror("cannot attach to shared memory\n"); sort(beg,mid); } else { child2=fork(); if (child2==0) { /* attach memory for second child */ if ( (in=shmat(share_key_in,(void *) 0,SHM_RND)) == (void *) -1) perror("cannot attach to shared memory\n"); sort(mid+1,end); } else { /* parent process */ waitpid(child1,&status1, 0); waitpid(child2, &status2, 0); merge(beg,mid,mid+1,end); printar(i); shmctl(share_key_in,IPC_RMID,&item); } } } }