1 1.11 christos /* $NetBSD: flockfile.c,v 1.11 2012/03/15 18:22:30 christos Exp $ */ 2 1.2 thorpej 3 1.2 thorpej /*- 4 1.2 thorpej * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 1.2 thorpej * All rights reserved. 6 1.2 thorpej * 7 1.2 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.2 thorpej * by Nathan J. Williams. 9 1.2 thorpej * 10 1.2 thorpej * Redistribution and use in source and binary forms, with or without 11 1.2 thorpej * modification, are permitted provided that the following conditions 12 1.2 thorpej * are met: 13 1.2 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.2 thorpej * notice, this list of conditions and the following disclaimer. 15 1.2 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.2 thorpej * documentation and/or other materials provided with the distribution. 18 1.2 thorpej * 19 1.2 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.2 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.2 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.2 thorpej */ 31 1.2 thorpej 32 1.2 thorpej #include <sys/cdefs.h> 33 1.2 thorpej #if defined(LIBC_SCCS) && !defined(lint) 34 1.11 christos __RCSID("$NetBSD: flockfile.c,v 1.11 2012/03/15 18:22:30 christos Exp $"); 35 1.2 thorpej #endif /* LIBC_SCCS and not lint */ 36 1.2 thorpej 37 1.2 thorpej #include "namespace.h" 38 1.2 thorpej 39 1.2 thorpej #include <assert.h> 40 1.2 thorpej #include <errno.h> 41 1.2 thorpej #include <stdio.h> 42 1.2 thorpej #include <string.h> 43 1.2 thorpej #include "reentrant.h" 44 1.2 thorpej #include "local.h" 45 1.2 thorpej 46 1.2 thorpej #ifdef __weak_alias 47 1.2 thorpej __weak_alias(flockfile,_flockfile) 48 1.2 thorpej __weak_alias(ftrylockfile,_ftrylockfile) 49 1.2 thorpej __weak_alias(funlockfile,_funlockfile) 50 1.2 thorpej #endif 51 1.2 thorpej 52 1.2 thorpej #ifdef _REENTRANT 53 1.2 thorpej /* 54 1.2 thorpej * XXX This code makes the assumption that a thr_t (pthread_t) is a 55 1.2 thorpej * XXX pointer. 56 1.2 thorpej */ 57 1.2 thorpej 58 1.2 thorpej void 59 1.2 thorpej flockfile(FILE *fp) 60 1.2 thorpej { 61 1.2 thorpej 62 1.5 nathanw __flockfile_internal(fp, 0); 63 1.2 thorpej } 64 1.2 thorpej 65 1.2 thorpej int 66 1.2 thorpej ftrylockfile(FILE *fp) 67 1.2 thorpej { 68 1.4 nathanw int retval; 69 1.2 thorpej 70 1.2 thorpej if (__isthreaded == 0) 71 1.2 thorpej return 0; 72 1.2 thorpej 73 1.4 nathanw retval = 0; 74 1.4 nathanw mutex_lock(&_LOCK(fp)); 75 1.4 nathanw 76 1.4 nathanw if (_LOCKOWNER(fp) == thr_self()) { 77 1.4 nathanw _LOCKCOUNT(fp)++; 78 1.4 nathanw } else if (_LOCKOWNER(fp) == NULL) { 79 1.4 nathanw _LOCKOWNER(fp) = thr_self(); 80 1.4 nathanw _LOCKCOUNT(fp) = 1; 81 1.4 nathanw } else 82 1.4 nathanw retval = -1; 83 1.4 nathanw 84 1.4 nathanw mutex_unlock(&_LOCK(fp)); 85 1.4 nathanw 86 1.4 nathanw return retval; 87 1.2 thorpej } 88 1.2 thorpej 89 1.2 thorpej void 90 1.2 thorpej funlockfile(FILE *fp) 91 1.2 thorpej { 92 1.2 thorpej 93 1.5 nathanw __funlockfile_internal(fp, 0); 94 1.5 nathanw } 95 1.5 nathanw 96 1.5 nathanw void 97 1.5 nathanw __flockfile_internal(FILE *fp, int internal) 98 1.5 nathanw { 99 1.5 nathanw 100 1.2 thorpej if (__isthreaded == 0) 101 1.2 thorpej return; 102 1.4 nathanw 103 1.4 nathanw mutex_lock(&_LOCK(fp)); 104 1.4 nathanw 105 1.5 nathanw if (_LOCKOWNER(fp) == thr_self()) { 106 1.5 nathanw _LOCKCOUNT(fp)++; 107 1.8 nathanw if (internal) 108 1.5 nathanw _LOCKINTERNAL(fp)++; 109 1.5 nathanw } else { 110 1.8 nathanw /* danger! cond_wait() is a cancellation point. */ 111 1.8 nathanw int oldstate; 112 1.8 nathanw thr_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 113 1.5 nathanw while (_LOCKOWNER(fp) != NULL) 114 1.5 nathanw cond_wait(&_LOCKCOND(fp), &_LOCK(fp)); 115 1.8 nathanw thr_setcancelstate(oldstate, NULL); 116 1.5 nathanw _LOCKOWNER(fp) = thr_self(); 117 1.5 nathanw _LOCKCOUNT(fp) = 1; 118 1.7 nathanw if (internal) 119 1.7 nathanw _LOCKINTERNAL(fp) = 1; 120 1.5 nathanw } 121 1.8 nathanw 122 1.8 nathanw if (_LOCKINTERNAL(fp) == 1) 123 1.8 nathanw /* stash cancellation state and disable */ 124 1.8 nathanw thr_setcancelstate(PTHREAD_CANCEL_DISABLE, 125 1.8 nathanw &_LOCKCANCELSTATE(fp)); 126 1.5 nathanw 127 1.5 nathanw mutex_unlock(&_LOCK(fp)); 128 1.5 nathanw } 129 1.5 nathanw 130 1.5 nathanw void 131 1.5 nathanw __funlockfile_internal(FILE *fp, int internal) 132 1.5 nathanw { 133 1.5 nathanw 134 1.5 nathanw if (__isthreaded == 0) 135 1.5 nathanw return; 136 1.5 nathanw 137 1.5 nathanw mutex_lock(&_LOCK(fp)); 138 1.5 nathanw 139 1.5 nathanw if (internal) { 140 1.5 nathanw _LOCKINTERNAL(fp)--; 141 1.5 nathanw if (_LOCKINTERNAL(fp) == 0) 142 1.6 nathanw thr_setcancelstate(_LOCKCANCELSTATE(fp), NULL); 143 1.5 nathanw } 144 1.5 nathanw 145 1.4 nathanw _LOCKCOUNT(fp)--; 146 1.4 nathanw if (_LOCKCOUNT(fp) == 0) { 147 1.4 nathanw _LOCKOWNER(fp) = NULL; 148 1.4 nathanw cond_signal(&_LOCKCOND(fp)); 149 1.4 nathanw } 150 1.2 thorpej 151 1.2 thorpej mutex_unlock(&_LOCK(fp)); 152 1.2 thorpej } 153 1.2 thorpej 154 1.2 thorpej #else /* _REENTRANT */ 155 1.2 thorpej 156 1.2 thorpej void 157 1.2 thorpej flockfile(FILE *fp) 158 1.2 thorpej { 159 1.2 thorpej /* LINTED deliberate lack of effect */ 160 1.2 thorpej (void)fp; 161 1.2 thorpej 162 1.2 thorpej return; 163 1.2 thorpej } 164 1.2 thorpej 165 1.2 thorpej int 166 1.2 thorpej ftrylockfile(FILE *fp) 167 1.2 thorpej { 168 1.2 thorpej /* LINTED deliberate lack of effect */ 169 1.2 thorpej (void)fp; 170 1.2 thorpej 171 1.11 christos return 0; 172 1.2 thorpej } 173 1.2 thorpej 174 1.2 thorpej void 175 1.2 thorpej funlockfile(FILE *fp) 176 1.2 thorpej { 177 1.2 thorpej /* LINTED deliberate lack of effect */ 178 1.2 thorpej (void)fp; 179 1.2 thorpej 180 1.2 thorpej return; 181 1.2 thorpej } 182 1.2 thorpej 183 1.2 thorpej #endif /* _REENTRANT */ 184