symbian-qemu-0.9.1-12/python-2.6.1/Python/thread_beos.h
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 #include <kernel/OS.h>
       
     2 #include <support/SupportDefs.h>
       
     3 #include <errno.h>
       
     4 
       
     5 /* ----------------------------------------------------------------------
       
     6  * Fast locking mechanism described by Benoit Schillings (benoit@be.com)
       
     7  * in the Be Developer's Newsletter, Issue #26 (http://www.be.com/).
       
     8  */
       
     9 typedef struct benaphore {
       
    10 	sem_id _sem;
       
    11 	int32  _atom;
       
    12 } benaphore_t;
       
    13 
       
    14 static status_t benaphore_create( const char *name, benaphore_t *ben );
       
    15 static status_t benaphore_destroy( benaphore_t *ben );
       
    16 static status_t benaphore_lock( benaphore_t *ben );
       
    17 static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros );
       
    18 static status_t benaphore_unlock( benaphore_t *ben );
       
    19 
       
    20 static status_t benaphore_create( const char *name, benaphore_t *ben )
       
    21 {
       
    22 	if( ben != NULL ) {
       
    23 		ben->_atom = 0;
       
    24 		ben->_sem = create_sem( 0, name );
       
    25 		
       
    26 		if( ben->_sem < B_NO_ERROR ) {
       
    27 			return B_BAD_SEM_ID;
       
    28 		}
       
    29 	} else {
       
    30 		return EFAULT;
       
    31 	}
       
    32 	
       
    33 	return EOK;
       
    34 }
       
    35 
       
    36 static status_t benaphore_destroy( benaphore_t *ben )
       
    37 {
       
    38 	if( ben->_sem >= B_NO_ERROR ) {
       
    39 		status_t retval = benaphore_timedlock( ben, 0 );
       
    40 		
       
    41 		if( retval == EOK || retval == EWOULDBLOCK ) {
       
    42 			status_t del_retval = delete_sem( ben->_sem );
       
    43 			
       
    44 			return del_retval;
       
    45 		}
       
    46 	}
       
    47 
       
    48 	return B_BAD_SEM_ID;
       
    49 }
       
    50 
       
    51 static status_t benaphore_lock( benaphore_t *ben )
       
    52 {
       
    53 	int32 prev = atomic_add( &(ben->_atom), 1 );
       
    54 	
       
    55 	if( prev > 0 ) {
       
    56 		return acquire_sem( ben->_sem );
       
    57 	}
       
    58 	
       
    59 	return EOK;
       
    60 }
       
    61 
       
    62 static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros )
       
    63 {
       
    64 	int32 prev = atomic_add( &(ben->_atom), 1 );
       
    65 	
       
    66 	if( prev > 0 ) {
       
    67 		status_t retval = acquire_sem_etc( ben->_sem, 1, B_TIMEOUT, micros );
       
    68 		
       
    69 		switch( retval ) {
       
    70 		case B_WOULD_BLOCK:	/* Fall through... */
       
    71 		case B_TIMED_OUT:
       
    72 			return EWOULDBLOCK;
       
    73 			break;
       
    74 		case B_OK:
       
    75 			return EOK;
       
    76 			break;
       
    77 		default:
       
    78 			return retval;
       
    79 			break;
       
    80 		}
       
    81 	}
       
    82 	
       
    83 	return EOK;
       
    84 }
       
    85 
       
    86 static status_t benaphore_unlock( benaphore_t *ben )
       
    87 {
       
    88 	int32 prev = atomic_add( &(ben->_atom), -1 );
       
    89 	
       
    90 	if( prev > 1 ) {
       
    91 		return release_sem( ben->_sem );
       
    92 	}
       
    93 	
       
    94 	return EOK;
       
    95 }
       
    96 
       
    97 /* ----------------------------------------------------------------------
       
    98  * Initialization.
       
    99  */
       
   100 static void PyThread__init_thread( void )
       
   101 {
       
   102 	/* Do nothing. */
       
   103 	return;
       
   104 }
       
   105 
       
   106 /* ----------------------------------------------------------------------
       
   107  * Thread support.
       
   108  *
       
   109  * Only ANSI C, renamed functions here; you can't use K&R on BeOS,
       
   110  * and there's no legacy thread module to support.
       
   111  */
       
   112 
       
   113 static int32 thread_count = 0;
       
   114 
       
   115 long PyThread_start_new_thread( void (*func)(void *), void *arg )
       
   116 {
       
   117 	status_t success = 0;
       
   118 	thread_id tid;
       
   119 	char name[B_OS_NAME_LENGTH];
       
   120 	int32 this_thread;
       
   121 
       
   122 	dprintf(("PyThread_start_new_thread called\n"));
       
   123 
       
   124 	/* We are so very thread-safe... */
       
   125 	this_thread = atomic_add( &thread_count, 1 );
       
   126 	PyOS_snprintf(name, sizeof(name),
       
   127 		      "python thread (%d)", this_thread );
       
   128 
       
   129 	tid = spawn_thread( (thread_func)func, name,
       
   130 	                    B_NORMAL_PRIORITY, arg );
       
   131 	if( tid > B_NO_ERROR ) {
       
   132 		success = resume_thread( tid );
       
   133 	}
       
   134 
       
   135 	return ( success == B_NO_ERROR ? tid : -1 );
       
   136 }
       
   137 
       
   138 long PyThread_get_thread_ident( void )
       
   139 {
       
   140 	/* Presumed to return the current thread's ID... */
       
   141 	thread_id tid;
       
   142 	tid = find_thread( NULL );
       
   143 	
       
   144 	return ( tid != B_NAME_NOT_FOUND ? tid : -1 );
       
   145 }
       
   146 
       
   147 static void do_PyThread_exit_thread( int no_cleanup )
       
   148 {
       
   149 	int32 threads;
       
   150 
       
   151 	dprintf(("PyThread_exit_thread called\n"));
       
   152 
       
   153 	/* Thread-safe way to read a variable without a mutex: */
       
   154 	threads = atomic_add( &thread_count, 0 );
       
   155 
       
   156 	if( threads == 0 ) {
       
   157 		/* No threads around, so exit main(). */
       
   158 		if( no_cleanup ) {
       
   159 			_exit(0);
       
   160 		} else {
       
   161 			exit(0);
       
   162 		}
       
   163 	} else {
       
   164 		/* Oh, we're a thread, let's try to exit gracefully... */
       
   165 		exit_thread( B_NO_ERROR );
       
   166 	}
       
   167 }
       
   168 
       
   169 void PyThread_exit_thread( void )
       
   170 {
       
   171 	do_PyThread_exit_thread(0);
       
   172 }
       
   173 
       
   174 void PyThread__exit_thread( void )
       
   175 {
       
   176 	do_PyThread_exit_thread(1);
       
   177 }
       
   178 
       
   179 #ifndef NO_EXIT_PROG
       
   180 static void do_PyThread_exit_prog( int status, int no_cleanup )
       
   181 {
       
   182 	dprintf(("PyThread_exit_prog(%d) called\n", status));
       
   183 
       
   184 	/* No need to do anything, the threads get torn down if main() exits. */
       
   185 
       
   186 	if (no_cleanup) {
       
   187 		_exit(status);
       
   188 	} else {
       
   189 		exit(status);
       
   190 	}
       
   191 }
       
   192 
       
   193 void PyThread_exit_prog( int status )
       
   194 {
       
   195 	do_PyThread_exit_prog(status, 0);
       
   196 }
       
   197 
       
   198 void PyThread__exit_prog( int status )
       
   199 {
       
   200 	do_PyThread_exit_prog(status, 1);
       
   201 }
       
   202 #endif /* NO_EXIT_PROG */
       
   203 
       
   204 /* ----------------------------------------------------------------------
       
   205  * Lock support.
       
   206  */
       
   207 
       
   208 static int32 lock_count = 0;
       
   209 
       
   210 PyThread_type_lock PyThread_allocate_lock( void )
       
   211 {
       
   212 	benaphore_t *lock;
       
   213 	status_t retval;
       
   214 	char name[B_OS_NAME_LENGTH];
       
   215 	int32 this_lock;
       
   216 	
       
   217 	dprintf(("PyThread_allocate_lock called\n"));
       
   218 
       
   219 	lock = (benaphore_t *)malloc( sizeof( benaphore_t ) );
       
   220 	if( lock == NULL ) {
       
   221 		/* TODO: that's bad, raise MemoryError */
       
   222 		return (PyThread_type_lock)NULL;
       
   223 	}
       
   224 
       
   225 	this_lock = atomic_add( &lock_count, 1 );
       
   226 	PyOS_snprintf(name, sizeof(name), "python lock (%d)", this_lock);
       
   227 
       
   228 	retval = benaphore_create( name, lock );
       
   229 	if( retval != EOK ) {
       
   230 		/* TODO: that's bad, raise an exception */
       
   231 		return (PyThread_type_lock)NULL;
       
   232 	}
       
   233 
       
   234 	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
       
   235 	return (PyThread_type_lock) lock;
       
   236 }
       
   237 
       
   238 void PyThread_free_lock( PyThread_type_lock lock )
       
   239 {
       
   240 	status_t retval;
       
   241 
       
   242 	dprintf(("PyThread_free_lock(%p) called\n", lock));
       
   243 	
       
   244 	retval = benaphore_destroy( (benaphore_t *)lock );
       
   245 	if( retval != EOK ) {
       
   246 		/* TODO: that's bad, raise an exception */
       
   247 		return;
       
   248 	}
       
   249 }
       
   250 
       
   251 int PyThread_acquire_lock( PyThread_type_lock lock, int waitflag )
       
   252 {
       
   253 	int success;
       
   254 	status_t retval;
       
   255 
       
   256 	dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
       
   257 
       
   258 	if( waitflag ) {
       
   259 		retval = benaphore_lock( (benaphore_t *)lock );
       
   260 	} else {
       
   261 		retval = benaphore_timedlock( (benaphore_t *)lock, 0 );
       
   262 	}
       
   263 	
       
   264 	if( retval == EOK ) {
       
   265 		success = 1;
       
   266 	} else {
       
   267 		success = 0;
       
   268 		
       
   269 		/* TODO: that's bad, raise an exception */
       
   270 	}
       
   271 
       
   272 	dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
       
   273 	return success;
       
   274 }
       
   275 
       
   276 void PyThread_release_lock( PyThread_type_lock lock )
       
   277 {
       
   278 	status_t retval;
       
   279 	
       
   280 	dprintf(("PyThread_release_lock(%p) called\n", lock));
       
   281 	
       
   282 	retval = benaphore_unlock( (benaphore_t *)lock );
       
   283 	if( retval != EOK ) {
       
   284 		/* TODO: that's bad, raise an exception */
       
   285 		return;
       
   286 	}
       
   287 }