Annotation of os2sdk/demos/examples/threads/threads.c, revision 1.1.1.2

1.1       root        1: /*
1.1.1.2 ! root        2:  * DosCreateThread example.
1.1       root        3:  *
1.1.1.2 ! root        4:  * Created by Microsoft Corp. 1986
1.1       root        5:  *
                      6:  * This example illustrates the use of threads and ram semaphores.
                      7:  * Two threads are given alternating access to a shared resource, in this
                      8:  * case, the screen. In this example a semaphore is used to protect
1.1.1.2 ! root        9:  * the shared resource. See the DosCritSec example for a different method.
1.1       root       10:  *
                     11:  * See example program "asmexmpl" for a version of this program in assembler.
                     12:  *
                     13:  * In general, threads in C are a little tricky, and require that the
                     14:  * programmer be aware of the following issues:
                     15:  *
                     16:  * - C functions can be used as thread bodies. The function must have
                     17:  *   no arguments.
                     18:  *
1.1.1.2 ! root       19:  * - The thread function must end with a call to DosExit to terminate
1.1       root       20:  *   either that thread or all threads. Simply returning, or falling
                     21:  *   off the end will lead to unpredictable results.
                     22:  *
                     23:  * - The C runtimes are not generally reentrant. If you call the
                     24:  *   runtime from more than one thread you need to protect it from
                     25:  *   being reentered using a semaphore.
                     26:  *
                     27:  *
                     28:  * - Some of the C runtimes are built with stack checking enabled (see
                     29:  *   section 2.5 of the C run-time library reference). The stack checking
                     30:  *   depends on SS==DS.  If you use these runtimes, you must allocate
                     31:  *   stack space for any threads from the default data segment and you
                     32:  *   must use the small- or medium- memory models.  That way, you will
                     33:  *   have SS==DS in these threads. This is accomplished by using malloc,
                     34:  *   which maps to _nmalloc in near-data models (small- and medium- models).
                     35:  *   _nmalloc allocates memory from within the default data segment.
                     36:  *
                     37:  *   The general solution is to use the -Aw option to tell the compiler that
                     38:  *   SS!=DS and not use the C runtimes which do stack checking (printf, etc.).
                     39:  *   Also, you must use the -Gs option to turn off stack checking in your
                     40:  *   program.  For examples of the -Au option (SS!=DS and DS reloaded on
                     41:  *   function entry) see the dynlink demo.
                     42:  *
                     43:  *
                     44:  * - Threads can have local variables. When accessing global data be
                     45:  *   careful about critical sections and collisions with other threads.
                     46:  *   Be especially careful of modifications to data structures which are
                     47:  *   not atomic operations. For example if you have a LONG INT in global
                     48:  *   data, and two threads access it, then you need a critical section
                     49:  *   around the code which accesses it, since the 286 is a 16 bit machine
                     50:  *   and the compiler has to generate multiple instructions to modify a
                     51:  *   long in memory. If one thread preempts another while it is half
                     52:  *   through modifying the LONG, it is left in an inconsistent state.
                     53:  */
                     54: 
1.1.1.2 ! root       55: #define INCL_DOSPROCESS
        !            56: #define INCL_DOSSEMAPHORES
        !            57: #define INCL_DOSFILEMGR
        !            58: 
        !            59: #include <os2def.h>
        !            60: #include <bsedos.h>
1.1       root       61: #include <malloc.h>
1.1.1.2 ! root       62: #undef NULL
1.1       root       63: #include <stdio.h>
                     64: 
1.1.1.2 ! root       65: #define        HELLO0          "thread zero hello\r\n"
        !            66: #define HELLO1         "THREAD ONE HELLO\r\n"
