Version 0.3.0 from FTP
[asterisk/asterisk.git] / include / asterisk / lock.h
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * General Asterisk channel definitions.
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #ifndef _ASTERISK_LOCK_H
15 #define _ASTERISK_LOCK_H
16
17 #include <pthread.h>
18
19 #ifdef DEBUG_THREADS
20
21 #define TRIES 50
22
23 #include <errno.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <unistd.h>
27
28 // #define AST_MUTEX_INITIALIZER      PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
29 // #define AST_MUTEX_KIND             PTHREAD_MUTEX_RECURSIVE_NP
30 #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
31 #define AST_MUTEX_INITIALIZER         PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
32 #define AST_MUTEX_KIND                PTHREAD_MUTEX_ERRORCHECK_NP
33 #else
34 #define AST_MUTEX_INITIALIZER      PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
35 #define AST_MUTEX_KIND             PTHREAD_MUTEX_RECURSIVE_NP
36 #endif
37
38 struct mutex_info {
39         pthread_mutex_t *mutex;
40         char *file;
41         int lineno;
42         char *func;
43         struct mutex_info *next;
44 };
45
46 static inline int ast_pthread_mutex_init(pthread_mutex_t *t) {
47         static pthread_mutexattr_t  attr;
48         static int  init = 1;
49         extern int  pthread_mutexattr_setkind_np(pthread_mutexattr_t *, int);
50
51         if (init) {
52                 pthread_mutexattr_init(&attr);
53                 pthread_mutexattr_setkind_np(&attr, AST_MUTEX_KIND);
54                 init = 0;
55         }
56         return pthread_mutex_init(t, &attr);
57 }
58
59 static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, pthread_mutex_t *t) {
60         int res;
61         int tries = TRIES;
62         do {
63                 res = pthread_mutex_trylock(t);
64                 /* If we can't run, yield */
65                 if (res) {
66                         sched_yield();
67                         usleep(1);
68                 }
69         } while(res && tries--);
70         if (res) {
71                 fprintf(stderr, "%s line %d (%s): Error obtaining mutex: %s\n", 
72                                 filename, lineno, func, strerror(res));
73                 if ((res = pthread_mutex_lock(t)))
74                         fprintf(stderr, "%s line %d (%s): Error waiting for mutex: %s\n", 
75                                filename, lineno, func, strerror(res));
76                 else
77                         fprintf(stderr, "%s line %d (%s): Got it eventually...\n",
78                                filename, lineno, func);
79         }
80         return res;
81 }
82
83 #define ast_pthread_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
84
85 static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *func, pthread_mutex_t *t) {
86         int res;
87         res = pthread_mutex_unlock(t);
88         if (res) 
89                 fprintf(stderr, "%s line %d (%s): Error releasing mutex: %s\n", 
90                                 filename, lineno, func, strerror(res));
91         return res;
92 }
93
94 #define ast_pthread_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
95
96 #else
97
98 #define AST_MUTEX_INITIALIZER      PTHREAD_MUTEX_INITIALIZER
99 #define AST_MUTEX_KIND             PTHREAD_MUTEX_FAST_NP
100
101 #define ast_pthread_mutex_init(mutex) pthread_mutex_init(mutex, NULL)
102 #define ast_pthread_mutex_lock pthread_mutex_lock
103 #define ast_pthread_mutex_unlock pthread_mutex_unlock
104
105 #endif
106
107 #endif