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

1.1       root        1: /*
                      2:  * DOSCREATETHREAD example.
                      3:  *
                      4:  * Copyright (C) Microsoft Corp. 1986
                      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
                      9:  * the shared resource. See the DOSCRITSEC example for a different method.
                     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:  *
                     19:  * - The thread function must end with a call to DOSEXIT to terminate
                     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: 
                     55: #include <malloc.h>
                     56: #include <stdio.h>
                     57: #include <doscalls.h>
                     58: #include <subcalls.h>
                     59: 
                     60: #define HELLO0          "thread zero hello\r\n"
                     61: #define HELLO1          "THREAD ONE HELLO\r\n"
                     62: 
                     63: #define THREAD_STK_SIZE 2048            /* thread stack size */
                     64: 
                     65: unsigned long    sem;           /* ram semaphore */
                     66: 
                     67: main(argc, argv)
                     68: int argc;
                     69: char *argv[];
                     70: {
                     71:         void far thread1();             /* address where thread1 gets control */
                     72:         char far *thread1Stack;         /* far pointer to thread1 stack */
                     73:         unsigned thread1ID;             /* thread ID */
                     74:         unsigned rc;                    /* return code */
                     75: 
                     76:         sem = 0L;                       /* init semaphore */
                     77: 
                     78:         /* allocate stack space for thread 1 */
                     79:         /* since this is written in C, DOSALLOCSEG cannot be used here */
                     80: 
                     81:         if ((thread1Stack = malloc(THREAD_STK_SIZE)) == NULL) {
                     82: 
                     83:                 printf("thread stack malloc failed\n");
                     84:                 DOSEXIT(1, 1);  /* terminate all threads and return error */
                     85:         }
                     86:         thread1Stack += THREAD_STK_SIZE;        /* since stack grows down */
                     87: 
                     88:         /* start another thread */
                     89:         if (rc = DOSCREATETHREAD( thread1, (unsigned far *) &thread1ID,
                     90:                                   thread1Stack ))  {
                     91: 
                     92:                 printf("create of thread failed, error: %d\n", rc);
                     93:                 DOSEXIT(1, 1);
                     94:         }
                     95: 
                     96:         thread0();              /* this will loop forever */
                     97: 
                     98:         DOSEXIT(1, 0);          /* Terminate all threads and exit */
                     99: }
                    100: 
                    101: 
                    102: thread0()       /* Thread 0 */
                    103: {
                    104:     unsigned BytesWrit;
                    105: 
                    106:     for (;;) {
                    107: 
                    108:         /* claim the resource - in this case, the screen */
                    109: 
                    110:         DOSSEMREQUEST( (long) &sem, -1L );      /* no timeout */
                    111: 
                    112:         /* write to the screen */
                    113: 
                    114:         DOSWRITE( 1, (char far *) HELLO0, sizeof(HELLO0) - 1,
                    115:                     (unsigned far *) &BytesWrit );
                    116: 
                    117:         DOSSEMCLEAR( (unsigned long) &sem );    /* release resource */
                    118: 
                    119:         DOSSLEEP(2000L);                        /* give up the processor */
                    120:     }
                    121: }
                    122: 
                    123: void far
                    124: thread1()       /* Thread 1 */
                    125: {
                    126:     unsigned BytesWrit;
                    127: 
                    128:     for (;;) {
                    129: 
                    130:         /* claim the resource - in this case, the screen */
                    131: 
                    132:         DOSSEMREQUEST( (unsigned long) &sem, -1L );     /* no timeout */
                    133: 
                    134:         /* write to the screen */
                    135: 
                    136:         DOSWRITE(1, (char far *)HELLO1, sizeof(HELLO1) - 1,
                    137:                     (unsigned far *) &BytesWrit );
                    138: 
                    139:         DOSSEMCLEAR( (unsigned long) &sem );    /* release resource */
                    140: 
                    141:         DOSSLEEP(2000L);                        /* give up the processor */
                    142:     }
                    143: }

unix.superglobalmegacorp.com

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