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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <pthread.h> 27 #include <memory.h> 28 #include "queue.h" 29 #include <stdio.h> 30 #include <assert.h> 31 #include "plugin.h" 32 33 #define DEBUG 0 34 35 #if DEBUG 36 extern FILE *dbfp; 37 extern FILE *__auditd_debug_file_open(); 38 #define DPRINT(x) {(void) fprintf x; } 39 #else 40 #define DPRINT(x) 41 #endif 42 43 void 44 audit_queue_init(au_queue_t *q) 45 { 46 q->auq_head = NULL; 47 q->auq_tail = NULL; 48 (void) pthread_mutex_init(&q->auq_lock, NULL); 49 q->auq_count = 0; 50 #if DEBUG 51 if (dbfp == NULL) { 52 dbfp = __auditd_debug_file_open(); 53 } 54 #endif 55 } 56 57 /* 58 * enqueue() caller creates queue entry 59 */ 60 61 void 62 audit_enqueue(au_queue_t *q, void *p) 63 { 64 (void) pthread_mutex_lock(&q->auq_lock); 65 66 DPRINT((dbfp, "enqueue0(%X): p=%X, head=%X, tail=%X, count=%d\n", 67 q, p, q->auq_head, q->auq_tail, q->auq_count)); 68 69 if (q->auq_head == NULL) 70 q->auq_head = p; 71 else { 72 DPRINT((dbfp, "\tindirect tail=%X\n", 73 &(((audit_link_t *)(q->auq_tail))->aln_next))); 74 75 ((audit_link_t *)(q->auq_tail))->aln_next = p; 76 } 77 q->auq_tail = p; 78 ((audit_link_t *)p)->aln_next = NULL; 79 q->auq_count++; 80 81 DPRINT((dbfp, "enqueue1(%X): p=%X, head=%X, tail=%X, " 82 "count=%d, pnext=%X\n", 83 q, p, q->auq_head, q->auq_tail, q->auq_count, 84 ((audit_link_t *)p)->aln_next)); 85 86 (void) pthread_mutex_unlock(&q->auq_lock); 87 } 88 89 /* 90 * audit_dequeue() returns entry; caller is responsible for free 91 */ 92 93 int 94 audit_dequeue(au_queue_t *q, void **p) 95 { 96 (void) pthread_mutex_lock(&q->auq_lock); 97 98 if ((*p = q->auq_head) == NULL) { 99 DPRINT((dbfp, "dequeue1(%X): p=%X, head=%X, " 100 "tail=%X, count=%d\n", 101 q, *p, q->auq_head, q->auq_tail, q->auq_count)); 102 103 (void) pthread_mutex_unlock(&q->auq_lock); 104 return (1); 105 } 106 q->auq_count--; 107 108 /* if *p is the last, next is NULL */ 109 q->auq_head = ((audit_link_t *)*p)->aln_next; 110 111 DPRINT((dbfp, "dequeue0(%X): p=%X, head=%X, tail=%X, " 112 "count=%d, pnext=%X\n", 113 q, *p, q->auq_head, q->auq_tail, q->auq_count, 114 ((audit_link_t *)*p)->aln_next)); 115 116 (void) pthread_mutex_unlock(&q->auq_lock); 117 return (0); 118 } 119 120 /* 121 * increment ref count 122 */ 123 void 124 audit_incr_ref(pthread_mutex_t *l, audit_rec_t *p) 125 { 126 (void) pthread_mutex_lock(l); 127 p->abq_ref_count++; 128 DPRINT((dbfp, "incr_ref: p=%X, count=%d\n", 129 p, p->abq_ref_count)); 130 (void) pthread_mutex_unlock(l); 131 } 132 /* 133 * decrement reference count; if it reaches zero, 134 * return a pointer to it. Otherwise, return NULL. 135 */ 136 audit_rec_t * 137 audit_release(pthread_mutex_t *l, audit_rec_t *p) 138 { 139 assert(p != NULL); 140 141 (void) pthread_mutex_lock(l); 142 143 DPRINT((dbfp, "release: p=%X, count=%d\n", 144 p, p->abq_ref_count)); 145 146 if (--(p->abq_ref_count) > 0) { 147 (void) pthread_mutex_unlock(l); 148 return (NULL); 149 } 150 (void) pthread_mutex_unlock(l); 151 152 return (p); 153 } 154 155 int 156 audit_queue_size(au_queue_t *q) 157 { 158 int size; 159 160 (void) pthread_mutex_lock(&q->auq_lock); 161 size = q->auq_count; 162 (void) pthread_mutex_unlock(&q->auq_lock); 163 164 return (size); 165 } 166 167 168 void 169 audit_queue_destroy(au_queue_t *q) 170 { 171 (void) pthread_mutex_destroy(&q->auq_lock); 172 } 173