symbian-qemu-0.9.1-12/python-2.6.1/Python/thread_os2.h
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /* This code implemented by cvale@netcom.com */
       
     2 
       
     3 #define INCL_DOSPROCESS
       
     4 #define INCL_DOSSEMAPHORES
       
     5 #include "os2.h"
       
     6 #include "limits.h"
       
     7 
       
     8 #include "process.h"
       
     9 
       
    10 #if defined(PYCC_GCC)
       
    11 #include <sys/builtin.h>
       
    12 #include <sys/fmutex.h>
       
    13 #else
       
    14 long PyThread_get_thread_ident(void);
       
    15 #endif
       
    16 
       
    17 /* default thread stack size of 64kB */
       
    18 #if !defined(THREAD_STACK_SIZE)
       
    19 #define	THREAD_STACK_SIZE	0x10000
       
    20 #endif
       
    21 
       
    22 #define OS2_STACKSIZE(x)	(x ? x : THREAD_STACK_SIZE)
       
    23 
       
    24 /*
       
    25  * Initialization of the C package, should not be needed.
       
    26  */
       
    27 static void
       
    28 PyThread__init_thread(void)
       
    29 {
       
    30 }
       
    31 
       
    32 /*
       
    33  * Thread support.
       
    34  */
       
    35 long
       
    36 PyThread_start_new_thread(void (*func)(void *), void *arg)
       
    37 {
       
    38 	int thread_id;
       
    39 
       
    40 	thread_id = _beginthread(func,
       
    41 				NULL,
       
    42 				OS2_STACKSIZE(_pythread_stacksize),
       
    43 				arg);
       
    44 
       
    45 	if (thread_id == -1) {
       
    46 		dprintf(("_beginthread failed. return %ld\n", errno));
       
    47 	}
       
    48 
       
    49 	return thread_id;
       
    50 }
       
    51 
       
    52 long
       
    53 PyThread_get_thread_ident(void)
       
    54 {
       
    55 #if !defined(PYCC_GCC)
       
    56 	PPIB pib;
       
    57 	PTIB tib;
       
    58 #endif
       
    59 
       
    60 	if (!initialized)
       
    61 		PyThread_init_thread();
       
    62 
       
    63 #if defined(PYCC_GCC)
       
    64 	return _gettid();
       
    65 #else
       
    66 	DosGetInfoBlocks(&tib, &pib);
       
    67 	return tib->tib_ptib2->tib2_ultid;
       
    68 #endif
       
    69 }
       
    70 
       
    71 static void
       
    72 do_PyThread_exit_thread(int no_cleanup)
       
    73 {
       
    74 	dprintf(("%ld: PyThread_exit_thread called\n",
       
    75 		 PyThread_get_thread_ident()));
       
    76 	if (!initialized)
       
    77 		if (no_cleanup)
       
    78 			_exit(0);
       
    79 		else
       
    80 			exit(0);
       
    81 	_endthread();
       
    82 }
       
    83 
       
    84 void 
       
    85 PyThread_exit_thread(void)
       
    86 {
       
    87 	do_PyThread_exit_thread(0);
       
    88 }
       
    89 
       
    90 void 
       
    91 PyThread__exit_thread(void)
       
    92 {
       
    93 	do_PyThread_exit_thread(1);
       
    94 }
       
    95 
       
    96 #ifndef NO_EXIT_PROG
       
    97 static void 
       
    98 do_PyThread_exit_prog(int status, int no_cleanup)
       
    99 {
       
   100 	dprintf(("PyThread_exit_prog(%d) called\n", status));
       
   101 	if (!initialized)
       
   102 		if (no_cleanup)
       
   103 			_exit(status);
       
   104 		else
       
   105 			exit(status);
       
   106 }
       
   107 
       
   108 void 
       
   109 PyThread_exit_prog(int status)
       
   110 {
       
   111 	do_PyThread_exit_prog(status, 0);
       
   112 }
       
   113 
       
   114 void 
       
   115 PyThread__exit_prog(int status)
       
   116 {
       
   117 	do_PyThread_exit_prog(status, 1);
       
   118 }
       
   119 #endif /* NO_EXIT_PROG */
       
   120 
       
   121 /*
       
   122  * Lock support.  This is implemented with an event semaphore and critical
       
   123  * sections to make it behave more like a posix mutex than its OS/2 
       
   124  * counterparts.
       
   125  */
       
   126 
       
   127 typedef struct os2_lock_t {
       
   128 	int is_set;
       
   129 	HEV changed;
       
   130 } *type_os2_lock;
       
   131 
       
   132 PyThread_type_lock 
       
   133 PyThread_allocate_lock(void)
       
   134 {
       
   135 #if defined(PYCC_GCC)
       
   136 	_fmutex *sem = malloc(sizeof(_fmutex));
       
   137 	if (!initialized)
       
   138 		PyThread_init_thread();
       
   139 	dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
       
   140 		 PyThread_get_thread_ident(),
       
   141 		 (long)sem));
       
   142 	if (_fmutex_create(sem, 0)) {
       
   143 		free(sem);
       
   144 		sem = NULL;
       
   145 	}
       
   146 	return (PyThread_type_lock)sem;
       
   147 #else
       
   148 	APIRET rc;
       
   149 	type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
       
   150 
       
   151 	dprintf(("PyThread_allocate_lock called\n"));
       
   152 	if (!initialized)
       
   153 		PyThread_init_thread();
       
   154 
       
   155 	lock->is_set = 0;
       
   156 
       
   157 	DosCreateEventSem(NULL, &lock->changed, 0, 0);
       
   158 
       
   159 	dprintf(("%ld: PyThread_allocate_lock() -> %p\n", 
       
   160 		 PyThread_get_thread_ident(), 
       
   161         	 lock->changed));
       
   162 
       
   163 	return (PyThread_type_lock)lock;
       
   164 #endif
       
   165 }
       
   166 
       
   167 void 
       
   168 PyThread_free_lock(PyThread_type_lock aLock)
       
   169 {
       
   170 #if !defined(PYCC_GCC)
       
   171 	type_os2_lock lock = (type_os2_lock)aLock;
       
   172 #endif
       
   173 
       
   174 	dprintf(("%ld: PyThread_free_lock(%p) called\n",
       
   175 		 PyThread_get_thread_ident(),aLock));
       
   176 
       
   177 #if defined(PYCC_GCC)
       
   178 	if (aLock) {
       
   179 		_fmutex_close((_fmutex *)aLock);
       
   180 		free((_fmutex *)aLock);
       
   181 	}
       
   182 #else
       
   183 	DosCloseEventSem(lock->changed);
       
   184 	free(aLock);
       
   185 #endif
       
   186 }
       
   187 
       
   188 /*
       
   189  * Return 1 on success if the lock was acquired
       
   190  *
       
   191  * and 0 if the lock was not acquired.
       
   192  */
       
   193 int 
       
   194 PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
       
   195 {
       
   196 #if !defined(PYCC_GCC)
       
   197 	int   done = 0;
       
   198 	ULONG count;
       
   199 	PID   pid = 0;
       
   200 	TID   tid = 0;
       
   201 	type_os2_lock lock = (type_os2_lock)aLock;
       
   202 #endif
       
   203 
       
   204 	dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
       
   205 		 PyThread_get_thread_ident(),
       
   206 		 aLock,
       
   207 		 waitflag));
       
   208 
       
   209 #if defined(PYCC_GCC)
       
   210 	/* always successful if the lock doesn't exist */
       
   211 	if (aLock &&
       
   212 	    _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
       
   213 		return 0;
       
   214 #else
       
   215 	while (!done) {
       
   216 		/* if the lock is currently set, we have to wait for
       
   217 		 * the state to change
       
   218 		 */
       
   219 		if (lock->is_set) {
       
   220 			if (!waitflag)
       
   221 				return 0;
       
   222 			DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
       
   223 		}
       
   224 
       
   225 		/* enter a critical section and try to get the semaphore.  If
       
   226 		 * it is still locked, we will try again.
       
   227 		 */
       
   228 		if (DosEnterCritSec())
       
   229 			return 0;
       
   230 
       
   231 		if (!lock->is_set) {
       
   232 			lock->is_set = 1;
       
   233 			DosResetEventSem(lock->changed, &count);
       
   234 			done = 1;
       
   235 		}
       
   236 
       
   237 		DosExitCritSec();
       
   238 	}
       
   239 #endif
       
   240 
       
   241 	return 1;
       
   242 }
       
   243 
       
   244 void
       
   245 PyThread_release_lock(PyThread_type_lock aLock)
       
   246 {
       
   247 #if !defined(PYCC_GCC)
       
   248 	type_os2_lock lock = (type_os2_lock)aLock;
       
   249 #endif
       
   250 
       
   251 	dprintf(("%ld: PyThread_release_lock(%p) called\n",
       
   252 		 PyThread_get_thread_ident(),
       
   253 		 aLock));
       
   254 
       
   255 #if defined(PYCC_GCC)
       
   256 	if (aLock)
       
   257 		_fmutex_release((_fmutex *)aLock);
       
   258 #else
       
   259 	if (!lock->is_set) {
       
   260 		dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
       
   261 			 PyThread_get_thread_ident(),
       
   262 			 aLock,
       
   263 			 GetLastError()));
       
   264 		return;
       
   265 	}
       
   266 
       
   267 	if (DosEnterCritSec()) {
       
   268 		dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
       
   269 			 PyThread_get_thread_ident(),
       
   270 			 aLock,
       
   271 			 GetLastError()));
       
   272 		return;
       
   273 	}
       
   274 
       
   275 	lock->is_set = 0;
       
   276 	DosPostEventSem(lock->changed);
       
   277 
       
   278 	DosExitCritSec();
       
   279 #endif
       
   280 }
       
   281 
       
   282 /* minimum/maximum thread stack sizes supported */
       
   283 #define THREAD_MIN_STACKSIZE	0x8000		/* 32kB */
       
   284 #define THREAD_MAX_STACKSIZE	0x2000000	/* 32MB */
       
   285 
       
   286 /* set the thread stack size.
       
   287  * Return 0 if size is valid, -1 otherwise.
       
   288  */
       
   289 static int
       
   290 _pythread_os2_set_stacksize(size_t size)
       
   291 {
       
   292 	/* set to default */
       
   293 	if (size == 0) {
       
   294 		_pythread_stacksize = 0;
       
   295 		return 0;
       
   296 	}
       
   297 
       
   298 	/* valid range? */
       
   299 	if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
       
   300 		_pythread_stacksize = size;
       
   301 		return 0;
       
   302 	}
       
   303 
       
   304 	return -1;
       
   305 }
       
   306 
       
   307 #define THREAD_SET_STACKSIZE(x)	_pythread_os2_set_stacksize(x)