|
|
1.1 root 1: /* threadwrap.c */
2:
3: /* Thread-related cross-platform development wrappers */
4:
1.1.1.2 ! root 5: /* $Id: threadwrap.c,v 1.31 2011/09/09 08:06:15 rswindell Exp $ */
1.1 root 6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
1.1.1.2 ! root 11: * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 12: * *
13: * This library is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU Lesser General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU Lesser General Public License for more details: lgpl.txt or *
18: * http://www.fsf.org/copyleft/lesser.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #if defined(__unix__)
39: #include <unistd.h> /* _POSIX_THREADS */
40: #include <sys/param.h> /* BSD */
41: #endif
42:
43: #if defined(_WIN32) && !defined(_WIN32_WINNT)
44: #define _WIN32_WINNT 0x0400 /* Needed for TryEnterCriticalSection */
45: #endif
46:
47: #include "threadwrap.h" /* DLLCALL */
48:
49: /****************************************************************************/
50: /* Wrapper for Win32 create/begin thread function */
51: /* Uses POSIX threads */
52: /****************************************************************************/
53: #if defined(__unix__)
54: #if defined(_POSIX_THREADS)
55: ulong _beginthread(void( *start_address )( void * )
56: ,unsigned stack_size, void *arglist)
57: {
58: pthread_t thread;
59: pthread_attr_t attr;
60: size_t default_stack;
61:
1.1.1.2 ! root 62: (void)stack_size;
! 63:
1.1 root 64: pthread_attr_init(&attr); /* initialize attribute structure */
65:
66: /* set thread attributes to PTHREAD_CREATE_DETACHED which will ensure
67: that thread resources are freed on exit() */
68: pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
69:
70: /* Default stack size in BSD is too small for JS stuff */
71: /* Force to at least 256k */
72: #define XPDEV_MIN_THREAD_STACK_SIZE (256*1024)
1.1.1.2 ! root 73: if(stack_size==0 && pthread_attr_getstacksize(&attr, &default_stack)==0
! 74: && default_stack < XPDEV_MIN_THREAD_STACK_SIZE)
1.1 root 75: stack_size=XPDEV_MIN_THREAD_STACK_SIZE;
76:
77: if(stack_size!=0)
78: pthread_attr_setstacksize(&attr, stack_size);
79:
80: if(pthread_create(&thread
81: #if defined(__BORLANDC__) /* a (hopefully temporary) work-around */
1.1.1.2 ! root 82: ,NULL
1.1 root 83: #else
1.1.1.2 ! root 84: ,&attr /* default attributes */
1.1 root 85: #endif
1.1.1.2 ! root 86: /* POSIX defines this arg as "void *(*start_address)" */
! 87: ,(void * (*)(void *)) start_address
! 88: ,arglist)==0) {
! 89: pthread_attr_destroy(&attr);
! 90: return((ulong) thread /* thread handle */);
! 91: }
1.1 root 92:
1.1.1.2 ! root 93: pthread_attr_destroy(&attr);
1.1 root 94: return(-1); /* error */
95: }
96: #else
97:
98: #error "Need _beginthread implementation for non-POSIX thread library."
99:
100: #endif
101:
102: #endif /* __unix__ */
103:
104: /****************************************************************************/
105: /* Wrappers for POSIX thread (pthread) mutexes */
106: /****************************************************************************/
1.1.1.2 ! root 107: pthread_mutex_t pthread_mutex_initializer_np(BOOL recursive)
1.1 root 108: {
109: pthread_mutex_t mutex;
1.1.1.2 ! root 110: #if defined(_POSIX_THREADS)
! 111: pthread_mutexattr_t attr;
! 112: pthread_mutexattr_init(&attr);
! 113: if(recursive)
! 114: #if defined(__linux__) && !defined(__USE_UNIX98)
! 115: pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE_NP);
! 116: #else
! 117: pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
! 118: #endif
! 119: pthread_mutex_init(&mutex, &attr);
! 120: #else /* Assumes recursive (e.g. Windows) */
! 121: (void)recursive;
1.1 root 122: pthread_mutex_init(&mutex,NULL);
1.1.1.2 ! root 123: #endif
1.1 root 124: return(mutex);
125: }
126:
127: #if !defined(_POSIX_THREADS)
128:
129: int pthread_mutex_init(pthread_mutex_t* mutex, void* attr)
130: {
1.1.1.2 ! root 131: (void)attr;
1.1 root 132: #if defined(PTHREAD_MUTEX_AS_WIN32_MUTEX)
133: return ((((*mutex)=CreateMutex(/* security */NULL, /* owned */FALSE, /* name */NULL))==NULL) ? -1 : 0);
134: #elif defined(_WIN32) /* Win32 Critical Section */
135: InitializeCriticalSection(mutex);
136: return 0; /* No error */
137: #elif defined(__OS2__)
138: return DosCreateMutexSem(/* name */NULL, mutex, /* attr */0, /* owned */0);
139: #endif
140: }
141:
142: int pthread_mutex_lock(pthread_mutex_t* mutex)
143: {
144: #if defined(PTHREAD_MUTEX_AS_WIN32_MUTEX)
145: return (WaitForSingleObject(*mutex, INFINITE)==WAIT_OBJECT_0 ? 0 : EBUSY);
146: #elif defined(_WIN32) /* Win32 Critical Section */
147: EnterCriticalSection(mutex);
148: return 0; /* No error */
149: #elif defined(__OS2__)
150: return DosRequestMutexSem(*mutex, -1 /* SEM_INDEFINITE_WAIT */);
151: #endif
152: }
153:
154: int pthread_mutex_trylock(pthread_mutex_t* mutex)
155: {
156: #if defined(PTHREAD_MUTEX_AS_WIN32_MUTEX)
157: return (WaitForSingleObject(*mutex, 0)==WAIT_OBJECT_0 ? 0 : EBUSY);
158: #elif defined(_WIN32) /* Win32 Critical Section */
159: /* TryEnterCriticalSection only available on NT4+ :-( */
160: return (TryEnterCriticalSection(mutex) ? 0 : EBUSY);
161: #elif defined(__OS2__)
162: return DosRequestMutexSem(*mutex, 0 /* SEM_IMMEDIATE_RETURN */);
163: #endif
164: }
165:
166: int pthread_mutex_unlock(pthread_mutex_t* mutex)
167: {
168: #if defined(PTHREAD_MUTEX_AS_WIN32_MUTEX)
169: return (ReleaseMutex(*mutex) ? 0 : GetLastError());
170: #elif defined(_WIN32) /* Win32 Critical Section */
171: LeaveCriticalSection(mutex);
172: return 0; /* No error */
173: #elif defined(__OS2__)
174: return DosReleaseMutexSem(*mutex);
175: #endif
176: }
177:
178: int pthread_mutex_destroy(pthread_mutex_t* mutex)
179: {
180: #if defined(PTHREAD_MUTEX_AS_WIN32_MUTEX)
181: return (CloseHandle(*mutex) ? 0 : GetLastError());
182: #elif defined(_WIN32) /* Win32 Critical Section */
183: DeleteCriticalSection(mutex);
184: return 0; /* No error */
185: #elif defined(__OS2__)
186: return DosCloseMutexSem(*mutex);
187: #endif
188: }
189:
190: #endif /* POSIX thread mutexes */
1.1.1.2 ! root 191:
! 192: /************************************************************************/
! 193: /* Protected (thread-safe) Integers (e.g. atomic/interlocked variables) */
! 194: /************************************************************************/
! 195:
! 196: int protected_int32_init(protected_int32_t* prot, int32_t value)
! 197: {
! 198: prot->value = value;
! 199: return pthread_mutex_init(&prot->mutex,NULL);
! 200: }
! 201:
! 202: int protected_int64_init(protected_int64_t* prot, int64_t value)
! 203: {
! 204: prot->value = value;
! 205: return pthread_mutex_init(&prot->mutex,NULL);
! 206: }
! 207:
! 208: int32_t protected_int32_adjust(protected_int32_t* i, int32_t adjustment)
! 209: {
! 210: int32_t newval;
! 211: pthread_mutex_lock(&i->mutex);
! 212: newval = i->value += adjustment;
! 213: pthread_mutex_unlock(&i->mutex);
! 214: return newval;
! 215: }
! 216:
! 217: uint32_t protected_uint32_adjust(protected_uint32_t* i, int32_t adjustment)
! 218: {
! 219: uint32_t newval;
! 220: pthread_mutex_lock(&i->mutex);
! 221: newval = i->value += adjustment;
! 222: pthread_mutex_unlock(&i->mutex);
! 223: return newval;
! 224: }
! 225:
! 226: int64_t protected_int64_adjust(protected_int64_t* i, int64_t adjustment)
! 227: {
! 228: int64_t newval;
! 229: pthread_mutex_lock(&i->mutex);
! 230: newval = i->value += adjustment;
! 231: pthread_mutex_unlock(&i->mutex);
! 232: return newval;
! 233: }
! 234:
! 235: uint64_t protected_uint64_adjust(protected_uint64_t* i, int64_t adjustment)
! 236: {
! 237: uint64_t newval;
! 238: pthread_mutex_lock(&i->mutex);
! 239: newval = i->value += adjustment;
! 240: pthread_mutex_unlock(&i->mutex);
! 241: return newval;
! 242: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.