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 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * utility for vntsd queue handling 28 */ 29 #include <stdio.h> 30 #include <sys/types.h> 31 #include <sys/ipc.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <unistd.h> 35 #include <sys/socket.h> 36 #include <sys/ipc.h> 37 #include <sys/shm.h> 38 #include <sys/sem.h> 39 #include <wait.h> 40 #include <time.h> 41 #include <netinet/in.h> 42 #include <thread.h> 43 #include <signal.h> 44 #include "vntsd.h" 45 46 /* alloc_que_el() allocates a queue element */ 47 static vntsd_que_t * 48 alloc_que_el(void *handle) 49 { 50 vntsd_que_t *el; 51 52 /* allocate a queue element */ 53 el = (vntsd_que_t *)malloc(sizeof (vntsd_que_t)); 54 if (el == NULL) { 55 return (NULL); 56 } 57 58 59 el->nextp = NULL; 60 el->prevp = NULL; 61 el->handle = handle; 62 63 return (el); 64 } 65 66 /* vntsd_que_append() appends a element to a queue */ 67 int 68 vntsd_que_append(vntsd_que_t **que_hd, void *handle) 69 { 70 vntsd_que_t *p; 71 vntsd_que_t *el; 72 73 assert(que_hd); 74 assert(handle); 75 76 /* allocate a queue element */ 77 el = alloc_que_el(handle); 78 79 if (el == NULL) { 80 return (VNTSD_ERR_NO_MEM); 81 } 82 83 p = *que_hd; 84 85 if (p == NULL) { 86 /* first one */ 87 *que_hd = el; 88 } else { 89 /* walk to the last one */ 90 while (p->nextp != NULL) 91 p = p->nextp; 92 p->nextp = el; 93 } 94 95 el->prevp = p; 96 97 return (VNTSD_SUCCESS); 98 } 99 100 /* vntsd_que_insert_after() inserts element arter the handle */ 101 int 102 vntsd_que_insert_after(vntsd_que_t *que, void *handle, void *next) 103 { 104 vntsd_que_t *q, *el; 105 106 assert(que); 107 108 q = que; 109 110 while (q != NULL) { 111 if (q->handle == handle) { 112 break; 113 } 114 115 q = q->nextp; 116 } 117 118 if (q == NULL) { 119 /* not in queue */ 120 return (VNTSD_ERR_EL_NOT_FOUND); 121 } 122 123 el = alloc_que_el(next); 124 125 if (el == NULL) { 126 return (VNTSD_ERR_NO_MEM); 127 } 128 129 el->nextp = q->nextp; 130 q->nextp = el; 131 el->prevp = q; 132 133 return (VNTSD_SUCCESS); 134 } 135 136 137 138 /* vntsd_que_rm() removes an element from a queue */ 139 int 140 vntsd_que_rm(vntsd_que_t **que_hd, void *handle) 141 { 142 vntsd_que_t *p = *que_hd; 143 vntsd_que_t *prevp = NULL; 144 145 146 while (p != NULL) { 147 /* match handle */ 148 if (p->handle == handle) { 149 break; 150 } 151 prevp = p; 152 p = p->nextp; 153 } 154 155 if (p == NULL) { 156 /* not found */ 157 return (VNTSD_ERR_EL_NOT_FOUND); 158 } 159 160 /* found */ 161 if (p == *que_hd) { 162 /* first one */ 163 *que_hd = p->nextp; 164 } else { 165 prevp->nextp = p->nextp; 166 } 167 168 if (p->nextp != NULL) { 169 p->nextp->prevp = prevp; 170 } 171 172 handle = p->handle; 173 174 free(p); 175 176 return (VNTSD_SUCCESS); 177 178 } 179 180 /* vntsd_que_walk() - walk queue and apply function to each element */ 181 void * 182 vntsd_que_walk(vntsd_que_t *que_hd, el_func_t el_func) 183 { 184 vntsd_que_t *p = que_hd; 185 186 while (p != NULL) { 187 if ((*el_func)(p->handle)) { 188 return (p->handle); 189 } 190 191 p = p->nextp; 192 } 193 return (VNTSD_SUCCESS); 194 } 195 196 197 /* vntsd_que_find() finds first match */ 198 void * 199 vntsd_que_find(vntsd_que_t *que_hd, compare_func_t compare_func, void *data) 200 { 201 vntsd_que_t *p = que_hd; 202 203 assert(compare_func != NULL); 204 while (p != NULL) { 205 if ((*compare_func)(p->handle, data)) { 206 /* found match */ 207 return (p->handle); 208 } 209 210 p = p->nextp; 211 } 212 213 /* not found */ 214 return (NULL); 215 } 216 217 /* vntsd_free_que() frees entire queue */ 218 void 219 vntsd_free_que(vntsd_que_t **q, clean_func_t clean_func) 220 { 221 vntsd_que_t *p; 222 223 while (*q != NULL) { 224 p = *q; 225 226 *q = p->nextp; 227 228 if (clean_func) { 229 /* clean func will free the handle */ 230 (*clean_func)(p->handle); 231 } else { 232 free(p->handle); 233 } 234 235 free(p); 236 } 237 } 238 239 /* 240 * vntsd_que_pos() matches a handle and returns a handle located at "pos" 241 * relative to the matched handle. pos supported are 1 or -1. 242 */ 243 void * 244 vntsd_que_pos(vntsd_que_t *que_hd, void *handle, int pos) 245 { 246 vntsd_que_t *p = que_hd; 247 248 assert((pos == 1) || (pos == -1)); 249 250 251 while (p != NULL) { 252 if (p->handle == handle) { 253 /* find match */ 254 if (pos == 1) { 255 /* forward 1 */ 256 if (p->nextp != NULL) { 257 return (p->nextp->handle); 258 } 259 260 /* last one go to first */ 261 return (que_hd->handle); 262 263 } else { 264 /* backward 1 */ 265 if (p->prevp != NULL) { 266 return (p->prevp->handle); 267 } 268 269 /* first one, return last one */ 270 while (p->nextp != NULL) { 271 p = p->nextp; 272 } 273 274 assert(p != NULL); 275 assert(p->handle != NULL); 276 return (p->handle); 277 278 } 279 } 280 p = p->nextp; 281 } 282 283 DERR(stderr, "t@%d vntsd_que_pos can not find handle \n", 284 thr_self()); 285 286 return (NULL); 287 } 288