1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 22 /* All Rights Reserved */ 23 24 25 /* 26 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/types.h> 32 #include <sys/sysmacros.h> 33 #include <sys/systm.h> 34 #include <sys/errno.h> 35 #include <sys/signal.h> 36 #include <sys/proc.h> 37 #include <sys/time.h> 38 #include <sys/cmn_err.h> 39 #include <sys/debug.h> 40 41 static void 42 sigalarm2proc(void *arg) 43 { 44 proc_t *p = arg; 45 46 mutex_enter(&p->p_lock); 47 p->p_alarmid = 0; 48 sigtoproc(p, NULL, SIGALRM); 49 mutex_exit(&p->p_lock); 50 } 51 52 int 53 alarm(int deltat) 54 { 55 proc_t *p = ttoproc(curthread); 56 clock_t del = 0; 57 clock_t ret; 58 timeout_id_t tmp_id; 59 clock_t delta = (uint_t)deltat; 60 61 /* 62 * We must single-thread this code relative to other 63 * lwps in the same process also performing an alarm(). 64 * The mutex dance in the while loop is necessary because 65 * we cannot call untimeout() while holding a lock that 66 * is grabbed by the timeout function, sigalarm2proc(). 67 * We can, however, hold p->p_lock across realtime_timeout(). 68 */ 69 mutex_enter(&p->p_lock); 70 while ((tmp_id = p->p_alarmid) != 0) { 71 p->p_alarmid = 0; 72 mutex_exit(&p->p_lock); 73 del = untimeout(tmp_id); 74 mutex_enter(&p->p_lock); 75 } 76 77 if (del < 0) 78 ret = 0; 79 else 80 ret = (del + hz - 1) / hz; /* convert to seconds */ 81 82 /* 83 * Our implementation defined limit for alarm is 84 * LONG_MAX / hz. Anything larger gets truncated 85 * to that limit. If delta is negative we can 86 * assume a wrap has occurred so peg delta in 87 * that case too. 64 bit platforms have higher limit. 88 */ 89 if (delta > (LONG_MAX / hz) || delta < 0) 90 delta = LONG_MAX / hz; 91 92 if (delta) 93 p->p_alarmid = realtime_timeout(sigalarm2proc, p, delta * hz); 94 mutex_exit(&p->p_lock); 95 return (ret); 96 } 97