Annotation of tme/machine/sun4/sun4-timer.c, revision 1.1

1.1     ! root        1: /* $Id: sun4-timer.c,v 1.2 2006/11/16 02:42:16 fredette Exp $ */
        !             2: 
        !             3: /* machine/sun4/sun4-timer.c - implementation of Sun 4 timer emulation: */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2006 Matt Fredette
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *      This product includes software developed by Matt Fredette.
        !            20:  * 4. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            33:  * POSSIBILITY OF SUCH DAMAGE.
        !            34:  */
        !            35: 
        !            36: #include <tme/common.h>
        !            37: _TME_RCSID("$Id: sun4-timer.c,v 1.2 2006/11/16 02:42:16 fredette Exp $");
        !            38: 
        !            39: /* includes: */
        !            40: #include <tme/generic/bus-device.h>
        !            41: #include "sun4-impl.h"
        !            42: 
        !            43: /* macros: */
        !            44: 
        !            45: /* real sun4/4c timer bits: */
        !            46: #define TME_SUN4_32_TIMER_LIMIT                TME_BIT(31)
        !            47: #define        TME_SUN44C_TIMER_MASK           (0x7ffffc00)
        !            48: #define        TME_SUN4M_TIMER_MASK            (0x7ffffe00)
        !            49: 
        !            50: /* define this to track interrupt rates, reporting once every N
        !            51:    seconds: */
        !            52: #if 1
        !            53: #define TME_SUN4_TIMER_TRACK_INT_RATE          (10)
        !            54: #endif
        !            55: 
        !            56: /* this makes timer callouts.  it must be called with the mutex held: */
        !            57: static void
        !            58: _tme_sun4_timer_callout(struct tme_sun4 *sun4)
        !            59: {
        !            60:   struct tme_bus_connection *conn_bus;
        !            61:   struct tme_sun4_timer *timer;
        !            62:   unsigned int int_asserted;
        !            63:   int again;
        !            64:   int rc;
        !            65: 
        !            66:   /* if this function is already running in another thread, return
        !            67:      now.  the other thread will do our work: */
        !            68:   if (sun4->tme_sun4_timer_callouts_running) {
        !            69:     return;
        !            70:   }
        !            71: 
        !            72:   /* callouts are now running: */
        !            73:   sun4->tme_sun4_timer_callouts_running = TRUE;
        !            74: 
        !            75:   /* get our bus connection: */
        !            76:   conn_bus = sun4->tme_sun4_buses[TME_SUN4_32_CONN_REG_TIMER];
        !            77: 
        !            78:   /* loop forever: */
        !            79:   for (again = TRUE; again;) {
        !            80:     again = FALSE;
        !            81: 
        !            82:     /* check all of the timers for changes: */
        !            83:     timer = &sun4->tme_sun4_timers[0];
        !            84:     do {
        !            85:       
        !            86:       /* if this timer needs an interrupt callout: */
        !            87:       int_asserted = (timer->tme_sun4_timer_counter & TME_SUN4_32_TIMER_LIMIT) != 0;
        !            88:       if (!int_asserted
        !            89:          != !timer->tme_sun4_timer_int_asserted) {
        !            90: 
        !            91:        /* unlock our mutex: */
        !            92:        tme_mutex_unlock(&sun4->tme_sun4_mutex);
        !            93: 
        !            94:        /* call out the bus interrupt signal edge: */
        !            95:        rc = (*conn_bus->tme_bus_signal)
        !            96:          (conn_bus,
        !            97:           ((timer == &sun4->tme_sun4_timers[0]
        !            98:             ? TME_BUS_SIGNAL_INT(10)
        !            99:             : TME_BUS_SIGNAL_INT(14))
        !           100:            | (int_asserted
        !           101:               ? TME_BUS_SIGNAL_LEVEL_ASSERTED
        !           102:               : TME_BUS_SIGNAL_LEVEL_NEGATED)));
        !           103: 
        !           104:        /* lock our mutex: */
        !           105:        tme_mutex_lock(&sun4->tme_sun4_mutex);
        !           106: 
        !           107:        /* if this callout was successful, note the new state of the
        !           108:           interrupt signal: */
        !           109:        if (rc == TME_OK) {
        !           110:          timer->tme_sun4_timer_int_asserted = int_asserted;
        !           111:          again = TRUE;
        !           112:        }
        !           113: 
        !           114:        /* otherwise, abort: */
        !           115:        else {
        !           116:          abort();
        !           117:        }
        !           118:       }
        !           119:     } while (++timer != (&sun4->tme_sun4_timers[0] + TME_ARRAY_ELS(sun4->tme_sun4_timers)));
        !           120: 
        !           121:   }
        !           122: 
        !           123:   /* there are no more callouts to make: */
        !           124:   sun4->tme_sun4_timer_callouts_running = FALSE;
        !           125: }
        !           126: 
        !           127: /* this can be called to force an immediate timer interrupt: */
        !           128: void
        !           129: _tme_sun4_timer_int_force(struct tme_sun4 *sun4,
        !           130:                          struct tme_sun4_timer *timer)
        !           131: {
        !           132: 
        !           133:   /* lock our mutex: */
        !           134:   tme_mutex_lock(&sun4->tme_sun4_mutex);
        !           135: 
        !           136:   /* force an immediate timer interrupt: */
        !           137:   timer->tme_sun4_timer_counter = TME_SUN4_32_TIMER_LIMIT;
        !           138:   timer->tme_sun4_timer_limit |= TME_SUN4_32_TIMER_LIMIT;
        !           139: 
        !           140:   /* call out any interrupts: */
        !           141:   _tme_sun4_timer_callout(sun4);
        !           142: 
        !           143:   /* unlock our mutex: */
        !           144:   tme_mutex_unlock(&sun4->tme_sun4_mutex);
        !           145: }
        !           146: 
        !           147: /* the sun4 timer update function.  it must be called with the mutex
        !           148:    locked: */
        !           149: static void
        !           150: _tme_sun4_timer_update(struct tme_sun4_timer *timer, struct timeval *now, struct timeval *sleep)
        !           151: {
        !           152: 
        !           153:   /* get the current time: */
        !           154:   gettimeofday(now, NULL);
        !           155: 
        !           156: #ifdef TME_SUN4_TIMER_TRACK_INT_RATE
        !           157: 
        !           158:   /* if the sample time has finished: */
        !           159:   if (timer->tme_sun4_timer_track_sample.tv_sec < now->tv_sec
        !           160:       || (timer->tme_sun4_timer_track_sample.tv_sec == now->tv_sec
        !           161:          && timer->tme_sun4_timer_track_sample.tv_usec <= now->tv_usec)) {
        !           162: 
        !           163:     /* if the timer has made any interrupts during the sample time: */
        !           164:     if (timer->tme_sun4_timer_track_ints > 0) {
        !           165: 
        !           166:       /* log the interrupt rate: */
        !           167:       tme_log(TME_SUN4_LOG_HANDLE(timer->tme_sun4_timer_sun4),
        !           168:              0, TME_OK,
        !           169:              (TME_SUN4_LOG_HANDLE(timer->tme_sun4_timer_sun4),
        !           170:               "level %d timer interrupt rate: %ld/sec",
        !           171:               (timer == &timer->tme_sun4_timer_sun4->tme_sun4_timers[0]
        !           172:                ? 10
        !           173:                : 14),
        !           174:               (timer->tme_sun4_timer_track_ints
        !           175:                / (now->tv_sec
        !           176:                   - (timer->tme_sun4_timer_track_sample.tv_sec
        !           177:                      - TME_SUN4_TIMER_TRACK_INT_RATE)))));
        !           178:     }
        !           179: 
        !           180:     /* reset the sampling: */
        !           181:     timer->tme_sun4_timer_track_ints = 0;
        !           182:     timer->tme_sun4_timer_track_sample = *now;
        !           183:     timer->tme_sun4_timer_track_sample.tv_sec += TME_SUN4_TIMER_TRACK_INT_RATE;
        !           184:   }
        !           185: 
        !           186: #endif /* TME_SUN4_TIMER_TRACK_INT_RATE */
        !           187: 
        !           188:   /* if this timer has not reached its next limit: */
        !           189:   if (__tme_predict_false(timer->tme_sun4_timer_limit_next.tv_sec > now->tv_sec
        !           190:                          || (timer->tme_sun4_timer_limit_next.tv_sec == now->tv_sec
        !           191:                              && timer->tme_sun4_timer_limit_next.tv_usec > now->tv_usec))) {
        !           192: 
        !           193:     /* sleep until this timer reaches its next limit: */
        !           194:     sleep->tv_sec = timer->tme_sun4_timer_limit_next.tv_sec - now->tv_sec;
        !           195:     sleep->tv_usec = timer->tme_sun4_timer_limit_next.tv_usec - now->tv_usec;
        !           196:     if (timer->tme_sun4_timer_limit_next.tv_usec < now->tv_usec) {
        !           197:       sleep->tv_sec--;
        !           198:       sleep->tv_usec += 1000000;
        !           199:     }
        !           200:     return;
        !           201:   }
        !           202: 
        !           203:   /* set this timer's next limit time: */
        !           204:   do {
        !           205:     timer->tme_sun4_timer_limit_next.tv_sec += timer->tme_sun4_timer_period.tv_sec;
        !           206:     timer->tme_sun4_timer_limit_next.tv_usec += timer->tme_sun4_timer_period.tv_usec;
        !           207:     if (__tme_predict_false(timer->tme_sun4_timer_limit_next.tv_usec >= 1000000)) {
        !           208:       timer->tme_sun4_timer_limit_next.tv_usec -= 1000000;
        !           209:       timer->tme_sun4_timer_limit_next.tv_sec += 1;
        !           210:     }
        !           211:   } while (timer->tme_sun4_timer_limit_next.tv_sec < now->tv_sec
        !           212:           || (timer->tme_sun4_timer_limit_next.tv_sec == now->tv_sec
        !           213:               && timer->tme_sun4_timer_limit_next.tv_usec <= now->tv_usec));
        !           214: 
        !           215:   /* mark this timer as having reached its limit: */
        !           216: #ifdef TME_SUN4_TIMER_TRACK_INT_RATE
        !           217:   if (!(timer->tme_sun4_timer_counter
        !           218:        & TME_SUN4_32_TIMER_LIMIT)) {
        !           219:     timer->tme_sun4_timer_track_ints++;
        !           220:   }
        !           221: #endif /* TME_SUN4_TIMER_TRACK_INT_RATE */
        !           222:   timer->tme_sun4_timer_counter = TME_SUN4_32_TIMER_LIMIT;
        !           223:   timer->tme_sun4_timer_limit |= TME_SUN4_32_TIMER_LIMIT;
        !           224: 
        !           225:   /* sleep for the normal period: */
        !           226:   *sleep = timer->tme_sun4_timer_period;
        !           227: }
        !           228: 
        !           229: /* this resets a timer: */
        !           230: static void
        !           231: _tme_sun4_timer_reset(struct tme_sun4_timer *timer)
        !           232: {
        !           233:   tme_uint32_t counter_one;
        !           234:   tme_uint32_t ticks;
        !           235:   tme_uint32_t ticks_max;
        !           236:   tme_uint32_t usecs;
        !           237: 
        !           238:   /* to keep things simpler, we always use the sun4m 500ns tick: */
        !           239:   counter_one = TME_SUN4_IS_SUN44C(timer->tme_sun4_timer_sun4) ? 2 : 1;
        !           240:   ticks_max = (TME_SUN4M_TIMER_MASK / _TME_FIELD_MASK_FACTOR(TME_SUN4M_TIMER_MASK)) + 1;
        !           241: 
        !           242:   /* get this timer's period, in 500ns ticks.  NB that we account for
        !           243:      the fact that timers count from [1..limit), and not [0..limit): */
        !           244:   /* XXX FIXME - we assume that the limit value of one gives the
        !           245:      longest possible period.  is this right? */
        !           246:   ticks = TME_FIELD_MASK_EXTRACTU(timer->tme_sun4_timer_limit, TME_SUN4M_TIMER_MASK);
        !           247:   ticks = (ticks - counter_one) & (ticks_max - counter_one);
        !           248:   if (__tme_predict_false(ticks == 0)) {
        !           249:     ticks = ticks_max;
        !           250:   }
        !           251: 
        !           252:   /* convert the timer's period from 500ns ticks to a struct timeval
        !           253:      and save it: */
        !           254:   usecs = ticks / 2;
        !           255:   timer->tme_sun4_timer_period.tv_sec = 0;
        !           256:   if (__tme_predict_false(usecs >= 1000000)) {
        !           257:     timer->tme_sun4_timer_period.tv_sec = usecs / 1000000;
        !           258:     usecs %= 1000000;
        !           259:   }
        !           260:   timer->tme_sun4_timer_period.tv_usec = usecs;
        !           261: 
        !           262:   /* set the next limit time for this timer: */
        !           263:   gettimeofday(&timer->tme_sun4_timer_limit_next, NULL);
        !           264:   timer->tme_sun4_timer_limit_next.tv_sec += timer->tme_sun4_timer_period.tv_sec;
        !           265:   timer->tme_sun4_timer_limit_next.tv_usec += timer->tme_sun4_timer_period.tv_usec;
        !           266:   if (timer->tme_sun4_timer_limit_next.tv_usec >= 1000000) {
        !           267:     timer->tme_sun4_timer_limit_next.tv_usec -= 1000000;
        !           268:     timer->tme_sun4_timer_limit_next.tv_sec += 1;
        !           269:   }
        !           270: }
        !           271: 
        !           272: /* the sun4 timer thread: */
        !           273: static void
        !           274: _tme_sun4_timer_th(struct tme_sun4_timer *timer)
        !           275: {
        !           276:   struct tme_sun4 *sun4;
        !           277:   struct timeval now;
        !           278:   struct timeval sleep;
        !           279: 
        !           280:   /* recover our sun4: */
        !           281:   sun4 = timer->tme_sun4_timer_sun4;
        !           282: 
        !           283:   /* lock our mutex: */
        !           284:   tme_mutex_lock(&sun4->tme_sun4_mutex);
        !           285: 
        !           286:   /* loop forever: */
        !           287:   for (;;) {
        !           288: 
        !           289:     /* update this timer: */
        !           290:     _tme_sun4_timer_update(timer, &now, &sleep);
        !           291: 
        !           292:     /* call out any interrupts: */
        !           293:     _tme_sun4_timer_callout(sun4);
        !           294: 
        !           295:     /* sleep, but wake up if our timer configuration changes: */
        !           296:     tme_cond_sleep_yield(&timer->tme_sun4_timer_cond,
        !           297:                         &sun4->tme_sun4_mutex,
        !           298:                         &sleep);
        !           299:   }
        !           300:   /* NOTREACHED */
        !           301: }
        !           302: 
        !           303: /* the sun4 timer control bus cycle handler: */
        !           304: int
        !           305: _tme_sun4_timer_cycle_control(void *_sun4, struct tme_bus_cycle *cycle_init)
        !           306: {
        !           307:   struct tme_sun4 *sun4;
        !           308:   unsigned int timer_i;
        !           309:   struct tme_sun4_timer *timer;
        !           310:   tme_uint32_t reg;
        !           311:   tme_uint32_t value32;
        !           312:   struct tme_bus_cycle cycle_resp;
        !           313:   struct timeval now;
        !           314:   struct timeval last_reset;
        !           315:   tme_uint32_t counter_one;
        !           316:   tme_uint32_t usecs;
        !           317:   tme_uint32_t ticks;
        !           318: 
        !           319:   /* recover our sun4: */
        !           320:   sun4 = (struct tme_sun4 *) _sun4;
        !           321: 
        !           322:   /* this must be a full 32-bit register access: */
        !           323:   if ((cycle_init->tme_bus_cycle_address % sizeof(tme_uint32_t)) != 0
        !           324:       || cycle_init->tme_bus_cycle_size != sizeof(tme_uint32_t)) {
        !           325:     abort();
        !           326:   }
        !           327: 
        !           328:   /* get the timer and register accessed: */
        !           329:   if (TME_SUN4_IS_SUN44C(sun4)) {
        !           330:     timer_i = cycle_init->tme_bus_cycle_address / TME_SUN44C_TIMER_SIZ_REG;
        !           331:     reg = cycle_init->tme_bus_cycle_address & TME_SUN4_32_TIMER_SIZ_COUNTER;
        !           332:   }
        !           333:   else {
        !           334:     abort();
        !           335:   }
        !           336:   timer = &sun4->tme_sun4_timers[timer_i];
        !           337: 
        !           338:   /* lock our mutex: */
        !           339:   tme_mutex_lock(&sun4->tme_sun4_mutex);
        !           340: 
        !           341:   /* if this is a read: */
        !           342:   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ) {
        !           343: 
        !           344:     /* dispatch on the register: */
        !           345:     switch (reg) {
        !           346:     default: assert(FALSE);
        !           347:     case TME_SUN4_32_TIMER_REG_COUNTER:
        !           348: 
        !           349:       /* update the timers: */
        !           350:       _tme_sun4_timer_update(timer, &now, &last_reset);
        !           351: 
        !           352:       /* get the time of the last reset: */
        !           353:       last_reset = timer->tme_sun4_timer_limit_next;
        !           354:       if (last_reset.tv_usec < timer->tme_sun4_timer_period.tv_usec) {
        !           355:        last_reset.tv_sec -= 1;
        !           356:        last_reset.tv_usec += 1000000;
        !           357:       }
        !           358:       last_reset.tv_sec -= timer->tme_sun4_timer_period.tv_sec;
        !           359:       last_reset.tv_usec -= timer->tme_sun4_timer_period.tv_usec;
        !           360: 
        !           361:       /* get the number of microseconds since the last reset: */
        !           362:       usecs = now.tv_sec - last_reset.tv_sec;
        !           363:       usecs *= 1000000;
        !           364:       usecs
        !           365:        += (((tme_int32_t) now.tv_usec)
        !           366:            - ((tme_int32_t) last_reset.tv_usec));
        !           367: 
        !           368:       /* to keep things simpler, we always use the sun4m 500ns tick: */
        !           369:       counter_one = TME_SUN4_IS_SUN44C(sun4) ? 2 : 1;
        !           370: 
        !           371:       /* convert the number of microseconds until this timer resets again,
        !           372:         to the 500ns tick counter value for the timer.  NB that we
        !           373:         account for the fact that timers count from [1..limit), and not
        !           374:         [0..limit): */
        !           375:       ticks = (usecs * 2) + counter_one;
        !           376:       TME_FIELD_MASK_DEPOSITU(timer->tme_sun4_timer_counter, 
        !           377:                              TME_SUN4M_TIMER_MASK,
        !           378:                              ticks);
        !           379: 
        !           380:       /* read this timer's counter register: */
        !           381:       value32 = timer->tme_sun4_timer_counter;
        !           382:       break;
        !           383: 
        !           384:     case TME_SUN4_32_TIMER_REG_LIMIT:
        !           385: 
        !           386:       /* read this timer's limit register: */
        !           387:       value32 = timer->tme_sun4_timer_limit;   
        !           388: 
        !           389:       /* a read of the limit register is used to acknowledge an
        !           390:         interrupt, which probably means clearing the limit bit on the
        !           391:         counter register: */
        !           392:       timer->tme_sun4_timer_counter = 0;
        !           393:       timer->tme_sun4_timer_limit &= ~TME_SUN4_32_TIMER_LIMIT;
        !           394:       break;
        !           395:     }
        !           396: 
        !           397:     tme_log(TME_SUN4_LOG_HANDLE(sun4), 2000, TME_OK,
        !           398:            (TME_SUN4_LOG_HANDLE(sun4),
        !           399:             _("timer #%d %s -> 0x%08x"),
        !           400:             timer_i,
        !           401:             (reg == TME_SUN4_32_TIMER_REG_COUNTER
        !           402:              ? "counter"
        !           403:              : "limit"),
        !           404:             value32));
        !           405: 
        !           406:     /* byteswap the register value: */
        !           407:     value32 = tme_htobe_u32(value32);
        !           408:   }
        !           409: 
        !           410:   /* run the bus cycle: */
        !           411:   cycle_resp.tme_bus_cycle_buffer = (tme_uint8_t *) &value32;
        !           412:   cycle_resp.tme_bus_cycle_buffer_increment = 1;
        !           413:   cycle_resp.tme_bus_cycle_lane_routing = cycle_init->tme_bus_cycle_lane_routing;
        !           414:   cycle_resp.tme_bus_cycle_address = 0;
        !           415:   cycle_resp.tme_bus_cycle_type = (cycle_init->tme_bus_cycle_type
        !           416:                                   ^ (TME_BUS_CYCLE_WRITE
        !           417:                                      | TME_BUS_CYCLE_READ));
        !           418:   cycle_resp.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2);
        !           419:   tme_bus_cycle_xfer(cycle_init, &cycle_resp);
        !           420: 
        !           421:   /* if this is a write: */
        !           422:   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
        !           423: 
        !           424:     /* byteswap the register value: */
        !           425:     value32 = tme_htobe_u32(value32);
        !           426: 
        !           427:     tme_log(TME_SUN4_LOG_HANDLE(sun4), 2000, TME_OK,
        !           428:            (TME_SUN4_LOG_HANDLE(sun4),
        !           429:             _("timer #%d %s <- 0x%08x"),
        !           430:             timer_i,
        !           431:             (reg == TME_SUN4_32_TIMER_REG_COUNTER
        !           432:              ? "counter"
        !           433:              : "limit"),
        !           434:             value32));
        !           435: 
        !           436:     /* dispatch on the register: */
        !           437:     switch (reg) {
        !           438:     default: assert(FALSE);
        !           439:     case TME_SUN4_32_TIMER_REG_COUNTER:
        !           440:       abort();
        !           441: 
        !           442:     case TME_SUN4_32_TIMER_REG_LIMIT:
        !           443: 
        !           444:       /* write the timer's limit register: */
        !           445:       timer->tme_sun4_timer_limit = value32;
        !           446: 
        !           447:       /* reset this timer: */
        !           448:       _tme_sun4_timer_reset(timer);
        !           449: 
        !           450:       /* wake up the thread for this timer: */
        !           451:       tme_cond_notify(&timer->tme_sun4_timer_cond, FALSE);
        !           452:       break;
        !           453:     }
        !           454:   }
        !           455: 
        !           456:   /* make any callouts: */
        !           457:   _tme_sun4_timer_callout(sun4);
        !           458:     
        !           459:   /* unlock the mutex: */
        !           460:   tme_mutex_unlock(&sun4->tme_sun4_mutex);
        !           461: 
        !           462:   /* no faults: */
        !           463:   return (TME_OK);
        !           464: }
        !           465: 
        !           466: /* this creates the sun4 timers: */
        !           467: void
        !           468: _tme_sun4_timer_new(struct tme_sun4 *sun4)
        !           469: {
        !           470:   struct tme_sun4_timer *timer;
        !           471: 
        !           472:   /* loop over the timers: */
        !           473:   timer = &sun4->tme_sun4_timers[0];
        !           474:   do {
        !           475: 
        !           476:     /* initialize and reset the timer: */
        !           477:     timer->tme_sun4_timer_sun4 = sun4;
        !           478:     tme_cond_init(&timer->tme_sun4_timer_cond);
        !           479:     _tme_sun4_timer_reset(timer);
        !           480: 
        !           481:     /* start the thread for this timer: */
        !           482:     tme_thread_create((tme_thread_t) _tme_sun4_timer_th, timer);
        !           483: 
        !           484:   } while (++timer != (&sun4->tme_sun4_timers[0] + TME_ARRAY_ELS(sun4->tme_sun4_timers)));
        !           485: }

unix.superglobalmegacorp.com

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