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 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <sys/param.h> 33 #include <sys/types.h> 34 #include <sys/sysmacros.h> 35 #include <sys/systm.h> 36 #include <sys/errno.h> 37 #include <sys/signal.h> 38 #include <sys/proc.h> 39 #include <sys/time.h> 40 #include <sys/cmn_err.h> 41 #include <sys/debug.h> 42 43 static void 44 sigalarm2proc(void *arg) 45 { 46 proc_t *p = arg; 47 48 mutex_enter(&p->p_lock); 49 p->p_alarmid = 0; 50 sigtoproc(p, NULL, SIGALRM); 51 mutex_exit(&p->p_lock); 52 } 53 54 int 55 alarm(int deltat) 56 { 57 proc_t *p = ttoproc(curthread); 58 clock_t del = 0; 59 clock_t ret; 60 timeout_id_t tmp_id; 61 clock_t delta = (uint_t)deltat; 62 63 /* 64 * We must single-thread this code relative to other 65 * lwps in the same process also performing an alarm(). 66 * The mutex dance in the while loop is necessary because 67 * we cannot call untimeout() while holding a lock that 68 * is grabbed by the timeout function, sigalarm2proc(). 69 * We can, however, hold p->p_lock across realtime_timeout(). 70 */ 71 mutex_enter(&p->p_lock); 72 while ((tmp_id = p->p_alarmid) != 0) { 73 p->p_alarmid = 0; 74 mutex_exit(&p->p_lock); 75 del = untimeout(tmp_id); 76 mutex_enter(&p->p_lock); 77 } 78 79 if (del < 0) 80 ret = 0; 81 else 82 ret = (del + hz - 1) / hz; /* convert to seconds */ 83 84 /* 85 * Our implementation defined limit for alarm is 86 * LONG_MAX / hz. Anything larger gets truncated 87 * to that limit. If delta is negative we can 88 * assume a wrap has occurred so peg delta in 89 * that case too. 64 bit platforms have higher limit. 90 */ 91 if (delta > (LONG_MAX / hz) || delta < 0) 92 delta = LONG_MAX / hz; 93 94 if (delta) 95 p->p_alarmid = realtime_timeout(sigalarm2proc, p, delta * hz); 96 mutex_exit(&p->p_lock); 97 return (ret); 98 } 99