spilt_thread.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:19k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2.  * THREAD.C - Solaris to POSIX Interface Layer for Threads.
  3.  *
  4.  * This code is public domain.  It may be freely distributed provided the
  5.  * Copyright notice is retained. This code is not supported in any way.
  6.  * Usage of the code is solely at the user's/programmer's discretion.
  7.  * Sun Microsystems makes no claim as to the reliabilty, correctness or
  8.  * suitability of this code. Sun Microsystems will not be held liable in
  9.  * any way as a result loss or damage arising from the use this code.
  10.  *
  11.  * Written by: Richard.Marejka@Canada.Sun.COM
  12.  * Copyright (c) 1994, by Sun Microsystems, Inc.
  13.  */
  14. /*
  15.  * Richard Marejka  Solaris 2 Migration Support Centre
  16.  * October 6, 1994
  17.  *      richard@canada.sun.com
  18.  * 405-477-1159
  19.  *
  20.  * This package can be used to run a Solaris threads application on a
  21.  * system that support POSIX threads.
  22.  *
  23.  * This package demonstrates that 
  24.  * 
  25.  * a) Solaris threads is not another proprietary threads package - it
  26.  *    is almost identical to the POSIX proposed standard.
  27.  * 
  28.  * b) Solaris threads programmers need not wait for POSIX to be
  29.  *    finalized as a standard, before they begin multithreading
  30.  *    their applications
  31.  *
  32.  * c) The differences between Solaris threads and POSIX threads
  33.  *    are primarily syntactic.
  34.  *
  35.  * In addition, although application programmers may contact OpCom to
  36.  * obtain a copy of the SunSoft POSIX.1c EA package, people should be
  37.  * aware that the SunSoft package is based on Draft 8 of the POSIX
  38.  * standard.   The SunSoft package is not a complete implementation of
  39.  * Draft 8. 
  40.  * 
  41.  * 
  42.  * This package implements Solaris threads in terms of
  43.  * POSIX.1c threads. This package allows an application programmer to
  44.  * write a Solaris threads program, and then port the application to a
  45.  * POSIX.1c based threads implentation.   This package  proves just
  46.  * how small the differences are.  
  47.  * 
  48.  * This package should not be used on Solaris systems. At this time
  49.  * our POSIX.1c threads are written in terms of Solaris threads.
  50.  */ 
  51. /*
  52.  * 
  53.  * SPILT - Solaris to POSIX Interface Layer for Threads.
  54.  * 
  55.  * This code is public-domain, it may be freely distributed provided the
  56.  * Copyright notice is retained. This code is not supported in any way.
  57.  * Usage of the code is solely at the user's/programmer's discretion.
  58.  * Sun Microsystems makes no claim as to the reliabilty, correctness or
  59.  * suitability of this code. Sun Microsystems will not be held liable in
  60.  * any way as a result loss or damage arising from the use this code.
  61.  * 
  62.  * This package implements an interface mapping between Solaris threads and
  63.  * POSIX.1c threads. The POSIX.1c material is based on the May 1994/D9 document.
  64.  * 
  65.  * This package should make porting Solaris thread source to a POSIX.1c based
  66.  * library a matter of "wedging" this interface between the Solaris thread
  67.  * source and the POSIX.1c library.
  68.  * 
  69.  * In producing the package, the goal was to acheive a high degree of mapping
  70.  * between Solaris and POSIX.1c. However, certain aspects of Solaris either
  71.  * do not have a POSIX.1c equivalent have only an "approximate" equivalent.
  72.  * Another small set of Solaris features can only be mapped into a POSIX.1c
  73.  * implementation if the implementation supports the corresponding feature.
  74.  * 
  75.  * The package uses two macros to control the characteristics of the
  76.  * package. If the macro SPILT_MACROS is defined then certain functions
  77.  * and typedef's will be implemented as macros to the POSIX.1c equivalent
  78.  * functions and typedef's. Otherwise, all functions and typedefs are
  79.  * strictly defined in the compilation. The second macro is SPILT_LIBERAL,
  80.  * refered to as the "test macro". This macro is built up from the bit-wise
  81.  * or'ing of _SPILT_LIBERAL_* macros. The "liberal" macros allows the
  82.  * package builder to control how tolerant the package will be of semantic
  83.  * incompleteness.
  84.  * 
  85.  * The following points describe the "approximate" mappings, how they are
  86.  * implemented and how the _SPILT_LIBERAL_* macro controls behavior.
  87.  * 
  88.  * THR_DAEMON
  89.  *  The thread create option for daemon threads has no equivalent in
  90.  *  POSIX.1c (ENOTSUP). If the test macro includes the
  91.  *  _SPILT_LIBERAL_DAEMON flag the option is silently ignored.
  92.  * 
  93.  * THR_SUSPENDED
  94.  *  The thread create option for suspended threads has no equivalent
  95.  *  in POSIX.1c (ENOTSUP). If the test macro includes the
  96.  *  _SPILT_LIBERAL_SUSPENDED flag the option is silently ignored.
  97.  * 
  98.  * THR_NEW_LWP
  99.  *  The thread create option for new LWPs has no equivalent in POSIX.1c
  100.  *  (ENOTSUP). If the test macro includes the _SPILT_LIBERAL_NEW_LWP
  101.  *  flag the option is silently ignored.
  102.  * 
  103.  * thr_setconcurrency
  104.  *  This function has no equivalent mapping in POSIX.1c (ENOSYS). If          
  105.  *  the test macro includes the _SPILT_LIBERAL_SETCONCURRENCY flag
  106.  *  the funciton will return success (0).
  107.  * 
  108.  * thr_getconcurrency
  109.  *  This function has no equivalent mapping in POSIX.1c (ENOSYS). If          
  110.  *  the test macro includes the _SPILT_LIBERAL_GETCONCURRENCY flag
  111.  *  the function will always return zero (0).
  112.  * 
  113.  * thr_suspend
  114.  *  This function has no equivalent mapping in POSIX.1c (ENOSYS). If          
  115.  *  the test macro includes the _SPILT_LIBERAL_SUSPEND flag the
  116.  *  function will always return success (0).
  117.  * 
  118.  * thr_continue
  119.  *  This function has no equivalent mapping in POSIX.1c (ENOSYS). If          
  120.  *  the test macro includes the _SPILT_LIBERAL_CONTINUE flag the
  121.  *  function will always return success (0).
  122.  * 
  123.  * thr_create
  124.  *  If the POSIX.1c macro _POSIX_THREAD_PRIORITY_SCHEDULING is defined
  125.  *  the pthread inheretsched attribute will be set to
  126.  *  PTHREAD_INHERIT_SCHED.
  127.  * 
  128.  * THR_BOUND
  129.  *  The thread create option for "bound" threads is only supported in
  130.  *  POSIX.1c if the macro _POSIX_THREAD_PRIORITY_SCHEDULING is defined.
  131.  *  Attempts to use THR_BOUND when the option is not supported will
  132.  *  return failure (ENOTSUP). If the test macro includes the
  133.  *  _SPILT_LIBERAL_BOUND flag the THR_BOUND option will be ignored if
  134.  *  not supported.
  135.  * 
  136.  * stack
  137.  *  The thread create attribute for stack address is only supported if
  138.  *  the macro _POSIX_THREAD_ATTR_STACKADDR is defined. Attempts to use
  139.  *  the stack option when the option is not supported will return
  140.  *  failure (ENOTSUP). If the test macro includes the
  141.  *  _SPILT_LIBERAL_STACKADDR flag the stack option will be ignored
  142.  *  if not supported.
  143.  * 
  144.  * stacksize
  145.  *  The thread create option for stack size is only supported if the
  146.  *  macro _POSIX_THREAD_ATTR_STACKSIZE is defined. Attempts to use
  147.  *  the stacksize option when the attribute is not supported will
  148.  *  return failure (ENOTSUP). If the test macro include the
  149.  *  _SPILT_LIBERAL_STACKSIZE flag the stacksize option will be
  150.  *  ignored if not supported.
  151.  * 
  152.  * thr_setprio
  153.  *  The thread priority management is only supported if the macro
  154.  *  _POSIX_THREAD_PRIORITY_SCHEDULING is defined. Attempts to use
  155.  *  thread scheduling will return failure (ENOSYS). If the test macro          
  156.  *  includes the _SPILT_LIBERAL_SETPRIO flag attempts to modify
  157.  *  thread priority will always return success (0).
  158.  * 
  159.  *  [Note: Thread priority managment is crudely mapped onto POSIX.1c
  160.  *  scheduling (if supported by the implementation), since POSIX.1c
  161.  *  supports multiple thread scheduling classes (SCHED_FIFO, SCHED_RR,
  162.  *  SCHED_OTHER and possibly others) and Solaris only has one
  163.  *  scheduling class. The implemenation here is analogeous to allowing
  164.  *  a process to modify its priority without being able to determine
  165.  *  1) its scheduling class and 2) the bounds of allowable priority
  166.  *  values.]
  167.  * 
  168.  * thr_getprio
  169.  *  The thread priority management is only supported if the macro
  170.  *  _POSIX_THREAD_PRIORITY_SCHEDULING is defined. Attempts to use
  171.  *  thread scheduling will return failure (ENOSYS). If the test macro          
  172.  *  includes the _SPILT_LIBERAL_GETPRIO flag attempts to retrieve
  173.  *  thread priority will always return success (0).
  174.  * 
  175.  * thr_join
  176.  *  POSIX.1c does not support the "non-targeted" join. Attempts 
  177.  *  to do so are undefined.
  178.  * 
  179.  * 
  180.  * XXX_init
  181.  *  Solaris synchronization variables are initialized to a default
  182.  *  state (USYNC_THREAD) by zero filling the variable. This is
  183.  *  achieved when the variable has external scope, i.e. it does not
  184.  *  have to be explicitly initialized, because ANSI C states that
  185.  *  all uninitialized, external data is zero-filled. In contrast,
  186.  *  POSIX.1c requires external synchronization objects to be
  187.  *  initialized by assignment of a type-specific macro. The result
  188.  *  of these differences is that to ensure "correct" semantics
  189.  *  of external Solaris synchronization objects when ported to
  190.  *  a POSIX.1c environment is that they must be initialized using
  191.  *  the appropriate XXX_init function.
  192.  * 
  193.  * Written by Richard.Marejka@Canada.Sun.COM
  194.  * Copyright (c) 1994, by Sun Microsystems, Inc.
  195.  * 
  196.  */
  197. #pragma ident "@(#) thread.c 1.2 94/10/05 Richard.Marejka@Canada.Sun.COM"
  198. /* Feature Test Macros */
  199. /* Include Files */
  200. #include <thread.h>
  201. #include <synch.h>
  202. #include <signal.h>
  203. #include <sys/types.h>
  204. #include <stdlib.h>
  205. #include <errno.h>
  206. /* Constants & Macros */
  207. /* Data Declarations */
  208. /* External References */
  209. /* External Declarations */
  210. /* Creation and Control */
  211. int
  212. thr_create( void *stackp, size_t stacksize, void *(*entry)( void * ), void *arg, long flags, thread_t *tidp ) {
  213. pthread_attr_t attr;
  214. pthread_t tid;
  215. if ( !tidp )
  216. tidp = &tid;
  217. if ( stackp && !stacksize ) /* stack but no size */
  218. return( EINVAL );
  219. /* unsupported flags */
  220. #if !(SPILT_LIBERAL & _SPILT_LIBERAL_NEW_LWP)
  221. if ( flags & THR_NEW_LWP )
  222. return( ENOTSUP );
  223. #endif
  224. #if !(SPILT_LIBERAL & _SPILT_LIBERAL_SUSPENDED)
  225. if ( flags & THR_SUSPENDED )
  226. return( ENOTSUP );
  227. #endif
  228. #if !(SPILT_LIBERAL & _SPILT_LIBERAL_DAEMON)
  229. if ( flags & THR_DAEMON )
  230. return( ENOTSUP );
  231. #endif
  232. pthread_attr_init( &attr );
  233. if ( stacksize )
  234. #if defined(_POSIX_THREAD_ATTR_STACKSIZE)
  235. pthread_attr_setstacksize( &attr, stacksize );
  236. #elif (SPILT_LIBERAL & _SPILT_LIBERAL_STACKSIZE)
  237. ;
  238. #else
  239. return( ENOTSUP );
  240. #endif
  241. if ( stackp )
  242. #if defined(_POSIX_THREAD_ATTR_STACKADDR)
  243. pthread_attr_setstackaddr( &attr, stackp );
  244. #elif (SPILT_LIBERAL & _SPILT_LIBERAL_STACKADDR)
  245. ;
  246. #else
  247. return( ENOTSUP );
  248. #endif
  249. if ( flags & THR_DETACHED )
  250. pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
  251. else
  252. pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
  253. #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
  254. if ( flags & THR_BOUND )
  255. pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );
  256. else
  257. pthread_attr_setscope( &attr, PTHREAD_SCOPE_PROCESS );
  258. pthread_attr_setinheritsched( &attr, PTHREAD_INHERIT_SCHED );
  259. #elif !(SPILT_LIBERAL & _SPILT_LIBERAL_BOUND)
  260. if ( flags & THR_BOUND )
  261. return( ENOTSUP );
  262. #endif
  263. return( pthread_create( tidp, &attr, entry, arg ) );
  264. }
  265. #if !defined(SPILT_MACROS)
  266. size_t
  267. thr_min_stack( void ) {
  268. return( PTHREAD_STACK_MIN );
  269. }
  270. #endif
  271. #if !defined(SPILT_MACROS)
  272. thread_t
  273. thr_self( void ) {
  274. return( pthread_self() );
  275. }
  276. #endif
  277. #if !defined(SPILT_MACROS)
  278. void
  279. thr_exit( void *status ) {
  280. pthread_exit( status );
  281. /* NOTREACHED */
  282. return;
  283. }
  284. #endif
  285. int
  286. thr_join( thread_t tid, thread_t *dtidp, void **statusp ) {
  287. int status = pthread_join( tid, statusp );
  288. if ( dtidp )
  289. *dtidp = tid;
  290. return( status );
  291. }
  292. /* Scheduling */
  293. int
  294. thr_setprio( thread_t tid, int prio ) {
  295. #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
  296. int policy;
  297. struct sched_param param;
  298. pthread_getschedparam( tid, &policy, &param );
  299. if ( ( policy == SCHED_RR ) || ( policy == SCHED_FIFO ) ) {
  300. param.sched_priority = prio;
  301. pthread_setschedparam( tid, policy, &param );
  302. }
  303. return( 0 );
  304. #elif (SPILT_LIBERAL & _SPILT_LIBERAL_SETPRIO)
  305. return( 0 );
  306. #else
  307. return( ENOSYS );
  308. #endif
  309. }
  310. int
  311. thr_getprio( thread_t tid, int *priop ) {
  312. #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
  313. int policy;
  314. struct sched_param param;
  315. pthread_getschedparam( tid, &policy, &param );
  316. *priop = param.sched_priority;
  317. return( 0 );
  318. #elif (SPILT_LIBERAL & _SPILT_LIBERAL_GETPRIO)
  319. *priop = 0;
  320. return( 0 );
  321. #else
  322. return( ENOSYS );
  323. #endif
  324. }
  325. int
  326. thr_suspend( thread_t tid ) {
  327. #if (SPILT_LIBERAL & _SPILT_LIBERAL_SUSPEND)
  328. return( 0 );
  329. #else
  330. return( ENOSYS );
  331. #endif
  332. }
  333. int
  334. thr_continue( thread_t tid ) {
  335. #if (SPILT_LIBERAL & _SPILT_LIBERAL_CONTINUE)
  336. return( 0 );
  337. #else
  338. return( ENOSYS );
  339. #endif
  340. }
  341. int
  342. thr_setconcurrency( int value ) {
  343. #if (SPILT_LIBERAL & _SPILT_LIBERAL_SETCONCURRENCY)
  344. return( 0 );
  345. #else
  346. return( ENOSYS );
  347. #endif
  348. }
  349. int
  350. thr_getconcurrency( void ) {
  351. #if (SPILT_LIBERAL & _SPILT_LIBERAL_GETCONCURRENCY)
  352. return( 0 );
  353. #else
  354. return( ENOSYS );
  355. #endif
  356. }
  357. #if !defined(SPILT_MACROS)
  358. int
  359. thr_yield( void ) {
  360. return( sched_yield() );
  361. }
  362. #endif
  363. /* Synchronization */
  364. static int
  365. setpshared( int type, int *ptypep ) {
  366. int status = 0;
  367. #ifdef PTHREAD_PROCESS_PRIVATE
  368. switch ( type ) {
  369.   case USYNC_THREAD :
  370. *ptypep = PTHREAD_PROCESS_PRIVATE;
  371. break;
  372.   case USYNC_PROCESS :
  373. *ptypep = PTHREAD_PROCESS_SHARED;
  374. break;
  375.   default :
  376. status = EINVAL;
  377. break;
  378. }
  379. #else
  380. status = EINVAL;
  381. #endif
  382. return( status );
  383. }
  384. /* Synchronization - mutex */
  385. int
  386. mutex_init( mutex_t *mp, int type, void *arg ) {
  387. int ptype;
  388. pthread_mutexattr_t attr;
  389. pthread_mutexattr_init( &attr );
  390. if ( setpshared( type, &ptype ) )
  391. return( EINVAL );
  392. pthread_mutexattr_setpshared( &attr, ptype );
  393. return( pthread_mutex_init( mp, &attr ) );
  394. }
  395. #if !defined(SPILT_MACROS)
  396. int
  397. mutex_destroy( mutex_t *mp ) {
  398. return( pthread_mutex_destroy( mp ) );
  399. }
  400. #endif
  401. #if !defined(SPILT_MACROS)
  402. int
  403. mutex_lock( mutex_t *mp ) {
  404. return( pthread_mutex_lock( mp ) );
  405. }
  406. #endif
  407. #if !defined(SPILT_MACROS)
  408. int
  409. mutex_trylock( mutex_t *mp ) {
  410. return( pthread_mutex_trylock( mp ) );
  411. }
  412. #endif
  413. #if !defined(SPILT_MACROS)
  414. int
  415. mutex_unlock( mutex_t *mp ) {
  416. return( pthread_mutex_unlock( mp ) );
  417. }
  418. #endif
  419. /* Synchronization - condition variable */
  420. int
  421. cond_init( cond_t *cvp, int type, void *arg ) {
  422. int ptype;
  423. pthread_condattr_t attr;
  424. pthread_condattr_init( &attr );
  425. if ( setpshared( type, &ptype ) )
  426. return( EINVAL );
  427. pthread_condattr_setpshared( &attr, ptype );
  428. return( pthread_cond_init( cvp, &attr ) );
  429. }
  430. #if !defined(SPILT_MACROS)
  431. int
  432. cond_destroy( cond_t *cvp ) {
  433. return( pthread_cond_destroy( cvp ) );
  434. }
  435. #endif
  436. #if !defined(SPILT_MACROS)
  437. int
  438. cond_wait( cond_t *cvp, mutex_t *mp ) {
  439. return( pthread_cond_wait( cvp, mp ) );
  440. }
  441. #endif
  442. int
  443. cond_timedwait( cond_t *cvp, mutex_t *mp, timestruc_t *abstimep ) {
  444. struct timespec tv;
  445. tv.tv_sec = abstimep->tv_sec;
  446. tv.tv_nsec = abstimep->tv_nsec;
  447. return( pthread_cond_timedwait( cvp, mp, &tv ) );
  448. }
  449. #if !defined(SPILT_MACROS)
  450. int
  451. cond_signal( cond_t *cvp ) {
  452. return( pthread_cond_signal( cvp ) );
  453. }
  454. #endif
  455. #if !defined(SPILT_MACROS)
  456. int
  457. cond_broadcast( cond_t *cvp ) {
  458. return( pthread_cond_broadcast( cvp ) );
  459. }
  460. #endif
  461. /* Synchronization - semaphore */
  462. int
  463. sema_init( sema_t *sp, unsigned int count, int type, void *arg ) {
  464. int ptype;
  465. pthread_mutexattr_t mutex_attr;
  466. pthread_condattr_t cond_attr;
  467. if ( setpshared( type, &ptype ) )
  468. return( EINVAL );
  469. pthread_mutexattr_init( &mutex_attr );
  470. pthread_mutexattr_setpshared( &mutex_attr, ptype );
  471. pthread_mutex_init( &sp->lock, &mutex_attr );
  472. pthread_condattr_init( &cond_attr );
  473. pthread_condattr_setpshared( &cond_attr, ptype );
  474. pthread_cond_init( &sp->waiters, &cond_attr );
  475. sp->count = count;
  476. return( 0 );
  477. }
  478. int
  479. sema_destroy( sema_t *sp ) {
  480. pthread_mutex_destroy( &sp->lock );
  481. pthread_cond_destroy( &sp->waiters );
  482. return( 0 );
  483. }
  484. int
  485. sema_wait( sema_t *sp ) {
  486. pthread_mutex_t *lkp = &sp->lock;
  487. pthread_mutex_lock( lkp );
  488. pthread_cleanup_push( pthread_mutex_unlock, lkp );
  489. while ( sp->count == 0 )
  490. pthread_cond_wait( &sp->waiters, lkp );
  491. sp->count--;
  492. pthread_cleanup_pop( 1 );
  493. return( 0 );
  494. }
  495. int
  496. sema_trywait( sema_t *sp ) {
  497. int status = EBUSY;
  498. pthread_mutex_lock( &sp->lock );
  499. if ( sp->count ) {
  500. sp->count--;
  501. status = 0;
  502. }
  503. pthread_mutex_unlock( &sp->lock );
  504. return( status );
  505. }
  506. int
  507. sema_post( sema_t *sp ) {
  508. pthread_mutex_lock( &sp->lock );
  509. if ( sp->count++ == 0 )
  510. pthread_cond_signal( &sp->waiters );
  511. pthread_mutex_unlock( &sp->lock );
  512. return( 0 );
  513. }
  514. /* Synchronization - readers / writer lock */
  515. int
  516. rwlock_init( rwlock_t *rwp, int type, void *arg ) {
  517. int ptype;
  518. pthread_mutexattr_t mutex_attr;
  519. pthread_condattr_t cond_attr;
  520. if ( setpshared( type, &ptype ) )
  521. return( EINVAL );
  522. pthread_mutexattr_init( &mutex_attr );
  523. pthread_mutexattr_setpshared( &mutex_attr, ptype );
  524. pthread_mutex_init( &rwp->lock, &mutex_attr );
  525. pthread_condattr_init( &cond_attr );
  526. pthread_condattr_setpshared( &cond_attr, ptype );
  527. pthread_cond_init( &rwp->readers, &cond_attr );
  528. pthread_cond_init( &rwp->writers, &cond_attr );
  529. rwp->state = 0;
  530. rwp->waiters = 0;
  531. return( 0 );
  532. }
  533. int
  534. rwlock_destroy( rwlock_t *rwp ) {
  535. pthread_mutex_destroy( &rwp->lock );
  536. pthread_cond_destroy( &rwp->readers );
  537. pthread_cond_destroy( &rwp->writers );
  538. return( 0 );
  539. }
  540. int
  541. rw_rdlock( rwlock_t *rwp ) {
  542. pthread_mutex_t *lkp = &rwp->lock;
  543. pthread_mutex_lock( lkp );
  544. pthread_cleanup_push( pthread_mutex_unlock, lkp );
  545. /* active or queued writers */
  546. while ( ( rwp->state < 0 ) && rwp->waiters )
  547. cond_wait( &rwp->readers, lkp );
  548. rwp->state++;
  549. pthread_cleanup_pop( 1 );
  550. return( 0 );
  551. }
  552. int
  553. rw_tryrdlock( rwlock_t *rwp ) {
  554. int status = EBUSY;
  555. pthread_mutex_lock( &rwp->lock );
  556. /* available and no writers queued */
  557. if ( ( rwp->state >= 0 ) && !rwp->waiters ) {
  558. rwp->state++;
  559. status = 0;
  560. }
  561. pthread_mutex_unlock( &rwp->lock );
  562. return( status );
  563. }
  564. static void
  565. rw_wrlock_cleanup( void *arg ) {
  566. rwlock_t *rwp = (rwlock_t *) arg;
  567. /*
  568.  * Was the only queued writer and lock is available for readers.
  569.  * Called through cancellation clean-up so lock is held at entry.
  570.  */
  571. if ( ( --rwp->waiters == 0 ) && ( rwp->state >= 0 ) )
  572. pthread_cond_broadcast( &rwp->readers );
  573. pthread_mutex_unlock( &rwp->lock );
  574. return;
  575. }
  576. int
  577. rw_wrlock( rwlock_t *rwp ) {
  578. pthread_mutex_t *lkp = &rwp->lock;
  579. pthread_mutex_lock( lkp );
  580. rwp->waiters++; /* another writer queued */
  581. pthread_cleanup_push( rw_wrlock_cleanup, rwp );
  582. while ( rwp->state )
  583. pthread_cond_wait( &rwp->writers, lkp );
  584. rwp->state = -1;
  585. pthread_cleanup_pop( 1 );
  586. return( 0 );
  587. }
  588. int
  589. rw_trywrlock( rwlock_t *rwp ) {
  590. int status = EBUSY;
  591. pthread_mutex_lock( &rwp->lock );
  592. /* no readers, no writers, no writers queued */
  593. if ( !rwp->state && !rwp->waiters ) {
  594. rwp->state = -1;
  595. status = 0;
  596. }
  597. pthread_mutex_unlock( &rwp->lock );
  598. return( status );
  599. }
  600. int
  601. rw_unlock( rwlock_t *rwp ) {
  602. pthread_mutex_lock( &rwp->lock );
  603. if ( rwp->state == -1 ) { /* writer releasing */
  604. rwp->state = 0; /* mark as available */
  605. if ( rwp->waiters ) /* writers queued */
  606. pthread_cond_signal( &rwp->writers );
  607. else
  608. pthread_cond_broadcast( &rwp->readers );
  609. } else {
  610. if ( --rwp->state == 0 ) /* no more readers */
  611. pthread_cond_signal( &rwp->writers );
  612. }
  613. pthread_mutex_unlock( &rwp->lock );
  614. return( 0 );
  615. }
  616. /* Signals */
  617. #if !defined(SPILT_MACROS)
  618. int
  619. thr_sigsetmask( int how, const sigset_t *setp, sigset_t *osetp ) {
  620. return( pthread_sigmask( how, setp, oldp ) );
  621. }
  622. #endif
  623. #if !defined(SPILT_MACROS)
  624. int
  625. thr_kill( thread_t tid, int signo ) {
  626. return( pthread_kill( tid, signo ) );
  627. }
  628. #endif
  629. /* Thread Specific Data */
  630. #if !defined(SPILT_MACROS)
  631. int
  632. thr_keycreate( thread_key_t *keyp, void (*destructor)( void * ) ) {
  633. return( pthread_key_create( keyp, destructor ) );
  634. }
  635. #endif
  636. #if !defined(SPILT_MACROS)
  637. int
  638. thr_setspecific( thread_key_t key, void *value ) {
  639. return( pthread_setspecific( key, value ) );
  640. }
  641. #endif
  642. int
  643. thr_getspecific( thread_key_t key, void **valuep ) {
  644. *valuep = pthread_getspecific( key );
  645. return( 0 );
  646. }