Annotation of embedaddon/sqlite3/src/mutex_os2.c, revision 1.1.1.1
1.1 misho 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: #include "sqliteInt.h"
15:
16: /*
17: ** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
18: ** See the mutex.h file for details.
19: */
20: #ifdef SQLITE_MUTEX_OS2
21:
22: /********************** OS/2 Mutex Implementation **********************
23: **
24: ** This implementation of mutexes is built using the OS/2 API.
25: */
26:
27: /*
28: ** The mutex object
29: ** Each recursive mutex is an instance of the following structure.
30: */
31: struct sqlite3_mutex {
32: HMTX mutex; /* Mutex controlling the lock */
33: int id; /* Mutex type */
34: #ifdef SQLITE_DEBUG
35: int trace; /* True to trace changes */
36: #endif
37: };
38:
39: #ifdef SQLITE_DEBUG
40: #define SQLITE3_MUTEX_INITIALIZER { 0, 0, 0 }
41: #else
42: #define SQLITE3_MUTEX_INITIALIZER { 0, 0 }
43: #endif
44:
45: /*
46: ** Initialize and deinitialize the mutex subsystem.
47: */
48: static int os2MutexInit(void){ return SQLITE_OK; }
49: static int os2MutexEnd(void){ return SQLITE_OK; }
50:
51: /*
52: ** The sqlite3_mutex_alloc() routine allocates a new
53: ** mutex and returns a pointer to it. If it returns NULL
54: ** that means that a mutex could not be allocated.
55: ** SQLite will unwind its stack and return an error. The argument
56: ** to sqlite3_mutex_alloc() is one of these integer constants:
57: **
58: ** <ul>
59: ** <li> SQLITE_MUTEX_FAST
60: ** <li> SQLITE_MUTEX_RECURSIVE
61: ** <li> SQLITE_MUTEX_STATIC_MASTER
62: ** <li> SQLITE_MUTEX_STATIC_MEM
63: ** <li> SQLITE_MUTEX_STATIC_MEM2
64: ** <li> SQLITE_MUTEX_STATIC_PRNG
65: ** <li> SQLITE_MUTEX_STATIC_LRU
66: ** <li> SQLITE_MUTEX_STATIC_LRU2
67: ** </ul>
68: **
69: ** The first two constants cause sqlite3_mutex_alloc() to create
70: ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
71: ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
72: ** The mutex implementation does not need to make a distinction
73: ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
74: ** not want to. But SQLite will only request a recursive mutex in
75: ** cases where it really needs one. If a faster non-recursive mutex
76: ** implementation is available on the host platform, the mutex subsystem
77: ** might return such a mutex in response to SQLITE_MUTEX_FAST.
78: **
79: ** The other allowed parameters to sqlite3_mutex_alloc() each return
80: ** a pointer to a static preexisting mutex. Six static mutexes are
81: ** used by the current version of SQLite. Future versions of SQLite
82: ** may add additional static mutexes. Static mutexes are for internal
83: ** use by SQLite only. Applications that use SQLite mutexes should
84: ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
85: ** SQLITE_MUTEX_RECURSIVE.
86: **
87: ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
88: ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
89: ** returns a different mutex on every call. But for the static
90: ** mutex types, the same mutex is returned on every call that has
91: ** the same type number.
92: */
93: static sqlite3_mutex *os2MutexAlloc(int iType){
94: sqlite3_mutex *p = NULL;
95: switch( iType ){
96: case SQLITE_MUTEX_FAST:
97: case SQLITE_MUTEX_RECURSIVE: {
98: p = sqlite3MallocZero( sizeof(*p) );
99: if( p ){
100: p->id = iType;
101: if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){
102: sqlite3_free( p );
103: p = NULL;
104: }
105: }
106: break;
107: }
108: default: {
109: static volatile int isInit = 0;
110: static sqlite3_mutex staticMutexes[6] = {
111: SQLITE3_MUTEX_INITIALIZER,
112: SQLITE3_MUTEX_INITIALIZER,
113: SQLITE3_MUTEX_INITIALIZER,
114: SQLITE3_MUTEX_INITIALIZER,
115: SQLITE3_MUTEX_INITIALIZER,
116: SQLITE3_MUTEX_INITIALIZER,
117: };
118: if ( !isInit ){
119: APIRET rc;
120: PTIB ptib;
121: PPIB ppib;
122: HMTX mutex;
123: char name[32];
124: DosGetInfoBlocks( &ptib, &ppib );
125: sqlite3_snprintf( sizeof(name), name, "\\SEM32\\SQLITE%04x",
126: ppib->pib_ulpid );
127: while( !isInit ){
128: mutex = 0;
129: rc = DosCreateMutexSem( name, &mutex, 0, FALSE);
130: if( rc == NO_ERROR ){
131: unsigned int i;
132: if( !isInit ){
133: for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){
134: DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE );
135: }
136: isInit = 1;
137: }
138: DosCloseMutexSem( mutex );
139: }else if( rc == ERROR_DUPLICATE_NAME ){
140: DosSleep( 1 );
141: }else{
142: return p;
143: }
144: }
145: }
146: assert( iType-2 >= 0 );
147: assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
148: p = &staticMutexes[iType-2];
149: p->id = iType;
150: break;
151: }
152: }
153: return p;
154: }
155:
156:
157: /*
158: ** This routine deallocates a previously allocated mutex.
159: ** SQLite is careful to deallocate every mutex that it allocates.
160: */
161: static void os2MutexFree(sqlite3_mutex *p){
162: #ifdef SQLITE_DEBUG
163: TID tid;
164: PID pid;
165: ULONG ulCount;
166: DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
167: assert( ulCount==0 );
168: assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
169: #endif
170: DosCloseMutexSem( p->mutex );
171: sqlite3_free( p );
172: }
173:
174: #ifdef SQLITE_DEBUG
175: /*
176: ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
177: ** intended for use inside assert() statements.
178: */
179: static int os2MutexHeld(sqlite3_mutex *p){
180: TID tid;
181: PID pid;
182: ULONG ulCount;
183: PTIB ptib;
184: DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
185: if( ulCount==0 || ( ulCount>1 && p->id!=SQLITE_MUTEX_RECURSIVE ) )
186: return 0;
187: DosGetInfoBlocks(&ptib, NULL);
188: return tid==ptib->tib_ptib2->tib2_ultid;
189: }
190: static int os2MutexNotheld(sqlite3_mutex *p){
191: TID tid;
192: PID pid;
193: ULONG ulCount;
194: PTIB ptib;
195: DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
196: if( ulCount==0 )
197: return 1;
198: DosGetInfoBlocks(&ptib, NULL);
199: return tid!=ptib->tib_ptib2->tib2_ultid;
200: }
201: static void os2MutexTrace(sqlite3_mutex *p, char *pAction){
202: TID tid;
203: PID pid;
204: ULONG ulCount;
205: DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
206: printf("%s mutex %p (%d) with nRef=%ld\n", pAction, (void*)p, p->trace, ulCount);
207: }
208: #endif
209:
210: /*
211: ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
212: ** to enter a mutex. If another thread is already within the mutex,
213: ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
214: ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
215: ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
216: ** be entered multiple times by the same thread. In such cases the,
217: ** mutex must be exited an equal number of times before another thread
218: ** can enter. If the same thread tries to enter any other kind of mutex
219: ** more than once, the behavior is undefined.
220: */
221: static void os2MutexEnter(sqlite3_mutex *p){
222: assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
223: DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
224: #ifdef SQLITE_DEBUG
225: if( p->trace ) os2MutexTrace(p, "enter");
226: #endif
227: }
228: static int os2MutexTry(sqlite3_mutex *p){
229: int rc = SQLITE_BUSY;
230: assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
231: if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR ) {
232: rc = SQLITE_OK;
233: #ifdef SQLITE_DEBUG
234: if( p->trace ) os2MutexTrace(p, "try");
235: #endif
236: }
237: return rc;
238: }
239:
240: /*
241: ** The sqlite3_mutex_leave() routine exits a mutex that was
242: ** previously entered by the same thread. The behavior
243: ** is undefined if the mutex is not currently entered or
244: ** is not currently allocated. SQLite will never do either.
245: */
246: static void os2MutexLeave(sqlite3_mutex *p){
247: assert( os2MutexHeld(p) );
248: DosReleaseMutexSem(p->mutex);
249: #ifdef SQLITE_DEBUG
250: if( p->trace ) os2MutexTrace(p, "leave");
251: #endif
252: }
253:
254: sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
255: static const sqlite3_mutex_methods sMutex = {
256: os2MutexInit,
257: os2MutexEnd,
258: os2MutexAlloc,
259: os2MutexFree,
260: os2MutexEnter,
261: os2MutexTry,
262: os2MutexLeave,
263: #ifdef SQLITE_DEBUG
264: os2MutexHeld,
265: os2MutexNotheld
266: #else
267: 0,
268: 0
269: #endif
270: };
271:
272: return &sMutex;
273: }
274: #endif /* SQLITE_MUTEX_OS2 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>