~ubuntu-branches/ubuntu/maverick/pdns/maverick-updates

« back to all changes in this revision

Viewing changes to pdns/mtasker.cc

  • Committer: Bazaar Package Importer
  • Author(s): Matthijs Mohlmann, Matthijs Mohlmann, Christoph Haas
  • Date: 2007-04-15 23:23:39 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070415232339-5x3scc8gx04e50um
Tags: 2.9.21-1
[ Matthijs Mohlmann ]
* New upstream release. (Closes: #420294)
* Remove meta pdns package.
* Added new sqlite3 backend package.
* Months and minutes where mixed up. (Closes: #406462)
* Case sensitivity in bind backend caused PowerDNS to not serve a certain
  zone. (Closes: #406461)
* Bind backend forgot about zones on a notify. (Closes: #398213)

[ Christoph Haas ]
* Documented incorporated backend bind. (Closes: #415471)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
    PowerDNS Versatile Database Driven Nameserver
3
 
    Copyright (C) 2002 - 2005  PowerDNS.COM BV
 
3
    Copyright (C) 2002 - 2006  PowerDNS.COM BV
4
4
 
5
5
    This program is free software; you can redistribute it and/or modify
6
 
    it under the terms of the GNU General Public License as published by
7
 
    the Free Software Foundation; either version 2 of the License, or
8
 
    (at your option) any later version.
 
6
    it under the terms of the GNU General Public License version 2 as 
 
7
    published by the Free Software Foundation
9
8
 
10
9
    This program is distributed in the hope that it will be useful,
11
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
13
 
15
14
    You should have received a copy of the GNU General Public License
16
15
    along with this program; if not, write to the Free Software
17
 
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
17
*/
19
18
#include "mtasker.hh"
20
19
#include <stdio.h>
25
24
    support for waiting on events which can return values.
26
25
 
27
26
    \section copyright Copyright and License
28
 
    MTasker is (c) 2002 - 2005 by bert hubert. It is licensed to you under the terms of the GPL version 2.
 
27
    MTasker is (c) 2002 - 2006 by bert hubert. It is licensed to you under the terms of the GPL version 2.
29
28
 
30
29
    \section overview High level overview
31
30
    MTasker is designed to support very simple cooperative multitasking to facilitate writing 
159
158
    \return returns -1 in case of error, 0 in case of timeout, 1 in case of an answer 
160
159
*/
161
160
 
162
 
template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::waitEvent(const EventKey &key, EventVal *val, unsigned int timeout)
 
161
template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::waitEvent(EventKey &key, EventVal *val, unsigned int timeout, unsigned int now)
163
162
{
164
163
  if(d_waiters.count(key)) { // there was already an exact same waiter
165
164
    return -1;
167
166
 
168
167
  Waiter w;
169
168
  w.context=new ucontext_t;
170
 
  w.ttd= timeout ? time(0)+timeout : 0;
 
169
  w.ttd=0;
 
170
  if(timeout)
 
171
    w.ttd= timeout + (now ? now : time(0));
 
172
 
171
173
  w.tid=d_tid;
172
174
  
173
175
  w.key=key;
181
183
  if(val && d_waitstatus==Answer) 
182
184
    *val=d_waitval;
183
185
  d_tid=w.tid;
 
186
  key=d_eventkey;
184
187
  return d_waitstatus;
185
188
}
186
189
 
190
193
template<class Key, class Val>void MTasker<Key,Val>::yield()
191
194
{
192
195
  d_runQueue.push(d_tid);
193
 
  if(swapcontext(d_threads[d_tid].first ,&d_kernel) < 0) { // give control to the kernel
 
196
  if(swapcontext(d_threads[d_tid] ,&d_kernel) < 0) { // give control to the kernel
194
197
    perror("swapcontext in  yield");
195
198
    exit(EXIT_FAILURE);
196
199
  }
201
204
    \param key Key of the event for which threads may be waiting
202
205
    \param val If non-zero, pointer to the content of the event
203
206
    \return Returns -1 in case of error, 0 if there were no waiters, 1 if a thread was woken up.
 
207
 
 
208
    WARNING: when passing val as zero, d_waitval is undefined, and hence waitEvent will return undefined!
204
209
*/
205
210
template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::sendEvent(const EventKey& key, const EventVal* val)
206
211
{
207
 
  if(!d_waiters.count(key)) {
 
212
  typename waiters_t::iterator waiter=d_waiters.find(key);
 
213
 
 
214
  if(waiter == d_waiters.end()) {
208
215
    //    cout<<"Event sent nobody was waiting for!"<<endl;
209
216
    return 0;
210
217
  }
213
220
  if(val)
214
221
    d_waitval=*val;
215
222
  
216
 
  ucontext_t *userspace=d_waiters.find(key)->context;
217
 
  d_tid=d_waiters.find(key)->tid;         // set tid 
218
 
  
219
 
  d_waiters.erase(key);             // removes the waitpoint 
 
223
  ucontext_t *userspace=waiter->context;
 
224
  d_tid=waiter->tid;         // set tid 
 
225
  d_eventkey=waiter->key;        // pass waitEvent the exact key it was woken for
 
226
  d_waiters.erase(waiter);             // removes the waitpoint 
220
227
  if(swapcontext(&d_kernel,userspace)) { // swaps back to the above point 'A'
221
228
    perror("swapcontext in sendEvent");
222
229
    exit(EXIT_FAILURE);
230
237
    \param start Pointer to the function which will form the start of the thread
231
238
    \param val A void pointer that can be used to pass data to the thread
232
239
*/
233
 
template<class Key, class Val>void MTasker<Key,Val>::makeThread(tfunc_t *start, void* val, const string& name)
 
240
template<class Key, class Val>void MTasker<Key,Val>::makeThread(tfunc_t *start, void* val)
234
241
{
235
242
  ucontext_t *uc=new ucontext_t;
236
243
  getcontext(uc);
239
246
  uc->uc_stack.ss_sp = new char[d_stacksize];
240
247
  
241
248
  uc->uc_stack.ss_size = d_stacksize;
242
 
#ifdef SOLARIS
 
249
#ifdef SOLARIS8
243
250
  uc->uc_stack.ss_sp = (void*)(((char*)uc->uc_stack.ss_sp)+d_stacksize);
244
251
  makecontext (uc,(void (*)(...))threadWrapper, 5, this, start, d_maxtid, val);
245
252
#else
246
253
  makecontext (uc, (void (*)(void))threadWrapper, 4, this, start, d_maxtid, val);
247
254
#endif
248
 
  d_threads[d_maxtid]=make_pair(uc, name);
 
255
  d_threads[d_maxtid]=uc;
249
256
  d_runQueue.push(d_maxtid++); // will run at next schedule invocation
250
257
}
251
258
 
260
267
    \return Returns if there is more work scheduled and recalling schedule now would be useful
261
268
      
262
269
*/
263
 
template<class Key, class Val>bool MTasker<Key,Val>::schedule()
 
270
template<class Key, class Val>bool MTasker<Key,Val>::schedule(unsigned int now)
264
271
{
265
272
  if(!d_runQueue.empty()) {
266
273
    d_tid=d_runQueue.front();
267
 
    if(swapcontext(&d_kernel, d_threads[d_tid].first)) {
 
274
    if(swapcontext(&d_kernel, d_threads[d_tid])) {
268
275
      perror("swapcontext in schedule");
269
276
      exit(EXIT_FAILURE);
270
277
    }
273
280
    return true;
274
281
  }
275
282
  if(!d_zombiesQueue.empty()) {
276
 
    delete[] (char *)d_threads[d_zombiesQueue.front()].first->uc_stack.ss_sp;
277
 
    delete d_threads[d_zombiesQueue.front()].first;
 
283
#ifdef SOLARIS8
 
284
    delete[] (((char *)d_threads[d_zombiesQueue.front()]->uc_stack.ss_sp)-d_stacksize);
 
285
#else
 
286
    delete[] (char *)d_threads[d_zombiesQueue.front()]->uc_stack.ss_sp;
 
287
#endif
 
288
    delete d_threads[d_zombiesQueue.front()];
278
289
    d_threads.erase(d_zombiesQueue.front());
279
290
    d_zombiesQueue.pop();
280
291
    return true;
281
292
  }
282
293
  if(!d_waiters.empty()) {
283
 
    time_t now=time(0);
 
294
    if(!now)
 
295
      now=time(0);
284
296
 
285
297
    typedef typename waiters_t::template index<KeyTag>::type waiters_by_ttd_index_t;
286
298
    //    waiters_by_ttd_index_t& ttdindex=d_waiters.template get<KeyTag>();
287
299
    waiters_by_ttd_index_t& ttdindex=boost::multi_index::get<KeyTag>(d_waiters);
288
300
 
289
 
 
290
301
    for(typename waiters_by_ttd_index_t::iterator i=ttdindex.begin(); i != ttdindex.end(); ) {
291
 
      if(i->ttd && i->ttd < now) {
 
302
      if(i->ttd && (unsigned int)i->ttd < now) {
292
303
        d_waitstatus=TimeOut;
293
304
        if(swapcontext(&d_kernel,i->context)) { // swaps back to the above point 'A'
294
305
          perror("swapcontext in schedule2");
322
333
  return d_threads.size();
323
334
}
324
335
 
325
 
 
326
336
//! gives access to the list of Events threads are waiting for
327
337
/** The kernel can call this to get a list of Events threads are waiting for. This is very useful
328
338
    to setup 'select' or 'poll' or 'aio' events needed to satisfy these requests.