1*f841f6adSraf /* 2*f841f6adSraf * CDDL HEADER START 3*f841f6adSraf * 4*f841f6adSraf * The contents of this file are subject to the terms of the 5*f841f6adSraf * Common Development and Distribution License (the "License"). 6*f841f6adSraf * You may not use this file except in compliance with the License. 7*f841f6adSraf * 8*f841f6adSraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*f841f6adSraf * or http://www.opensolaris.org/os/licensing. 10*f841f6adSraf * See the License for the specific language governing permissions 11*f841f6adSraf * and limitations under the License. 12*f841f6adSraf * 13*f841f6adSraf * When distributing Covered Code, include this CDDL HEADER in each 14*f841f6adSraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*f841f6adSraf * If applicable, add the following below this CDDL HEADER, with the 16*f841f6adSraf * fields enclosed by brackets "[]" replaced with your own identifying 17*f841f6adSraf * information: Portions Copyright [yyyy] [name of copyright owner] 18*f841f6adSraf * 19*f841f6adSraf * CDDL HEADER END 20*f841f6adSraf */ 21*f841f6adSraf 22*f841f6adSraf /* 23*f841f6adSraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*f841f6adSraf * Use is subject to license terms. 25*f841f6adSraf */ 26*f841f6adSraf 27*f841f6adSraf #pragma ident "%Z%%M% %I% %E% SMI" 28*f841f6adSraf 29*f841f6adSraf #pragma weak clock_getres = _clock_getres 30*f841f6adSraf #pragma weak clock_gettime = _clock_gettime 31*f841f6adSraf #pragma weak clock_settime = _clock_settime 32*f841f6adSraf #pragma weak timer_create = _timer_create 33*f841f6adSraf #pragma weak timer_delete = _timer_delete 34*f841f6adSraf #pragma weak timer_getoverrun = _timer_getoverrun 35*f841f6adSraf #pragma weak timer_gettime = _timer_gettime 36*f841f6adSraf #pragma weak timer_settime = _timer_settime 37*f841f6adSraf 38*f841f6adSraf #include "synonyms.h" 39*f841f6adSraf #include <time.h> 40*f841f6adSraf #include <sys/types.h> 41*f841f6adSraf #include <stdlib.h> 42*f841f6adSraf #include <string.h> 43*f841f6adSraf #include <errno.h> 44*f841f6adSraf #include "sigev_thread.h" 45*f841f6adSraf 46*f841f6adSraf /* 47*f841f6adSraf * System call wrappers found elsewhere in libc (common/sys/__clock_timer.s). 48*f841f6adSraf */ 49*f841f6adSraf extern int __clock_getres(clockid_t, timespec_t *); 50*f841f6adSraf extern int __clock_gettime(clockid_t, timespec_t *); 51*f841f6adSraf extern int __clock_settime(clockid_t, const timespec_t *); 52*f841f6adSraf extern int __timer_create(clockid_t, struct sigevent *, timer_t *); 53*f841f6adSraf extern int __timer_delete(timer_t); 54*f841f6adSraf extern int __timer_getoverrun(timer_t); 55*f841f6adSraf extern int __timer_gettime(timer_t, itimerspec_t *); 56*f841f6adSraf extern int __timer_settime(timer_t, int, const itimerspec_t *, itimerspec_t *); 57*f841f6adSraf 58*f841f6adSraf /* 59*f841f6adSraf * Array of pointers to tcd's, indexed by timer id. 60*f841f6adSraf * No more than 'timer_max' timers can be created by any process. 61*f841f6adSraf */ 62*f841f6adSraf int timer_max = 0; 63*f841f6adSraf thread_communication_data_t **timer_tcd; 64*f841f6adSraf static pthread_once_t timer_once = PTHREAD_ONCE_INIT; 65*f841f6adSraf 66*f841f6adSraf static void 67*f841f6adSraf timer_init(void) 68*f841f6adSraf { 69*f841f6adSraf timer_max = (int)_sysconf(_SC_TIMER_MAX); 70*f841f6adSraf timer_tcd = malloc(timer_max * sizeof (*timer_tcd)); 71*f841f6adSraf (void) memset(timer_tcd, 0, timer_max * sizeof (*timer_tcd)); 72*f841f6adSraf } 73*f841f6adSraf 74*f841f6adSraf int 75*f841f6adSraf _clock_getres(clockid_t clock_id, timespec_t *res) 76*f841f6adSraf { 77*f841f6adSraf return (__clock_getres(clock_id, res)); 78*f841f6adSraf } 79*f841f6adSraf 80*f841f6adSraf int 81*f841f6adSraf _clock_gettime(clockid_t clock_id, timespec_t *tp) 82*f841f6adSraf { 83*f841f6adSraf return (__clock_gettime(clock_id, tp)); 84*f841f6adSraf } 85*f841f6adSraf 86*f841f6adSraf int 87*f841f6adSraf _clock_settime(clockid_t clock_id, const timespec_t *tp) 88*f841f6adSraf { 89*f841f6adSraf return (__clock_settime(clock_id, tp)); 90*f841f6adSraf } 91*f841f6adSraf 92*f841f6adSraf int 93*f841f6adSraf _timer_create(clockid_t clock_id, struct sigevent *sigevp, timer_t *timerid) 94*f841f6adSraf { 95*f841f6adSraf struct sigevent sigevent; 96*f841f6adSraf port_notify_t port_notify; 97*f841f6adSraf thread_communication_data_t *tcdp; 98*f841f6adSraf int sigev_thread = 0; 99*f841f6adSraf int rc; 100*f841f6adSraf 101*f841f6adSraf (void) pthread_once(&timer_once, timer_init); 102*f841f6adSraf 103*f841f6adSraf if (sigevp != NULL && 104*f841f6adSraf sigevp->sigev_notify == SIGEV_THREAD && 105*f841f6adSraf sigevp->sigev_notify_function != NULL) { 106*f841f6adSraf sigev_thread = 1; 107*f841f6adSraf tcdp = setup_sigev_handler(sigevp, TIMER); 108*f841f6adSraf if (tcdp == NULL) 109*f841f6adSraf return (-1); 110*f841f6adSraf /* copy the sigevent structure so we can modify it */ 111*f841f6adSraf sigevent = *sigevp; 112*f841f6adSraf sigevp = &sigevent; 113*f841f6adSraf port_notify.portnfy_port = tcdp->tcd_port; 114*f841f6adSraf port_notify.portnfy_user = NULL; 115*f841f6adSraf sigevp->sigev_value.sival_ptr = &port_notify; 116*f841f6adSraf } 117*f841f6adSraf 118*f841f6adSraf rc = __timer_create(clock_id, sigevp, timerid); 119*f841f6adSraf 120*f841f6adSraf if (sigev_thread) { 121*f841f6adSraf if (rc == 0) { 122*f841f6adSraf if ((rc = launch_spawner(tcdp)) != 0) 123*f841f6adSraf __timer_delete(*timerid); 124*f841f6adSraf else 125*f841f6adSraf timer_tcd[*timerid] = tcdp; 126*f841f6adSraf } 127*f841f6adSraf if (rc != 0) 128*f841f6adSraf free_sigev_handler(tcdp); 129*f841f6adSraf } 130*f841f6adSraf 131*f841f6adSraf return (rc); 132*f841f6adSraf } 133*f841f6adSraf 134*f841f6adSraf int 135*f841f6adSraf _timer_delete(timer_t timerid) 136*f841f6adSraf { 137*f841f6adSraf int rc; 138*f841f6adSraf 139*f841f6adSraf if ((rc = del_sigev_timer(timerid)) == 0) 140*f841f6adSraf return (__timer_delete(timerid)); 141*f841f6adSraf else 142*f841f6adSraf return (rc); 143*f841f6adSraf } 144*f841f6adSraf 145*f841f6adSraf int 146*f841f6adSraf _timer_getoverrun(timer_t timerid) 147*f841f6adSraf { 148*f841f6adSraf return (__timer_getoverrun(timerid) + sigev_timer_getoverrun(timerid)); 149*f841f6adSraf } 150*f841f6adSraf 151*f841f6adSraf int 152*f841f6adSraf _timer_gettime(timer_t timerid, itimerspec_t *value) 153*f841f6adSraf { 154*f841f6adSraf return (__timer_gettime(timerid, value)); 155*f841f6adSraf } 156*f841f6adSraf 157*f841f6adSraf int 158*f841f6adSraf _timer_settime(timer_t timerid, int flags, const itimerspec_t *value, 159*f841f6adSraf itimerspec_t *ovalue) 160*f841f6adSraf { 161*f841f6adSraf return (__timer_settime(timerid, flags, value, ovalue)); 162*f841f6adSraf } 163*f841f6adSraf 164*f841f6adSraf /* 165*f841f6adSraf * Cleanup after fork1() in the child process. 166*f841f6adSraf */ 167*f841f6adSraf void 168*f841f6adSraf postfork1_child_sigev_timer(void) 169*f841f6adSraf { 170*f841f6adSraf thread_communication_data_t *tcdp; 171*f841f6adSraf int timer; 172*f841f6adSraf 173*f841f6adSraf for (timer = 0; timer < timer_max; timer++) { 174*f841f6adSraf if ((tcdp = timer_tcd[timer]) != NULL) { 175*f841f6adSraf timer_tcd[timer] = NULL; 176*f841f6adSraf tcd_teardown(tcdp); 177*f841f6adSraf } 178*f841f6adSraf } 179*f841f6adSraf } 180