netwerk/sctp/src/netinet/sctp_callout.c

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rwxr-xr-x

Correct small whitespace inconsistency, lost while renaming variables.

michael@0 1 /*-
michael@0 2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
michael@0 3 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
michael@0 4 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
michael@0 5 *
michael@0 6 * Redistribution and use in source and binary forms, with or without
michael@0 7 * modification, are permitted provided that the following conditions are met:
michael@0 8 *
michael@0 9 * a) Redistributions of source code must retain the above copyright notice,
michael@0 10 * this list of conditions and the following disclaimer.
michael@0 11 *
michael@0 12 * b) Redistributions in binary form must reproduce the above copyright
michael@0 13 * notice, this list of conditions and the following disclaimer in
michael@0 14 * the documentation and/or other materials provided with the distribution.
michael@0 15 *
michael@0 16 * c) Neither the name of Cisco Systems, Inc. nor the names of its
michael@0 17 * contributors may be used to endorse or promote products derived
michael@0 18 * from this software without specific prior written permission.
michael@0 19 *
michael@0 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
michael@0 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
michael@0 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
michael@0 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
michael@0 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
michael@0 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
michael@0 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
michael@0 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
michael@0 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
michael@0 30 * THE POSSIBILITY OF SUCH DAMAGE.
michael@0 31 */
michael@0 32
michael@0 33 #if defined(__Userspace__)
michael@0 34 #include <sys/types.h>
michael@0 35 #if !defined (__Userspace_os_Windows)
michael@0 36 #include <sys/wait.h>
michael@0 37 #include <unistd.h>
michael@0 38 #include <pthread.h>
michael@0 39 #endif
michael@0 40 #if defined(__Userspace_os_NaCl)
michael@0 41 #include <sys/select.h>
michael@0 42 #endif
michael@0 43 #include <stdlib.h>
michael@0 44 #include <string.h>
michael@0 45 #include <stdio.h>
michael@0 46 #include <errno.h>
michael@0 47 #include <netinet/sctp_sysctl.h>
michael@0 48 #include <netinet/sctp_pcb.h>
michael@0 49 #else
michael@0 50 #include <netinet/sctp_os.h>
michael@0 51 #include <netinet/sctp_callout.h>
michael@0 52 #include <netinet/sctp_pcb.h>
michael@0 53 #endif
michael@0 54
michael@0 55 /*
michael@0 56 * Callout/Timer routines for OS that doesn't have them
michael@0 57 */
michael@0 58 #if defined(__APPLE__) || defined(__Userspace__)
michael@0 59 int ticks = 0;
michael@0 60 #else
michael@0 61 extern int ticks;
michael@0 62 #endif
michael@0 63
michael@0 64 /*
michael@0 65 * SCTP_TIMERQ_LOCK protects:
michael@0 66 * - SCTP_BASE_INFO(callqueue)
michael@0 67 * - sctp_os_timer_current: current timer in process
michael@0 68 * - sctp_os_timer_next: next timer to check
michael@0 69 */
michael@0 70 static sctp_os_timer_t *sctp_os_timer_current = NULL;
michael@0 71 static sctp_os_timer_t *sctp_os_timer_next = NULL;
michael@0 72
michael@0 73 void
michael@0 74 sctp_os_timer_init(sctp_os_timer_t *c)
michael@0 75 {
michael@0 76 bzero(c, sizeof(*c));
michael@0 77 }
michael@0 78
michael@0 79 void
michael@0 80 sctp_os_timer_start(sctp_os_timer_t *c, int to_ticks, void (*ftn) (void *),
michael@0 81 void *arg)
michael@0 82 {
michael@0 83 /* paranoia */
michael@0 84 if ((c == NULL) || (ftn == NULL))
michael@0 85 return;
michael@0 86
michael@0 87 SCTP_TIMERQ_LOCK();
michael@0 88 /* check to see if we're rescheduling a timer */
michael@0 89 if (c->c_flags & SCTP_CALLOUT_PENDING) {
michael@0 90 if (c == sctp_os_timer_next) {
michael@0 91 sctp_os_timer_next = TAILQ_NEXT(c, tqe);
michael@0 92 }
michael@0 93 TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe);
michael@0 94 /*
michael@0 95 * part of the normal "stop a pending callout" process
michael@0 96 * is to clear the CALLOUT_ACTIVE and CALLOUT_PENDING
michael@0 97 * flags. We don't bother since we are setting these
michael@0 98 * below and we still hold the lock.
michael@0 99 */
michael@0 100 }
michael@0 101
michael@0 102 /*
michael@0 103 * We could unlock/splx here and lock/spl at the TAILQ_INSERT_TAIL,
michael@0 104 * but there's no point since doing this setup doesn't take much time.
michael@0 105 */
michael@0 106 if (to_ticks <= 0)
michael@0 107 to_ticks = 1;
michael@0 108
michael@0 109 c->c_arg = arg;
michael@0 110 c->c_flags = (SCTP_CALLOUT_ACTIVE | SCTP_CALLOUT_PENDING);
michael@0 111 c->c_func = ftn;
michael@0 112 c->c_time = ticks + to_ticks;
michael@0 113 TAILQ_INSERT_TAIL(&SCTP_BASE_INFO(callqueue), c, tqe);
michael@0 114 SCTP_TIMERQ_UNLOCK();
michael@0 115 }
michael@0 116
michael@0 117 int
michael@0 118 sctp_os_timer_stop(sctp_os_timer_t *c)
michael@0 119 {
michael@0 120 SCTP_TIMERQ_LOCK();
michael@0 121 /*
michael@0 122 * Don't attempt to delete a callout that's not on the queue.
michael@0 123 */
michael@0 124 if (!(c->c_flags & SCTP_CALLOUT_PENDING)) {
michael@0 125 c->c_flags &= ~SCTP_CALLOUT_ACTIVE;
michael@0 126 SCTP_TIMERQ_UNLOCK();
michael@0 127 return (0);
michael@0 128 }
michael@0 129 c->c_flags &= ~(SCTP_CALLOUT_ACTIVE | SCTP_CALLOUT_PENDING);
michael@0 130 if (c == sctp_os_timer_next) {
michael@0 131 sctp_os_timer_next = TAILQ_NEXT(c, tqe);
michael@0 132 }
michael@0 133 TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe);
michael@0 134 SCTP_TIMERQ_UNLOCK();
michael@0 135 return (1);
michael@0 136 }
michael@0 137
michael@0 138 static void
michael@0 139 sctp_handle_tick(int delta)
michael@0 140 {
michael@0 141 sctp_os_timer_t *c;
michael@0 142 void (*c_func)(void *);
michael@0 143 void *c_arg;
michael@0 144
michael@0 145 SCTP_TIMERQ_LOCK();
michael@0 146 /* update our tick count */
michael@0 147 ticks += delta;
michael@0 148 c = TAILQ_FIRST(&SCTP_BASE_INFO(callqueue));
michael@0 149 while (c) {
michael@0 150 if (c->c_time <= ticks) {
michael@0 151 sctp_os_timer_next = TAILQ_NEXT(c, tqe);
michael@0 152 TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe);
michael@0 153 c_func = c->c_func;
michael@0 154 c_arg = c->c_arg;
michael@0 155 c->c_flags &= ~SCTP_CALLOUT_PENDING;
michael@0 156 sctp_os_timer_current = c;
michael@0 157 SCTP_TIMERQ_UNLOCK();
michael@0 158 c_func(c_arg);
michael@0 159 SCTP_TIMERQ_LOCK();
michael@0 160 sctp_os_timer_current = NULL;
michael@0 161 c = sctp_os_timer_next;
michael@0 162 } else {
michael@0 163 c = TAILQ_NEXT(c, tqe);
michael@0 164 }
michael@0 165 }
michael@0 166 sctp_os_timer_next = NULL;
michael@0 167 SCTP_TIMERQ_UNLOCK();
michael@0 168 }
michael@0 169
michael@0 170 #if defined(__APPLE__)
michael@0 171 void
michael@0 172 sctp_timeout(void *arg SCTP_UNUSED)
michael@0 173 {
michael@0 174 sctp_handle_tick(SCTP_BASE_VAR(sctp_main_timer_ticks));
michael@0 175 sctp_start_main_timer();
michael@0 176 }
michael@0 177 #endif
michael@0 178
michael@0 179 #if defined(__Userspace__)
michael@0 180 #define TIMEOUT_INTERVAL 10
michael@0 181
michael@0 182 void *
michael@0 183 user_sctp_timer_iterate(void *arg)
michael@0 184 {
michael@0 185 for (;;) {
michael@0 186 #if defined (__Userspace_os_Windows)
michael@0 187 Sleep(TIMEOUT_INTERVAL);
michael@0 188 #else
michael@0 189 struct timeval timeout;
michael@0 190
michael@0 191 timeout.tv_sec = 0;
michael@0 192 timeout.tv_usec = 1000 * TIMEOUT_INTERVAL;
michael@0 193 select(0, NULL, NULL, NULL, &timeout);
michael@0 194 #endif
michael@0 195 if (SCTP_BASE_VAR(timer_thread_should_exit)) {
michael@0 196 break;
michael@0 197 }
michael@0 198 sctp_handle_tick(MSEC_TO_TICKS(TIMEOUT_INTERVAL));
michael@0 199 }
michael@0 200 return (NULL);
michael@0 201 }
michael@0 202
michael@0 203 void
michael@0 204 sctp_start_timer(void)
michael@0 205 {
michael@0 206 /*
michael@0 207 * No need to do SCTP_TIMERQ_LOCK_INIT();
michael@0 208 * here, it is being done in sctp_pcb_init()
michael@0 209 */
michael@0 210 #if defined (__Userspace_os_Windows)
michael@0 211 if ((SCTP_BASE_VAR(timer_thread) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)user_sctp_timer_iterate, NULL, 0, NULL)) == NULL) {
michael@0 212 SCTP_PRINTF("ERROR; Creating ithread failed\n");
michael@0 213 }
michael@0 214 #else
michael@0 215 int rc;
michael@0 216
michael@0 217 rc = pthread_create(&SCTP_BASE_VAR(timer_thread), NULL, user_sctp_timer_iterate, NULL);
michael@0 218 if (rc) {
michael@0 219 SCTP_PRINTF("ERROR; return code from pthread_create() is %d\n", rc);
michael@0 220 }
michael@0 221 #endif
michael@0 222 }
michael@0 223
michael@0 224 #endif

mercurial