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