diff options
Diffstat (limited to 'libraries/sqlite/win32/mutex_os2.c')
-rwxr-xr-x | libraries/sqlite/win32/mutex_os2.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/libraries/sqlite/win32/mutex_os2.c b/libraries/sqlite/win32/mutex_os2.c new file mode 100755 index 0000000..e0258c7 --- /dev/null +++ b/libraries/sqlite/win32/mutex_os2.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* | ||
2 | ** 2007 August 28 | ||
3 | ** | ||
4 | ** The author disclaims copyright to this source code. In place of | ||
5 | ** a legal notice, here is a blessing: | ||
6 | ** | ||
7 | ** May you do good and not evil. | ||
8 | ** May you find forgiveness for yourself and forgive others. | ||
9 | ** May you share freely, never taking more than you give. | ||
10 | ** | ||
11 | ************************************************************************* | ||
12 | ** This file contains the C functions that implement mutexes for OS/2 | ||
13 | ** | ||
14 | ** $Id: mutex_os2.c,v 1.3 2007/10/02 19:56:04 pweilbacher Exp $ | ||
15 | */ | ||
16 | #include "sqliteInt.h" | ||
17 | |||
18 | /* | ||
19 | ** The code in this file is only used if SQLITE_MUTEX_OS2 is defined. | ||
20 | ** See the mutex.h file for details. | ||
21 | */ | ||
22 | #ifdef SQLITE_MUTEX_OS2 | ||
23 | |||
24 | /********************** OS/2 Mutex Implementation ********************** | ||
25 | ** | ||
26 | ** This implementation of mutexes is built using the OS/2 API. | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | ** The mutex object | ||
31 | ** Each recursive mutex is an instance of the following structure. | ||
32 | */ | ||
33 | struct sqlite3_mutex { | ||
34 | PSZ mutexName; /* Mutex name controlling the lock */ | ||
35 | HMTX mutex; /* Mutex controlling the lock */ | ||
36 | int id; /* Mutex type */ | ||
37 | int nRef; /* Number of references */ | ||
38 | TID owner; /* Thread holding this mutex */ | ||
39 | }; | ||
40 | |||
41 | /* | ||
42 | ** The sqlite3_mutex_alloc() routine allocates a new | ||
43 | ** mutex and returns a pointer to it. If it returns NULL | ||
44 | ** that means that a mutex could not be allocated. | ||
45 | ** SQLite will unwind its stack and return an error. The argument | ||
46 | ** to sqlite3_mutex_alloc() is one of these integer constants: | ||
47 | ** | ||
48 | ** <ul> | ||
49 | ** <li> SQLITE_MUTEX_FAST 0 | ||
50 | ** <li> SQLITE_MUTEX_RECURSIVE 1 | ||
51 | ** <li> SQLITE_MUTEX_STATIC_MASTER 2 | ||
52 | ** <li> SQLITE_MUTEX_STATIC_MEM 3 | ||
53 | ** <li> SQLITE_MUTEX_STATIC_PRNG 4 | ||
54 | ** </ul> | ||
55 | ** | ||
56 | ** The first two constants cause sqlite3_mutex_alloc() to create | ||
57 | ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE | ||
58 | ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. | ||
59 | ** The mutex implementation does not need to make a distinction | ||
60 | ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does | ||
61 | ** not want to. But SQLite will only request a recursive mutex in | ||
62 | ** cases where it really needs one. If a faster non-recursive mutex | ||
63 | ** implementation is available on the host platform, the mutex subsystem | ||
64 | ** might return such a mutex in response to SQLITE_MUTEX_FAST. | ||
65 | ** | ||
66 | ** The other allowed parameters to sqlite3_mutex_alloc() each return | ||
67 | ** a pointer to a static preexisting mutex. Three static mutexes are | ||
68 | ** used by the current version of SQLite. Future versions of SQLite | ||
69 | ** may add additional static mutexes. Static mutexes are for internal | ||
70 | ** use by SQLite only. Applications that use SQLite mutexes should | ||
71 | ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or | ||
72 | ** SQLITE_MUTEX_RECURSIVE. | ||
73 | ** | ||
74 | ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST | ||
75 | ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() | ||
76 | ** returns a different mutex on every call. But for the static | ||
77 | ** mutex types, the same mutex is returned on every call that has | ||
78 | ** the same type number. | ||
79 | */ | ||
80 | sqlite3_mutex *sqlite3_mutex_alloc(int iType){ | ||
81 | PSZ mutex_name = "\\SEM32\\SQLITE\\MUTEX"; | ||
82 | int mutex_name_len = strlen(mutex_name) + 1; /* name length + null byte */ | ||
83 | sqlite3_mutex *p; | ||
84 | |||
85 | switch( iType ){ | ||
86 | case SQLITE_MUTEX_FAST: | ||
87 | case SQLITE_MUTEX_RECURSIVE: { | ||
88 | p = sqlite3MallocZero( sizeof(*p) ); | ||
89 | if( p ){ | ||
90 | p->mutexName = (PSZ)malloc(mutex_name_len); | ||
91 | sqlite3_snprintf(mutex_name_len, p->mutexName, "%s", mutex_name); | ||
92 | p->id = iType; | ||
93 | DosCreateMutexSem(p->mutexName, &p->mutex, 0, FALSE); | ||
94 | DosOpenMutexSem(p->mutexName, &p->mutex); | ||
95 | } | ||
96 | break; | ||
97 | } | ||
98 | default: { | ||
99 | static sqlite3_mutex staticMutexes[5]; | ||
100 | static int isInit = 0; | ||
101 | while( !isInit ) { | ||
102 | static long lock = 0; | ||
103 | DosEnterCritSec(); | ||
104 | lock++; | ||
105 | if( lock == 1 ) { | ||
106 | DosExitCritSec(); | ||
107 | int i; | ||
108 | for(i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++) { | ||
109 | staticMutexes[i].mutexName = (PSZ)malloc(mutex_name_len + 1); | ||
110 | sqlite3_snprintf(mutex_name_len + 1, /* one more for the number */ | ||
111 | staticMutexes[i].mutexName, "%s%1d", mutex_name, i); | ||
112 | DosCreateMutexSem(staticMutexes[i].mutexName, | ||
113 | &staticMutexes[i].mutex, 0, FALSE); | ||
114 | DosOpenMutexSem(staticMutexes[i].mutexName, | ||
115 | &staticMutexes[i].mutex); | ||
116 | } | ||
117 | isInit = 1; | ||
118 | } else { | ||
119 | DosExitCritSec(); | ||
120 | DosSleep(1); | ||
121 | } | ||
122 | } | ||
123 | assert( iType-2 >= 0 ); | ||
124 | assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) ); | ||
125 | p = &staticMutexes[iType-2]; | ||
126 | p->id = iType; | ||
127 | break; | ||
128 | } | ||
129 | } | ||
130 | return p; | ||
131 | } | ||
132 | |||
133 | |||
134 | /* | ||
135 | ** This routine deallocates a previously allocated mutex. | ||
136 | ** SQLite is careful to deallocate every mutex that it allocates. | ||
137 | */ | ||
138 | void sqlite3_mutex_free(sqlite3_mutex *p){ | ||
139 | assert( p ); | ||
140 | assert( p->nRef==0 ); | ||
141 | assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); | ||
142 | DosCloseMutexSem(p->mutex); | ||
143 | free(p->mutexName); | ||
144 | sqlite3_free(p); | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt | ||
149 | ** to enter a mutex. If another thread is already within the mutex, | ||
150 | ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return | ||
151 | ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK | ||
152 | ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can | ||
153 | ** be entered multiple times by the same thread. In such cases the, | ||
154 | ** mutex must be exited an equal number of times before another thread | ||
155 | ** can enter. If the same thread tries to enter any other kind of mutex | ||
156 | ** more than once, the behavior is undefined. | ||
157 | */ | ||
158 | void sqlite3_mutex_enter(sqlite3_mutex *p){ | ||
159 | TID tid; | ||
160 | PID holder1; | ||
161 | ULONG holder2; | ||
162 | assert( p ); | ||
163 | assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); | ||
164 | DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT); | ||
165 | DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2); | ||
166 | p->owner = tid; | ||
167 | p->nRef++; | ||
168 | } | ||
169 | int sqlite3_mutex_try(sqlite3_mutex *p){ | ||
170 | int rc; | ||
171 | TID tid; | ||
172 | PID holder1; | ||
173 | ULONG holder2; | ||
174 | assert( p ); | ||
175 | assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); | ||
176 | if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR) { | ||
177 | DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2); | ||
178 | p->owner = tid; | ||
179 | p->nRef++; | ||
180 | rc = SQLITE_OK; | ||
181 | } else { | ||
182 | rc = SQLITE_BUSY; | ||
183 | } | ||
184 | |||
185 | return rc; | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | ** The sqlite3_mutex_leave() routine exits a mutex that was | ||
190 | ** previously entered by the same thread. The behavior | ||
191 | ** is undefined if the mutex is not currently entered or | ||
192 | ** is not currently allocated. SQLite will never do either. | ||
193 | */ | ||
194 | void sqlite3_mutex_leave(sqlite3_mutex *p){ | ||
195 | TID tid; | ||
196 | PID holder1; | ||
197 | ULONG holder2; | ||
198 | assert( p->nRef>0 ); | ||
199 | DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2); | ||
200 | assert( p->owner==tid ); | ||
201 | p->nRef--; | ||
202 | assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); | ||
203 | DosReleaseMutexSem(p->mutex); | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are | ||
208 | ** intended for use inside assert() statements. | ||
209 | */ | ||
210 | int sqlite3_mutex_held(sqlite3_mutex *p){ | ||
211 | TID tid; | ||
212 | PID pid; | ||
213 | ULONG ulCount; | ||
214 | PTIB ptib; | ||
215 | if( p!=0 ) { | ||
216 | DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); | ||
217 | } else { | ||
218 | DosGetInfoBlocks(&ptib, NULL); | ||
219 | tid = ptib->tib_ptib2->tib2_ultid; | ||
220 | } | ||
221 | return p==0 || (p->nRef!=0 && p->owner==tid); | ||
222 | } | ||
223 | int sqlite3_mutex_notheld(sqlite3_mutex *p){ | ||
224 | TID tid; | ||
225 | PID pid; | ||
226 | ULONG ulCount; | ||
227 | PTIB ptib; | ||
228 | if( p!= 0 ) { | ||
229 | DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); | ||
230 | } else { | ||
231 | DosGetInfoBlocks(&ptib, NULL); | ||
232 | tid = ptib->tib_ptib2->tib2_ultid; | ||
233 | } | ||
234 | return p==0 || p->nRef==0 || p->owner!=tid; | ||
235 | } | ||
236 | #endif /* SQLITE_MUTEX_OS2 */ | ||