home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / OS2AP.ZIP / DUMP.C < prev    next >
Text File  |  1987-09-14  |  7KB  |  172 lines

  1. Here is the C code for the DUMP.C program to demonstrate semaphores,
  2. multiple threads, etc. from high level.  
  3.  
  4.  
  5.  
  6. /*
  7.         DUMP.C          Displays the binary contents of a file in
  8.                         hex and ASCII on the standard output device.
  9.  
  10.                         Program has been deliberately complicated 
  11.                         to demonstrate direct calls from C to 
  12.                         operating system, use of multiple threads,
  13.                         and synchronization with semaphores.
  14.  
  15.         Usage is:       C>DUMP unit:path\filename.ext [ >destination ]
  16.  
  17.         Compile with:   C>CL /AL /Zi /Gs /F 2000 DUMP.C
  18. */
  19.  
  20. #include <stdio.h>
  21. #include <malloc.h>
  22. #include <doscalls.h>
  23.  
  24. #define REC_SIZE 16                     /* size of file records */
  25. #define STK_SIZE 1024                   /* stack size for threads */
  26.  
  27. char Buf1[REC_SIZE];                    /* first disk buffer */
  28. unsigned Buf1Len;                       /* amount of data in buffer */
  29.  
  30. char Buf2[REC_SIZE];                    /* second disk buffer */
  31. unsigned Buf2Len;                       /* amount of data in buffer */
  32.  
  33. unsigned Handle;                        /* file Handle from DOSOPEN */ 
  34. long filptr;                            /* file offset in bytes */
  35.  
  36. unsigned long ExitSem;                  /* semaphore for process exit */
  37. unsigned long Buf1FullSem;              /* semaphores for disk buffer #1 */
  38. unsigned long Buf1EmptySem;
  39. unsigned long Buf2FullSem;              /* semaphores for disk buffer #2 */
  40. unsigned long Buf2EmptySem;
  41.  
  42. main(int argc, char *argv[])
  43. {
  44.     void far DisplayThr();              /* entry point for Display Thread */
  45.     void far DiskThr();                 /* entry point for Disk Thread */
  46.  
  47.     unsigned DisplayThrID;              /* receives Thread ID */
  48.     unsigned DiskThrID;                 /* receives Thread ID */
  49.  
  50.     char DisplayThrStk[STK_SIZE];       /* allocate stacks for threads */
  51.     char DiskThrStk[STK_SIZE];
  52.     int action;                         /* receives DOSOPEN result */
  53.     int openflag=0x01;                  /* fail open if file not found */
  54.     int openmode=0x40;                  /* read only, deny none */
  55.  
  56.     filptr=0L;                          /* initialize file pointer */
  57.  
  58.     ExitSem=0L;                         /* initialize semaphores */
  59.     Buf1EmptySem=Buf1FullSem=0L;
  60.     Buf2EmptySem=Buf2FullSem=0L;
  61.     DOSSEMSET((long) &ExitSem);
  62.     DOSSEMSET((long) &Buf1FullSem);
  63.     DOSSEMSET((long) &Buf2FullSem);
  64.  
  65.     if (argc < 2)                       /* check command tail */
  66.     {   fprintf(stderr,"\ndump: missing file name\n");
  67.         exit(1);
  68.     }
  69.                                         /* open file or exit */
  70.     if (DOSOPEN(argv[1],&Handle,&action,0L,0,openflag,openmode,0L)) 
  71.     {   fprintf(stderr,"\ndump: can't find file %s\n",argv[1]);
  72.         exit(1);
  73.     }  
  74.                                         /* create Disk Thread */
  75.     if (DOSCREATETHREAD(DiskThr,&DiskThrID,DiskThrStk+STK_SIZE))
  76.     {   fprintf(stderr,"\ndump: can't create Disk Thread");
  77.         exit(1);
  78.     }
  79.                                         /* Create Display Thread */
  80.     if (DOSCREATETHREAD(DisplayThr,&DisplayThrID,DisplayThrStk+STK_SIZE))
  81.     {   fprintf(stderr,"\ndump: can't create Display Thread");
  82.         exit(1);
  83.     }
  84.  
  85.     DOSSEMWAIT((long) &ExitSem,-1L);    /* wait for exit signal */
  86.  
  87.     DOSSUSPENDTHREAD(DiskThrID);        /* suspend other threads */
  88.     DOSSUSPENDTHREAD(DisplayThrID);
  89.     DOSCLOSE(Handle);                   /* close file */
  90.     DOSEXIT(1,0);                       /* terminate all threads */     
  91. }
  92.  
  93. /* 
  94.         The Disk Thread reads the disk file, alternating between 
  95.         Buf1 and Buf2.  This thread gets terminated externally
  96.         when the other threads see end of file has been reached.
  97. */
  98. void far DiskThr()
  99. {   
  100.     while(1)    
  101.     {   DOSREAD(Handle,Buf1,REC_SIZE,&Buf1Len); /* read disk */
  102.         SemFlip(&Buf1EmptySem,&Buf1FullSem);    /* mark buffer 1 full */
  103.         DOSSEMWAIT((long) &Buf2EmptySem,-1L);   /* wait for buffer 2 empty */
  104.         DOSREAD(Handle,Buf2,REC_SIZE,&Buf2Len); /* read disk */
  105.         SemFlip(&Buf2EmptySem,&Buf2FullSem);    /* mark buffer 2 full */
  106.         DOSSEMWAIT((long) &Buf1EmptySem,-1L);   /* wait for buffer 1 empty */
  107.     }
  108. }
  109.  
  110. /* 
  111.         The Display Thread formats and displays the data in the 
  112.         disk buffers, alternating between Buf1 and Buf2.
  113. */
  114. void far DisplayThr()
  115. {   
  116.     while(1)    
  117.     {   DOSSEMWAIT((long) &Buf1FullSem,-1L);    /* wait for buffer 1 full */
  118.         DumpRec(Buf1,Buf1Len);                  /* format and display it */     
  119.         SemFlip(&Buf1FullSem,&Buf1EmptySem);    /* mark buffer 1 empty */
  120.         DOSSEMWAIT((long) &Buf2FullSem,-1L);    /* wait for buffer 2 full */
  121.         DumpRec(Buf2,Buf2Len);                  /* format and display it */     
  122.         SemFlip(&Buf2FullSem,&Buf2EmptySem);    /* mark buffer 2 empty */
  123.     }
  124. }
  125.  
  126. /*
  127.         Display record in hex and ASCII on standard output.
  128.         Clear exit semaphore and terminate thread if record length=0.
  129. */
  130. DumpRec(char *buffer,int length)
  131. {   
  132.     int i;                              /* index to current record */
  133.  
  134.     if (length==0)                      /* check if record length = 0 */
  135.     {   DOSSEMCLEAR((long) &ExitSem);   /* yes, signal main thread  */
  136.         DOSEXIT(0,0);                   /* and terminate this thread! */
  137.     }
  138.  
  139.     if (filptr % 128 == 0)              /* maybe print heading */
  140.         printf("\n\n       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F");
  141.  
  142.     printf("\n%04lX ",filptr);          /* file offset */
  143.  
  144.     for (i = 0; i < length; i++)        /* print hex equiv. of each byte */
  145.        printf( " %02X", (unsigned char) buffer[i] );
  146.  
  147.                                         /* space over if partial record */
  148.     if (length != 16) for(i=0; i<(16-length); i++) printf("   ");
  149.  
  150.     printf("  ");
  151.  
  152.     for (i = 0; i < length; i++)        /* print ASCII equiv. of bytes */
  153.         {  if (buffer[i] < 32 || buffer[i] > 126) putchar('.');
  154.            else putchar(buffer[i]);
  155.         }
  156.  
  157.     filptr += REC_SIZE;                 /* update file offset */
  158.  
  159. /* 
  160.         Since there is no operation to wait until a semaphore
  161.         is set, we must maintain two semaphores to control each 
  162.         buffer and flip them atomically.
  163. */
  164. SemFlip(long *sem1, long *sem2)
  165. {   DOSENTERCRITSEC();                  /* block other threads */
  166.     DOSSEMSET((long) sem1);             /* set the first semaphore */
  167.     DOSSEMCLEAR((long) sem2);           /* clear the second semaphore */
  168.     DOSEXITCRITSEC();                   /* unblock other threads */
  169. }
  170.  
  171.