]> git.sur5r.net Git - openldap/blob - servers/slurpd/tsleep.c
Fixup bugs created by merge.
[openldap] / servers / slurpd / tsleep.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  * tsleep.c - allow a thread to sleep without putting the whole process
15  * (e.g. pod under lwp) to sleep.  Contains platform-specific code to
16  * allow this:
17  *
18  * Under non-preemptive threads packages like SunOS lwp, tsleep() adds
19  * the thread to a list of sleepers.  The lwp_scheduler process takes
20  * care of resuming suspended threads.
21  *
22  * Under a fully-preemptive threads package, like Solaris threads,
23  * tsleep just calls sleep(), and there is no scheduler thread.  Life
24  * is so much simpler...
25  */
26
27 #include "portable.h"
28
29 #include <stdio.h>
30
31 #include "slurp.h"
32 #include "globals.h"
33
34
35 #if defined( HAVE_LWP )
36
37 extern stkalign_t *get_stack( int * );
38 extern void free_stack( int );
39
40 int
41 tsleep(
42     int interval
43 )
44 {
45     thread_t    mylwp;
46     tl_t        *t, *nt;
47     time_t      now;
48
49
50     if ( lwp_self( &mylwp ) < 0 ) {
51         return -1;
52     }
53     time( &now );
54
55     mon_enter( &sglob->tsl_mon );
56     if ( sglob->tsl_list != NULL ) {
57         for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
58             if ( SAMETHREAD( t->tl_tid, mylwp )) {
59                 /* We're already sleeping? */
60                 t->tl_wake = now + (time_t) interval;
61                 mon_exit( &sglob->tsl_mon );
62                 lwp_suspend( mylwp );
63                 return 0;
64             }
65         }
66     }
67     nt = (tl_t *) malloc( sizeof( tl_t ));
68
69     nt->tl_next = sglob->tsl_list;
70     nt->tl_wake = now + (time_t) interval;
71     nt->tl_tid = mylwp;
72     sglob->tsl_list = nt;
73     mon_exit( &sglob->tsl_mon );
74     lwp_suspend( mylwp );
75     return 0;
76 }
77
78 /*
79  * The lwp_scheduler thread periodically checks to see if any threads
80  * are due to be resumed.  If there are, it resumes them.  Otherwise,
81  * it computes the lesser of ( 1 second ) or ( the minimum time until
82  * a thread need to be resumed ) and puts itself to sleep for that amount
83  * of time.
84  */
85 void
86 lwp_scheduler(
87     int stackno
88 )
89 {
90     time_t              now, min;
91     struct timeval      interval;
92     tl_t                *t;
93
94     while ( !sglob->slurpd_shutdown ) {
95         mon_enter( &sglob->tsl_mon );
96         time( &now );
97         min = 0L;
98         if ( sglob->tsl_list != NULL ) {
99             for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
100                 if (( t->tl_wake  > 0L ) && ( t->tl_wake < now )) {
101                     lwp_resume( t->tl_tid );
102                     t->tl_wake = 0L;
103                 }
104                 if (( t->tl_wake > now ) && ( t->tl_wake < min )) {
105                     min =  t->tl_wake;
106                 }
107             }
108         }
109         mon_exit( &sglob->tsl_mon );
110         interval.tv_usec = 0L;
111         if ( min == 0L ) {
112             interval.tv_sec = 1L;
113         } else {
114             interval.tv_sec = min;
115         }
116         lwp_sleep( &interval );
117     }
118     mon_enter( &sglob->tsl_mon );
119     for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
120         lwp_resume( t->tl_tid );
121     }
122     mon_exit( &sglob->tsl_mon );
123     free_stack( stackno );
124 }
125
126
127 /*
128  * Create the lwp_scheduler thread.
129  */
130 void
131 start_lwp_scheduler()
132 {
133     thread_t    tid;
134     stkalign_t  *stack;
135     int         stackno;
136
137     if (( stack = get_stack( &stackno )) == NULL ) {
138         return;
139     }
140     lwp_create( &tid, lwp_scheduler, MINPRIO, 0, stack, 1, stackno );
141     return;
142 }
143
144
145 #else /* !HAVE_LWP */
146
147 /*
148  * Here we assume we have fully preemptive threads, and that sleep()
149  * does the right thing.
150  */
151 void
152 tsleep(
153     time_t      interval
154 )
155 {
156     sleep( interval );
157 }
158 #endif /* !HAVE_LWP */
159
160
161