Annotation of driverkit/Examples/ioThread/ioThread.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: /*
                     25:  * ioThread.m - I/O thread example. 
                     26:  *
                     27:  * This example consists of a simple driver class with one I/O thread. 
                     28:  * Exported methods are invoked interactively via stdin. These methods 
                     29:  * pass commands to the I/O thread, which performs various trivial tasks
                     30:  * and then notifies the exported methods of command complete.
                     31:  */
                     32: 
                     33: #include "ioThread.h"
                     34: #include "ioThreadPrivate.h"
                     35:  
                     36: static void MyDeviceThread(id deviceId);
                     37: 
                     38: /*
                     39:  * A regular old Unix-y program to exercise the MyDevice class.
                     40:  */
                     41: int main(int argc, char **argv)
                     42: {
                     43:        id devId;
                     44:        char in_string[40];
                     45:        int aNumber;
                     46:        
                     47:        /*
                     48:         * Create and initialize one instance of MyDevice. Forget devPort
                     49:         * for this example.
                     50:         */
                     51:        devId = [MyDevice alloc];
                     52:        [devId myDeviceInit];
                     53:        
                     54:        /*
                     55:         * Main I/O loop. We'll invoke the exported methods on myDevice 
                     56:         * per user input.
                     57:         */
                     58:         
                     59:        while(1) {
                     60:                printf("Main Loop:\n");
                     61:                printf("  p  print number\n");
                     62:                printf("  g  get number\n");
                     63:                printf("  q  quit program\n\n");
                     64:                printf("Enter Selection: ");
                     65:                gets(in_string);
                     66:                switch(in_string[0]) {
                     67:                   case 'p':
                     68:                        /*
                     69:                         * Get a number, pass it throught to MyDevice's
                     70:                         * I/O thread for display.
                     71:                         */
                     72:                        printf("\nEnter number to pass to I/O thread: ");
                     73:                        gets(in_string);
                     74:                        aNumber = atoi(in_string);
                     75:                        [devId printNumber:aNumber];
                     76:                        break;
                     77:                        
                     78:                   case 'g':
                     79:                        /*
                     80:                         * Get a number via MyDevice's I/O thread.
                     81:                         */
                     82:                        aNumber = [devId getNumber];
                     83:                        printf("getNumber returned %d\n", aNumber);
                     84:                        break;
                     85:                                                
                     86:                   case 'q':
                     87:                        /*
                     88:                         * Shut down.
                     89:                         */
                     90:                        [devId free];
                     91:                        exit(0);
                     92:                        
                     93:                   default:
                     94:                        printf("**Illegal Selection\n");
                     95:                        break;
                     96:                }
                     97:        }
                     98:        
                     99:        /* NOT REACHED */
                    100: }
                    101: 
                    102: /*
                    103:  * Implementation of simple device.
                    104:  */
                    105: @implementation MyDevice
                    106: 
                    107: /*
                    108:  * Initialization.
                    109:  */
                    110: - myDeviceInit
                    111: {
                    112:        /*
                    113:         * Initialize instance variables.
                    114:         */
                    115:        ioQueueLock = [NXConditionLock new];
                    116:        queue_init(&ioQueue);
                    117:        
                    118:        /*
                    119:         * Start up the I/O thread.
                    120:         */
                    121:        ioThread = IOForkThread((IOThreadFunc)MyDeviceThread, self);
                    122: 
                    123:        /*
                    124:         * Register with IODevice-level code.
                    125:         */
                    126:        [self setName:"myDevice"];
                    127:        [super init];
                    128:        [self registerDevice];
                    129:        return self;
                    130: }
                    131: 
                    132: /*
                    133:  * Run-time methods.
                    134:  */
                    135:  
                    136: /*
                    137:  * Have I/O thread get a number from user.
                    138:  */
                    139: - (int)getNumber
                    140: {
                    141:        cmdBuf_t *cmdBuf;
                    142:        int result;
                    143:        
                    144:        /*
                    145:         * Set up a cmdBuf.
                    146:         */
                    147:        cmdBuf = [self cmdBufAlloc];
                    148:        cmdBuf->cmd = IOC_GETNUM;
                    149:        
                    150:        /*
                    151:         * Pass the cmdBuf to the I/O thread. On return, the desired
                    152:         * number is in cmdBuf.aNumber.
                    153:         */
                    154:        [self cmdBufExec:cmdBuf];
                    155:        result = cmdBuf->aNumber;
                    156:        [self cmdBufFree:cmdBuf];
                    157:        return result;
                    158: }
                    159: 
                    160: /*
                    161:  * Have I/O thread print a number.
                    162:  */
                    163: - (void)printNumber : (int)aNumber
                    164: {
                    165:        cmdBuf_t *cmdBuf;
                    166:        
                    167:        /*
                    168:         * Set up a cmdBuf.
                    169:         */
                    170:        cmdBuf = [self cmdBufAlloc];
                    171:        cmdBuf->cmd = IOC_PRINTNUM;
                    172:        cmdBuf->aNumber = aNumber;
                    173:        
                    174:        /*
                    175:         * Pass the cmdBuf to the I/O thread.
                    176:         */
                    177:        [self cmdBufExec:cmdBuf];
                    178:        [self cmdBufFree:cmdBuf];
                    179:        return;
                    180: }
                    181: 
                    182: /*
                    183:  * Have I/O thread shut down cleanly.
                    184:  */
                    185: - free
                    186: {
                    187:        cmdBuf_t *cmdBuf;
                    188:        
                    189:        /*
                    190:         * Set up a cmdBuf.
                    191:         */
                    192:        cmdBuf = [self cmdBufAlloc];
                    193:        cmdBuf->cmd = IOC_QUIT;
                    194:        
                    195:        /*
                    196:         * Pass the cmdBuf to the I/O thread.
                    197:         */
                    198:        [self cmdBufExec:cmdBuf];
                    199:        [self cmdBufFree:cmdBuf];
                    200: 
                    201:        /*
                    202:         * Free instance variables.
                    203:         */     
                    204:        [ioQueueLock free];
                    205:        
                    206:        /*
                    207:         * Have superclass take care of the rest.
                    208:         */
                    209:        return [super free];
                    210: }
                    211: 
                    212: 
                    213: /*
                    214:  * Methods invoked by ioThread.
                    215:  */
                    216:  
                    217: /*
                    218:  * Wait for a work to appear in ioQueue.
                    219:  */
                    220: - (cmdBuf_t *)waitForCmdBuf
                    221: {
                    222:        cmdBuf_t *cmdBuf;
                    223:        
                    224:        [ioQueueLock lockWhen:QUEUE_FULL];
                    225: 
                    226:        /*
                    227:         * At this point, we still hold ioQueueLock'. Remove 
                    228:         * the first element in ioQueue.
                    229:         */
                    230:        cmdBuf = (cmdBuf_t *)queue_first(&ioQueue);
                    231:        queue_remove(&ioQueue,
                    232:                cmdBuf,
                    233:                cmdBuf_t *,
                    234:                link);
                    235:                
                    236:        /*
                    237:         * Release ioQueueLock, updating its condition variable as 
                    238:         * appropriate, and return the new cmdBuf to the ioThread.
                    239:         */
                    240:        if(queue_empty(&ioQueue))
                    241:                [ioQueueLock unlockWith:QUEUE_EMPTY];
                    242:        else
                    243:                [ioQueueLock unlockWith:QUEUE_FULL];
                    244:        return cmdBuf;
                    245: }
                    246: 
                    247: /*
                    248:  * Notify client of I/O complete.
                    249:  */
                    250: - (void)cmdBufComplete : (cmdBuf_t *)cmdBuf
                    251: {
                    252:        [cmdBuf->cmdLock lock];
                    253:        [cmdBuf->cmdLock unlockWith:CMD_COMPLETE];
                    254: }
                    255: 
                    256: @end
                    257: 
                    258: 
                    259: 
                    260: /*
                    261:  * Private methods.
                    262:  */
                    263:  
                    264: @implementation MyDevice ( MyDevicePrivate )
                    265: 
                    266: /*
                    267:  * Create and initialize a new cmdBuf_t.
                    268:  */
                    269: - (cmdBuf_t *)cmdBufAlloc
                    270: {
                    271:        cmdBuf_t *cmdBuf;
                    272:        
                    273:        cmdBuf = IOMalloc(sizeof(cmdBuf_t));
                    274:        cmdBuf->cmdLock = [NXConditionLock new];
                    275:        [cmdBuf->cmdLock lock];
                    276:        [cmdBuf->cmdLock unlockWith:CMD_BUSY];
                    277:        return cmdBuf;
                    278: }
                    279: 
                    280: /*
                    281:  * Free a cmdBuf_t.
                    282:  */
                    283: - (void)cmdBufFree : (cmdBuf_t *)cmdBuf
                    284: {
                    285:        [cmdBuf->cmdLock free];
                    286:        IOFree(cmdBuf, sizeof(cmdBuf_t));
                    287: }
                    288: 
                    289: /*
                    290:  * Pass a cmdBuf to the I/O thread and wait for completion.
                    291:  */
                    292: - (void)cmdBufExec : (cmdBuf_t *)cmdBuf
                    293: {
                    294:        /*
                    295:         * Add the cmdBuf to the ioQueue and let the ioThread know it has 
                    296:         * work to do.
                    297:         */
                    298:        [ioQueueLock lock];
                    299:        queue_enter(&ioQueue,
                    300:                cmdBuf,
                    301:                cmdBuf_t *,
                    302:                link);
                    303:        [ioQueueLock unlockWith:QUEUE_FULL];
                    304:        
                    305:        /*
                    306:         * Wait for I/O complete.
                    307:         */
                    308:        [cmdBuf->cmdLock lockWhen:CMD_COMPLETE];
                    309:        [cmdBuf->cmdLock unlock];
                    310:        
                    311:        return;
                    312: }
                    313: 
                    314: @end
                    315: 
                    316: 
                    317: /*
                    318:  * The I/O thread. This thread sits around waiting for work to do on
                    319:  * the ioQueue, then behaves accordingly.
                    320:  */
                    321: static void MyDeviceThread(id deviceId)
                    322: {
                    323:        cmdBuf_t *cmdBuf;
                    324:        char in_string[40];
                    325:        
                    326:        while(1) {
                    327:                
                    328:                /*
                    329:                 * Wait for something to do.
                    330:                 */
                    331:                cmdBuf = [deviceId waitForCmdBuf];
                    332:                
                    333:                /*
                    334:                 * OK, What's up?
                    335:                 */
                    336:                switch(cmdBuf->cmd) {
                    337:                    case IOC_GETNUM:
                    338:                        /*
                    339:                         * Get a number from user, pass back to client.
                    340:                         */
                    341:                        printf("MyDeviceThread: Enter number: ");
                    342:                        gets(in_string);
                    343:                        cmdBuf->aNumber = atoi(in_string);
                    344:                        break;
                    345:                        
                    346:                    case IOC_PRINTNUM:
                    347:                        /*
                    348:                         * Just display client's number.
                    349:                         */
                    350:                        printf("MyDeviceThread: cmdBuf->aNumber = %d\n",
                    351:                                cmdBuf->aNumber);
                    352:                        break;
                    353:                        
                    354:                    case IOC_QUIT:
                    355:                        /*
                    356:                         * Time to die. First notify client that we got 
                    357:                         * the command, then terminate.
                    358:                         */
                    359:                        [deviceId cmdBufComplete:cmdBuf];
                    360:                        IOExitThread();
                    361:                         
                    362:                }
                    363:                
                    364:                /*
                    365:                 * Notify client of I/O complete.
                    366:                 */
                    367:                [deviceId cmdBufComplete:cmdBuf];
                    368:        }
                    369:        
                    370:        /* NOT REACHED */
                    371: }

unix.superglobalmegacorp.com

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