xref: /onnv-gate/usr/src/lib/libc/port/rt/clock_timer.c (revision 11411:c2fe1bf96826)
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