Annotation of driverkit/libDriver/User/generalFuncs.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: /*     Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved. 
                     25:  *
                     26:  * libIO.m - IO Library, user version.
                     27:  *
                     28:  * HISTORY
                     29:  * 17-Apr-91    Doug Mitchell at NeXT
                     30:  *      Created.
                     31:  */
                     32: 
                     33: #import <bsd/sys/types.h>
                     34: #import <objc/objc.h>
                     35: #import <driverkit/return.h>
                     36: #import <driverkit/memcpy.h>
                     37: #import <driverkit/generalFuncs.h>
                     38: #import <mach/cthreads.h>
                     39: #import <mach/mach.h>
                     40: #import <bsd/syslog.h>
                     41: #import        <stdarg.h>
                     42: #import <machkit/NXLock.h>
                     43: #import <kernserv/queue.h>
                     44: #import <driverkit/Device_ddm.h>
                     45: #import <kern/time_stamp.h>
                     46: 
                     47: #if    0
                     48: /*
                     49:  * For now...
                     50:  */
                     51: #define xpr_libio(x,a,b,c,d,e) printf(x,a,b,c,d,e)
                     52: #endif 0
                     53: 
                     54: /*
                     55:  * Struct for queueing IOScheduleFunc() requests.
                     56:  */
                     57: typedef struct {
                     58:        IOThreadFunc    fcn;
                     59:        void            *arg;
                     60:        ns_time_t       calloutTime;
                     61:        queue_chain_t   link;
                     62: } ioCallout_t;
                     63: 
                     64: /*
                     65:  * Static variables for this module. 
                     66:  */
                     67: static queue_head_t    calloutChain;           // queue of ioCallout_t's
                     68: static id              calloutLock;            // NXLock
                     69: static port_t          sleepPort;
                     70: 
                     71: /*
                     72:  * Local prototypes.
                     73:  */
                     74: static void calloutThread(void *foo);
                     75: 
                     76: /*
                     77:  * User-level libIO implementation.
                     78:  */
                     79:  
                     80: void *IOMalloc(int size)
                     81: {
                     82:        return(malloc(size));
                     83: }
                     84: 
                     85: void IOFree(void *p, int size)
                     86: {
                     87:        free(p);
                     88: }
                     89: 
                     90: void IOCopyMemory(void *from, void *to, unsigned int numBytes, 
                     91:        unsigned int bytesPerTransfer)
                     92: {
                     93:        _IOCopyMemory(from, to, numBytes, bytesPerTransfer);    
                     94: }
                     95: 
                     96: /*
                     97:  * Note in user space:
                     98:  *      IOThread == cthread_t 
                     99:  *      IOThreadFunc = cthread_fn_t
                    100:  * for now.
                    101:  */
                    102: IOThread IOForkThread(IOThreadFunc fcn, void *arg)
                    103: {
                    104:        return((IOThread)cthread_fork((cthread_fn_t)fcn, (any_t *)arg));
                    105: }
                    106: 
                    107: void IOSuspendThread(IOThread thread)
                    108: {
                    109:        cthread_t cth = (cthread_t)thread;
                    110:        
                    111:        /*
                    112:         * Note no cthread_suspend...what a kludge.
                    113:         */
                    114:        thread_suspend(cthread_thread(cth));
                    115: }
                    116: 
                    117: void IOResumeThread(IOThread thread)
                    118: {
                    119:        cthread_t cth = (cthread_t)thread;
                    120: 
                    121:        thread_resume(cthread_thread(cth));
                    122: }
                    123: 
                    124: /*
                    125:  * 30-Jul-91 - removed IOThreadAbort(); there's no way for this to work 
                    126:  *            cleanly (dmitch)
                    127:  */
                    128: #ifdef notdef
                    129: void IOThreadAbort(IOThread thread)
                    130: {
                    131:        cthread_abort(thread);
                    132: }
                    133: #endif notdef
                    134: 
                    135: volatile void IOExitThread()
                    136: {
                    137:        (volatile void)cthread_exit((any_t)-1);
                    138: }
                    139: 
                    140: /*
                    141:  * Sleep for indicated number of milliseconds.
                    142:  *
                    143:  * Current implementation is like libc's msleep, which uses 
                    144:  * the millisecond-resolution timeout on a msg_receive() on a local
                    145:  * port (to which no messages will ever be sent). Unlike the libc version,
                    146:  * this will return if the current thread is interrupted before the desired
                    147:  * delay expires.
                    148:  */
                    149: void IOSleep(unsigned milliseconds)
                    150: {
                    151:        msg_header_t null_msg;
                    152:        
                    153:        null_msg.msg_local_port = sleepPort;
                    154:        null_msg.msg_size = sizeof(null_msg);
                    155:        msg_receive(&null_msg, RCV_TIMEOUT|RCV_INTERRUPT, milliseconds);
                    156: }
                    157: 
                    158: /*
                    159:  * Spin for indicated number of microseconds.
                    160:  */
                    161: void IODelay(unsigned microseconds)
                    162: {
                    163:        ns_time_t currentTime;
                    164:        ns_time_t endTime;
                    165:        unsigned diff;
                    166:        
                    167:        IOGetTimestamp(&endTime);
                    168:        endTime += ((ns_time_t)microseconds * 1000);
                    169:        while(1) {
                    170:                IOGetTimestamp(&currentTime);
                    171:                diff = (unsigned)(endTime - currentTime);
                    172:                if((int)(diff) < 0) {
                    173:                        return;
                    174:                }
                    175:        }
                    176: }
                    177: 
                    178: /*
                    179:  * Call function fcn with argument arg in specified number of seconds.
                    180:  */
                    181: void IOScheduleFunc(IOThreadFunc fcn, void *arg, int seconds)
                    182: {
                    183:        ioCallout_t *callout;
                    184:        ns_time_t ns = 0;
                    185:        
                    186:        /* 
                    187:         * Enqueue this request. The calloutThread will eventually process
                    188:         * it.
                    189:         */
                    190:        if(seconds == 0) {
                    191:                (*fcn)(arg);
                    192:                return;
                    193:        }
                    194:        callout = IOMalloc(sizeof(*callout));
                    195:        callout->fcn = fcn;
                    196:        callout->arg = arg;
                    197:        [calloutLock lock];
                    198:        IOGetTimestamp(&callout->calloutTime);
                    199:        ns = seconds;
                    200:        ns *= (1000 * 1000 * 1000);
                    201:        callout->calloutTime += ns;
                    202:        xpr_libio("IOScheduleFunc(%d): making request\n", 
                    203:                seconds, 2,3,4,5);
                    204:        queue_enter(&calloutChain,
                    205:                callout,
                    206:                ioCallout_t *,
                    207:                link);
                    208:        [calloutLock unlock];
                    209:        return;
                    210: }
                    211: 
                    212: /*
                    213:  * This thread's job is to wake up once a second, scan the calloutChain, and
                    214:  * do callouts for each entry whose time has come. This is pretty inefficient
                    215:  * (yet another thread waiting around, running every second...). Maybe we can
                    216:  * do better in the future.
                    217:  *
                    218:  * FIXME - this doesn't work. The libc long long support seems to be broken...
                    219:  */
                    220: static void calloutThread(void *foo)
                    221: {
                    222:        ioCallout_t *callout, *calloutNext;
                    223:        ns_time_t currentTime;
                    224: 
                    225:        while(1) {
                    226:                [calloutLock lock];
                    227:                callout = (ioCallout_t *)queue_first(&calloutChain);    
                    228:                while(!queue_end(&calloutChain, (queue_t)callout)) {
                    229:                        calloutNext = (ioCallout_t *)callout->link.next;
                    230:                        IOGetTimestamp(&currentTime);
                    231:                        xpr_libio("calloutThread: currentTime %u:%u\n",
                    232:                                (unsigned)(currentTime / 0x100000000ULL),
                    233:                                (unsigned)(currentTime && 0xffffffff), 3,4,5);
                    234:                        if(currentTime >= callout->calloutTime) {
                    235:                                xpr_libio("calloutThread: doing callout\n",
                    236:                                        1,2,3,4,5);
                    237:                                queue_remove(&calloutChain,
                    238:                                        callout,
                    239:                                        ioCallout_t *,
                    240:                                        link);
                    241:                                [calloutLock unlock];
                    242:                                (*callout->fcn)(callout->arg);
                    243:                                IOFree(callout, sizeof(*callout));
                    244:                                [calloutLock lock];
                    245:                        }
                    246:                        callout = calloutNext;
                    247:                }
                    248:                [calloutLock unlock];
                    249:                IOSleep(1000);
                    250:        }
                    251:        /* NOT REACHED */
                    252: }
                    253: 
                    254: 
                    255: /*
                    256:  * Cancel callout requested in IOScheduleFunc().
                    257:  */
                    258: void IOUnscheduleFunc(IOThreadFunc fcn, void *arg)
                    259: {
                    260:        ioCallout_t *callout;
                    261:        
                    262:        [calloutLock lock];
                    263:        callout = (ioCallout_t *)queue_first(&calloutChain);    
                    264:        while(!queue_end(&calloutChain, (queue_t)callout)) {
                    265:                if((callout->fcn == fcn) && (callout->arg == arg)) {
                    266:                        queue_remove(&calloutChain,
                    267:                                callout,
                    268:                                ioCallout_t *,
                    269:                                link);
                    270:                        IOFree(callout, sizeof(*callout));
                    271:                        goto done;
                    272:                }
                    273:                callout = (ioCallout_t *)callout->link.next;
                    274:        }
                    275:        xpr_libio("IOUnTimeout: callout not registered\n", 1,2,3,4,5);
                    276: done:
                    277:        [calloutLock unlock];
                    278:        return;
                    279: }
                    280: 
                    281: /*
                    282:  * Obtain current time in nanoseconds.
                    283:  */
                    284: 
                    285: static inline ns_time_t
                    286: tsval_to_ns_time(struct tsval *tsp)
                    287: {
                    288:        ns_time_t       a_time;
                    289:        
                    290:        a_time = ((ns_time_t)tsp->high_val) << 32;
                    291:        a_time += tsp->low_val;
                    292:        a_time *= 1000;
                    293:        
                    294:        return a_time;
                    295: }
                    296: 
                    297: 
                    298: void IOGetTimestamp(ns_time_t *nsp)
                    299: {
                    300:        struct tsval ts;
                    301:        ns_time_t ns;
                    302:        
                    303:        kern_timestamp(&ts);
                    304: #if    0
                    305:        ns = tsval_to_ns_time(&ts);
                    306: #else  0
                    307:        ns = ((ns_time_t)ts.high_val) * 0x100000000ULL;
                    308:        ns += ts.low_val;
                    309:        ns *= 1000;
                    310: #endif 0
                    311:        *nsp = ns;
                    312: }
                    313: 
                    314: void IOLog(const char *format, ...)
                    315: {
                    316:         va_list ap;
                    317:         char buf[300];
                    318:         
                    319:         va_start(ap, format);
                    320:         vsprintf(buf, format, ap);
                    321:         syslog(LOG_ERR, "%s", buf);
                    322:         va_end(ap);
                    323: }
                    324: 
                    325: void IOPanic(const char *reason)
                    326: {
                    327:        IOLog(reason);
                    328:        IOLog("waiting for debugger connection...");
                    329:        /* FIXME */
                    330:        while(1)
                    331:                ;
                    332: }
                    333: 
                    334: /*
                    335:  * Convert a integer constant (typically a #define or enum) to a string.
                    336:  */
                    337: static char noValue[80];
                    338: 
                    339: const char *IOFindNameForValue(int value, const IONamedValue *regValueArray)
                    340: {
                    341:        for( ; regValueArray->name; regValueArray++) {
                    342:                if(regValueArray->value == value)
                    343:                        return(regValueArray->name);
                    344:        }
                    345:        sprintf(noValue, "%d(d) (UNDEFINED)", value);
                    346:        return((const char *)noValue);
                    347: }
                    348: 
                    349: IOReturn IOFindValueForName(const char *string, 
                    350:        const IONamedValue *regValueArray,
                    351:        int *value)
                    352: {
                    353:        for( ; regValueArray->name; regValueArray++) {
                    354:                if(!strcmp(regValueArray->name, string)) {
                    355:                        *value = regValueArray->value;
                    356:                        return IO_R_SUCCESS;
                    357:                }
                    358:        }
                    359:        return IO_R_INVALID_ARG;
                    360: }
                    361: 
                    362: /*
                    363:  * One-time only init for this module.
                    364:  */
                    365: void IOInitGeneralFuncs()
                    366: {      
                    367:        queue_init(&calloutChain);
                    368:        calloutLock = [NXLock new];
                    369:        if(port_allocate(task_self(), &sleepPort) != KERN_SUCCESS) {
                    370:                IOLog("IOInitGeneralFunc: port_allocate error\n");
                    371:        }
                    372:        IOForkThread((IOThreadFunc)&calloutThread, NULL);
                    373: }
                    374: 

unix.superglobalmegacorp.com

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