]> git.sur5r.net Git - openldap/blob - libraries/libldap_r/thr_sleep.c
include ldap_pvt_thread.h, to verify func declarations against their definitinos
[openldap] / libraries / libldap_r / thr_sleep.c
1 /*
2  * Copyright (c) 1996 Regents of the University of Michigan.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of Michigan at Ann Arbor. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12
13 /*
14  * ldap_pvt_thread_sleep.c - allow a thread to sleep without putting
15  * the whole process (e.g. pod under lwp) to sleep.
16  *
17  * Contains platform-specific code to allow this:
18  *
19  * Under non-preemptive threads packages like SunOS lwp, tsleep() adds
20  * the thread to a list of sleepers.  The lwp_scheduler process takes
21  * care of resuming suspended threads.
22  *
23  * Under a fully-preemptive threads package, like Solaris threads,
24  * tsleep just calls sleep(), and there is no scheduler thread.  Life
25  * is so much simpler...
26  */
27
28 #include "portable.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ac/unistd.h>                  /* get sleep() */
33
34 #include "ldap_pvt_thread.h"
35
36 #if !defined( HAVE_LWP )
37
38 /*
39  * Here we assume we have fully preemptive threads and that sleep()
40  * does the right thing.
41  */
42 unsigned int
43 ldap_pvt_thread_sleep(
44         unsigned int interval
45 )
46 {
47         sleep( interval );
48         return 0;
49 }
50
51 #else
52
53 unsigned int
54 ldap_pvt_thread_sleep(
55         unsigned int interval
56 )
57 {
58         thread_t                mylwp;
59         tl_t            *t, *nt;
60         time_t          now;
61
62
63         if ( lwp_self( &mylwp ) < 0 ) {
64                 return -1;
65         }
66
67         time( &now );
68
69         mon_enter( &sglob->tsl_mon );
70
71         if ( sglob->tsl_list != NULL ) {
72                 for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
73                         if ( SAMETHREAD( t->tl_tid, mylwp )) {
74                                 /* We're already sleeping? */
75                                 t->tl_wake = now + interval;
76                                 mon_exit( &sglob->tsl_mon );
77                                 lwp_suspend( mylwp );
78                                 return 0;
79                         }
80                 }
81         }
82
83         nt = (tl_t *) malloc( sizeof( tl_t ));
84
85         nt->tl_next = sglob->tsl_list;
86         nt->tl_wake = now + interval;
87         nt->tl_tid = mylwp;
88         sglob->tsl_list = nt;
89
90         mon_exit( &sglob->tsl_mon );
91
92         lwp_suspend( mylwp );
93         return 0;
94 }
95
96 /*
97  * The lwp_scheduler thread periodically checks to see if any threads
98  * are due to be resumed.  If there are, it resumes them.  Otherwise,
99  * it computes the lesser of ( 1 second ) or ( the minimum time until
100  * a thread need to be resumed ) and puts itself to sleep for that amount
101  * of time.
102  */
103 void
104 lwp_scheduler(
105         int             stackno
106 )
107 {
108         time_t                  now, min;
109         struct timeval          interval;
110         tl_t                    *t;
111
112         while ( !sglob->slurpd_shutdown ) {
113                 mon_enter( &sglob->tsl_mon );
114
115                 time( &now );
116                 min = 0L;
117                 if ( sglob->tsl_list != NULL ) {
118                         for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
119                                 if (( t->tl_wake  > 0L ) && ( t->tl_wake < now )) {
120                                         lwp_resume( t->tl_tid );
121                                         t->tl_wake = 0L;
122                                 }
123
124                                 if (( t->tl_wake > now ) && ( t->tl_wake < min )) {
125                                         min =  t->tl_wake;
126                                 }
127                         }
128                 }
129
130                 mon_exit( &sglob->tsl_mon );
131
132                 interval.tv_usec = 0L;
133                 if ( min == 0L ) {
134                         interval.tv_sec = 1L;
135                 } else {
136                         interval.tv_sec = min;
137                 }
138
139                 lwp_sleep( &interval );
140         }
141
142         mon_enter( &sglob->tsl_mon );
143
144         for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
145                 lwp_resume( t->tl_tid );
146         }
147
148         mon_exit( &sglob->tsl_mon );
149
150         free_stack( stackno );
151 }
152
153 #endif /* HAVE_LWP */