1.1       root       67: 
1.1.1.2 ! root       68: #define THREAD_STK_SIZE 400            /* thread stack size */
1.1       root       69: 
1.1.1.2 ! root       70: HSEM   sem;          /* ram semaphore */
1.1       root       71: 
                     72: main(argc, argv)
                     73: int argc;
                     74: char *argv[];
                     75: {
1.1.1.2 ! root       76:        void far thread1();             /* address where thread1 gets control */
        !            77:        PSZ thread1Stack;               /* far pointer to thread1 stack */
        !            78:        TID thread1ID;                  /* thread ID */
        !            79:        unsigned rc;                    /* return code */
1.1       root       80: 
1.1.1.2 ! root       81:        sem = 0L;                       /* init semaphore */
1.1       root       82: 
1.1.1.2 ! root       83:        /* allocate stack space for thread 1 */
        !            84:        /* since this is written in C, DosAllocSeg cannot be used here */
1.1       root       85: 
1.1.1.2 ! root       86:        if ((thread1Stack = malloc(THREAD_STK_SIZE)) == NULL) {
1.1       root       87: 
1.1.1.2 ! root       88:                printf("thread stack malloc failed\n");
        !            89:                DosExit(EXIT_PROCESS, 1); /* term all threads,return error */
        !            90:        }
        !            91:        thread1Stack += THREAD_STK_SIZE;        /* since stack grows down */
1.1       root       92: 
1.1.1.2 ! root       93:        /* start another thread */
        !            94:        if (rc = DosCreateThread( thread1, &thread1ID,
        !            95:                                  thread1Stack ))  {
1.1       root       96: 
1.1.1.2 ! root       97:                printf("create of thread failed, error: %d\n", rc);
        !            98:                DosExit(EXIT_PROCESS, 1);
        !            99:        }
1.1       root      100: 
1.1.1.2 ! root      101:        thread0();              /* this will loop forever */
1.1       root      102: 
1.1.1.2 ! root      103:        DosExit(EXIT_PROCESS, 0);      /* Terminate all threads and exit */
1.1       root      104: }
                    105: 
                    106: 
1.1.1.2 ! root      107: thread0()      /* Thread 0 */
1.1       root      108: {
1.1.1.2 ! root      109:     USHORT BytesWrit;
1.1       root      110: 
                    111:     for (;;) {
                    112: 
1.1.1.2 ! root      113:        /* claim the resource - in this case, the screen */
1.1       root      114: 
1.1.1.2 ! root      115:        DosSemRequest( &sem, -1L );      /* no timeout */
1.1       root      116: 
1.1.1.2 ! root      117:        /* write to the screen */
1.1       root      118: 
1.1.1.2 ! root      119:        DosWrite( 1, (char far *) HELLO0, sizeof(HELLO0) - 1,
        !           120:                    &BytesWrit );
1.1       root      121: 
1.1.1.2 ! root      122:        DosSemClear( &sem );    /* release resource */
1.1       root      123: 
1.1.1.2 ! root      124:        DosSleep(2000L);                        /* give up the processor */
1.1       root      125:     }
                    126: }
                    127: 
                    128: void far
1.1.1.2 ! root      129: thread1()      /* Thread 1 */
1.1       root      130: {
1.1.1.2 ! root      131:     USHORT BytesWrit;
1.1       root      132: 
                    133:     for (;;) {
                    134: 
1.1.1.2 ! root      135:        /* claim the resource - in this case, the screen */
1.1       root      136: 
1.1.1.2 ! root      137:        DosSemRequest( &sem, -1L );     /* no timeout */
1.1       root      138: 
1.1.1.2 ! root      139:        /* write to the screen */
1.1       root      140: 
1.1.1.2 ! root      141:        DosWrite(1, (char far *)HELLO1, sizeof(HELLO1) - 1,
        !           142:                    &BytesWrit );
1.1       root      143: 
1.1.1.2 ! root      144:        DosSemClear( &sem );    /* release resource */
1.1       root      145: 
1.1.1.2 ! root      146:        DosSleep(2000L);                        /* give up the processor */
1.1       root      147:     }
                    148: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.