Add locking for FILE.
[dragonfly.git] / lib / libc / stdio / _flock_stub.c
1 /*
2  * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by John Birrell.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD: src/lib/libc/stdio/_flock_stub.c,v 1.3 1999/08/28 00:00:55 peter Exp $
33  * $DragonFly: src/lib/libc/stdio/_flock_stub.c,v 1.7 2005/05/09 12:43:40 davidxu Exp $
34  *
35  */
36
37 #include "namespace.h"
38 #include <stdio.h>
39 #include <pthread.h>
40 #include "un-namespace.h"
41
42 #include "local.h"
43
44 /* Don't build this in libc_r, just libc: */
45 /*
46  * Declare weak references in case the application is not linked
47  * with libpthread.
48  */
49 __weak_reference(_flockfile_stub,flockfile);
50 __weak_reference(_flockfile_stub,_flockfile);
51 __weak_reference(_flockfile_debug_stub,_flockfile_debug);
52 __weak_reference(_ftrylockfile_stub,ftrylockfile);
53 __weak_reference(_ftrylockfile_stub,_ftrylockfile);
54 __weak_reference(_funlockfile_stub,funlockfile);
55 __weak_reference(_funlockfile_stub,_funlockfile);
56
57 void    flockfile(FILE *);
58 void    _flockfile_debug(FILE *, char *, int);
59 int     ftrylockfile(FILE *);
60 void    funlockfile(FILE *);
61
62 #define _lock _extra
63
64 /*
65  * This function is a stub for the _flockfile function in libpthread.
66  */
67 void
68 _flockfile_stub(FILE *fp)
69 {
70         pthread_t curthread = _pthread_self();
71
72         if (fp->_lock->fl_owner == curthread)
73                 fp->_lock->fl_count++;
74         else {
75                 /*
76                  * Make sure this mutex is treated as a private
77                  * internal mutex:
78                  */
79                 _pthread_mutex_lock(&fp->_lock->fl_mutex);
80                 fp->_lock->fl_owner = curthread;
81                 fp->_lock->fl_count = 1;
82         }
83 }
84
85 /*
86  * This function is a stub for the _flockfile_debug function in libpthread.
87  */
88 void
89 _flockfile_debug_stub(FILE *fp, char *fname, int lineno)
90 {
91         _flockfile(fp);
92 }
93
94 /*
95  * This function is a stub for the _ftrylockfile function in libpthread.
96  */
97 int
98 _ftrylockfile_stub(FILE *fp)
99 {
100         pthread_t curthread = _pthread_self();
101         int     ret = 0;
102
103         if (fp->_lock->fl_owner == curthread)
104                 fp->_lock->fl_count++;
105         /*
106          * Make sure this mutex is treated as a private
107          * internal mutex:
108          */
109         else if (_pthread_mutex_trylock(&fp->_lock->fl_mutex) == 0) {
110                 fp->_lock->fl_owner = curthread;
111                 fp->_lock->fl_count = 1;
112         }
113         else
114                 ret = -1;
115         return (ret);
116 }
117
118 /*
119  * This function is a stub for the _funlockfile function in libpthread.
120  */
121 void
122 _funlockfile_stub(FILE *fp)
123 {
124         pthread_t       curthread = _pthread_self();
125
126         /*
127          * Check if this file is owned by the current thread:
128          */
129         if (fp->_lock->fl_owner == curthread) {
130                 /*
131                  * Check if this thread has locked the FILE
132                  * more than once:
133                  */
134                 if (fp->_lock->fl_count > 1)
135                         /*
136                          * Decrement the count of the number of
137                          * times the running thread has locked this
138                          * file:
139                          */
140                         fp->_lock->fl_count--;
141                 else {
142                         /*
143                          * The running thread will release the
144                          * lock now:
145                          */
146                         fp->_lock->fl_count = 0;
147                         fp->_lock->fl_owner = NULL;
148                         _pthread_mutex_unlock(&fp->_lock->fl_mutex);
149                 }
150         }
151 }