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