Build on latest glibc.
[openais.git] / exec / timer.c
blobb126eb9bdb10d9fb20d641a00e194c0881252394
1 /*
2 * Copyright (c) 2002-2006 MontaVista Software, Inc.
3 * Copyright (c) 2006 Sun Microsystems, Inc.
4 * Copyright (c) 2006-2007 Red Hat, Inc.
6 * All rights reserved.
8 * Author: Steven Dake (sdake@mvista.com)
10 * This software licensed under BSD license, the text of which follows:
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
15 * - Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 * - Neither the name of the MontaVista Software, Inc. nor the names of its
21 * contributors may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 * THE POSSIBILITY OF SUCH DAMAGE.
36 #include <pthread.h>
37 #include <assert.h>
38 #include <pwd.h>
39 #include <grp.h>
40 #include <sys/types.h>
41 #include <sys/poll.h>
42 #include <sys/uio.h>
43 #include <sys/mman.h>
44 #include <sys/socket.h>
45 #include <sys/un.h>
46 #include <sys/time.h>
47 #include <sys/resource.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #include <unistd.h>
51 #include <fcntl.h>
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <errno.h>
55 #include <signal.h>
56 #include <sched.h>
57 #include <time.h>
59 #include "swab.h"
60 #include "../include/saAis.h"
61 #include "../include/list.h"
62 #include "../include/queue.h"
63 #include "../lcr/lcr_ifact.h"
64 #include "poll.h"
65 #include "totempg.h"
66 #include "totemsrp.h"
67 #include "mempool.h"
68 #include "mainconfig.h"
69 #include "totemconfig.h"
70 #include "main.h"
71 #include "service.h"
72 #include "sync.h"
73 #include "swab.h"
74 #include "objdb.h"
75 #include "config.h"
76 #include "tlist.h"
77 #define LOG_SERVICE LOG_SERVICE_IPC
78 #include "logsys.h"
80 #include "util.h"
82 #define SERVER_BACKLOG 5
84 static pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER;
86 static pthread_t expiry_thread;
88 static pthread_attr_t thread_attr;
90 static struct timerlist timers_timerlist;
92 static void (*timer_serialize_lock_fn) (void);
94 static void (*timer_serialize_unlock_fn) (void);
96 static void *prioritized_timer_thread (void *data);
98 extern void pthread_exit(void *) __attribute__((noreturn));
101 * This thread runs at the highest priority to run system wide timers
103 static void *prioritized_timer_thread (void *data)
105 int fds;
106 unsigned long long timeout;
108 #if ! defined(TS_CLASS) && (defined(OPENAIS_BSD) || defined(OPENAIS_LINUX) || defined(OPENAIS_SOLARIS))
109 struct sched_param sched_param;
110 int res;
112 sched_param.sched_priority = 2;
113 res = pthread_setschedparam (expiry_thread, SCHED_RR, &sched_param);
114 #endif
116 pthread_mutex_unlock (&timer_mutex);
117 for (;;) {
118 retry_poll:
119 timer_serialize_lock_fn ();
120 timeout = timerlist_msec_duration_to_expire (&timers_timerlist);
121 if (timeout != -1 && timeout > 0xFFFFFFFF) {
122 timeout = 0xFFFFFFFE;
124 timer_serialize_unlock_fn ();
125 fds = poll (NULL, 0, timeout);
126 if (fds == -1) {
127 goto retry_poll;
129 pthread_mutex_lock (&timer_mutex);
130 timer_serialize_lock_fn ();
132 timerlist_expire (&timers_timerlist);
134 timer_serialize_unlock_fn ();
135 pthread_mutex_unlock (&timer_mutex);
138 pthread_exit (0);
141 static void sigusr1_handler (int num) {
142 #ifdef OPENAIS_SOLARIS
143 /* Rearm the signal facility */
144 signal (num, sigusr1_handler);
145 #endif
148 int openais_timer_init (
149 void (*serialize_lock_fn) (void),
150 void (*serialize_unlock_fn) (void))
152 int res;
154 timer_serialize_lock_fn = serialize_lock_fn;
155 timer_serialize_unlock_fn = serialize_unlock_fn;
157 timerlist_init (&timers_timerlist);
159 signal (SIGUSR1, sigusr1_handler);
161 pthread_mutex_lock (&timer_mutex);
162 pthread_attr_init (&thread_attr);
163 pthread_attr_setstacksize (&thread_attr, 100000);
164 pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);
165 res = pthread_create (&expiry_thread, &thread_attr,
166 prioritized_timer_thread, NULL);
168 return (res);
171 int openais_timer_add_absolute (
172 unsigned long long nanosec_from_epoch,
173 void *data,
174 void (*timer_fn) (void *data),
175 timer_handle *handle)
177 int res;
178 int unlock;
180 if (pthread_equal (pthread_self(), expiry_thread) != 0) {
181 unlock = 0;
182 } else {
183 unlock = 1;
184 pthread_mutex_lock (&timer_mutex);
187 res = timerlist_add_absolute (
188 &timers_timerlist,
189 timer_fn,
190 data,
191 nanosec_from_epoch,
192 handle);
194 if (unlock) {
195 pthread_mutex_unlock (&timer_mutex);
198 pthread_kill (expiry_thread, SIGUSR1);
200 return (res);
203 int openais_timer_add_duration (
204 unsigned long long nanosec_duration,
205 void *data,
206 void (*timer_fn) (void *data),
207 timer_handle *handle)
209 int res;
210 int unlock;
212 if (pthread_equal (pthread_self(), expiry_thread) != 0) {
213 unlock = 0;
214 } else {
215 unlock = 1;
216 pthread_mutex_lock (&timer_mutex);
219 res = timerlist_add_duration (
220 &timers_timerlist,
221 timer_fn,
222 data,
223 nanosec_duration,
224 handle);
226 if (unlock) {
227 pthread_mutex_unlock (&timer_mutex);
230 pthread_kill (expiry_thread, SIGUSR1);
232 return (res);
235 void openais_timer_delete (
236 timer_handle timer_handle)
238 int unlock;
240 if (timer_handle == 0) {
241 return;
244 if (pthread_equal (pthread_self(), expiry_thread) != 0) {
245 unlock = 0;
246 } else {
247 unlock = 1;
248 pthread_mutex_lock (&timer_mutex);
251 timerlist_del (&timers_timerlist, timer_handle);
253 if (unlock) {
254 pthread_mutex_unlock (&timer_mutex);
258 void openais_timer_lock (void)
260 pthread_mutex_lock (&timer_mutex);
263 void openais_timer_unlock (void)
265 pthread_mutex_unlock (&timer_mutex);