12248Sraf /*
22248Sraf * CDDL HEADER START
32248Sraf *
42248Sraf * The contents of this file are subject to the terms of the
52248Sraf * Common Development and Distribution License (the "License").
62248Sraf * You may not use this file except in compliance with the License.
72248Sraf *
82248Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92248Sraf * or http://www.opensolaris.org/os/licensing.
102248Sraf * See the License for the specific language governing permissions
112248Sraf * and limitations under the License.
122248Sraf *
132248Sraf * When distributing Covered Code, include this CDDL HEADER in each
142248Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152248Sraf * If applicable, add the following below this CDDL HEADER, with the
162248Sraf * fields enclosed by brackets "[]" replaced with your own identifying
172248Sraf * information: Portions Copyright [yyyy] [name of copyright owner]
182248Sraf *
192248Sraf * CDDL HEADER END
202248Sraf */
212248Sraf
222248Sraf /*
23*11411SSurya.Prakki@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
242248Sraf * Use is subject to license terms.
252248Sraf */
262248Sraf
276812Sraf #include "lint.h"
282248Sraf #include <time.h>
292248Sraf #include <sys/types.h>
302248Sraf #include <stdlib.h>
312248Sraf #include <string.h>
322248Sraf #include <errno.h>
332248Sraf #include "sigev_thread.h"
342248Sraf
352248Sraf /*
362248Sraf * System call wrappers found elsewhere in libc (common/sys/__clock_timer.s).
372248Sraf */
382248Sraf extern int __clock_getres(clockid_t, timespec_t *);
392248Sraf extern int __clock_gettime(clockid_t, timespec_t *);
402248Sraf extern int __clock_settime(clockid_t, const timespec_t *);
412248Sraf extern int __timer_create(clockid_t, struct sigevent *, timer_t *);
422248Sraf extern int __timer_delete(timer_t);
432248Sraf extern int __timer_getoverrun(timer_t);
442248Sraf extern int __timer_gettime(timer_t, itimerspec_t *);
452248Sraf extern int __timer_settime(timer_t, int, const itimerspec_t *, itimerspec_t *);
462248Sraf
472248Sraf /*
482248Sraf * Array of pointers to tcd's, indexed by timer id.
492248Sraf * No more than 'timer_max' timers can be created by any process.
502248Sraf */
512248Sraf int timer_max = 0;
522248Sraf thread_communication_data_t **timer_tcd;
532248Sraf static pthread_once_t timer_once = PTHREAD_ONCE_INIT;
542248Sraf
552248Sraf static void
timer_init(void)562248Sraf timer_init(void)
572248Sraf {
582248Sraf timer_max = (int)_sysconf(_SC_TIMER_MAX);
592248Sraf timer_tcd = malloc(timer_max * sizeof (*timer_tcd));
602248Sraf (void) memset(timer_tcd, 0, timer_max * sizeof (*timer_tcd));
612248Sraf }
622248Sraf
632248Sraf int
clock_getres(clockid_t clock_id,timespec_t * res)646812Sraf clock_getres(clockid_t clock_id, timespec_t *res)
652248Sraf {
662248Sraf return (__clock_getres(clock_id, res));
672248Sraf }
682248Sraf
692248Sraf int
clock_gettime(clockid_t clock_id,timespec_t * tp)706812Sraf clock_gettime(clockid_t clock_id, timespec_t *tp)
712248Sraf {
722248Sraf return (__clock_gettime(clock_id, tp));
732248Sraf }
742248Sraf
752248Sraf int
clock_settime(clockid_t clock_id,const timespec_t * tp)766812Sraf clock_settime(clockid_t clock_id, const timespec_t *tp)
772248Sraf {
782248Sraf return (__clock_settime(clock_id, tp));
792248Sraf }
802248Sraf
812248Sraf int
timer_create(clockid_t clock_id,struct sigevent * sigevp,timer_t * timerid)826812Sraf timer_create(clockid_t clock_id, struct sigevent *sigevp, timer_t *timerid)
832248Sraf {
842248Sraf struct sigevent sigevent;
852248Sraf port_notify_t port_notify;
862248Sraf thread_communication_data_t *tcdp;
872248Sraf int sigev_thread = 0;
882248Sraf int rc;
892248Sraf
902248Sraf (void) pthread_once(&timer_once, timer_init);
912248Sraf
922248Sraf if (sigevp != NULL &&
932248Sraf sigevp->sigev_notify == SIGEV_THREAD &&
942248Sraf sigevp->sigev_notify_function != NULL) {
952248Sraf sigev_thread = 1;
962248Sraf tcdp = setup_sigev_handler(sigevp, TIMER);
972248Sraf if (tcdp == NULL)
982248Sraf return (-1);
992248Sraf /* copy the sigevent structure so we can modify it */
1002248Sraf sigevent = *sigevp;
1012248Sraf sigevp = &sigevent;
1022248Sraf port_notify.portnfy_port = tcdp->tcd_port;
1032248Sraf port_notify.portnfy_user = NULL;
1042248Sraf sigevp->sigev_value.sival_ptr = &port_notify;
1052248Sraf }
1062248Sraf
1072248Sraf rc = __timer_create(clock_id, sigevp, timerid);
1082248Sraf
1092248Sraf if (sigev_thread) {
1102248Sraf if (rc == 0) {
1112248Sraf if ((rc = launch_spawner(tcdp)) != 0)
112*11411SSurya.Prakki@Sun.COM (void) __timer_delete(*timerid);
1132248Sraf else
1142248Sraf timer_tcd[*timerid] = tcdp;
1152248Sraf }
1162248Sraf if (rc != 0)
1172248Sraf free_sigev_handler(tcdp);
1182248Sraf }
1192248Sraf
1202248Sraf return (rc);
1212248Sraf }
1222248Sraf
1232248Sraf int
timer_delete(timer_t timerid)1246812Sraf timer_delete(timer_t timerid)
1252248Sraf {
1262248Sraf int rc;
1272248Sraf
1282248Sraf if ((rc = del_sigev_timer(timerid)) == 0)
1292248Sraf return (__timer_delete(timerid));
1302248Sraf else
1312248Sraf return (rc);
1322248Sraf }
1332248Sraf
1342248Sraf int
timer_getoverrun(timer_t timerid)1356812Sraf timer_getoverrun(timer_t timerid)
1362248Sraf {
1372248Sraf return (__timer_getoverrun(timerid) + sigev_timer_getoverrun(timerid));
1382248Sraf }
1392248Sraf
1402248Sraf int
timer_gettime(timer_t timerid,itimerspec_t * value)1416812Sraf timer_gettime(timer_t timerid, itimerspec_t *value)
1422248Sraf {
1432248Sraf return (__timer_gettime(timerid, value));
1442248Sraf }
1452248Sraf
1462248Sraf int
timer_settime(timer_t timerid,int flags,const itimerspec_t * value,itimerspec_t * ovalue)1476812Sraf timer_settime(timer_t timerid, int flags, const itimerspec_t *value,
1482248Sraf itimerspec_t *ovalue)
1492248Sraf {
1502248Sraf return (__timer_settime(timerid, flags, value, ovalue));
1512248Sraf }
1522248Sraf
1532248Sraf /*
1542248Sraf * Cleanup after fork1() in the child process.
1552248Sraf */
1562248Sraf void
postfork1_child_sigev_timer(void)1572248Sraf postfork1_child_sigev_timer(void)
1582248Sraf {
1592248Sraf thread_communication_data_t *tcdp;
1602248Sraf int timer;
1612248Sraf
1622248Sraf for (timer = 0; timer < timer_max; timer++) {
1632248Sraf if ((tcdp = timer_tcd[timer]) != NULL) {
1642248Sraf timer_tcd[timer] = NULL;
1652248Sraf tcd_teardown(tcdp);
1662248Sraf }
1672248Sraf }
1682248Sraf }
169