]> git.sur5r.net Git - openldap/blob - libraries/libldap_r/thr_sleep.c
Use ldap_pvt_strtok directly and unconditionally.
[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 #if !defined( HAVE_LWP )
35
36 /*
37  * Here we assume we have fully preemptive threads and that sleep()
38  * does the right thing.
39  */
40 unsigned int
41 ldap_pvt_thread_sleep(
42         unsigned int interval
43 )
44 {
45         sleep( interval );
46         return 0;
47 }
48
49 #else
50
51 unsigned int
52 ldap_pvt_thread_sleep(
53         unsigned int interval
54 )
55 {
56         thread_t                mylwp;
57         tl_t            *t, *nt;
58         time_t          now;
59
60
61         if ( lwp_self( &mylwp ) < 0 ) {
62                 return -1;
63         }
64
65         time( &now );
66
67         mon_enter( &sglob->tsl_mon );
68
69         if ( sglob->tsl_list != NULL ) {
70                 for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
71                         if ( SAMETHREAD( t->tl_tid, mylwp )) {
72                                 /* We're already sleeping? */
73                                 t->tl_wake = now + interval;
74                                 mon_exit( &sglob->tsl_mon );
75                                 lwp_suspend( mylwp );
76                                 return 0;
77                         }
78                 }
79         }
80
81         nt = (tl_t *) malloc( sizeof( tl_t ));
82
83         nt->tl_next = sglob->tsl_list;
84         nt->tl_wake = now + interval;
85         nt->tl_tid = mylwp;
86         sglob->tsl_list = nt;
87
88         mon_exit( &sglob->tsl_mon );
89
90         lwp_suspend( mylwp );
91         return 0;
92 }
93
94 /*
95  * The lwp_scheduler thread periodically checks to see if any threads
96  * are due to be resumed.  If there are, it resumes them.  Otherwise,
97  * it computes the lesser of ( 1 second ) or ( the minimum time until
98  * a thread need to be resumed ) and puts itself to sleep for that amount
99  * of time.
100  */
101 void
102 lwp_scheduler(
103         int             stackno
104 )
105 {
106         time_t                  now, min;
107         struct timeval          interval;
108         tl_t                    *t;
109
110         while ( !sglob->slurpd_shutdown ) {
111                 mon_enter( &sglob->tsl_mon );
112
113                 time( &now );
114                 min = 0L;
115                 if ( sglob->tsl_list != NULL ) {
116                         for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
117                                 if (( t->tl_wake  > 0L ) && ( t->tl_wake < now )) {
118                                         lwp_resume( t->tl_tid );
119                                         t->tl_wake = 0L;
120                                 }
121
122                                 if (( t->tl_wake > now ) && ( t->tl_wake < min )) {
123                                         min =  t->tl_wake;
124                                 }
125                         }
126                 }
127
128                 mon_exit( &sglob->tsl_mon );
129
130                 interval.tv_usec = 0L;
131                 if ( min == 0L ) {
132                         interval.tv_sec = 1L;
133                 } else {
134                         interval.tv_sec = min;
135                 }
136
137                 lwp_sleep( &interval );
138         }
139
140         mon_enter( &sglob->tsl_mon );
141
142         for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
143                 lwp_resume( t->tl_tid );
144         }
145
146         mon_exit( &sglob->tsl_mon );
147
148         free_stack( stackno );
149 }
150
151 #endif /* HAVE_LWP */