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