home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / libraries / libldap_r / thr_lwp.c < prev    next >
C/C++ Source or Header  |  2000-06-14  |  7KB  |  364 lines

  1. /* $OpenLDAP: pkg/ldap/libraries/libldap_r/thr_lwp.c,v 1.8.2.2 2000/06/13 17:57:22 kurt Exp $ */
  2. /*
  3.  * Copyright 1998-2000 The OpenLDAP Foundation, Redwood City, California, USA
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted only
  7.  * as authorized by the OpenLDAP Public License.  A copy of this
  8.  * license is available at http://www.OpenLDAP.org/license.html or
  9.  * in file LICENSE in the top-level directory of the distribution.
  10.  */
  11.  
  12. /* thr_lwp.c - wrappers around SunOS LWP threads */
  13.  
  14. /* BUGS:
  15.  * - slurpd calls the get_stack/free_stack functions. Should be fixed, so
  16.  *   they can become static.
  17.  */
  18.  
  19. #include "portable.h"
  20.  
  21. #if defined( HAVE_LWP )
  22.  
  23. /*************
  24.  *           *
  25.  * SunOS LWP *
  26.  *           *
  27.  *************/
  28.  
  29. /* This implementation NEEDS WORK.   It currently does not compile */
  30.  
  31. #include <stdio.h>
  32.  
  33. #include <ac/time.h>
  34. #include <ac/socket.h>
  35.  
  36. #include "ldap-int.h"
  37.  
  38. #include "ldap_pvt_thread.h"
  39.  
  40. #include <lwp/lwp.h>
  41. #include <lwp/stackdep.h>
  42.  
  43. #define MAX_STACK    51200
  44. #define MAX_THREADS    20
  45.  
  46. /*
  47.  * Initialize LWP by spinning of a schedular
  48.  */
  49. int
  50. ldap_int_thread_initialize( void )
  51. {
  52.     thread_t        tid;
  53.     stkalign_t        *stack;
  54.     int            stackno;
  55.  
  56.     if (( stack = get_stack( &stackno )) == NULL ) {
  57.         return -1;
  58.     }
  59.  
  60.     lwp_create( &tid, lwp_scheduler, MINPRIO, 0, stack, 1, stackno );
  61.     return 0;
  62. }
  63.  
  64. int
  65. ldap_int_thread_destroy( void )
  66. {
  67.     /* need to destory lwp_scheduler thread and clean up private
  68.         variables */
  69.     return 0;
  70. }
  71.  
  72. struct stackinfo {
  73.     int        stk_inuse;
  74.     stkalign_t    *stk_stack;
  75. };
  76.  
  77. static struct stackinfo    *stacks;
  78.  
  79. static stkalign_t * ldap_int_thread_get_stack( int *stacknop )
  80. {
  81.     int    i;
  82.  
  83.     if ( stacks == NULL ) {
  84.         stacks = (struct stackinfo *) LDAP_CALLOC( 1, MAX_THREADS *
  85.             sizeof(struct stackinfo) );
  86.  
  87.         if( stacks == NULL ) {
  88.             Debug( LDAP_DEBUG_ANY, "stacks allocation failed",
  89.                 0, 0, 0 );
  90.             return NULL;
  91.         }
  92.     }
  93.  
  94.     for ( i = 0; i < MAX_THREADS; i++ ) {
  95.         if ( stacks[i].stk_inuse == 0 ) {
  96.             break;
  97.         }
  98.     }
  99.  
  100.     if ( i == MAX_THREADS ) {
  101.         Debug( LDAP_DEBUG_ANY,
  102.             "no more stacks (max %d) - increase MAX_THREADS for more",
  103.             MAX_THREADS, 0, 0 );
  104.         return( NULL );
  105.     }
  106.  
  107.     if ( stacks[i].stk_stack == NULL ) {
  108.         stacks[i].stk_stack = (stkalign_t *) LDAP_MALLOC(
  109.             (MAX_STACK / sizeof(stkalign_t) + 1 )
  110.             * sizeof(stkalign_t) );
  111.  
  112.         if( stacks[i].stk_stack == NULL ) {
  113.             Debug( LDAP_DEBUG_ANY, "stack allocation failed",
  114.                 0, 0, 0 );
  115.             return( NULL );
  116.         }
  117.     }
  118.  
  119.     *stacknop = i;
  120.     stacks[i].stk_inuse = 1;
  121.     return( stacks[i].stk_stack + MAX_STACK / sizeof(stkalign_t) );
  122. }
  123.  
  124. static void
  125. ldap_int_thread_free_stack( int    stackno )
  126. {
  127.     if ( stackno < 0 || stackno > MAX_THREADS ) {
  128.         Debug( LDAP_DEBUG_ANY, "free_stack of bogus stack %d\n",
  129.             stackno, 0, 0 );
  130.     }
  131.  
  132.     stacks[stackno].stk_inuse = 0;
  133. }
  134.  
  135. static void
  136. lwp_create_stack( void *(*func)(), void *arg, int stackno )
  137. {
  138.     (*func)( arg );
  139.  
  140.     ldap_int_thread_free_stack( stackno );
  141. }
  142.  
  143. int 
  144. ldap_pvt_thread_create( ldap_pvt_thread_t * thread, 
  145.     int detach,
  146.     void *(*start_routine)( void *),
  147.     void *arg)
  148. {
  149.     stkalign_t    *stack;
  150.     int        stackno;
  151.  
  152.     if ( (stack = ldap_int_thread_get_stack( &stackno )) == NULL ) {
  153.         return( -1 );
  154.     }
  155.     return( lwp_create( thread, lwp_create_stack, MINPRIO, 0, 
  156.                stack, 3, start_routine, arg, stackno ) );
  157. }
  158.  
  159. void 
  160. ldap_pvt_thread_exit( void *retval )
  161. {
  162.     lwp_destroy( SELF );
  163. }
  164.  
  165. unsigned int
  166. ldap_pvt_thread_sleep(
  167.     unsigned int interval
  168. )
  169. {
  170.     thread_t        mylwp;
  171.     tl_t        *t, *nt;
  172.     time_t        now;
  173.  
  174.  
  175.     if ( lwp_self( &mylwp ) < 0 ) {
  176.         return -1;
  177.     }
  178.  
  179.     time( &now );
  180.  
  181.     mon_enter( &sglob->tsl_mon );
  182.  
  183.     if ( sglob->tsl_list != NULL ) {
  184.         for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
  185.             if ( SAMETHREAD( t->tl_tid, mylwp )) {
  186.                 /* We're already sleeping? */
  187.                 t->tl_wake = now + interval;
  188.                 mon_exit( &sglob->tsl_mon );
  189.                 lwp_suspend( mylwp );
  190.                 return 0;
  191.             }
  192.         }
  193.     }
  194.  
  195.     nt = (tl_t *) LDAP_MALLOC( sizeof( tl_t ));
  196.  
  197.     if( nt == NULL ) return -1;
  198.  
  199.     nt->tl_next = sglob->tsl_list;
  200.     nt->tl_wake = now + interval;
  201.     nt->tl_tid = mylwp;
  202.     sglob->tsl_list = nt;
  203.  
  204.     mon_exit( &sglob->tsl_mon );
  205.  
  206.     lwp_suspend( mylwp );
  207.     return 0;
  208. }
  209.  
  210. /*
  211.  * The lwp_scheduler thread periodically checks to see if any threads
  212.  * are due to be resumed.  If there are, it resumes them.  Otherwise,
  213.  * it computes the lesser of ( 1 second ) or ( the minimum time until
  214.  * a thread need to be resumed ) and puts itself to sleep for that amount
  215.  * of time.
  216.  */
  217. static void
  218. lwp_scheduler(
  219.     int        stackno
  220. )
  221. {
  222.     time_t            now, min;
  223.     struct timeval        interval;
  224.     tl_t            *t;
  225.  
  226.     while ( !sglob->slurpd_shutdown ) {
  227.         mon_enter( &sglob->tsl_mon );
  228.  
  229.         time( &now );
  230.         min = 0L;
  231.         if ( sglob->tsl_list != NULL ) {
  232.             for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
  233.                 if (( t->tl_wake  > 0L ) && ( t->tl_wake < now )) {
  234.                     lwp_resume( t->tl_tid );
  235.                     t->tl_wake = 0L;
  236.                 }
  237.  
  238.                 if (( t->tl_wake > now ) && ( t->tl_wake < min )) {
  239.                     min =  t->tl_wake;
  240.                 }
  241.             }
  242.         }
  243.  
  244.         mon_exit( &sglob->tsl_mon );
  245.  
  246.         interval.tv_usec = 0L;
  247.         if ( min == 0L ) {
  248.             interval.tv_sec = 1L;
  249.         } else {
  250.             interval.tv_sec = min;
  251.         }
  252.  
  253.         lwp_sleep( &interval );
  254.     }
  255.  
  256.     mon_enter( &sglob->tsl_mon );
  257.  
  258.     for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
  259.         lwp_resume( t->tl_tid );
  260.     }
  261.  
  262.     mon_exit( &sglob->tsl_mon );
  263.  
  264.     free_stack( stackno );
  265. }
  266.  
  267. int 
  268. ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
  269. {
  270.     lwp_join( thread );
  271.     return 0;
  272. }
  273.  
  274. int 
  275. ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo )
  276. {
  277.     return 0;
  278. }
  279.  
  280. int 
  281. ldap_pvt_thread_yield( void )
  282. {
  283.     lwp_yield( SELF );
  284.     return 0;
  285. }
  286.  
  287. int 
  288. ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
  289. {
  290.     /*
  291.      * lwp cv_create requires the monitor id be passed in
  292.      * when the cv is created, pthreads passes it when the
  293.      * condition is waited for.  so, we fake the creation
  294.      * here and actually do it when the cv is waited for
  295.      * later.
  296.      */
  297.  
  298.     cond->lcv_created = 0;
  299.  
  300.     return( 0 );
  301. }
  302.  
  303. int 
  304. ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
  305. {
  306.     return( cond->lcv_created ? cv_notify( cv->lcv_cv ) : 0 );
  307. }
  308.  
  309. int 
  310. ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, 
  311.     ldap_int_thread_mutex_t *mutex )
  312. {
  313.     if ( ! cond->lcv_created ) {
  314.         cv_create( &cond->lcv_cv, *mutex );
  315.         cond->lcv_created = 1;
  316.     }
  317.  
  318.     return( cv_wait( cond->lcv_cv ) );    
  319. }
  320.  
  321. int 
  322. ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
  323. {
  324.     return( mon_create( mutex ) );
  325. }
  326.  
  327. int 
  328. ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
  329. {
  330.     return( mon_destroy( *mutex ) );
  331. }
  332.  
  333. int 
  334. ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
  335. {
  336.     return( mon_enter( *mutex ) );
  337. }
  338.  
  339. int 
  340. ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
  341. {
  342.     return( mon_exit( *mutex ) );
  343. }
  344.  
  345. int
  346. ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mp )
  347. {
  348.     return( mon_cond_enter( *mp ) );
  349. }
  350.  
  351. int
  352. ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cv )
  353. {
  354.     return( cv->lcv_created ? cv_destroy( cv->lcv_cv ) : 0 );
  355. }
  356.  
  357. int
  358. ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cv )
  359. {
  360.     return( cv->lcv_created ? cv_broadcast( cv->lcv_cv ) : 0 );
  361. }
  362.  
  363. #endif /* HAVE_LWP */
  364.