Annotation of driverkit/libDriver/User/generalFuncs.m, revision 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.