Annotation of OSKit-Mach/kern/eventcount.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
        !             4:  * Copyright (c) 1993,1994 The University of Utah and
        !             5:  * the Computer Systems Laboratory (CSL).
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Permission to use, copy, modify and distribute this software and its
        !             9:  * documentation is hereby granted, provided that both the copyright
        !            10:  * notice and this permission notice appear in all copies of the
        !            11:  * software, derivative works or modified versions, and any portions
        !            12:  * thereof, and that both notices appear in supporting documentation.
        !            13:  *
        !            14:  * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
        !            15:  * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
        !            16:  * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
        !            17:  * THIS SOFTWARE.
        !            18:  *
        !            19:  * Carnegie Mellon requests users of this software to return to
        !            20:  *
        !            21:  *  Software Distribution Coordinator  or  [email protected]
        !            22:  *  School of Computer Science
        !            23:  *  Carnegie Mellon University
        !            24:  *  Pittsburgh PA 15213-3890
        !            25:  *
        !            26:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            27:  * the rights to redistribute these changes.
        !            28:  */
        !            29: /*
        !            30:  *     File:   eventcount.c
        !            31:  *     Author: Alessandro Forin
        !            32:  *     Date:   10/91
        !            33:  *
        !            34:  *     Eventcounters, for user-level drivers synchronization
        !            35:  *
        !            36:  */
        !            37: 
        !            38: 
        !            39: #include <cpus.h>
        !            40: 
        !            41: #include <mach/machine.h>
        !            42: #include <kern/ast.h>
        !            43: #include "cpu_number.h"
        !            44: #include <kern/lock.h>
        !            45: #include <kern/processor.h>
        !            46: #include <kern/queue.h>
        !            47: #include <kern/sched.h>
        !            48: #include <kern/sched_prim.h>
        !            49: #include <kern/thread.h>
        !            50: 
        !            51: #include <machine/machspl.h>   /* For def'n of splsched() */
        !            52: 
        !            53: #include <kern/eventcount.h>
        !            54: 
        !            55: 
        !            56: #if  NCPUS <= 1
        !            57: void simpler_thread_setrun(
        !            58:        thread_t        th,
        !            59:        boolean_t       may_preempt); /* forward */
        !            60: #endif
        !            61: 
        !            62: #define        MAX_EVCS        10              /* xxx for now */
        !            63: evc_t  all_eventcounters[MAX_EVCS];
        !            64: 
        !            65: /*
        !            66:  * Initialization
        !            67:  */
        !            68: void
        !            69: evc_init(evc_t ev)
        !            70: {
        !            71:        int i;
        !            72: 
        !            73:        bzero((char*)ev, sizeof(*ev));
        !            74: 
        !            75:        /* keep track of who is who */
        !            76:        for (i = 0; i < MAX_EVCS; i++)
        !            77:                if (all_eventcounters[i] == 0) break;
        !            78:        if (i == MAX_EVCS) {
        !            79:                printf("Too many eventcounters\n");
        !            80:                return;
        !            81:        }
        !            82: 
        !            83:        all_eventcounters[i] = ev;
        !            84:        ev->ev_id = i;
        !            85:        ev->sanity = ev;
        !            86:        ev->waiting_thread = THREAD_NULL;
        !            87:        simple_lock_init(&ev->lock);
        !            88: }
        !            89: 
        !            90: /*
        !            91:  * Finalization
        !            92:  */
        !            93: void
        !            94: evc_destroy(evc_t      ev)
        !            95: {
        !            96:        evc_signal(ev);
        !            97:        ev->sanity = 0;
        !            98:        if (all_eventcounters[ev->ev_id] == ev)
        !            99:                all_eventcounters[ev->ev_id] = 0;
        !           100:        ev->ev_id = -1;
        !           101: }
        !           102: 
        !           103: /*
        !           104:  * Thread termination.
        !           105:  * HORRIBLE. This stuff needs to be fixed.
        !           106:  */
        !           107: void evc_notify_abort(thread_t thread)
        !           108: {
        !           109:     int i;
        !           110:     evc_t ev;
        !           111:     int s = splsched();
        !           112:     for (i = 0; i < MAX_EVCS; i++)  {
        !           113:        ev = all_eventcounters[i];
        !           114:        if (ev)  {
        !           115:            simple_lock(&ev->lock);
        !           116:            if (ev->waiting_thread == thread)  
        !           117:              {
        !           118:                ev->waiting_thread = 0;
        !           119:                /* Removal of a waiting thread has to bump the count by one */
        !           120:                ev->count++;
        !           121:              }
        !           122:            simple_unlock(&ev->lock);
        !           123:        }
        !           124:     }
        !           125:     splx(s);
        !           126: }
        !           127: 
        !           128: #ifdef CONTINUATIONS
        !           129: /*
        !           130:  * Just so that we return success, and give
        !           131:  * up the stack while blocked
        !           132:  */
        !           133: static void
        !           134: evc_continue(void)
        !           135: {
        !           136:        thread_syscall_return(KERN_SUCCESS);
        !           137:        /* NOTREACHED */
        !           138: }
        !           139: #else /* not CONTINUATIONS */
        !           140: #define evc_continue 0
        !           141: #endif /* not CONTINUATIONS */
        !           142: 
        !           143: /*
        !           144:  * User-trappable
        !           145:  */
        !           146: kern_return_t evc_wait(natural_t ev_id)
        !           147: {
        !           148:        spl_t           s;
        !           149:        kern_return_t   ret;
        !           150:        evc_t           ev;
        !           151: 
        !           152:        if ((ev_id >= MAX_EVCS) ||
        !           153:            ((ev = all_eventcounters[ev_id]) == 0) ||
        !           154:            (ev->ev_id != ev_id) || (ev->sanity != ev))
        !           155:                return KERN_INVALID_ARGUMENT;
        !           156: 
        !           157:        s = splsched();
        !           158:        simple_lock(&ev->lock);
        !           159:                /*
        !           160:                 * The values assumed by the "count" field are
        !           161:                 * as follows:
        !           162:                 *      0       At initialization time, and with no
        !           163:                 *              waiting thread means no events pending;
        !           164:                 *              with waiting thread means the event
        !           165:                 *              was signalled and the thread not yet resumed
        !           166:                 *      -1      no events, there must be a waiting thread
        !           167:                 *      N>0     no waiting thread means N pending,
        !           168:                 *              with waiting thread N-1 pending.
        !           169:                 *      
        !           170:                 */
        !           171:                if (ev->count > 0) {
        !           172:                        ev->count--;
        !           173:                        ret = KERN_SUCCESS;
        !           174:                } else {
        !           175:                        if (ev->waiting_thread == THREAD_NULL) {
        !           176:                                ev->count--;
        !           177:                                ev->waiting_thread = current_thread();
        !           178:                                assert_wait((event_t) 0, TRUE); /* ifnot race */
        !           179:                                simple_unlock(&ev->lock);
        !           180:                                thread_block(evc_continue);
        !           181:                                return KERN_SUCCESS;
        !           182:                        }
        !           183:                        ret = KERN_NO_SPACE; /* XX */
        !           184:                }
        !           185:        simple_unlock(&ev->lock);
        !           186:        splx(s);
        !           187:        return ret;
        !           188: }
        !           189: 
        !           190: /*
        !           191:  * User-trappable
        !           192:  */
        !           193: kern_return_t evc_wait_clear(natural_t ev_id)
        !           194: {
        !           195:        spl_t           s;
        !           196:        kern_return_t   ret;
        !           197:        evc_t           ev;
        !           198: 
        !           199:        if ((ev_id >= MAX_EVCS) ||
        !           200:            ((ev = all_eventcounters[ev_id]) == 0) ||
        !           201:            (ev->ev_id != ev_id) || (ev->sanity != ev))
        !           202:                return KERN_INVALID_ARGUMENT;
        !           203: 
        !           204:        s = splsched();
        !           205:        simple_lock(&ev->lock);
        !           206: 
        !           207:                /*
        !           208:                 * The values assumed by the "count" field are
        !           209:                 * as follows:
        !           210:                 *      0       At initialization time, and with no
        !           211:                 *              waiting thread means no events pending;
        !           212:                 *              with waiting thread means the event
        !           213:                 *              was signalled and the thread not yet resumed
        !           214:                 *      -1      no events, there must be a waiting thread
        !           215:                 *      N>0     no waiting thread means N pending,
        !           216:                 *              with waiting thread N-1 pending.
        !           217:                 *      
        !           218:                 */
        !           219:                /*
        !           220:                 *  Note that we always clear count before blocking.
        !           221:                 */
        !           222:                if (ev->waiting_thread == THREAD_NULL) {
        !           223:                        ev->count = -1;
        !           224:                        ev->waiting_thread = current_thread();
        !           225:                        assert_wait((event_t) 0, TRUE); /* ifnot race */
        !           226:                        simple_unlock(&ev->lock);
        !           227:                        thread_block(evc_continue);
        !           228:                        /* NOTREACHED */
        !           229:                }
        !           230: 
        !           231:        simple_unlock(&ev->lock);
        !           232:        splx(s);
        !           233:        ret = KERN_NO_SPACE; /* XX */
        !           234: }
        !           235: 
        !           236: /*
        !           237:  * Called exclusively from interrupt context
        !           238:  */
        !           239: void
        !           240: evc_signal(evc_t ev)
        !           241: {
        !           242:     register volatile thread_t thread;
        !           243:     register int state;
        !           244:     spl_t    s;
        !           245:     if (ev->sanity != ev)
        !           246:       return;
        !           247: 
        !           248:     s = splsched();
        !           249:     simple_lock(&ev->lock);
        !           250:     ev->count++;
        !           251:     if (thread = ev->waiting_thread, thread != THREAD_NULL)
        !           252:     {
        !           253:        ev->waiting_thread = 0;
        !           254: 
        !           255: #if (NCPUS > 1)
        !           256:       retry:
        !           257:        while((thread->state & TH_RUN) || thread->lock.lock_data)
        !           258:                ;
        !           259: #endif
        !           260:        thread_lock(thread);
        !           261: 
        !           262:        /* make thread runnable on this processor */
        !           263:        /* taken from clear_wait */
        !           264:        switch ((state = thread->state) & TH_SCHED_STATE)
        !           265:        {
        !           266:            case  TH_WAIT | TH_SUSP | TH_UNINT:
        !           267:            case  TH_WAIT           | TH_UNINT:
        !           268:            case  TH_WAIT:
        !           269:                /*
        !           270:                 *      Sleeping and not suspendable - put
        !           271:                 *      on run queue.
        !           272:                 */
        !           273:                thread->state = (state &~ TH_WAIT) | TH_RUN;
        !           274:                thread_unlock(thread);
        !           275: #if NCPUS > 1
        !           276:                thread_setrun(thread, TRUE);
        !           277: #else
        !           278:                simpler_thread_setrun(thread, TRUE);
        !           279: #endif
        !           280:                break;
        !           281: 
        !           282:            case TH_RUN | TH_WAIT:
        !           283: #if (NCPUS > 1)
        !           284:                /*
        !           285:                 * Legal on MP: between assert_wait()
        !           286:                 * and thread_block(), in evc_wait() above.
        !           287:                 *
        !           288:                 * Mmm. Maybe don't need now that the while(..) check is
        !           289:                 * done before the thread lock is grabbed.....
        !           290:                 */
        !           291:                thread_unlock(thread);
        !           292:                goto retry;
        !           293: #else
        !           294:                /*FALLTHROUGH*/
        !           295: #endif
        !           296:            case          TH_WAIT | TH_SUSP:
        !           297:            case TH_RUN | TH_WAIT | TH_SUSP:
        !           298:            case TH_RUN | TH_WAIT           | TH_UNINT:
        !           299:            case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
        !           300: 
        !           301:                /*
        !           302:                 *      Either already running, or suspended.
        !           303:                 *      Just clear the wait.
        !           304:                 */
        !           305:                thread->state = state &~ TH_WAIT;
        !           306:                thread_unlock(thread);
        !           307:                break;
        !           308: 
        !           309:            default:
        !           310:                /*
        !           311:                 *      Not waiting.
        !           312:                 */
        !           313:                panic("evc_signal.3");
        !           314:                thread_unlock(thread);
        !           315:                break;
        !           316:        }
        !           317:     }
        !           318: 
        !           319:     simple_unlock(&ev->lock);
        !           320:     splx(s);
        !           321: }
        !           322: 
        !           323: #if    NCPUS <= 1
        !           324: /*
        !           325:  * The scheduler is too messy for my old little brain
        !           326:  */
        !           327: void
        !           328: simpler_thread_setrun(
        !           329:        thread_t        th,
        !           330:        boolean_t       may_preempt)
        !           331: {
        !           332:        register struct run_queue       *rq;
        !           333:        register                        whichq;
        !           334: 
        !           335:        /*
        !           336:         *      XXX should replace queue with a boolean in this case.
        !           337:         */
        !           338:        if (default_pset.idle_count > 0) {
        !           339:                processor_t     processor;
        !           340: 
        !           341:                processor = (processor_t) queue_first(&default_pset.idle_queue);
        !           342:                queue_remove(&default_pset.idle_queue, processor,
        !           343:                processor_t, processor_queue);
        !           344:                default_pset.idle_count--;
        !           345:                processor->next_thread = th;
        !           346:                processor->state = PROCESSOR_DISPATCHING;
        !           347:                return;
        !           348:        }
        !           349:        rq = &(master_processor->runq);
        !           350:        ast_on(cpu_number(), AST_BLOCK);
        !           351: 
        !           352:        whichq = (th)->sched_pri;
        !           353:        simple_lock(&(rq)->lock);       /* lock the run queue */
        !           354:        enqueue_head(&(rq)->runq[whichq], (queue_entry_t) (th));
        !           355: 
        !           356:        if (whichq < (rq)->low || (rq)->count == 0)
        !           357:                 (rq)->low = whichq;    /* minimize */
        !           358:        (rq)->count++;
        !           359: #ifdef MIGRATING_THREADS
        !           360:        (th)->shuttle.runq = (rq);
        !           361: #else
        !           362:        (th)->runq = (rq);
        !           363: #endif
        !           364:        simple_unlock(&(rq)->lock);
        !           365: 
        !           366:        /*
        !           367:         *      Turn off first_quantum to allow context switch.
        !           368:         */
        !           369:        current_processor()->first_quantum = FALSE;
        !           370: }
        !           371: #endif /* NCPUS > 1 */
        !           372: 

unix.superglobalmegacorp.com

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